* xt-mouse.el (xterm-mouse-mode): Make it a global mode.
[emacs.git] / lib-src / etags.c
blobe6ca44d968e1deebec825db5a23e969c9f634daf
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. */
22 * Authors:
23 * Ctags originally by Ken Arnold.
24 * Fortran added by Jim Kleckner.
25 * Ed Pelegri-Llopart added C typedefs.
26 * Gnu Emacs TAGS format and modifications by RMS?
27 * 1989 Sam Kendall added C++.
28 * 1992 Joseph B. Wells improved C and C++ parsing.
29 * 1993 Francesco Potortì reorganised C and C++.
30 * 1994 Line-by-line regexp tags by Tom Tromey.
31 * 2001 Nested classes by Francesco Potortì (concept by Mykola Dzyuba).
32 * 2002 #line directives by Francesco Potortì.
34 * Francesco Potortì <pot@gnu.org> has maintained and improved it since 1993.
38 char pot_etags_version[] = "@(#) pot revision number is 16.32";
40 #define TRUE 1
41 #define FALSE 0
43 #ifdef DEBUG
44 # undef DEBUG
45 # define DEBUG TRUE
46 #else
47 # define DEBUG FALSE
48 # define NDEBUG /* disable assert */
49 #endif
51 #ifdef HAVE_CONFIG_H
52 # include <config.h>
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. */
55 # undef static
56 # define ETAGS_REGEXPS /* use the regexp features */
57 # define LONG_OPTIONS /* accept long options */
58 # ifndef PTR /* for Xemacs */
59 # define PTR void *
60 # endif
61 # ifndef __P /* for Xemacs */
62 # define __P(args) args
63 # endif
64 #else
65 # if defined(__STDC__) && (__STDC__ || defined(__SUNPRO_C))
66 # define __P(args) args /* use prototypes */
67 # define PTR void * /* for generic pointers */
68 # else
69 # define __P(args) () /* no prototypes */
70 # define const /* remove const for old compilers' sake */
71 # define PTR long * /* don't use void* */
72 # endif
73 #endif /* !HAVE_CONFIG_H */
75 #ifndef _GNU_SOURCE
76 # define _GNU_SOURCE 1 /* enables some compiler checks on GNU */
77 #endif
79 /* WIN32_NATIVE is for Xemacs.
80 MSDOS, WINDOWSNT, DOS_NT are for Emacs. */
81 #ifdef WIN32_NATIVE
82 # undef MSDOS
83 # undef WINDOWSNT
84 # define WINDOWSNT
85 #endif /* WIN32_NATIVE */
87 #ifdef MSDOS
88 # undef MSDOS
89 # define MSDOS TRUE
90 # include <fcntl.h>
91 # include <sys/param.h>
92 # include <io.h>
93 # ifndef HAVE_CONFIG_H
94 # define DOS_NT
95 # include <sys/config.h>
96 # endif
97 #else
98 # define MSDOS FALSE
99 #endif /* MSDOS */
101 #ifdef WINDOWSNT
102 # include <stdlib.h>
103 # include <fcntl.h>
104 # include <string.h>
105 # include <direct.h>
106 # include <io.h>
107 # define MAXPATHLEN _MAX_PATH
108 # undef HAVE_NTGUI
109 # undef DOS_NT
110 # define DOS_NT
111 # ifndef HAVE_GETCWD
112 # define HAVE_GETCWD
113 # endif /* undef HAVE_GETCWD */
114 #else /* !WINDOWSNT */
115 # ifdef STDC_HEADERS
116 # include <stdlib.h>
117 # include <string.h>
118 # else
119 extern char *getenv ();
120 # endif
121 #endif /* !WINDOWSNT */
123 #ifdef HAVE_UNISTD_H
124 # include <unistd.h>
125 #else
126 # if defined (HAVE_GETCWD) && !defined (WINDOWSNT)
127 extern char *getcwd (char *buf, size_t size);
128 # endif
129 #endif /* HAVE_UNISTD_H */
131 #include <stdio.h>
132 #include <ctype.h>
133 #include <errno.h>
134 #ifndef errno
135 extern int errno;
136 #endif
137 #include <sys/types.h>
138 #include <sys/stat.h>
140 #include <assert.h>
141 #ifdef NDEBUG
142 # undef assert /* some systems have a buggy assert.h */
143 # define assert(x) ((void) 0)
144 #endif
146 #if !defined (S_ISREG) && defined (S_IFREG)
147 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
148 #endif
150 #ifdef LONG_OPTIONS
151 # include <getopt.h>
152 #else
153 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
154 extern char *optarg;
155 extern int optind, opterr;
156 #endif /* LONG_OPTIONS */
158 #ifdef ETAGS_REGEXPS
159 # ifndef HAVE_CONFIG_H /* this is a standalone compilation */
160 # ifdef __CYGWIN__ /* compiling on Cygwin */
161 !!! NOTICE !!!
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.
165 # endif
166 # endif
167 # include <regex.h>
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. */
173 #ifdef CTAGS
174 # undef CTAGS
175 # define CTAGS TRUE
176 #else
177 # define CTAGS FALSE
178 #endif
180 /* Exit codes for success and failure. */
181 #ifdef VMS
182 # define GOOD 1
183 # define BAD 0
184 #else
185 # define GOOD 0
186 # define BAD 1
187 #endif
189 #define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t))
190 #define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
192 #define CHARS 256 /* 2^sizeof(char) */
193 #define CHAR(x) ((unsigned int)(x) & (CHARS - 1))
194 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */
195 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
196 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
197 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
198 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
200 #define ISALNUM(c) isalnum (CHAR(c))
201 #define ISALPHA(c) isalpha (CHAR(c))
202 #define ISDIGIT(c) isdigit (CHAR(c))
203 #define ISLOWER(c) islower (CHAR(c))
205 #define lowcase(c) tolower (CHAR(c))
206 #define upcase(c) toupper (CHAR(c))
210 * xnew, xrnew -- allocate, reallocate storage
212 * SYNOPSIS: Type *xnew (int n, Type);
213 * void xrnew (OldPointer, int n, Type);
215 #if DEBUG
216 # include "chkmalloc.h"
217 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
218 (n) * sizeof (Type)))
219 # define xrnew(op,n,Type) ((op) = (Type *) trace_realloc (__FILE__, __LINE__, \
220 (char *) (op), (n) * sizeof (Type)))
221 #else
222 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
223 # define xrnew(op,n,Type) ((op) = (Type *) xrealloc ( \
224 (char *) (op), (n) * sizeof (Type)))
225 #endif
227 #define bool int
229 typedef void Lang_function __P((FILE *));
231 typedef struct
233 char *suffix; /* file name suffix for this compressor */
234 char *command; /* takes one arg and decompresses to stdout */
235 } compressor;
237 typedef struct
239 char *name; /* language name */
240 bool metasource; /* source used to generate other sources */
241 Lang_function *function; /* parse function */
242 char **filenames; /* names of this language's files */
243 char **suffixes; /* name suffixes of this language's files */
244 char **interpreters; /* interpreters for this language */
245 } language;
247 typedef struct fdesc
249 struct fdesc *next; /* for the linked list */
250 char *infname; /* uncompressed input file name */
251 char *infabsname; /* absolute uncompressed input file name */
252 char *infabsdir; /* absolute dir of input file */
253 char *taggedfname; /* file name to write in tagfile */
254 language *lang; /* language of file */
255 char *prop; /* file properties to write in tagfile */
256 bool usecharno; /* etags tags shall contain char number */
257 } fdesc;
259 typedef struct node_st
260 { /* sorting structure */
261 struct node_st *left, *right; /* left and right sons */
262 fdesc *fdp; /* description of file to whom tag belongs */
263 char *name; /* tag name */
264 char *pat; /* search pattern */
265 bool valid; /* write this tag on the tag file */
266 bool is_func; /* function tag: use pattern in CTAGS mode */
267 bool been_warned; /* warning already given for duplicated tag */
268 int lno; /* line number tag is on */
269 long cno; /* character number line starts on */
270 } node;
273 * A `linebuffer' is a structure which holds a line of text.
274 * `readline_internal' reads a line from a stream into a linebuffer
275 * and works regardless of the length of the line.
276 * SIZE is the size of BUFFER, LEN is the length of the string in
277 * BUFFER after readline reads it.
279 typedef struct
281 long size;
282 int len;
283 char *buffer;
284 } linebuffer;
286 /* Used to support mixing of --lang and file names. */
287 typedef struct
289 enum {
290 at_language, /* a language specification */
291 at_regexp, /* a regular expression */
292 at_filename, /* a file name */
293 at_stdin /* read from stdin here */
294 } arg_type; /* argument type */
295 language *lang; /* language associated with the argument */
296 char *what; /* the argument itself */
297 } argument;
299 #ifdef ETAGS_REGEXPS
300 /* Structure defining a regular expression. */
301 typedef struct pattern
303 struct pattern *p_next;
304 language *lang;
305 char *regex;
306 struct re_pattern_buffer *pat;
307 struct re_registers regs;
308 char *name_pattern;
309 bool error_signaled;
310 bool ignore_case;
311 bool multi_line;
312 } pattern;
313 #endif /* ETAGS_REGEXPS */
316 /* Many compilers barf on this:
317 Lang_function Ada_funcs;
318 so let's write it this way */
319 static void Ada_funcs __P((FILE *));
320 static void Asm_labels __P((FILE *));
321 static void C_entries __P((int c_ext, FILE *));
322 static void default_C_entries __P((FILE *));
323 static void plain_C_entries __P((FILE *));
324 static void Cjava_entries __P((FILE *));
325 static void Cobol_paragraphs __P((FILE *));
326 static void Cplusplus_entries __P((FILE *));
327 static void Cstar_entries __P((FILE *));
328 static void Erlang_functions __P((FILE *));
329 static void Fortran_functions __P((FILE *));
330 static void Yacc_entries __P((FILE *));
331 static void Lisp_functions __P((FILE *));
332 static void Makefile_targets __P((FILE *));
333 static void Pascal_functions __P((FILE *));
334 static void Perl_functions __P((FILE *));
335 static void PHP_functions __P((FILE *));
336 static void Postscript_functions __P((FILE *));
337 static void Prolog_functions __P((FILE *));
338 static void Python_functions __P((FILE *));
339 static void Scheme_functions __P((FILE *));
340 static void TeX_commands __P((FILE *));
341 static void Texinfo_nodes __P((FILE *));
342 static void just_read_file __P((FILE *));
344 static void print_language_names __P((void));
345 static void print_version __P((void));
346 static void print_help __P((void));
347 int main __P((int, char **));
349 static compressor *get_compressor_from_suffix __P((char *, char **));
350 static language *get_language_from_langname __P((const char *));
351 static language *get_language_from_interpreter __P((char *));
352 static language *get_language_from_filename __P((char *, bool));
353 static void readline __P((linebuffer *, FILE *));
354 static long readline_internal __P((linebuffer *, FILE *));
355 static bool nocase_tail __P((char *));
356 static void get_tag __P((char *, char **));
358 #ifdef ETAGS_REGEXPS
359 static void analyse_regex __P((char *));
360 static void free_patterns __P((void));
361 static void regex_tag_multiline __P((void));
362 #endif /* ETAGS_REGEXPS */
363 static void error __P((const char *, const char *));
364 static void suggest_asking_for_help __P((void));
365 void fatal __P((char *, char *));
366 static void pfatal __P((char *));
367 static void add_node __P((node *, node **));
369 static void init __P((void));
370 static void initbuffer __P((linebuffer *));
371 static void process_file_name __P((char *, language *));
372 static void process_file __P((FILE *, char *, language *));
373 static void find_entries __P((FILE *));
374 static void free_tree __P((node *));
375 static void free_fdesc __P((fdesc *));
376 static void pfnote __P((char *, bool, char *, int, int, long));
377 static void make_tag __P((char *, int, bool, char *, int, int, long));
378 static void invalidate_nodes __P((fdesc *, node **));
379 static void put_entries __P((node *));
381 static char *concat __P((char *, char *, char *));
382 static char *skip_spaces __P((char *));
383 static char *skip_non_spaces __P((char *));
384 static char *savenstr __P((char *, int));
385 static char *savestr __P((char *));
386 static char *etags_strchr __P((const char *, int));
387 static char *etags_strrchr __P((const char *, int));
388 static bool strcaseeq __P((const char *, const char *));
389 static char *etags_getcwd __P((void));
390 static char *relative_filename __P((char *, char *));
391 static char *absolute_filename __P((char *, char *));
392 static char *absolute_dirname __P((char *, char *));
393 static bool filename_is_absolute __P((char *f));
394 static void canonicalize_filename __P((char *));
395 static void linebuffer_setlen __P((linebuffer *, int));
396 static PTR xmalloc __P((unsigned int));
397 static PTR xrealloc __P((char *, unsigned int));
400 static char searchar = '/'; /* use /.../ searches */
402 static char *tagfile; /* output file */
403 static char *progname; /* name this program was invoked with */
404 static char *cwd; /* current working directory */
405 static char *tagfiledir; /* directory of tagfile */
406 static FILE *tagf; /* ioptr for tags file */
408 static fdesc *fdhead; /* head of file description list */
409 static fdesc *curfdp; /* current file description */
410 static int lineno; /* line number of current line */
411 static long charno; /* current character number */
412 static long linecharno; /* charno of start of current line */
413 static char *dbp; /* pointer to start of current tag */
415 static const int invalidcharno = -1;
417 static node *nodehead; /* the head of the binary tree of tags */
418 static node *last_node; /* the last node created */
420 static linebuffer lb; /* the current line */
421 static linebuffer filebuf; /* a buffer containing the whole file */
423 /* boolean "functions" (see init) */
424 static bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
425 static char
426 /* white chars */
427 *white = " \f\t\n\r\v",
428 /* not in a name */
429 *nonam = " \f\t\n\r()=,;", /* look at make_tag before modifying! */
430 /* token ending chars */
431 *endtk = " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
432 /* token starting chars */
433 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
434 /* valid in-token chars */
435 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
437 static bool append_to_tagfile; /* -a: append to tags */
438 /* The next four default to TRUE for etags, but to FALSE for ctags. */
439 static bool typedefs; /* -t: create tags for C and Ada typedefs */
440 static bool typedefs_or_cplusplus; /* -T: create tags for C typedefs, level */
441 /* 0 struct/enum/union decls, and C++ */
442 /* member functions. */
443 static bool constantypedefs; /* -d: create tags for C #define, enum */
444 /* constants and variables. */
445 /* -D: opposite of -d. Default under ctags. */
446 static bool globals; /* create tags for global variables */
447 static bool declarations; /* --declarations: tag them and extern in C&Co*/
448 static bool members; /* create tags for C member variables */
449 static bool no_line_directive; /* ignore #line directives (undocumented) */
450 static bool update; /* -u: update tags */
451 static bool vgrind_style; /* -v: create vgrind style index output */
452 static bool no_warnings; /* -w: suppress warnings */
453 static bool cxref_style; /* -x: create cxref style output */
454 static bool cplusplus; /* .[hc] means C++, not C */
455 static bool noindentypedefs; /* -I: ignore indentation in C */
456 static bool packages_only; /* --packages-only: in Ada, only tag packages*/
458 #define STDIN 0x1001 /* returned by getopt_long on --parse-stdin */
459 static bool parsing_stdin; /* --parse-stdin used */
461 #ifdef ETAGS_REGEXPS
462 static pattern *p_head; /* list of all regexps */
463 static bool need_filebuf; /* some regexes are multi-line */
464 #else
465 # define need_filebuf FALSE
466 #endif /* ETAGS_REGEXPS */
468 #ifdef LONG_OPTIONS
469 static struct option longopts[] =
471 { "packages-only", no_argument, &packages_only, TRUE },
472 { "c++", no_argument, NULL, 'C' },
473 { "declarations", no_argument, &declarations, TRUE },
474 { "no-line-directive", no_argument, &no_line_directive, TRUE },
475 { "help", no_argument, NULL, 'h' },
476 { "help", no_argument, NULL, 'H' },
477 { "ignore-indentation", no_argument, NULL, 'I' },
478 { "language", required_argument, NULL, 'l' },
479 { "members", no_argument, &members, TRUE },
480 { "no-members", no_argument, &members, FALSE },
481 { "output", required_argument, NULL, 'o' },
482 #ifdef ETAGS_REGEXPS
483 { "regex", required_argument, NULL, 'r' },
484 { "no-regex", no_argument, NULL, 'R' },
485 { "ignore-case-regex", required_argument, NULL, 'c' },
486 #endif /* ETAGS_REGEXPS */
487 { "parse-stdin", required_argument, NULL, STDIN },
488 { "version", no_argument, NULL, 'V' },
490 #if CTAGS /* Etags options */
491 { "backward-search", no_argument, NULL, 'B' },
492 { "cxref", no_argument, NULL, 'x' },
493 { "defines", no_argument, NULL, 'd' },
494 { "globals", no_argument, &globals, TRUE },
495 { "typedefs", no_argument, NULL, 't' },
496 { "typedefs-and-c++", no_argument, NULL, 'T' },
497 { "update", no_argument, NULL, 'u' },
498 { "vgrind", no_argument, NULL, 'v' },
499 { "no-warn", no_argument, NULL, 'w' },
501 #else /* Ctags options */
502 { "append", no_argument, NULL, 'a' },
503 { "no-defines", no_argument, NULL, 'D' },
504 { "no-globals", no_argument, &globals, FALSE },
505 { "include", required_argument, NULL, 'i' },
506 #endif
507 { NULL }
509 #endif /* LONG_OPTIONS */
511 static compressor compressors[] =
513 { "z", "gzip -d -c"},
514 { "Z", "gzip -d -c"},
515 { "gz", "gzip -d -c"},
516 { "GZ", "gzip -d -c"},
517 { "bz2", "bzip2 -d -c" },
518 { NULL }
522 * Language stuff.
525 /* Ada code */
526 static char *Ada_suffixes [] =
527 { "ads", "adb", "ada", NULL };
529 /* Assembly code */
530 static char *Asm_suffixes [] =
531 { "a", /* Unix assembler */
532 "asm", /* Microcontroller assembly */
533 "def", /* BSO/Tasking definition includes */
534 "inc", /* Microcontroller include files */
535 "ins", /* Microcontroller include files */
536 "s", "sa", /* Unix assembler */
537 "S", /* cpp-processed Unix assembler */
538 "src", /* BSO/Tasking C compiler output */
539 NULL
542 /* Note that .c and .h can be considered C++, if the --c++ flag was
543 given, or if the `class' keyowrd is met inside the file.
544 That is why default_C_entries is called for these. */
545 static char *default_C_suffixes [] =
546 { "c", "h", NULL };
548 static char *Cplusplus_suffixes [] =
549 { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
550 "M", /* Objective C++ */
551 "pdb", /* Postscript with C syntax */
552 NULL };
554 static char *Cjava_suffixes [] =
555 { "java", NULL };
557 static char *Cobol_suffixes [] =
558 { "COB", "cob", NULL };
560 static char *Cstar_suffixes [] =
561 { "cs", "hs", NULL };
563 static char *Erlang_suffixes [] =
564 { "erl", "hrl", NULL };
566 static char *Fortran_suffixes [] =
567 { "F", "f", "f90", "for", NULL };
569 static char *Lisp_suffixes [] =
570 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL };
572 static char *Makefile_filenames [] =
573 { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL};
575 static char *Pascal_suffixes [] =
576 { "p", "pas", NULL };
578 static char *Perl_suffixes [] =
579 { "pl", "pm", NULL };
581 static char *Perl_interpreters [] =
582 { "perl", "@PERL@", NULL };
584 static char *PHP_suffixes [] =
585 { "php", "php3", "php4", NULL };
587 static char *plain_C_suffixes [] =
588 { "lm", /* Objective lex file */
589 "m", /* Objective C file */
590 "pc", /* Pro*C file */
591 NULL };
593 static char *Postscript_suffixes [] =
594 { "ps", "psw", NULL }; /* .psw is for PSWrap */
596 static char *Prolog_suffixes [] =
597 { "prolog", NULL };
599 static char *Python_suffixes [] =
600 { "py", NULL };
602 /* Can't do the `SCM' or `scm' prefix with a version number. */
603 static char *Scheme_suffixes [] =
604 { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL };
606 static char *TeX_suffixes [] =
607 { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL };
609 static char *Texinfo_suffixes [] =
610 { "texi", "texinfo", "txi", NULL };
612 static char *Yacc_suffixes [] =
613 { "y", "y++", "ym", "yxx", "yy", NULL }; /* .ym is Objective yacc file */
616 * Table of languages.
618 * It is ok for a given function to be listed under more than one
619 * name. I just didn't.
622 static language lang_names [] =
624 { "ada", FALSE, Ada_funcs, NULL, Ada_suffixes, NULL },
625 { "asm", FALSE, Asm_labels, NULL, Asm_suffixes, NULL },
626 { "c", FALSE, default_C_entries, NULL, default_C_suffixes, NULL },
627 { "c++", FALSE, Cplusplus_entries, NULL, Cplusplus_suffixes, NULL },
628 { "c*", FALSE, Cstar_entries, NULL, Cstar_suffixes, NULL },
629 { "cobol", FALSE, Cobol_paragraphs, NULL, Cobol_suffixes, NULL },
630 { "erlang", FALSE, Erlang_functions, NULL, Erlang_suffixes, NULL },
631 { "fortran", FALSE, Fortran_functions, NULL, Fortran_suffixes, NULL },
632 { "java", FALSE, Cjava_entries, NULL, Cjava_suffixes, NULL },
633 { "lisp", FALSE, Lisp_functions, NULL, Lisp_suffixes, NULL },
634 { "makefile", FALSE, Makefile_targets, Makefile_filenames, NULL, NULL },
635 { "pascal", FALSE, Pascal_functions, NULL, Pascal_suffixes, NULL },
636 { "perl", FALSE, Perl_functions,NULL, Perl_suffixes, Perl_interpreters },
637 { "php", FALSE, PHP_functions, NULL, PHP_suffixes, NULL },
638 { "postscript",FALSE, Postscript_functions,NULL, Postscript_suffixes, NULL },
639 { "proc", FALSE, plain_C_entries, NULL, plain_C_suffixes, NULL },
640 { "prolog", FALSE, Prolog_functions, NULL, Prolog_suffixes, NULL },
641 { "python", FALSE, Python_functions, NULL, Python_suffixes, NULL },
642 { "scheme", FALSE, Scheme_functions, NULL, Scheme_suffixes, NULL },
643 { "tex", FALSE, TeX_commands, NULL, TeX_suffixes, NULL },
644 { "texinfo", FALSE, Texinfo_nodes, NULL, Texinfo_suffixes, NULL },
645 { "yacc", TRUE, Yacc_entries, NULL, Yacc_suffixes, NULL },
646 { "auto", FALSE, NULL }, /* default guessing scheme */
647 { "none", FALSE, just_read_file }, /* regexp matching only */
648 { NULL, FALSE, NULL } /* end of list */
652 static void
653 print_language_names ()
655 language *lang;
656 char **name, **ext;
658 puts ("\nThese are the currently supported languages, along with the\n\
659 default file names and dot suffixes:");
660 for (lang = lang_names; lang->name != NULL; lang++)
662 printf (" %-*s", 10, lang->name);
663 if (lang->filenames != NULL)
664 for (name = lang->filenames; *name != NULL; name++)
665 printf (" %s", *name);
666 if (lang->suffixes != NULL)
667 for (ext = lang->suffixes; *ext != NULL; ext++)
668 printf (" .%s", *ext);
669 puts ("");
671 puts ("Where `auto' means use default language for files based on file\n\
672 name suffix, and `none' means only do regexp processing on files.\n\
673 If no language is specified and no matching suffix is found,\n\
674 the first line of the file is read for a sharp-bang (#!) sequence\n\
675 followed by the name of an interpreter. If no such sequence is found,\n\
676 Fortran is tried first; if no tags are found, C is tried next.\n\
677 When parsing any C file, a \"class\" keyword switches to C++.\n\
678 Compressed files are supported using gzip and bzip2.");
681 #ifndef EMACS_NAME
682 # define EMACS_NAME "standalone"
683 #endif
684 #ifndef VERSION
685 # define VERSION "version"
686 #endif
687 static void
688 print_version ()
690 printf ("%s (%s %s)\n", (CTAGS) ? "ctags" : "etags", EMACS_NAME, VERSION);
691 puts ("Copyright (C) 2002 Free Software Foundation, Inc. and Ken Arnold");
692 puts ("This program is distributed under the same terms as Emacs");
694 exit (GOOD);
697 static void
698 print_help ()
700 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
702 These are the options accepted by %s.\n", progname, progname);
703 #ifdef LONG_OPTIONS
704 puts ("You may use unambiguous abbreviations for the long option names.");
705 #else
706 puts ("Long option names do not work with this executable, as it is not\n\
707 linked with GNU getopt.");
708 #endif /* LONG_OPTIONS */
709 puts (" A - as file name means read names from stdin (one per line).\n\
710 Absolute names are stored in the output file as they are.\n\
711 Relative ones are stored relative to the output file's directory.\n");
713 if (!CTAGS)
714 puts ("-a, --append\n\
715 Append tag entries to existing tags file.");
717 puts ("--packages-only\n\
718 For Ada files, only generate tags for packages.");
720 if (CTAGS)
721 puts ("-B, --backward-search\n\
722 Write the search commands for the tag entries using '?', the\n\
723 backward-search command instead of '/', the forward-search command.");
725 /* This option is mostly obsolete, because etags can now automatically
726 detect C++. Retained for backward compatibility and for debugging and
727 experimentation. In principle, we could want to tag as C++ even
728 before any "class" keyword.
729 puts ("-C, --c++\n\
730 Treat files whose name suffix defaults to C language as C++ files.");
733 puts ("--declarations\n\
734 In C and derived languages, create tags for function declarations,");
735 if (CTAGS)
736 puts ("\tand create tags for extern variables if --globals is used.");
737 else
738 puts
739 ("\tand create tags for extern variables unless --no-globals is used.");
741 if (CTAGS)
742 puts ("-d, --defines\n\
743 Create tag entries for C #define constants and enum constants, too.");
744 else
745 puts ("-D, --no-defines\n\
746 Don't create tag entries for C #define constants and enum constants.\n\
747 This makes the tags file smaller.");
749 if (!CTAGS)
750 puts ("-i FILE, --include=FILE\n\
751 Include a note in tag file indicating that, when searching for\n\
752 a tag, one should also consult the tags file FILE after\n\
753 checking the current file.");
755 puts ("-l LANG, --language=LANG\n\
756 Force the following files to be considered as written in the\n\
757 named language up to the next --language=LANG option.");
759 if (CTAGS)
760 puts ("--globals\n\
761 Create tag entries for global variables in some languages.");
762 else
763 puts ("--no-globals\n\
764 Do not create tag entries for global variables in some\n\
765 languages. This makes the tags file smaller.");
766 puts ("--members\n\
767 Create tag entries for member variables in C and derived languages.");
769 #ifdef ETAGS_REGEXPS
770 puts ("-r REGEXP, --regex=REGEXP or --regex=@regexfile\n\
771 Make a tag for each line matching the regular expression pattern\n\
772 in the following files. {LANGUAGE}REGEXP uses REGEXP for LANGUAGE\n\
773 files only. REGEXFILE is a file containing one REGEXP per line.\n\
774 REGEXP takes the form /TAGREGEXP/TAGNAME/MODS, where TAGNAME/ is\n\
775 optional. The TAGREGEXP pattern is anchored (as if preceded by ^).");
776 puts (" If TAGNAME/ is present, the tags created are named.\n\
777 For example Tcl named tags can be created with:\n\
778 --regex=\"/proc[ \\t]+\\([^ \\t]+\\)/\\1/.\".\n\
779 MODS are optional one-letter modifiers: `i' means to ignore case,\n\
780 `m' means to allow multi-line matches, `s' implies `m' and\n\
781 causes dot to match the newline character as well.");
782 puts ("-R, --no-regex\n\
783 Don't create tags from regexps for the following files.");
784 #endif /* ETAGS_REGEXPS */
785 puts ("-I, --ignore-indentation\n\
786 Don't rely on indentation quite as much as normal. Currently,\n\
787 this means not to assume that a closing brace in the first\n\
788 column is the final brace of a function or structure\n\
789 definition in C and C++.");
790 puts ("-o FILE, --output=FILE\n\
791 Write the tags to FILE.");
792 puts ("--parse-stdin=NAME\n\
793 Read from standard input and record tags as belonging to file NAME.");
795 if (CTAGS)
797 puts ("-t, --typedefs\n\
798 Generate tag entries for C and Ada typedefs.");
799 puts ("-T, --typedefs-and-c++\n\
800 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
801 and C++ member functions.");
804 if (CTAGS)
805 puts ("-u, --update\n\
806 Update the tag entries for the given files, leaving tag\n\
807 entries for other files in place. Currently, this is\n\
808 implemented by deleting the existing entries for the given\n\
809 files and then rewriting the new entries at the end of the\n\
810 tags file. It is often faster to simply rebuild the entire\n\
811 tag file than to use this.");
813 if (CTAGS)
815 puts ("-v, --vgrind\n\
816 Generates an index of items intended for human consumption,\n\
817 similar to the output of vgrind. The index is sorted, and\n\
818 gives the page number of each item.");
819 puts ("-w, --no-warn\n\
820 Suppress warning messages about entries defined in multiple\n\
821 files.");
822 puts ("-x, --cxref\n\
823 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
824 The output uses line numbers instead of page numbers, but\n\
825 beyond that the differences are cosmetic; try both to see\n\
826 which you like.");
829 puts ("-V, --version\n\
830 Print the version of the program.\n\
831 -h, --help\n\
832 Print this help message.");
834 print_language_names ();
836 puts ("");
837 puts ("Report bugs to bug-gnu-emacs@gnu.org");
839 exit (GOOD);
843 #ifdef VMS /* VMS specific functions */
845 #define EOS '\0'
847 /* This is a BUG! ANY arbitrary limit is a BUG!
848 Won't someone please fix this? */
849 #define MAX_FILE_SPEC_LEN 255
850 typedef struct {
851 short curlen;
852 char body[MAX_FILE_SPEC_LEN + 1];
853 } vspec;
856 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
857 returning in each successive call the next file name matching the input
858 spec. The function expects that each in_spec passed
859 to it will be processed to completion; in particular, up to and
860 including the call following that in which the last matching name
861 is returned, the function ignores the value of in_spec, and will
862 only start processing a new spec with the following call.
863 If an error occurs, on return out_spec contains the value
864 of in_spec when the error occurred.
866 With each successive file name returned in out_spec, the
867 function's return value is one. When there are no more matching
868 names the function returns zero. If on the first call no file
869 matches in_spec, or there is any other error, -1 is returned.
872 #include <rmsdef.h>
873 #include <descrip.h>
874 #define OUTSIZE MAX_FILE_SPEC_LEN
875 static short
876 fn_exp (out, in)
877 vspec *out;
878 char *in;
880 static long context = 0;
881 static struct dsc$descriptor_s o;
882 static struct dsc$descriptor_s i;
883 static bool pass1 = TRUE;
884 long status;
885 short retval;
887 if (pass1)
889 pass1 = FALSE;
890 o.dsc$a_pointer = (char *) out;
891 o.dsc$w_length = (short)OUTSIZE;
892 i.dsc$a_pointer = in;
893 i.dsc$w_length = (short)strlen(in);
894 i.dsc$b_dtype = DSC$K_DTYPE_T;
895 i.dsc$b_class = DSC$K_CLASS_S;
896 o.dsc$b_dtype = DSC$K_DTYPE_VT;
897 o.dsc$b_class = DSC$K_CLASS_VS;
899 if ((status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL)
901 out->body[out->curlen] = EOS;
902 return 1;
904 else if (status == RMS$_NMF)
905 retval = 0;
906 else
908 strcpy(out->body, in);
909 retval = -1;
911 lib$find_file_end(&context);
912 pass1 = TRUE;
913 return retval;
917 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
918 name of each file specified by the provided arg expanding wildcards.
920 static char *
921 gfnames (arg, p_error)
922 char *arg;
923 bool *p_error;
925 static vspec filename = {MAX_FILE_SPEC_LEN, "\0"};
927 switch (fn_exp (&filename, arg))
929 case 1:
930 *p_error = FALSE;
931 return filename.body;
932 case 0:
933 *p_error = FALSE;
934 return NULL;
935 default:
936 *p_error = TRUE;
937 return filename.body;
941 #ifndef OLD /* Newer versions of VMS do provide `system'. */
942 system (cmd)
943 char *cmd;
945 error ("%s", "system() function not implemented under VMS");
947 #endif
949 #define VERSION_DELIM ';'
950 char *massage_name (s)
951 char *s;
953 char *start = s;
955 for ( ; *s; s++)
956 if (*s == VERSION_DELIM)
958 *s = EOS;
959 break;
961 else
962 *s = lowcase (*s);
963 return start;
965 #endif /* VMS */
969 main (argc, argv)
970 int argc;
971 char *argv[];
973 int i;
974 unsigned int nincluded_files;
975 char **included_files;
976 argument *argbuffer;
977 int current_arg, file_count;
978 linebuffer filename_lb;
979 #ifdef VMS
980 bool got_err;
981 #endif
982 char *optstring;
983 int opt;
986 #ifdef DOS_NT
987 _fmode = O_BINARY; /* all of files are treated as binary files */
988 #endif /* DOS_NT */
990 progname = argv[0];
991 nincluded_files = 0;
992 included_files = xnew (argc, char *);
993 current_arg = 0;
994 file_count = 0;
996 /* Allocate enough no matter what happens. Overkill, but each one
997 is small. */
998 argbuffer = xnew (argc, argument);
1001 * If etags, always find typedefs and structure tags. Why not?
1002 * Also default to find macro constants, enum constants and
1003 * global variables.
1005 if (!CTAGS)
1007 typedefs = typedefs_or_cplusplus = constantypedefs = TRUE;
1008 globals = TRUE;
1011 optstring = "-";
1012 #ifdef ETAGS_REGEXPS
1013 optstring = "-r:Rc:";
1014 #endif /* ETAGS_REGEXPS */
1015 #ifndef LONG_OPTIONS
1016 optstring = optstring + 1;
1017 #endif /* LONG_OPTIONS */
1018 optstring = concat (optstring,
1019 "Cf:Il:o:SVhH",
1020 (CTAGS) ? "BxdtTuvw" : "aDi:");
1022 while ((opt = getopt_long (argc, argv, optstring, longopts, 0)) != EOF)
1023 switch (opt)
1025 case 0:
1026 /* If getopt returns 0, then it has already processed a
1027 long-named option. We should do nothing. */
1028 break;
1030 case 1:
1031 /* This means that a file name has been seen. Record it. */
1032 argbuffer[current_arg].arg_type = at_filename;
1033 argbuffer[current_arg].what = optarg;
1034 ++current_arg;
1035 ++file_count;
1036 break;
1038 case STDIN:
1039 /* Parse standard input. Idea by Vivek <vivek@etla.org>. */
1040 argbuffer[current_arg].arg_type = at_stdin;
1041 argbuffer[current_arg].what = optarg;
1042 ++current_arg;
1043 ++file_count;
1044 if (parsing_stdin)
1045 fatal ("cannot parse standard input more than once", (char *)NULL);
1046 parsing_stdin = TRUE;
1047 break;
1049 /* Common options. */
1050 case 'C': cplusplus = TRUE; break;
1051 case 'f': /* for compatibility with old makefiles */
1052 case 'o':
1053 if (tagfile)
1055 error ("-o option may only be given once.", (char *)NULL);
1056 suggest_asking_for_help ();
1058 tagfile = optarg;
1059 break;
1060 case 'I':
1061 case 'S': /* for backward compatibility */
1062 noindentypedefs = TRUE;
1063 break;
1064 case 'l':
1066 language *lang = get_language_from_langname (optarg);
1067 if (lang != NULL)
1069 argbuffer[current_arg].lang = lang;
1070 argbuffer[current_arg].arg_type = at_language;
1071 ++current_arg;
1074 break;
1075 case 'c':
1076 /* Backward compatibility: support obsolete --ignore-case-regexp. */
1077 optarg = concat (optarg, "i", ""); /* memory leak here */
1078 /* FALLTHRU */
1079 case 'r':
1080 argbuffer[current_arg].arg_type = at_regexp;
1081 argbuffer[current_arg].what = optarg;
1082 ++current_arg;
1083 break;
1084 case 'R':
1085 argbuffer[current_arg].arg_type = at_regexp;
1086 argbuffer[current_arg].what = NULL;
1087 ++current_arg;
1088 break;
1089 case 'V':
1090 print_version ();
1091 break;
1092 case 'h':
1093 case 'H':
1094 print_help ();
1095 break;
1097 /* Etags options */
1098 case 'a': append_to_tagfile = TRUE; break;
1099 case 'D': constantypedefs = FALSE; break;
1100 case 'i': included_files[nincluded_files++] = optarg; break;
1102 /* Ctags options. */
1103 case 'B': searchar = '?'; break;
1104 case 'd': constantypedefs = TRUE; break;
1105 case 't': typedefs = TRUE; break;
1106 case 'T': typedefs = typedefs_or_cplusplus = TRUE; break;
1107 case 'u': update = TRUE; break;
1108 case 'v': vgrind_style = TRUE; /*FALLTHRU*/
1109 case 'x': cxref_style = TRUE; break;
1110 case 'w': no_warnings = TRUE; break;
1111 default:
1112 suggest_asking_for_help ();
1115 for (; optind < argc; ++optind)
1117 argbuffer[current_arg].arg_type = at_filename;
1118 argbuffer[current_arg].what = argv[optind];
1119 ++current_arg;
1120 ++file_count;
1123 if (nincluded_files == 0 && file_count == 0)
1125 error ("no input files specified.", (char *)NULL);
1126 suggest_asking_for_help ();
1129 if (tagfile == NULL)
1130 tagfile = CTAGS ? "tags" : "TAGS";
1131 cwd = etags_getcwd (); /* the current working directory */
1132 if (cwd[strlen (cwd) - 1] != '/')
1134 char *oldcwd = cwd;
1135 cwd = concat (oldcwd, "/", "");
1136 free (oldcwd);
1138 if (streq (tagfile, "-"))
1139 tagfiledir = cwd;
1140 else
1141 tagfiledir = absolute_dirname (tagfile, cwd);
1143 init (); /* set up boolean "functions" */
1145 initbuffer (&lb);
1146 initbuffer (&filename_lb);
1147 initbuffer (&filebuf);
1149 if (!CTAGS)
1151 if (streq (tagfile, "-"))
1153 tagf = stdout;
1154 #ifdef DOS_NT
1155 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1156 doesn't take effect until after `stdout' is already open). */
1157 if (!isatty (fileno (stdout)))
1158 setmode (fileno (stdout), O_BINARY);
1159 #endif /* DOS_NT */
1161 else
1162 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1163 if (tagf == NULL)
1164 pfatal (tagfile);
1168 * Loop through files finding functions.
1170 for (i = 0; i < current_arg; ++i)
1172 static language *lang; /* non-NULL if language is forced */
1173 char *this_file;
1175 switch (argbuffer[i].arg_type)
1177 case at_language:
1178 lang = argbuffer[i].lang;
1179 break;
1180 #ifdef ETAGS_REGEXPS
1181 case at_regexp:
1182 analyse_regex (argbuffer[i].what);
1183 break;
1184 #endif
1185 case at_filename:
1186 #ifdef VMS
1187 while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL)
1189 if (got_err)
1191 error ("can't find file %s\n", this_file);
1192 argc--, argv++;
1194 else
1196 this_file = massage_name (this_file);
1198 #else
1199 this_file = argbuffer[i].what;
1200 #endif
1201 /* Input file named "-" means read file names from stdin
1202 (one per line) and use them. */
1203 if (streq (this_file, "-"))
1205 if (parsing_stdin)
1206 fatal ("cannot parse standard input AND read file names from it",
1207 (char *)NULL);
1208 while (readline_internal (&filename_lb, stdin) > 0)
1209 process_file_name (filename_lb.buffer, lang);
1211 else
1212 process_file_name (this_file, lang);
1213 #ifdef VMS
1215 #endif
1216 break;
1217 case at_stdin:
1218 this_file = argbuffer[i].what;
1219 process_file (stdin, this_file, lang);
1220 break;
1224 #ifdef ETAGS_REGEXPS
1225 free_patterns ();
1226 #endif /* ETAGS_REGEXPS */
1227 free (filebuf.buffer);
1229 if (!CTAGS || cxref_style)
1231 put_entries (nodehead); /* write the remainig tags (ETAGS) */
1232 free_tree (nodehead);
1233 nodehead = NULL;
1234 if (!CTAGS)
1235 while (nincluded_files-- > 0)
1236 fprintf (tagf, "\f\n%s,include\n", *included_files++);
1238 if (fclose (tagf) == EOF)
1239 pfatal (tagfile);
1240 exit (GOOD);
1243 if (update)
1245 char cmd[BUFSIZ];
1246 for (i = 0; i < current_arg; ++i)
1248 switch (argbuffer[i].arg_type)
1250 case at_filename:
1251 case at_stdin:
1252 break;
1253 default:
1254 continue; /* the for loop */
1256 sprintf (cmd,
1257 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1258 tagfile, argbuffer[i].what, tagfile);
1259 if (system (cmd) != GOOD)
1260 fatal ("failed to execute shell command", (char *)NULL);
1262 append_to_tagfile = TRUE;
1265 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1266 if (tagf == NULL)
1267 pfatal (tagfile);
1268 put_entries (nodehead); /* write all the tags (CTAGS) */
1269 free_tree (nodehead);
1270 nodehead = NULL;
1271 if (fclose (tagf) == EOF)
1272 pfatal (tagfile);
1274 if (update)
1276 char cmd[2*BUFSIZ+10];
1277 sprintf (cmd, "sort -o %.*s %.*s", BUFSIZ, tagfile, BUFSIZ, tagfile);
1278 exit (system (cmd));
1280 return GOOD;
1285 * Return a compressor given the file name. If EXTPTR is non-zero,
1286 * return a pointer into FILE where the compressor-specific
1287 * extension begins. If no compressor is found, NULL is returned
1288 * and EXTPTR is not significant.
1289 * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca> (1998)
1291 static compressor *
1292 get_compressor_from_suffix (file, extptr)
1293 char *file;
1294 char **extptr;
1296 compressor *compr;
1297 char *slash, *suffix;
1299 /* This relies on FN to be after canonicalize_filename,
1300 so we don't need to consider backslashes on DOS_NT. */
1301 slash = etags_strrchr (file, '/');
1302 suffix = etags_strrchr (file, '.');
1303 if (suffix == NULL || suffix < slash)
1304 return NULL;
1305 if (extptr != NULL)
1306 *extptr = suffix;
1307 suffix += 1;
1308 /* Let those poor souls who live with DOS 8+3 file name limits get
1309 some solace by treating foo.cgz as if it were foo.c.gz, etc.
1310 Only the first do loop is run if not MSDOS */
1313 for (compr = compressors; compr->suffix != NULL; compr++)
1314 if (streq (compr->suffix, suffix))
1315 return compr;
1316 if (!MSDOS)
1317 break; /* do it only once: not really a loop */
1318 if (extptr != NULL)
1319 *extptr = ++suffix;
1320 } while (*suffix != '\0');
1321 return NULL;
1327 * Return a language given the name.
1329 static language *
1330 get_language_from_langname (name)
1331 const char *name;
1333 language *lang;
1335 if (name == NULL)
1336 error ("empty language name", (char *)NULL);
1337 else
1339 for (lang = lang_names; lang->name != NULL; lang++)
1340 if (streq (name, lang->name))
1341 return lang;
1342 error ("unknown language \"%s\"", name);
1345 return NULL;
1350 * Return a language given the interpreter name.
1352 static language *
1353 get_language_from_interpreter (interpreter)
1354 char *interpreter;
1356 language *lang;
1357 char **iname;
1359 if (interpreter == NULL)
1360 return NULL;
1361 for (lang = lang_names; lang->name != NULL; lang++)
1362 if (lang->interpreters != NULL)
1363 for (iname = lang->interpreters; *iname != NULL; iname++)
1364 if (streq (*iname, interpreter))
1365 return lang;
1367 return NULL;
1373 * Return a language given the file name.
1375 static language *
1376 get_language_from_filename (file, case_sensitive)
1377 char *file;
1378 bool case_sensitive;
1380 language *lang;
1381 char **name, **ext, *suffix;
1383 /* Try whole file name first. */
1384 for (lang = lang_names; lang->name != NULL; lang++)
1385 if (lang->filenames != NULL)
1386 for (name = lang->filenames; *name != NULL; name++)
1387 if ((case_sensitive)
1388 ? streq (*name, file)
1389 : strcaseeq (*name, file))
1390 return lang;
1392 /* If not found, try suffix after last dot. */
1393 suffix = etags_strrchr (file, '.');
1394 if (suffix == NULL)
1395 return NULL;
1396 suffix += 1;
1397 for (lang = lang_names; lang->name != NULL; lang++)
1398 if (lang->suffixes != NULL)
1399 for (ext = lang->suffixes; *ext != NULL; ext++)
1400 if ((case_sensitive)
1401 ? streq (*ext, suffix)
1402 : strcaseeq (*ext, suffix))
1403 return lang;
1404 return NULL;
1409 * This routine is called on each file argument.
1411 static void
1412 process_file_name (file, lang)
1413 char *file;
1414 language *lang;
1416 struct stat stat_buf;
1417 FILE *inf;
1418 fdesc *fdp;
1419 compressor *compr;
1420 char *compressed_name, *uncompressed_name;
1421 char *ext, *real_name;
1422 int retval;
1424 canonicalize_filename (file);
1425 if (streq (file, tagfile) && !streq (tagfile, "-"))
1427 error ("skipping inclusion of %s in self.", file);
1428 return;
1430 if ((compr = get_compressor_from_suffix (file, &ext)) == NULL)
1432 compressed_name = NULL;
1433 real_name = uncompressed_name = savestr (file);
1435 else
1437 real_name = compressed_name = savestr (file);
1438 uncompressed_name = savenstr (file, ext - file);
1441 /* If the canonicalized uncompressed name
1442 has already been dealt with, skip it silently. */
1443 for (fdp = fdhead; fdp != NULL; fdp = fdp->next)
1445 assert (fdp->infname != NULL);
1446 if (streq (uncompressed_name, fdp->infname))
1447 goto cleanup;
1450 if (stat (real_name, &stat_buf) != 0)
1452 /* Reset real_name and try with a different name. */
1453 real_name = NULL;
1454 if (compressed_name != NULL) /* try with the given suffix */
1456 if (stat (uncompressed_name, &stat_buf) == 0)
1457 real_name = uncompressed_name;
1459 else /* try all possible suffixes */
1461 for (compr = compressors; compr->suffix != NULL; compr++)
1463 compressed_name = concat (file, ".", compr->suffix);
1464 if (stat (compressed_name, &stat_buf) != 0)
1466 if (MSDOS)
1468 char *suf = compressed_name + strlen (file);
1469 size_t suflen = strlen (compr->suffix) + 1;
1470 for ( ; suf[1]; suf++, suflen--)
1472 memmove (suf, suf + 1, suflen);
1473 if (stat (compressed_name, &stat_buf) == 0)
1475 real_name = compressed_name;
1476 break;
1479 if (real_name != NULL)
1480 break;
1481 } /* MSDOS */
1482 free (compressed_name);
1483 compressed_name = NULL;
1485 else
1487 real_name = compressed_name;
1488 break;
1492 if (real_name == NULL)
1494 perror (file);
1495 goto cleanup;
1497 } /* try with a different name */
1499 if (!S_ISREG (stat_buf.st_mode))
1501 error ("skipping %s: it is not a regular file.", real_name);
1502 goto cleanup;
1504 if (real_name == compressed_name)
1506 char *cmd = concat (compr->command, " ", real_name);
1507 inf = (FILE *) popen (cmd, "r");
1508 free (cmd);
1510 else
1511 inf = fopen (real_name, "r");
1512 if (inf == NULL)
1514 perror (real_name);
1515 goto cleanup;
1518 process_file (inf, uncompressed_name, lang);
1520 if (real_name == compressed_name)
1521 retval = pclose (inf);
1522 else
1523 retval = fclose (inf);
1524 if (retval < 0)
1525 pfatal (file);
1527 cleanup:
1528 if (compressed_name) free (compressed_name);
1529 if (uncompressed_name) free (uncompressed_name);
1530 last_node = NULL;
1531 curfdp = NULL;
1532 return;
1535 static void
1536 process_file (fh, fn, lang)
1537 FILE *fh;
1538 char *fn;
1539 language *lang;
1541 static const fdesc emptyfdesc;
1542 fdesc *fdp;
1544 /* Create a new input file description entry. */
1545 fdp = xnew (1, fdesc);
1546 *fdp = emptyfdesc;
1547 fdp->next = fdhead;
1548 fdp->infname = savestr (fn);
1549 fdp->lang = lang;
1550 fdp->infabsname = absolute_filename (fn, cwd);
1551 fdp->infabsdir = absolute_dirname (fn, cwd);
1552 if (filename_is_absolute (fn))
1554 /* An absolute file name. Canonicalize it. */
1555 fdp->taggedfname = absolute_filename (fn, NULL);
1557 else
1559 /* A file name relative to cwd. Make it relative
1560 to the directory of the tags file. */
1561 fdp->taggedfname = relative_filename (fn, tagfiledir);
1563 fdp->usecharno = TRUE; /* use char position when making tags */
1564 fdp->prop = NULL;
1566 fdhead = fdp;
1567 curfdp = fdhead; /* the current file description */
1569 find_entries (fh);
1571 /* If not Ctags, and if this is not metasource and if it contained no #line
1572 directives, we can write the tags and free all nodes pointing to
1573 curfdp. */
1574 if (!CTAGS
1575 && curfdp->usecharno /* no #line directives in this file */
1576 && !curfdp->lang->metasource)
1578 node *np, *prev;
1580 /* Look for the head of the sublist relative to this file. See add_node
1581 for the structure of the node tree. */
1582 prev = NULL;
1583 for (np = nodehead; np != NULL; prev = np, np = np->left)
1584 if (np->fdp == curfdp)
1585 break;
1587 /* If we generated tags for this file, write and delete them. */
1588 if (np != NULL)
1590 /* This is the head of the last sublist, if any. The following
1591 instructions depend on this being true. */
1592 assert (np->left == NULL);
1594 assert (fdhead == curfdp);
1595 assert (last_node->fdp == curfdp);
1596 put_entries (np); /* write tags for file curfdp->taggedfname */
1597 free_tree (np); /* remove the written nodes */
1598 if (prev == NULL)
1599 nodehead = NULL; /* no nodes left */
1600 else
1601 prev->left = NULL; /* delete the pointer to the sublist */
1607 * This routine sets up the boolean pseudo-functions which work
1608 * by setting boolean flags dependent upon the corresponding character.
1609 * Every char which is NOT in that string is not a white char. Therefore,
1610 * all of the array "_wht" is set to FALSE, and then the elements
1611 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1612 * of a char is TRUE if it is the string "white", else FALSE.
1614 static void
1615 init ()
1617 register char *sp;
1618 register int i;
1620 for (i = 0; i < CHARS; i++)
1621 iswhite(i) = notinname(i) = begtoken(i) = intoken(i) = endtoken(i) = FALSE;
1622 for (sp = white; *sp != '\0'; sp++) iswhite (*sp) = TRUE;
1623 for (sp = nonam; *sp != '\0'; sp++) notinname (*sp) = TRUE;
1624 notinname('\0') = notinname('\n');
1625 for (sp = begtk; *sp != '\0'; sp++) begtoken (*sp) = TRUE;
1626 begtoken('\0') = begtoken('\n');
1627 for (sp = midtk; *sp != '\0'; sp++) intoken (*sp) = TRUE;
1628 intoken('\0') = intoken('\n');
1629 for (sp = endtk; *sp != '\0'; sp++) endtoken (*sp) = TRUE;
1630 endtoken('\0') = endtoken('\n');
1634 * This routine opens the specified file and calls the function
1635 * which finds the function and type definitions.
1637 static void
1638 find_entries (inf)
1639 FILE *inf;
1641 char *cp;
1642 language *lang = curfdp->lang;
1643 Lang_function *parser = NULL;
1645 /* If user specified a language, use it. */
1646 if (lang != NULL && lang->function != NULL)
1648 parser = lang->function;
1651 /* Else try to guess the language given the file name. */
1652 if (parser == NULL)
1654 lang = get_language_from_filename (curfdp->infname, TRUE);
1655 if (lang != NULL && lang->function != NULL)
1657 curfdp->lang = lang;
1658 parser = lang->function;
1662 /* Else look for sharp-bang as the first two characters. */
1663 if (parser == NULL
1664 && readline_internal (&lb, inf) > 0
1665 && lb.len >= 2
1666 && lb.buffer[0] == '#'
1667 && lb.buffer[1] == '!')
1669 char *lp;
1671 /* Set lp to point at the first char after the last slash in the
1672 line or, if no slashes, at the first nonblank. Then set cp to
1673 the first successive blank and terminate the string. */
1674 lp = etags_strrchr (lb.buffer+2, '/');
1675 if (lp != NULL)
1676 lp += 1;
1677 else
1678 lp = skip_spaces (lb.buffer + 2);
1679 cp = skip_non_spaces (lp);
1680 *cp = '\0';
1682 if (strlen (lp) > 0)
1684 lang = get_language_from_interpreter (lp);
1685 if (lang != NULL && lang->function != NULL)
1687 curfdp->lang = lang;
1688 parser = lang->function;
1693 /* We rewind here, even if inf may be a pipe. We fail if the
1694 length of the first line is longer than the pipe block size,
1695 which is unlikely. */
1696 rewind (inf);
1698 /* Else try to guess the language given the case insensitive file name. */
1699 if (parser == NULL)
1701 lang = get_language_from_filename (curfdp->infname, FALSE);
1702 if (lang != NULL && lang->function != NULL)
1704 curfdp->lang = lang;
1705 parser = lang->function;
1709 /* Else try Fortran or C. */
1710 if (parser == NULL)
1712 node *old_last_node = last_node;
1714 curfdp->lang = get_language_from_langname ("fortran");
1715 find_entries (inf);
1717 if (old_last_node == last_node)
1718 /* No Fortran entries found. Try C. */
1720 /* We do not tag if rewind fails.
1721 Only the file name will be recorded in the tags file. */
1722 rewind (inf);
1723 curfdp->lang = get_language_from_langname (cplusplus ? "c++" : "c");
1724 find_entries (inf);
1726 return;
1729 if (!no_line_directive
1730 && curfdp->lang != NULL && curfdp->lang->metasource)
1731 /* It may be that this is a bingo.y file, and we already parsed a bingo.c
1732 file, or anyway we parsed a file that is automatically generated from
1733 this one. If this is the case, the bingo.c file contained #line
1734 directives that generated tags pointing to this file. Let's delete
1735 them all before parsing this file, which is the real source. */
1737 fdesc **fdpp = &fdhead;
1738 while (*fdpp != NULL)
1739 if (*fdpp != curfdp
1740 && streq ((*fdpp)->taggedfname, curfdp->taggedfname))
1741 /* We found one of those! We must delete both the file description
1742 and all tags referring to it. */
1744 fdesc *badfdp = *fdpp;
1746 if (DEBUG)
1747 fprintf (stderr,
1748 "Removing references to \"%s\" obtained from \"%s\"\n",
1749 badfdp->taggedfname, badfdp->infname);
1751 /* Delete the tags referring to badfdp. */
1752 invalidate_nodes (badfdp, &nodehead);
1754 *fdpp = badfdp->next; /* remove the bad description from the list */
1755 free_fdesc (badfdp);
1757 else
1758 fdpp = &(*fdpp)->next; /* advance the list pointer */
1761 assert (parser != NULL);
1763 /* Generic initialisations before reading from file. */
1764 filebuf.len = 0; /* reset the file buffer */
1766 /* Generic initialisations before parsing file with readline. */
1767 lineno = 0; /* reset global line number */
1768 charno = 0; /* reset global char number */
1769 linecharno = 0; /* reset global char number of line start */
1771 parser (inf);
1773 #ifdef ETAGS_REGEXPS
1774 regex_tag_multiline ();
1775 #endif /* ETAGS_REGEXPS */
1780 * Check whether an implicitly named tag should be created,
1781 * then call `pfnote'.
1782 * NAME is a string that is internally copied by this function.
1784 * TAGS format specification
1785 * Idea by Sam Kendall <kendall@mv.mv.com> (1997)
1786 * The following is explained in some more detail in etc/ETAGS.EBNF.
1788 * make_tag creates tags with "implicit tag names" (unnamed tags)
1789 * if the following are all true, assuming NONAM=" \f\t\n\r()=,;":
1790 * 1. NAME does not contain any of the characters in NONAM;
1791 * 2. LINESTART contains name as either a rightmost, or rightmost but
1792 * one character, substring;
1793 * 3. the character, if any, immediately before NAME in LINESTART must
1794 * be a character in NONAM;
1795 * 4. the character, if any, immediately after NAME in LINESTART must
1796 * also be a character in NONAM.
1798 * The implementation uses the notinname() macro, which recognises the
1799 * characters stored in the string `nonam'.
1800 * etags.el needs to use the same characters that are in NONAM.
1802 static void
1803 make_tag (name, namelen, is_func, linestart, linelen, lno, cno)
1804 char *name; /* tag name, or NULL if unnamed */
1805 int namelen; /* tag length */
1806 bool is_func; /* tag is a function */
1807 char *linestart; /* start of the line where tag is */
1808 int linelen; /* length of the line where tag is */
1809 int lno; /* line number */
1810 long cno; /* character number */
1812 bool named = TRUE;
1814 if (!CTAGS && name != NULL && namelen > 0)
1816 int i;
1817 register char *cp = name;
1819 for (i = 0; i < namelen; i++)
1820 if (notinname (*cp++))
1821 break;
1822 if (i == namelen) /* rule #1 */
1824 cp = linestart + linelen - namelen;
1825 if (notinname (linestart[linelen-1]))
1826 cp -= 1; /* rule #4 */
1827 if (cp >= linestart /* rule #2 */
1828 && (cp == linestart
1829 || notinname (cp[-1])) /* rule #3 */
1830 && strneq (name, cp, namelen)) /* rule #2 */
1831 named = FALSE; /* use implicit tag name */
1835 if (named)
1836 name = savenstr (name, namelen);
1837 else
1838 name = NULL;
1839 pfnote (name, is_func, linestart, linelen, lno, cno);
1842 /* Record a tag. */
1843 static void
1844 pfnote (name, is_func, linestart, linelen, lno, cno)
1845 char *name; /* tag name, or NULL if unnamed */
1846 bool is_func; /* tag is a function */
1847 char *linestart; /* start of the line where tag is */
1848 int linelen; /* length of the line where tag is */
1849 int lno; /* line number */
1850 long cno; /* character number */
1852 register node *np;
1854 if (CTAGS && name == NULL)
1855 return;
1857 np = xnew (1, node);
1859 /* If ctags mode, change name "main" to M<thisfilename>. */
1860 if (CTAGS && !cxref_style && streq (name, "main"))
1862 register char *fp = etags_strrchr (curfdp->taggedfname, '/');
1863 np->name = concat ("M", fp == NULL ? curfdp->taggedfname : fp + 1, "");
1864 fp = etags_strrchr (np->name, '.');
1865 if (fp != NULL && fp[1] != '\0' && fp[2] == '\0')
1866 fp[0] = '\0';
1868 else
1869 np->name = name;
1870 np->valid = TRUE;
1871 np->been_warned = FALSE;
1872 np->fdp = curfdp;
1873 np->is_func = is_func;
1874 np->lno = lno;
1875 if (np->fdp->usecharno)
1876 /* Our char numbers are 0-base, because of C language tradition?
1877 ctags compatibility? old versions compatibility? I don't know.
1878 Anyway, since emacs's are 1-base we expect etags.el to take care
1879 of the difference. If we wanted to have 1-based numbers, we would
1880 uncomment the +1 below. */
1881 np->cno = cno /* + 1 */ ;
1882 else
1883 np->cno = invalidcharno;
1884 np->left = np->right = NULL;
1885 if (CTAGS && !cxref_style)
1887 if (strlen (linestart) < 50)
1888 np->pat = concat (linestart, "$", "");
1889 else
1890 np->pat = savenstr (linestart, 50);
1892 else
1893 np->pat = savenstr (linestart, linelen);
1895 add_node (np, &nodehead);
1899 * free_tree ()
1900 * recurse on left children, iterate on right children.
1902 static void
1903 free_tree (np)
1904 register node *np;
1906 while (np)
1908 register node *node_right = np->right;
1909 free_tree (np->left);
1910 if (np->name != NULL)
1911 free (np->name);
1912 free (np->pat);
1913 free (np);
1914 np = node_right;
1919 * free_fdesc ()
1920 * delete a file description
1922 static void
1923 free_fdesc (fdp)
1924 register fdesc *fdp;
1926 if (fdp->infname != NULL) free (fdp->infname);
1927 if (fdp->infabsname != NULL) free (fdp->infabsname);
1928 if (fdp->infabsdir != NULL) free (fdp->infabsdir);
1929 if (fdp->taggedfname != NULL) free (fdp->taggedfname);
1930 if (fdp->prop != NULL) free (fdp->prop);
1931 free (fdp);
1935 * add_node ()
1936 * Adds a node to the tree of nodes. In etags mode, sort by file
1937 * name. In ctags mode, sort by tag name. Make no attempt at
1938 * balancing.
1940 * add_node is the only function allowed to add nodes, so it can
1941 * maintain state.
1943 static void
1944 add_node (np, cur_node_p)
1945 node *np, **cur_node_p;
1947 register int dif;
1948 register node *cur_node = *cur_node_p;
1950 if (cur_node == NULL)
1952 *cur_node_p = np;
1953 last_node = np;
1954 return;
1957 if (!CTAGS)
1958 /* Etags Mode */
1960 /* For each file name, tags are in a linked sublist on the right
1961 pointer. The first tags of different files are a linked list
1962 on the left pointer. last_node points to the end of the last
1963 used sublist. */
1964 if (last_node != NULL && last_node->fdp == np->fdp)
1966 /* Let's use the same sublist as the last added node. */
1967 assert (last_node->right == NULL);
1968 last_node->right = np;
1969 last_node = np;
1971 else if (cur_node->fdp == np->fdp)
1973 /* Scanning the list we found the head of a sublist which is
1974 good for us. Let's scan this sublist. */
1975 add_node (np, &cur_node->right);
1977 else
1978 /* The head of this sublist is not good for us. Let's try the
1979 next one. */
1980 add_node (np, &cur_node->left);
1981 } /* if ETAGS mode */
1983 else
1985 /* Ctags Mode */
1986 dif = strcmp (np->name, cur_node->name);
1989 * If this tag name matches an existing one, then
1990 * do not add the node, but maybe print a warning.
1992 if (!dif)
1994 if (np->fdp == cur_node->fdp)
1996 if (!no_warnings)
1998 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1999 np->fdp->infname, lineno, np->name);
2000 fprintf (stderr, "Second entry ignored\n");
2003 else if (!cur_node->been_warned && !no_warnings)
2005 fprintf
2006 (stderr,
2007 "Duplicate entry in files %s and %s: %s (Warning only)\n",
2008 np->fdp->infname, cur_node->fdp->infname, np->name);
2009 cur_node->been_warned = TRUE;
2011 return;
2014 /* Actually add the node */
2015 add_node (np, dif < 0 ? &cur_node->left : &cur_node->right);
2016 } /* if CTAGS mode */
2020 * invalidate_nodes ()
2021 * Scan the node tree and invalidate all nodes pointing to the
2022 * given file description (CTAGS case) or free them (ETAGS case).
2024 static void
2025 invalidate_nodes (badfdp, npp)
2026 fdesc *badfdp;
2027 node **npp;
2029 node *np = *npp;
2031 if (np == NULL)
2032 return;
2034 if (CTAGS)
2036 if (np->left != NULL)
2037 invalidate_nodes (badfdp, &np->left);
2038 if (np->fdp == badfdp)
2039 np->valid = FALSE;
2040 if (np->right != NULL)
2041 invalidate_nodes (badfdp, &np->right);
2043 else
2045 assert (np->fdp != NULL);
2046 if (np->fdp == badfdp)
2048 *npp = np->left; /* detach the sublist from the list */
2049 np->left = NULL; /* isolate it */
2050 free_tree (np); /* free it */
2051 invalidate_nodes (badfdp, npp);
2053 else
2054 invalidate_nodes (badfdp, &np->left);
2059 static int total_size_of_entries __P((node *));
2060 static int number_len __P((long));
2062 /* Length of a non-negative number's decimal representation. */
2063 static int
2064 number_len (num)
2065 long num;
2067 int len = 1;
2068 while ((num /= 10) > 0)
2069 len += 1;
2070 return len;
2074 * Return total number of characters that put_entries will output for
2075 * the nodes in the linked list at the right of the specified node.
2076 * This count is irrelevant with etags.el since emacs 19.34 at least,
2077 * but is still supplied for backward compatibility.
2079 static int
2080 total_size_of_entries (np)
2081 register node *np;
2083 register int total = 0;
2085 for (; np != NULL; np = np->right)
2087 total += strlen (np->pat) + 1; /* pat\177 */
2088 if (np->name != NULL)
2089 total += strlen (np->name) + 1; /* name\001 */
2090 total += number_len ((long) np->lno) + 1; /* lno, */
2091 if (np->cno != invalidcharno) /* cno */
2092 total += number_len (np->cno);
2093 total += 1; /* newline */
2096 return total;
2099 static void
2100 put_entries (np)
2101 register node *np;
2103 register char *sp;
2104 static fdesc *fdp = NULL;
2106 if (np == NULL)
2107 return;
2109 /* Output subentries that precede this one */
2110 if (CTAGS)
2111 put_entries (np->left);
2113 /* Output this entry */
2114 if (np->valid)
2116 if (!CTAGS)
2118 /* Etags mode */
2119 if (fdp != np->fdp)
2121 fdp = np->fdp;
2122 fprintf (tagf, "\f\n%s,%d\n",
2123 fdp->taggedfname, total_size_of_entries (np));
2125 fputs (np->pat, tagf);
2126 fputc ('\177', tagf);
2127 if (np->name != NULL)
2129 fputs (np->name, tagf);
2130 fputc ('\001', tagf);
2132 fprintf (tagf, "%d,", np->lno);
2133 if (np->cno != invalidcharno)
2134 fprintf (tagf, "%ld", np->cno);
2135 fputs ("\n", tagf);
2137 else
2139 /* Ctags mode */
2140 if (np->name == NULL)
2141 error ("internal error: NULL name in ctags mode.", (char *)NULL);
2143 if (cxref_style)
2145 if (vgrind_style)
2146 fprintf (stdout, "%s %s %d\n",
2147 np->name, np->fdp->taggedfname, (np->lno + 63) / 64);
2148 else
2149 fprintf (stdout, "%-16s %3d %-16s %s\n",
2150 np->name, np->lno, np->fdp->taggedfname, np->pat);
2152 else
2154 fprintf (tagf, "%s\t%s\t", np->name, np->fdp->taggedfname);
2156 if (np->is_func)
2157 { /* function or #define macro with args */
2158 putc (searchar, tagf);
2159 putc ('^', tagf);
2161 for (sp = np->pat; *sp; sp++)
2163 if (*sp == '\\' || *sp == searchar)
2164 putc ('\\', tagf);
2165 putc (*sp, tagf);
2167 putc (searchar, tagf);
2169 else
2170 { /* anything else; text pattern inadequate */
2171 fprintf (tagf, "%d", np->lno);
2173 putc ('\n', tagf);
2176 } /* if this node contains a valid tag */
2178 /* Output subentries that follow this one */
2179 put_entries (np->right);
2180 if (!CTAGS)
2181 put_entries (np->left);
2185 /* C extensions. */
2186 #define C_EXT 0x00fff /* C extensions */
2187 #define C_PLAIN 0x00000 /* C */
2188 #define C_PLPL 0x00001 /* C++ */
2189 #define C_STAR 0x00003 /* C* */
2190 #define C_JAVA 0x00005 /* JAVA */
2191 #define C_AUTO 0x01000 /* C, but switch to C++ if `class' is met */
2192 #define YACC 0x10000 /* yacc file */
2195 * The C symbol tables.
2197 enum sym_type
2199 st_none,
2200 st_C_objprot, st_C_objimpl, st_C_objend,
2201 st_C_gnumacro,
2202 st_C_ignore,
2203 st_C_javastruct,
2204 st_C_operator,
2205 st_C_class, st_C_template,
2206 st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
2209 static unsigned int hash __P((const char *, unsigned int));
2210 static struct C_stab_entry * in_word_set __P((const char *, unsigned int));
2211 static enum sym_type C_symtype __P((char *, int, int));
2213 /* Feed stuff between (but not including) %[ and %] lines to:
2214 gperf -c -k 1,3 -o -p -r -t
2216 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
2218 if, 0, st_C_ignore
2219 for, 0, st_C_ignore
2220 while, 0, st_C_ignore
2221 switch, 0, st_C_ignore
2222 return, 0, st_C_ignore
2223 @interface, 0, st_C_objprot
2224 @protocol, 0, st_C_objprot
2225 @implementation,0, st_C_objimpl
2226 @end, 0, st_C_objend
2227 import, C_JAVA, st_C_ignore
2228 package, C_JAVA, st_C_ignore
2229 friend, C_PLPL, st_C_ignore
2230 extends, C_JAVA, st_C_javastruct
2231 implements, C_JAVA, st_C_javastruct
2232 interface, C_JAVA, st_C_struct
2233 class, 0, st_C_class
2234 namespace, C_PLPL, st_C_struct
2235 domain, C_STAR, st_C_struct
2236 union, 0, st_C_struct
2237 struct, 0, st_C_struct
2238 extern, 0, st_C_extern
2239 enum, 0, st_C_enum
2240 typedef, 0, st_C_typedef
2241 define, 0, st_C_define
2242 operator, C_PLPL, st_C_operator
2243 template, 0, st_C_template
2244 bool, C_PLPL, st_C_typespec
2245 long, 0, st_C_typespec
2246 short, 0, st_C_typespec
2247 int, 0, st_C_typespec
2248 char, 0, st_C_typespec
2249 float, 0, st_C_typespec
2250 double, 0, st_C_typespec
2251 signed, 0, st_C_typespec
2252 unsigned, 0, st_C_typespec
2253 auto, 0, st_C_typespec
2254 void, 0, st_C_typespec
2255 static, 0, st_C_typespec
2256 const, 0, st_C_typespec
2257 volatile, 0, st_C_typespec
2258 explicit, C_PLPL, st_C_typespec
2259 mutable, C_PLPL, st_C_typespec
2260 typename, C_PLPL, st_C_typespec
2261 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
2262 DEFUN, 0, st_C_gnumacro
2263 SYSCALL, 0, st_C_gnumacro
2264 ENTRY, 0, st_C_gnumacro
2265 PSEUDO, 0, st_C_gnumacro
2266 # These are defined inside C functions, so currently they are not met.
2267 # EXFUN used in glibc, DEFVAR_* in emacs.
2268 #EXFUN, 0, st_C_gnumacro
2269 #DEFVAR_, 0, st_C_gnumacro
2271 and replace lines between %< and %> with its output,
2272 then make in_word_set and C_stab_entry static. */
2273 /*%<*/
2274 /* C code produced by gperf version 2.7.1 (19981006 egcs) */
2275 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
2276 struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
2278 #define TOTAL_KEYWORDS 47
2279 #define MIN_WORD_LENGTH 2
2280 #define MAX_WORD_LENGTH 15
2281 #define MIN_HASH_VALUE 18
2282 #define MAX_HASH_VALUE 138
2283 /* maximum key range = 121, duplicates = 0 */
2285 #ifdef __GNUC__
2286 __inline
2287 #endif
2288 static unsigned int
2289 hash (str, len)
2290 register const char *str;
2291 register unsigned int len;
2293 static unsigned char asso_values[] =
2295 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2296 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2297 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2298 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2299 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2300 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2301 139, 139, 139, 139, 63, 139, 139, 139, 33, 44,
2302 62, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2303 42, 139, 139, 12, 32, 139, 139, 139, 139, 139,
2304 139, 139, 139, 139, 139, 139, 139, 34, 59, 37,
2305 24, 58, 33, 3, 139, 16, 139, 139, 42, 60,
2306 18, 11, 39, 139, 23, 57, 4, 63, 6, 20,
2307 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2308 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2309 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2310 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2311 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2312 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2313 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2314 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2315 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2316 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2317 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2318 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2319 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2320 139, 139, 139, 139, 139, 139
2322 register int hval = len;
2324 switch (hval)
2326 default:
2327 case 3:
2328 hval += asso_values[(unsigned char)str[2]];
2329 case 2:
2330 case 1:
2331 hval += asso_values[(unsigned char)str[0]];
2332 break;
2334 return hval;
2337 #ifdef __GNUC__
2338 __inline
2339 #endif
2340 static struct C_stab_entry *
2341 in_word_set (str, len)
2342 register const char *str;
2343 register unsigned int len;
2345 static struct C_stab_entry wordlist[] =
2347 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2348 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2349 {"if", 0, st_C_ignore},
2350 {""}, {""}, {""}, {""},
2351 {"int", 0, st_C_typespec},
2352 {""}, {""},
2353 {"void", 0, st_C_typespec},
2354 {""}, {""},
2355 {"interface", C_JAVA, st_C_struct},
2356 {""},
2357 {"SYSCALL", 0, st_C_gnumacro},
2358 {""},
2359 {"return", 0, st_C_ignore},
2360 {""}, {""}, {""}, {""}, {""}, {""}, {""},
2361 {"while", 0, st_C_ignore},
2362 {"auto", 0, st_C_typespec},
2363 {""}, {""}, {""}, {""}, {""}, {""},
2364 {"float", 0, st_C_typespec},
2365 {"typedef", 0, st_C_typedef},
2366 {"typename", C_PLPL, st_C_typespec},
2367 {""}, {""}, {""},
2368 {"friend", C_PLPL, st_C_ignore},
2369 {"volatile", 0, st_C_typespec},
2370 {""}, {""},
2371 {"for", 0, st_C_ignore},
2372 {"const", 0, st_C_typespec},
2373 {"import", C_JAVA, st_C_ignore},
2374 {""},
2375 {"define", 0, st_C_define},
2376 {"long", 0, st_C_typespec},
2377 {"implements", C_JAVA, st_C_javastruct},
2378 {"signed", 0, st_C_typespec},
2379 {""},
2380 {"extern", 0, st_C_extern},
2381 {"extends", C_JAVA, st_C_javastruct},
2382 {""},
2383 {"mutable", C_PLPL, st_C_typespec},
2384 {"template", 0, st_C_template},
2385 {"short", 0, st_C_typespec},
2386 {"bool", C_PLPL, st_C_typespec},
2387 {"char", 0, st_C_typespec},
2388 {"class", 0, st_C_class},
2389 {"operator", C_PLPL, st_C_operator},
2390 {""},
2391 {"switch", 0, st_C_ignore},
2392 {""},
2393 {"ENTRY", 0, st_C_gnumacro},
2394 {""},
2395 {"package", C_JAVA, st_C_ignore},
2396 {"union", 0, st_C_struct},
2397 {"@end", 0, st_C_objend},
2398 {"struct", 0, st_C_struct},
2399 {"namespace", C_PLPL, st_C_struct},
2400 {""}, {""},
2401 {"domain", C_STAR, st_C_struct},
2402 {"@interface", 0, st_C_objprot},
2403 {"PSEUDO", 0, st_C_gnumacro},
2404 {"double", 0, st_C_typespec},
2405 {""},
2406 {"@protocol", 0, st_C_objprot},
2407 {""},
2408 {"static", 0, st_C_typespec},
2409 {""}, {""},
2410 {"DEFUN", 0, st_C_gnumacro},
2411 {""}, {""}, {""}, {""},
2412 {"explicit", C_PLPL, st_C_typespec},
2413 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2414 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2415 {""},
2416 {"enum", 0, st_C_enum},
2417 {""}, {""},
2418 {"unsigned", 0, st_C_typespec},
2419 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2420 {"@implementation",0, st_C_objimpl}
2423 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
2425 register int key = hash (str, len);
2427 if (key <= MAX_HASH_VALUE && key >= 0)
2429 register const char *s = wordlist[key].name;
2431 if (*str == *s && !strncmp (str + 1, s + 1, len - 1))
2432 return &wordlist[key];
2435 return 0;
2437 /*%>*/
2439 static enum sym_type
2440 C_symtype (str, len, c_ext)
2441 char *str;
2442 int len;
2443 int c_ext;
2445 register struct C_stab_entry *se = in_word_set (str, len);
2447 if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
2448 return st_none;
2449 return se->type;
2454 * C functions and variables are recognized using a simple
2455 * finite automaton. fvdef is its state variable.
2457 static enum
2459 fvnone, /* nothing seen */
2460 fdefunkey, /* Emacs DEFUN keyword seen */
2461 fdefunname, /* Emacs DEFUN name seen */
2462 foperator, /* func: operator keyword seen (cplpl) */
2463 fvnameseen, /* function or variable name seen */
2464 fstartlist, /* func: just after open parenthesis */
2465 finlist, /* func: in parameter list */
2466 flistseen, /* func: after parameter list */
2467 fignore, /* func: before open brace */
2468 vignore /* var-like: ignore until ';' */
2469 } fvdef;
2471 static bool fvextern; /* func or var: extern keyword seen; */
2474 * typedefs are recognized using a simple finite automaton.
2475 * typdef is its state variable.
2477 static enum
2479 tnone, /* nothing seen */
2480 tkeyseen, /* typedef keyword seen */
2481 ttypeseen, /* defined type seen */
2482 tinbody, /* inside typedef body */
2483 tend, /* just before typedef tag */
2484 tignore /* junk after typedef tag */
2485 } typdef;
2488 * struct-like structures (enum, struct and union) are recognized
2489 * using another simple finite automaton. `structdef' is its state
2490 * variable.
2492 static enum
2494 snone, /* nothing seen yet,
2495 or in struct body if cblev > 0 */
2496 skeyseen, /* struct-like keyword seen */
2497 stagseen, /* struct-like tag seen */
2498 sintemplate, /* inside template (ignore) */
2499 scolonseen /* colon seen after struct-like tag */
2500 } structdef;
2503 * When objdef is different from onone, objtag is the name of the class.
2505 static char *objtag = "<uninited>";
2508 * Yet another little state machine to deal with preprocessor lines.
2510 static enum
2512 dnone, /* nothing seen */
2513 dsharpseen, /* '#' seen as first char on line */
2514 ddefineseen, /* '#' and 'define' seen */
2515 dignorerest /* ignore rest of line */
2516 } definedef;
2519 * State machine for Objective C protocols and implementations.
2520 * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995)
2522 static enum
2524 onone, /* nothing seen */
2525 oprotocol, /* @interface or @protocol seen */
2526 oimplementation, /* @implementations seen */
2527 otagseen, /* class name seen */
2528 oparenseen, /* parenthesis before category seen */
2529 ocatseen, /* category name seen */
2530 oinbody, /* in @implementation body */
2531 omethodsign, /* in @implementation body, after +/- */
2532 omethodtag, /* after method name */
2533 omethodcolon, /* after method colon */
2534 omethodparm, /* after method parameter */
2535 oignore /* wait for @end */
2536 } objdef;
2540 * Use this structure to keep info about the token read, and how it
2541 * should be tagged. Used by the make_C_tag function to build a tag.
2543 static struct tok
2545 bool valid;
2546 bool named;
2547 int offset;
2548 int length;
2549 int lineno;
2550 long linepos;
2551 char *line;
2552 } token; /* latest token read */
2553 static linebuffer token_name; /* its name */
2556 * Variables and functions for dealing with nested structures.
2557 * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001)
2559 static void pushclass_above __P((int, char *, int));
2560 static void popclass_above __P((int));
2561 static void write_classname __P((linebuffer *, char *qualifier));
2563 static struct {
2564 char **cname; /* nested class names */
2565 int *cblev; /* nested class curly brace level */
2566 int nl; /* class nesting level (elements used) */
2567 int size; /* length of the array */
2568 } cstack; /* stack for nested declaration tags */
2569 /* Current struct nesting depth (namespace, class, struct, union, enum). */
2570 #define nestlev (cstack.nl)
2571 /* After struct keyword or in struct body, not inside an nested function. */
2572 #define instruct (structdef == snone && nestlev > 0 \
2573 && cblev == cstack.cblev[nestlev-1] + 1)
2575 static void
2576 pushclass_above (cblev, str, len)
2577 int cblev;
2578 char *str;
2579 int len;
2581 int nl;
2583 popclass_above (cblev);
2584 nl = cstack.nl;
2585 if (nl >= cstack.size)
2587 int size = cstack.size *= 2;
2588 xrnew (cstack.cname, size, char *);
2589 xrnew (cstack.cblev, size, int);
2591 assert (nl == 0 || cstack.cblev[nl-1] < cblev);
2592 cstack.cname[nl] = (str == NULL) ? NULL : savenstr (str, len);
2593 cstack.cblev[nl] = cblev;
2594 cstack.nl = nl + 1;
2597 static void
2598 popclass_above (cblev)
2599 int cblev;
2601 int nl;
2603 for (nl = cstack.nl - 1;
2604 nl >= 0 && cstack.cblev[nl] >= cblev;
2605 nl--)
2607 if (cstack.cname[nl] != NULL)
2608 free (cstack.cname[nl]);
2609 cstack.nl = nl;
2613 static void
2614 write_classname (cn, qualifier)
2615 linebuffer *cn;
2616 char *qualifier;
2618 int i, len;
2619 int qlen = strlen (qualifier);
2621 if (cstack.nl == 0 || cstack.cname[0] == NULL)
2623 len = 0;
2624 cn->len = 0;
2625 cn->buffer[0] = '\0';
2627 else
2629 len = strlen (cstack.cname[0]);
2630 linebuffer_setlen (cn, len);
2631 strcpy (cn->buffer, cstack.cname[0]);
2633 for (i = 1; i < cstack.nl; i++)
2635 char *s;
2636 int slen;
2638 s = cstack.cname[i];
2639 if (s == NULL)
2640 continue;
2641 slen = strlen (s);
2642 len += slen + qlen;
2643 linebuffer_setlen (cn, len);
2644 strncat (cn->buffer, qualifier, qlen);
2645 strncat (cn->buffer, s, slen);
2650 static bool consider_token __P((char *, int, int, int *, int, int, bool *));
2651 static void make_C_tag __P((bool));
2654 * consider_token ()
2655 * checks to see if the current token is at the start of a
2656 * function or variable, or corresponds to a typedef, or
2657 * is a struct/union/enum tag, or #define, or an enum constant.
2659 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2660 * with args. C_EXTP points to which language we are looking at.
2662 * Globals
2663 * fvdef IN OUT
2664 * structdef IN OUT
2665 * definedef IN OUT
2666 * typdef IN OUT
2667 * objdef IN OUT
2670 static bool
2671 consider_token (str, len, c, c_extp, cblev, parlev, is_func_or_var)
2672 register char *str; /* IN: token pointer */
2673 register int len; /* IN: token length */
2674 register int c; /* IN: first char after the token */
2675 int *c_extp; /* IN, OUT: C extensions mask */
2676 int cblev; /* IN: curly brace level */
2677 int parlev; /* IN: parenthesis level */
2678 bool *is_func_or_var; /* OUT: function or variable found */
2680 /* When structdef is stagseen, scolonseen, or snone with cblev > 0,
2681 structtype is the type of the preceding struct-like keyword, and
2682 structcblev is the curly brace level where it has been seen. */
2683 static enum sym_type structtype;
2684 static int structcblev;
2685 static enum sym_type toktype;
2688 toktype = C_symtype (str, len, *c_extp);
2691 * Advance the definedef state machine.
2693 switch (definedef)
2695 case dnone:
2696 /* We're not on a preprocessor line. */
2697 if (toktype == st_C_gnumacro)
2699 fvdef = fdefunkey;
2700 return FALSE;
2702 break;
2703 case dsharpseen:
2704 if (toktype == st_C_define)
2706 definedef = ddefineseen;
2708 else
2710 definedef = dignorerest;
2712 return FALSE;
2713 case ddefineseen:
2715 * Make a tag for any macro, unless it is a constant
2716 * and constantypedefs is FALSE.
2718 definedef = dignorerest;
2719 *is_func_or_var = (c == '(');
2720 if (!*is_func_or_var && !constantypedefs)
2721 return FALSE;
2722 else
2723 return TRUE;
2724 case dignorerest:
2725 return FALSE;
2726 default:
2727 error ("internal error: definedef value.", (char *)NULL);
2731 * Now typedefs
2733 switch (typdef)
2735 case tnone:
2736 if (toktype == st_C_typedef)
2738 if (typedefs)
2739 typdef = tkeyseen;
2740 fvextern = FALSE;
2741 fvdef = fvnone;
2742 return FALSE;
2744 break;
2745 case tkeyseen:
2746 switch (toktype)
2748 case st_none:
2749 case st_C_typespec:
2750 case st_C_class:
2751 case st_C_struct:
2752 case st_C_enum:
2753 typdef = ttypeseen;
2754 break;
2756 break;
2757 case ttypeseen:
2758 if (structdef == snone && fvdef == fvnone)
2760 fvdef = fvnameseen;
2761 return TRUE;
2763 break;
2764 case tend:
2765 switch (toktype)
2767 case st_C_typespec:
2768 case st_C_class:
2769 case st_C_struct:
2770 case st_C_enum:
2771 return FALSE;
2773 return TRUE;
2777 * This structdef business is NOT invoked when we are ctags and the
2778 * file is plain C. This is because a struct tag may have the same
2779 * name as another tag, and this loses with ctags.
2781 switch (toktype)
2783 case st_C_javastruct:
2784 if (structdef == stagseen)
2785 structdef = scolonseen;
2786 return FALSE;
2787 case st_C_template:
2788 case st_C_class:
2789 if (cblev == 0
2790 && (*c_extp & C_AUTO) /* automatic detection of C++ language */
2791 && definedef == dnone && structdef == snone
2792 && typdef == tnone && fvdef == fvnone)
2793 *c_extp = (*c_extp | C_PLPL) & ~C_AUTO;
2794 if (toktype == st_C_template)
2795 break;
2796 /* FALLTHRU */
2797 case st_C_struct:
2798 case st_C_enum:
2799 if (parlev == 0
2800 && fvdef != vignore
2801 && (typdef == tkeyseen
2802 || (typedefs_or_cplusplus && structdef == snone)))
2804 structdef = skeyseen;
2805 structtype = toktype;
2806 structcblev = cblev;
2808 return FALSE;
2811 if (structdef == skeyseen)
2813 structdef = stagseen;
2814 return TRUE;
2817 if (typdef != tnone)
2818 definedef = dnone;
2820 /* Detect Objective C constructs. */
2821 switch (objdef)
2823 case onone:
2824 switch (toktype)
2826 case st_C_objprot:
2827 objdef = oprotocol;
2828 return FALSE;
2829 case st_C_objimpl:
2830 objdef = oimplementation;
2831 return FALSE;
2833 break;
2834 case oimplementation:
2835 /* Save the class tag for functions or variables defined inside. */
2836 objtag = savenstr (str, len);
2837 objdef = oinbody;
2838 return FALSE;
2839 case oprotocol:
2840 /* Save the class tag for categories. */
2841 objtag = savenstr (str, len);
2842 objdef = otagseen;
2843 *is_func_or_var = TRUE;
2844 return TRUE;
2845 case oparenseen:
2846 objdef = ocatseen;
2847 *is_func_or_var = TRUE;
2848 return TRUE;
2849 case oinbody:
2850 break;
2851 case omethodsign:
2852 if (parlev == 0)
2854 objdef = omethodtag;
2855 linebuffer_setlen (&token_name, len);
2856 strncpy (token_name.buffer, str, len);
2857 token_name.buffer[len] = '\0';
2858 return TRUE;
2860 return FALSE;
2861 case omethodcolon:
2862 if (parlev == 0)
2863 objdef = omethodparm;
2864 return FALSE;
2865 case omethodparm:
2866 if (parlev == 0)
2868 objdef = omethodtag;
2869 linebuffer_setlen (&token_name, token_name.len + len);
2870 strncat (token_name.buffer, str, len);
2871 return TRUE;
2873 return FALSE;
2874 case oignore:
2875 if (toktype == st_C_objend)
2877 /* Memory leakage here: the string pointed by objtag is
2878 never released, because many tests would be needed to
2879 avoid breaking on incorrect input code. The amount of
2880 memory leaked here is the sum of the lengths of the
2881 class tags.
2882 free (objtag); */
2883 objdef = onone;
2885 return FALSE;
2888 /* A function, variable or enum constant? */
2889 switch (toktype)
2891 case st_C_extern:
2892 fvextern = TRUE;
2893 /* FALLTHRU */
2894 case st_C_typespec:
2895 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2896 fvdef = fvnone; /* should be useless */
2897 return FALSE;
2898 case st_C_ignore:
2899 fvextern = FALSE;
2900 fvdef = vignore;
2901 return FALSE;
2902 case st_C_operator:
2903 fvdef = foperator;
2904 *is_func_or_var = TRUE;
2905 return TRUE;
2906 case st_none:
2907 if (constantypedefs
2908 && structdef == snone
2909 && structtype == st_C_enum && cblev > structcblev)
2910 return TRUE; /* enum constant */
2911 switch (fvdef)
2913 case fdefunkey:
2914 if (cblev > 0)
2915 break;
2916 fvdef = fdefunname; /* GNU macro */
2917 *is_func_or_var = TRUE;
2918 return TRUE;
2919 case fvnone:
2920 if ((strneq (str, "asm", 3) && endtoken (str[3]))
2921 || (strneq (str, "__asm__", 7) && endtoken (str[7])))
2923 fvdef = vignore;
2924 return FALSE;
2926 if ((*c_extp & C_PLPL) && strneq (str+len-10, "::operator", 10))
2928 fvdef = foperator;
2929 *is_func_or_var = TRUE;
2930 return TRUE;
2932 if (cblev > 0 && !instruct)
2933 break;
2934 fvdef = fvnameseen; /* function or variable */
2935 *is_func_or_var = TRUE;
2936 return TRUE;
2938 break;
2941 return FALSE;
2946 * C_entries often keeps pointers to tokens or lines which are older than
2947 * the line currently read. By keeping two line buffers, and switching
2948 * them at end of line, it is possible to use those pointers.
2950 static struct
2952 long linepos;
2953 linebuffer lb;
2954 } lbs[2];
2956 #define current_lb_is_new (newndx == curndx)
2957 #define switch_line_buffers() (curndx = 1 - curndx)
2959 #define curlb (lbs[curndx].lb)
2960 #define newlb (lbs[newndx].lb)
2961 #define curlinepos (lbs[curndx].linepos)
2962 #define newlinepos (lbs[newndx].linepos)
2964 #define CNL_SAVE_DEFINEDEF() \
2965 do { \
2966 curlinepos = charno; \
2967 readline (&curlb, inf); \
2968 lp = curlb.buffer; \
2969 quotednl = FALSE; \
2970 newndx = curndx; \
2971 } while (0)
2973 #define CNL() \
2974 do { \
2975 CNL_SAVE_DEFINEDEF(); \
2976 if (savetoken.valid) \
2978 token = savetoken; \
2979 savetoken.valid = FALSE; \
2981 definedef = dnone; \
2982 } while (0)
2985 static void
2986 make_C_tag (isfun)
2987 bool isfun;
2989 /* This function should never be called when token.valid is FALSE, but
2990 we must protect against invalid input or internal errors. */
2991 if (!DEBUG && !token.valid)
2992 return;
2994 if (!token.valid) /* this case is optimised away if !DEBUG */
2995 make_tag (concat (token_name.buffer, "##invalid token##", ""),
2996 token_name.len + 17, isfun, token.line,
2997 token.offset+token.length+1, token.lineno, token.linepos);
2998 else
2999 make_tag (token_name.buffer, token_name.len, isfun, token.line,
3000 token.offset+token.length+1, token.lineno, token.linepos);
3002 token.valid = FALSE;
3007 * C_entries ()
3008 * This routine finds functions, variables, typedefs,
3009 * #define's, enum constants and struct/union/enum definitions in
3010 * C syntax and adds them to the list.
3012 static void
3013 C_entries (c_ext, inf)
3014 int c_ext; /* extension of C */
3015 FILE *inf; /* input file */
3017 register char c; /* latest char read; '\0' for end of line */
3018 register char *lp; /* pointer one beyond the character `c' */
3019 int curndx, newndx; /* indices for current and new lb */
3020 register int tokoff; /* offset in line of start of current token */
3021 register int toklen; /* length of current token */
3022 char *qualifier; /* string used to qualify names */
3023 int qlen; /* length of qualifier */
3024 int cblev; /* current curly brace level */
3025 int parlev; /* current parenthesis level */
3026 int typdefcblev; /* cblev where a typedef struct body begun */
3027 bool incomm, inquote, inchar, quotednl, midtoken;
3028 bool cplpl, cjava;
3029 bool yacc_rules; /* in the rules part of a yacc file */
3030 struct tok savetoken; /* token saved during preprocessor handling */
3033 initbuffer (&token_name);
3034 initbuffer (&lbs[0].lb);
3035 initbuffer (&lbs[1].lb);
3036 if (cstack.size == 0)
3038 cstack.size = (DEBUG) ? 1 : 4;
3039 cstack.nl = 0;
3040 cstack.cname = xnew (cstack.size, char *);
3041 cstack.cblev = xnew (cstack.size, int);
3044 tokoff = toklen = typdefcblev = 0; /* keep compiler quiet */
3045 curndx = newndx = 0;
3046 lp = curlb.buffer;
3047 *lp = 0;
3049 fvdef = fvnone; fvextern = FALSE; typdef = tnone;
3050 structdef = snone; definedef = dnone; objdef = onone;
3051 yacc_rules = FALSE;
3052 midtoken = inquote = inchar = incomm = quotednl = FALSE;
3053 token.valid = savetoken.valid = FALSE;
3054 cblev = 0;
3055 parlev = 0;
3056 cplpl = (c_ext & C_PLPL) == C_PLPL;
3057 cjava = (c_ext & C_JAVA) == C_JAVA;
3058 if (cjava)
3059 { qualifier = "."; qlen = 1; }
3060 else
3061 { qualifier = "::"; qlen = 2; }
3064 while (!feof (inf))
3066 c = *lp++;
3067 if (c == '\\')
3069 /* If we're at the end of the line, the next character is a
3070 '\0'; don't skip it, because it's the thing that tells us
3071 to read the next line. */
3072 if (*lp == '\0')
3074 quotednl = TRUE;
3075 continue;
3077 lp++;
3078 c = ' ';
3080 else if (incomm)
3082 switch (c)
3084 case '*':
3085 if (*lp == '/')
3087 c = *lp++;
3088 incomm = FALSE;
3090 break;
3091 case '\0':
3092 /* Newlines inside comments do not end macro definitions in
3093 traditional cpp. */
3094 CNL_SAVE_DEFINEDEF ();
3095 break;
3097 continue;
3099 else if (inquote)
3101 switch (c)
3103 case '"':
3104 inquote = FALSE;
3105 break;
3106 case '\0':
3107 /* Newlines inside strings do not end macro definitions
3108 in traditional cpp, even though compilers don't
3109 usually accept them. */
3110 CNL_SAVE_DEFINEDEF ();
3111 break;
3113 continue;
3115 else if (inchar)
3117 switch (c)
3119 case '\0':
3120 /* Hmmm, something went wrong. */
3121 CNL ();
3122 /* FALLTHRU */
3123 case '\'':
3124 inchar = FALSE;
3125 break;
3127 continue;
3129 else
3130 switch (c)
3132 case '"':
3133 inquote = TRUE;
3134 switch (fvdef)
3136 case fdefunkey:
3137 case fstartlist:
3138 case finlist:
3139 case fignore:
3140 case vignore:
3141 break;
3142 default:
3143 fvextern = FALSE;
3144 fvdef = fvnone;
3146 continue;
3147 case '\'':
3148 inchar = TRUE;
3149 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
3151 fvextern = FALSE;
3152 fvdef = fvnone;
3154 continue;
3155 case '/':
3156 if (*lp == '*')
3158 lp++;
3159 incomm = TRUE;
3160 continue;
3162 else if (/* cplpl && */ *lp == '/')
3164 c = '\0';
3165 break;
3167 else
3168 break;
3169 case '%':
3170 if ((c_ext & YACC) && *lp == '%')
3172 /* Entering or exiting rules section in yacc file. */
3173 lp++;
3174 definedef = dnone; fvdef = fvnone; fvextern = FALSE;
3175 typdef = tnone; structdef = snone;
3176 midtoken = inquote = inchar = incomm = quotednl = FALSE;
3177 cblev = 0;
3178 yacc_rules = !yacc_rules;
3179 continue;
3181 else
3182 break;
3183 case '#':
3184 if (definedef == dnone)
3186 char *cp;
3187 bool cpptoken = TRUE;
3189 /* Look back on this line. If all blanks, or nonblanks
3190 followed by an end of comment, this is a preprocessor
3191 token. */
3192 for (cp = newlb.buffer; cp < lp-1; cp++)
3193 if (!iswhite (*cp))
3195 if (*cp == '*' && *(cp+1) == '/')
3197 cp++;
3198 cpptoken = TRUE;
3200 else
3201 cpptoken = FALSE;
3203 if (cpptoken)
3204 definedef = dsharpseen;
3205 } /* if (definedef == dnone) */
3207 continue;
3208 } /* switch (c) */
3211 /* Consider token only if some involved conditions are satisfied. */
3212 if (typdef != tignore
3213 && definedef != dignorerest
3214 && fvdef != finlist
3215 && structdef != sintemplate
3216 && (definedef != dnone
3217 || structdef != scolonseen))
3219 if (midtoken)
3221 if (endtoken (c))
3223 if (c == ':' && cplpl && *lp == ':' && begtoken (lp[1]))
3226 * This handles :: in the middle, but not at the
3227 * beginning of an identifier. Also, space-separated
3228 * :: is not recognised.
3230 lp += 2;
3231 toklen += 2;
3232 c = lp[-1];
3233 goto still_in_token;
3235 else
3237 bool funorvar = FALSE;
3239 if (yacc_rules
3240 || consider_token (newlb.buffer + tokoff, toklen, c,
3241 &c_ext, cblev, parlev, &funorvar))
3243 if (fvdef == foperator)
3245 char *oldlp = lp;
3246 lp = skip_spaces (lp-1);
3247 if (*lp != '\0')
3248 lp += 1;
3249 while (*lp != '\0'
3250 && !iswhite (*lp) && *lp != '(')
3251 lp += 1;
3252 c = *lp++;
3253 toklen += lp - oldlp;
3255 token.named = FALSE;
3256 if ((c_ext & C_EXT) /* not pure C */
3257 && nestlev > 0 && definedef == dnone)
3258 /* in struct body */
3260 write_classname (&token_name, qualifier);
3261 linebuffer_setlen (&token_name,
3262 token_name.len+qlen+toklen);
3263 strcat (token_name.buffer, qualifier);
3264 strncat (token_name.buffer,
3265 newlb.buffer + tokoff, toklen);
3266 token.named = TRUE;
3268 else if (objdef == ocatseen)
3269 /* Objective C category */
3271 int len = strlen (objtag) + 2 + toklen;
3272 linebuffer_setlen (&token_name, len);
3273 strcpy (token_name.buffer, objtag);
3274 strcat (token_name.buffer, "(");
3275 strncat (token_name.buffer,
3276 newlb.buffer + tokoff, toklen);
3277 strcat (token_name.buffer, ")");
3278 token.named = TRUE;
3280 else if (objdef == omethodtag
3281 || objdef == omethodparm)
3282 /* Objective C method */
3284 token.named = TRUE;
3286 else if (fvdef == fdefunname)
3287 /* GNU DEFUN and similar macros */
3289 bool defun = (newlb.buffer[tokoff] == 'F');
3290 int off = tokoff;
3291 int len = toklen;
3293 /* Rewrite the tag so that emacs lisp DEFUNs
3294 can be found by their elisp name */
3295 if (defun)
3297 off += 1;
3298 len -= 1;
3300 len = toklen;
3301 linebuffer_setlen (&token_name, len);
3302 strncpy (token_name.buffer,
3303 newlb.buffer + off, len);
3304 token_name.buffer[len] = '\0';
3305 if (defun)
3306 while (--len >= 0)
3307 if (token_name.buffer[len] == '_')
3308 token_name.buffer[len] = '-';
3309 token.named = defun;
3311 else
3313 linebuffer_setlen (&token_name, toklen);
3314 strncpy (token_name.buffer,
3315 newlb.buffer + tokoff, toklen);
3316 token_name.buffer[toklen] = '\0';
3317 /* Name macros and members. */
3318 token.named = (structdef == stagseen
3319 || typdef == ttypeseen
3320 || typdef == tend
3321 || (funorvar
3322 && definedef == dignorerest)
3323 || (funorvar
3324 && definedef == dnone
3325 && structdef == snone
3326 && cblev > 0));
3328 token.lineno = lineno;
3329 token.offset = tokoff;
3330 token.length = toklen;
3331 token.line = newlb.buffer;
3332 token.linepos = newlinepos;
3333 token.valid = TRUE;
3335 if (definedef == dnone
3336 && (fvdef == fvnameseen
3337 || fvdef == foperator
3338 || structdef == stagseen
3339 || typdef == tend
3340 || typdef == ttypeseen
3341 || objdef != onone))
3343 if (current_lb_is_new)
3344 switch_line_buffers ();
3346 else if (definedef != dnone
3347 || fvdef == fdefunname
3348 || instruct)
3349 make_C_tag (funorvar);
3351 midtoken = FALSE;
3353 } /* if (endtoken (c)) */
3354 else if (intoken (c))
3355 still_in_token:
3357 toklen++;
3358 continue;
3360 } /* if (midtoken) */
3361 else if (begtoken (c))
3363 switch (definedef)
3365 case dnone:
3366 switch (fvdef)
3368 case fstartlist:
3369 fvdef = finlist;
3370 continue;
3371 case flistseen:
3372 make_C_tag (TRUE); /* a function */
3373 fvdef = fignore;
3374 break;
3375 case fvnameseen:
3376 fvdef = fvnone;
3377 break;
3379 if (structdef == stagseen && !cjava)
3381 popclass_above (cblev);
3382 structdef = snone;
3384 break;
3385 case dsharpseen:
3386 savetoken = token;
3387 break;
3389 if (!yacc_rules || lp == newlb.buffer + 1)
3391 tokoff = lp - 1 - newlb.buffer;
3392 toklen = 1;
3393 midtoken = TRUE;
3395 continue;
3396 } /* if (begtoken) */
3397 } /* if must look at token */
3400 /* Detect end of line, colon, comma, semicolon and various braces
3401 after having handled a token.*/
3402 switch (c)
3404 case ':':
3405 if (yacc_rules && token.offset == 0 && token.valid)
3407 make_C_tag (FALSE); /* a yacc function */
3408 break;
3410 if (definedef != dnone)
3411 break;
3412 switch (objdef)
3414 case otagseen:
3415 objdef = oignore;
3416 make_C_tag (TRUE); /* an Objective C class */
3417 break;
3418 case omethodtag:
3419 case omethodparm:
3420 objdef = omethodcolon;
3421 linebuffer_setlen (&token_name, token_name.len + 1);
3422 strcat (token_name.buffer, ":");
3423 break;
3425 if (structdef == stagseen)
3426 structdef = scolonseen;
3427 break;
3428 case ';':
3429 if (definedef != dnone)
3430 break;
3431 switch (typdef)
3433 case tend:
3434 case ttypeseen:
3435 make_C_tag (FALSE); /* a typedef */
3436 typdef = tnone;
3437 fvdef = fvnone;
3438 break;
3439 case tnone:
3440 case tinbody:
3441 case tignore:
3442 switch (fvdef)
3444 case fignore:
3445 if (typdef == tignore)
3446 fvdef = fvnone;
3447 break;
3448 case fvnameseen:
3449 if ((globals && cblev == 0 && (!fvextern || declarations))
3450 || (members && instruct))
3451 make_C_tag (FALSE); /* a variable */
3452 fvextern = FALSE;
3453 fvdef = fvnone;
3454 token.valid = FALSE;
3455 break;
3456 case flistseen:
3457 if ((declarations && typdef == tnone && !instruct)
3458 || (members && typdef != tignore && instruct))
3459 make_C_tag (TRUE); /* a function declaration */
3460 /* FALLTHRU */
3461 default:
3462 fvextern = FALSE;
3463 fvdef = fvnone;
3464 if (declarations
3465 && structdef == stagseen && (c_ext & C_PLPL))
3466 make_C_tag (FALSE); /* forward declaration */
3467 else
3468 /* The following instruction invalidates the token.
3469 Probably the token should be invalidated in all other
3470 cases where some state machine is reset prematurely. */
3471 token.valid = FALSE;
3472 } /* switch (fvdef) */
3473 /* FALLTHRU */
3474 default:
3475 if (!instruct)
3476 typdef = tnone;
3478 if (structdef == stagseen)
3479 structdef = snone;
3480 break;
3481 case ',':
3482 if (definedef != dnone)
3483 break;
3484 switch (objdef)
3486 case omethodtag:
3487 case omethodparm:
3488 make_C_tag (TRUE); /* an Objective C method */
3489 objdef = oinbody;
3490 break;
3492 switch (fvdef)
3494 case fdefunkey:
3495 case foperator:
3496 case fstartlist:
3497 case finlist:
3498 case fignore:
3499 case vignore:
3500 break;
3501 case fdefunname:
3502 fvdef = fignore;
3503 break;
3504 case fvnameseen: /* a variable */
3505 if ((globals && cblev == 0 && (!fvextern || declarations))
3506 || (members && instruct))
3507 make_C_tag (FALSE);
3508 break;
3509 case flistseen: /* a function */
3510 if ((declarations && typdef == tnone && !instruct)
3511 || (members && typdef != tignore && instruct))
3513 make_C_tag (TRUE); /* a function declaration */
3514 fvdef = fvnameseen;
3516 else if (!declarations)
3517 fvdef = fvnone;
3518 token.valid = FALSE;
3519 break;
3520 default:
3521 fvdef = fvnone;
3523 if (structdef == stagseen)
3524 structdef = snone;
3525 break;
3526 case '[':
3527 if (definedef != dnone)
3528 break;
3529 if (structdef == stagseen)
3530 structdef = snone;
3531 switch (typdef)
3533 case ttypeseen:
3534 case tend:
3535 typdef = tignore;
3536 make_C_tag (FALSE); /* a typedef */
3537 break;
3538 case tnone:
3539 case tinbody:
3540 switch (fvdef)
3542 case foperator:
3543 case finlist:
3544 case fignore:
3545 case vignore:
3546 break;
3547 case fvnameseen:
3548 if ((members && cblev == 1)
3549 || (globals && cblev == 0
3550 && (!fvextern || declarations)))
3551 make_C_tag (FALSE); /* a variable */
3552 /* FALLTHRU */
3553 default:
3554 fvdef = fvnone;
3556 break;
3558 break;
3559 case '(':
3560 if (definedef != dnone)
3561 break;
3562 if (objdef == otagseen && parlev == 0)
3563 objdef = oparenseen;
3564 switch (fvdef)
3566 case fvnameseen:
3567 if (typdef == ttypeseen
3568 && *lp != '*'
3569 && !instruct)
3571 /* This handles constructs like:
3572 typedef void OperatorFun (int fun); */
3573 make_C_tag (FALSE);
3574 typdef = tignore;
3575 fvdef = fignore;
3576 break;
3578 /* FALLTHRU */
3579 case foperator:
3580 fvdef = fstartlist;
3581 break;
3582 case flistseen:
3583 fvdef = finlist;
3584 break;
3586 parlev++;
3587 break;
3588 case ')':
3589 if (definedef != dnone)
3590 break;
3591 if (objdef == ocatseen && parlev == 1)
3593 make_C_tag (TRUE); /* an Objective C category */
3594 objdef = oignore;
3596 if (--parlev == 0)
3598 switch (fvdef)
3600 case fstartlist:
3601 case finlist:
3602 fvdef = flistseen;
3603 break;
3605 if (!instruct
3606 && (typdef == tend
3607 || typdef == ttypeseen))
3609 typdef = tignore;
3610 make_C_tag (FALSE); /* a typedef */
3613 else if (parlev < 0) /* can happen due to ill-conceived #if's. */
3614 parlev = 0;
3615 break;
3616 case '{':
3617 if (definedef != dnone)
3618 break;
3619 if (typdef == ttypeseen)
3621 /* Whenever typdef is set to tinbody (currently only
3622 here), typdefcblev should be set to cblev. */
3623 typdef = tinbody;
3624 typdefcblev = cblev;
3626 switch (fvdef)
3628 case flistseen:
3629 make_C_tag (TRUE); /* a function */
3630 /* FALLTHRU */
3631 case fignore:
3632 fvdef = fvnone;
3633 break;
3634 case fvnone:
3635 switch (objdef)
3637 case otagseen:
3638 make_C_tag (TRUE); /* an Objective C class */
3639 objdef = oignore;
3640 break;
3641 case omethodtag:
3642 case omethodparm:
3643 make_C_tag (TRUE); /* an Objective C method */
3644 objdef = oinbody;
3645 break;
3646 default:
3647 /* Neutralize `extern "C" {' grot. */
3648 if (cblev == 0 && structdef == snone && nestlev == 0
3649 && typdef == tnone)
3650 cblev = -1;
3652 break;
3654 switch (structdef)
3656 case skeyseen: /* unnamed struct */
3657 pushclass_above (cblev, NULL, 0);
3658 structdef = snone;
3659 break;
3660 case stagseen: /* named struct or enum */
3661 case scolonseen: /* a class */
3662 pushclass_above (cblev, token.line+token.offset, token.length);
3663 structdef = snone;
3664 make_C_tag (FALSE); /* a struct or enum */
3665 break;
3667 cblev++;
3668 break;
3669 case '*':
3670 if (definedef != dnone)
3671 break;
3672 if (fvdef == fstartlist)
3673 fvdef = fvnone; /* avoid tagging `foo' in `foo (*bar()) ()' */
3674 break;
3675 case '}':
3676 if (definedef != dnone)
3677 break;
3678 if (!noindentypedefs && lp == newlb.buffer + 1)
3680 cblev = 0; /* reset curly brace level if first column */
3681 parlev = 0; /* also reset paren level, just in case... */
3683 else if (cblev > 0)
3684 cblev--;
3685 popclass_above (cblev);
3686 structdef = snone;
3687 /* Only if typdef == tinbody is typdefcblev significant. */
3688 if (typdef == tinbody && cblev <= typdefcblev)
3690 assert (cblev == typdefcblev);
3691 typdef = tend;
3693 break;
3694 case '=':
3695 if (definedef != dnone)
3696 break;
3697 switch (fvdef)
3699 case foperator:
3700 case finlist:
3701 case fignore:
3702 case vignore:
3703 break;
3704 case fvnameseen:
3705 if ((members && cblev == 1)
3706 || (globals && cblev == 0 && (!fvextern || declarations)))
3707 make_C_tag (FALSE); /* a variable */
3708 /* FALLTHRU */
3709 default:
3710 fvdef = vignore;
3712 break;
3713 case '<':
3714 if (cplpl && structdef == stagseen)
3716 structdef = sintemplate;
3717 break;
3719 goto resetfvdef;
3720 case '>':
3721 if (structdef == sintemplate)
3723 structdef = stagseen;
3724 break;
3726 goto resetfvdef;
3727 case '+':
3728 case '-':
3729 if (objdef == oinbody && cblev == 0)
3731 objdef = omethodsign;
3732 break;
3734 /* FALLTHRU */
3735 resetfvdef:
3736 case '#': case '~': case '&': case '%': case '/': case '|':
3737 case '^': case '!': case '.': case '?': case ']':
3738 if (definedef != dnone)
3739 break;
3740 /* These surely cannot follow a function tag in C. */
3741 switch (fvdef)
3743 case foperator:
3744 case finlist:
3745 case fignore:
3746 case vignore:
3747 break;
3748 default:
3749 fvdef = fvnone;
3751 break;
3752 case '\0':
3753 if (objdef == otagseen)
3755 make_C_tag (TRUE); /* an Objective C class */
3756 objdef = oignore;
3758 /* If a macro spans multiple lines don't reset its state. */
3759 if (quotednl)
3760 CNL_SAVE_DEFINEDEF ();
3761 else
3762 CNL ();
3763 break;
3764 } /* switch (c) */
3766 } /* while not eof */
3768 free (token_name.buffer);
3769 free (lbs[0].lb.buffer);
3770 free (lbs[1].lb.buffer);
3774 * Process either a C++ file or a C file depending on the setting
3775 * of a global flag.
3777 static void
3778 default_C_entries (inf)
3779 FILE *inf;
3781 C_entries (cplusplus ? C_PLPL : C_AUTO, inf);
3784 /* Always do plain C. */
3785 static void
3786 plain_C_entries (inf)
3787 FILE *inf;
3789 C_entries (0, inf);
3792 /* Always do C++. */
3793 static void
3794 Cplusplus_entries (inf)
3795 FILE *inf;
3797 C_entries (C_PLPL, inf);
3800 /* Always do Java. */
3801 static void
3802 Cjava_entries (inf)
3803 FILE *inf;
3805 C_entries (C_JAVA, inf);
3808 /* Always do C*. */
3809 static void
3810 Cstar_entries (inf)
3811 FILE *inf;
3813 C_entries (C_STAR, inf);
3816 /* Always do Yacc. */
3817 static void
3818 Yacc_entries (inf)
3819 FILE *inf;
3821 C_entries (YACC, inf);
3825 /* Useful macros. */
3826 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3827 for (; /* loop initialization */ \
3828 !feof (file_pointer) /* loop test */ \
3829 && /* instructions at start of loop */ \
3830 (readline (&line_buffer, file_pointer), \
3831 char_pointer = line_buffer.buffer, \
3832 TRUE); \
3834 #define LOOKING_AT(cp, keyword) /* keyword is a constant string */ \
3835 (strneq ((cp), keyword, sizeof(keyword)-1) /* cp points at keyword */ \
3836 && notinname ((cp)[sizeof(keyword)-1]) /* end of keyword */ \
3837 && ((cp) = skip_spaces((cp)+sizeof(keyword)-1))) /* skip spaces */
3840 * Read a file, but do no processing. This is used to do regexp
3841 * matching on files that have no language defined.
3843 static void
3844 just_read_file (inf)
3845 FILE *inf;
3847 register char *dummy;
3849 LOOP_ON_INPUT_LINES (inf, lb, dummy)
3850 continue;
3854 /* Fortran parsing */
3856 static void F_takeprec __P((void));
3857 static void F_getit __P((FILE *));
3859 static void
3860 F_takeprec ()
3862 dbp = skip_spaces (dbp);
3863 if (*dbp != '*')
3864 return;
3865 dbp++;
3866 dbp = skip_spaces (dbp);
3867 if (strneq (dbp, "(*)", 3))
3869 dbp += 3;
3870 return;
3872 if (!ISDIGIT (*dbp))
3874 --dbp; /* force failure */
3875 return;
3878 dbp++;
3879 while (ISDIGIT (*dbp));
3882 static void
3883 F_getit (inf)
3884 FILE *inf;
3886 register char *cp;
3888 dbp = skip_spaces (dbp);
3889 if (*dbp == '\0')
3891 readline (&lb, inf);
3892 dbp = lb.buffer;
3893 if (dbp[5] != '&')
3894 return;
3895 dbp += 6;
3896 dbp = skip_spaces (dbp);
3898 if (!ISALPHA (*dbp) && *dbp != '_' && *dbp != '$')
3899 return;
3900 for (cp = dbp + 1; *cp != '\0' && intoken (*cp); cp++)
3901 continue;
3902 make_tag (dbp, cp-dbp, TRUE,
3903 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3907 static void
3908 Fortran_functions (inf)
3909 FILE *inf;
3911 LOOP_ON_INPUT_LINES (inf, lb, dbp)
3913 if (*dbp == '%')
3914 dbp++; /* Ratfor escape to fortran */
3915 dbp = skip_spaces (dbp);
3916 if (*dbp == '\0')
3917 continue;
3918 switch (lowcase (*dbp))
3920 case 'i':
3921 if (nocase_tail ("integer"))
3922 F_takeprec ();
3923 break;
3924 case 'r':
3925 if (nocase_tail ("real"))
3926 F_takeprec ();
3927 break;
3928 case 'l':
3929 if (nocase_tail ("logical"))
3930 F_takeprec ();
3931 break;
3932 case 'c':
3933 if (nocase_tail ("complex") || nocase_tail ("character"))
3934 F_takeprec ();
3935 break;
3936 case 'd':
3937 if (nocase_tail ("double"))
3939 dbp = skip_spaces (dbp);
3940 if (*dbp == '\0')
3941 continue;
3942 if (nocase_tail ("precision"))
3943 break;
3944 continue;
3946 break;
3948 dbp = skip_spaces (dbp);
3949 if (*dbp == '\0')
3950 continue;
3951 switch (lowcase (*dbp))
3953 case 'f':
3954 if (nocase_tail ("function"))
3955 F_getit (inf);
3956 continue;
3957 case 's':
3958 if (nocase_tail ("subroutine"))
3959 F_getit (inf);
3960 continue;
3961 case 'e':
3962 if (nocase_tail ("entry"))
3963 F_getit (inf);
3964 continue;
3965 case 'b':
3966 if (nocase_tail ("blockdata") || nocase_tail ("block data"))
3968 dbp = skip_spaces (dbp);
3969 if (*dbp == '\0') /* assume un-named */
3970 make_tag ("blockdata", 9, TRUE,
3971 lb.buffer, dbp - lb.buffer, lineno, linecharno);
3972 else
3973 F_getit (inf); /* look for name */
3975 continue;
3982 * Ada parsing
3983 * Original code by
3984 * Philippe Waroquiers <philippe.waroquiers@eurocontrol.be> (1998)
3987 static void Ada_getit __P((FILE *, char *));
3989 /* Once we are positioned after an "interesting" keyword, let's get
3990 the real tag value necessary. */
3991 static void
3992 Ada_getit (inf, name_qualifier)
3993 FILE *inf;
3994 char *name_qualifier;
3996 register char *cp;
3997 char *name;
3998 char c;
4000 while (!feof (inf))
4002 dbp = skip_spaces (dbp);
4003 if (*dbp == '\0'
4004 || (dbp[0] == '-' && dbp[1] == '-'))
4006 readline (&lb, inf);
4007 dbp = lb.buffer;
4009 switch (lowcase(*dbp))
4011 case 'b':
4012 if (nocase_tail ("body"))
4014 /* Skipping body of procedure body or package body or ....
4015 resetting qualifier to body instead of spec. */
4016 name_qualifier = "/b";
4017 continue;
4019 break;
4020 case 't':
4021 /* Skipping type of task type or protected type ... */
4022 if (nocase_tail ("type"))
4023 continue;
4024 break;
4026 if (*dbp == '"')
4028 dbp += 1;
4029 for (cp = dbp; *cp != '\0' && *cp != '"'; cp++)
4030 continue;
4032 else
4034 dbp = skip_spaces (dbp);
4035 for (cp = dbp;
4036 (*cp != '\0'
4037 && (ISALPHA (*cp) || ISDIGIT (*cp) || *cp == '_' || *cp == '.'));
4038 cp++)
4039 continue;
4040 if (cp == dbp)
4041 return;
4043 c = *cp;
4044 *cp = '\0';
4045 name = concat (dbp, name_qualifier, "");
4046 *cp = c;
4047 make_tag (name, strlen (name), TRUE,
4048 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4049 free (name);
4050 if (c == '"')
4051 dbp = cp + 1;
4052 return;
4056 static void
4057 Ada_funcs (inf)
4058 FILE *inf;
4060 bool inquote = FALSE;
4062 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4064 while (*dbp != '\0')
4066 /* Skip a string i.e. "abcd". */
4067 if (inquote || (*dbp == '"'))
4069 dbp = etags_strchr ((inquote) ? dbp : dbp+1, '"');
4070 if (dbp != NULL)
4072 inquote = FALSE;
4073 dbp += 1;
4074 continue; /* advance char */
4076 else
4078 inquote = TRUE;
4079 break; /* advance line */
4083 /* Skip comments. */
4084 if (dbp[0] == '-' && dbp[1] == '-')
4085 break; /* advance line */
4087 /* Skip character enclosed in single quote i.e. 'a'
4088 and skip single quote starting an attribute i.e. 'Image. */
4089 if (*dbp == '\'')
4091 dbp++ ;
4092 if (*dbp != '\0')
4093 dbp++;
4094 continue;
4097 /* Search for beginning of a token. */
4098 if (!begtoken (*dbp))
4100 dbp++;
4101 continue; /* advance char */
4104 /* We are at the beginning of a token. */
4105 switch (lowcase(*dbp))
4107 case 'f':
4108 if (!packages_only && nocase_tail ("function"))
4109 Ada_getit (inf, "/f");
4110 else
4111 break; /* from switch */
4112 continue; /* advance char */
4113 case 'p':
4114 if (!packages_only && nocase_tail ("procedure"))
4115 Ada_getit (inf, "/p");
4116 else if (nocase_tail ("package"))
4117 Ada_getit (inf, "/s");
4118 else if (nocase_tail ("protected")) /* protected type */
4119 Ada_getit (inf, "/t");
4120 else
4121 break; /* from switch */
4122 continue; /* advance char */
4123 case 't':
4124 if (!packages_only && nocase_tail ("task"))
4125 Ada_getit (inf, "/k");
4126 else if (typedefs && !packages_only && nocase_tail ("type"))
4128 Ada_getit (inf, "/t");
4129 while (*dbp != '\0')
4130 dbp += 1;
4132 else
4133 break; /* from switch */
4134 continue; /* advance char */
4137 /* Look for the end of the token. */
4138 while (!endtoken (*dbp))
4139 dbp++;
4141 } /* advance char */
4142 } /* advance line */
4147 * Unix and microcontroller assembly tag handling
4148 * Labels: /^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]/
4149 * Idea by Bob Weiner, Motorola Inc. (1994)
4151 static void
4152 Asm_labels (inf)
4153 FILE *inf;
4155 register char *cp;
4157 LOOP_ON_INPUT_LINES (inf, lb, cp)
4159 /* If first char is alphabetic or one of [_.$], test for colon
4160 following identifier. */
4161 if (ISALPHA (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
4163 /* Read past label. */
4164 cp++;
4165 while (ISALNUM (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
4166 cp++;
4167 if (*cp == ':' || iswhite (*cp))
4168 /* Found end of label, so copy it and add it to the table. */
4169 make_tag (lb.buffer, cp - lb.buffer, TRUE,
4170 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4177 * Perl support
4178 * Perl sub names: /^sub[ \t\n]+[^ \t\n{]+/
4179 * Perl variable names: /^(my|local).../
4180 * Original code by Bart Robinson <lomew@cs.utah.edu> (1995)
4181 * Additions by Michael Ernst <mernst@alum.mit.edu> (1997)
4182 * Ideas by Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE> (2001)
4184 static void
4185 Perl_functions (inf)
4186 FILE *inf;
4188 char *package = savestr ("main"); /* current package name */
4189 register char *cp;
4191 LOOP_ON_INPUT_LINES (inf, lb, cp)
4193 skip_spaces(cp);
4195 if (LOOKING_AT (cp, "package"))
4197 free (package);
4198 get_tag (cp, &package);
4200 else if (LOOKING_AT (cp, "sub"))
4202 char *pos;
4203 char *sp = cp;
4205 while (!notinname (*cp))
4206 cp++;
4207 if (cp == sp)
4208 continue; /* nothing found */
4209 if ((pos = etags_strchr (sp, ':')) != NULL
4210 && pos < cp && pos[1] == ':')
4211 /* The name is already qualified. */
4212 make_tag (sp, cp - sp, TRUE,
4213 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4214 else
4215 /* Qualify it. */
4217 char savechar, *name;
4219 savechar = *cp;
4220 *cp = '\0';
4221 name = concat (package, "::", sp);
4222 *cp = savechar;
4223 make_tag (name, strlen(name), TRUE,
4224 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4225 free (name);
4228 else if (globals) /* only if we are tagging global vars */
4230 /* Skip a qualifier, if any. */
4231 bool qual = LOOKING_AT (cp, "my") || LOOKING_AT (cp, "local");
4232 /* After "my" or "local", but before any following paren or space. */
4233 char *varstart = cp;
4235 if (qual /* should this be removed? If yes, how? */
4236 && (*cp == '$' || *cp == '@' || *cp == '%'))
4238 varstart += 1;
4240 cp++;
4241 while (ISALNUM (*cp) || *cp == '_');
4243 else if (qual)
4245 /* Should be examining a variable list at this point;
4246 could insist on seeing an open parenthesis. */
4247 while (*cp != '\0' && *cp != ';' && *cp != '=' && *cp != ')')
4248 cp++;
4250 else
4251 continue;
4253 make_tag (varstart, cp - varstart, FALSE,
4254 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4261 * Python support
4262 * Look for /^[\t]*def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
4263 * Idea by Eric S. Raymond <esr@thyrsus.com> (1997)
4264 * More ideas by seb bacon <seb@jamkit.com> (2002)
4266 static void
4267 Python_functions (inf)
4268 FILE *inf;
4270 register char *cp;
4272 LOOP_ON_INPUT_LINES (inf, lb, cp)
4274 cp = skip_spaces (cp);
4275 if (LOOKING_AT (cp, "def") || LOOKING_AT (cp, "class"))
4277 char *name = cp;
4278 while (!notinname (*cp) && *cp != ':')
4279 cp++;
4280 make_tag (name, cp - name, TRUE,
4281 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4288 * PHP support
4289 * Look for:
4290 * - /^[ \t]*function[ \t\n]+[^ \t\n(]+/
4291 * - /^[ \t]*class[ \t\n]+[^ \t\n]+/
4292 * - /^[ \t]*define\(\"[^\"]+/
4293 * Only with --members:
4294 * - /^[ \t]*var[ \t\n]+\$[^ \t\n=;]/
4295 * Idea by Diez B. Roggisch (2001)
4297 static void
4298 PHP_functions (inf)
4299 FILE *inf;
4301 register char *cp, *name;
4302 bool search_identifier = FALSE;
4304 LOOP_ON_INPUT_LINES (inf, lb, cp)
4306 cp = skip_spaces (cp);
4307 name = cp;
4308 if (search_identifier
4309 && *cp != '\0')
4311 while (!notinname (*cp))
4312 cp++;
4313 make_tag (name, cp - name, TRUE,
4314 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4315 search_identifier = FALSE;
4317 else if (LOOKING_AT (cp, "function"))
4319 if(*cp == '&')
4320 cp = skip_spaces (cp+1);
4321 if(*cp != '\0')
4323 name = cp;
4324 while (!notinname (*cp))
4325 cp++;
4326 make_tag (name, cp - name, TRUE,
4327 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4329 else
4330 search_identifier = TRUE;
4332 else if (LOOKING_AT (cp, "class"))
4334 if (*cp != '\0')
4336 name = cp;
4337 while (*cp != '\0' && !iswhite (*cp))
4338 cp++;
4339 make_tag (name, cp - name, FALSE,
4340 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4342 else
4343 search_identifier = TRUE;
4345 else if (strneq (cp, "define", 6)
4346 && (cp = skip_spaces (cp+6))
4347 && *cp++ == '('
4348 && (*cp == '"' || *cp == '\''))
4350 char quote = *cp++;
4351 name = cp;
4352 while (*cp != quote && *cp != '\0')
4353 cp++;
4354 make_tag (name, cp - name, FALSE,
4355 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4357 else if (members
4358 && LOOKING_AT (cp, "var")
4359 && *cp == '$')
4361 name = cp;
4362 while (!notinname(*cp))
4363 cp++;
4364 make_tag (name, cp - name, FALSE,
4365 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4372 * Cobol tag functions
4373 * We could look for anything that could be a paragraph name.
4374 * i.e. anything that starts in column 8 is one word and ends in a full stop.
4375 * Idea by Corny de Souza (1993)
4377 static void
4378 Cobol_paragraphs (inf)
4379 FILE *inf;
4381 register char *bp, *ep;
4383 LOOP_ON_INPUT_LINES (inf, lb, bp)
4385 if (lb.len < 9)
4386 continue;
4387 bp += 8;
4389 /* If eoln, compiler option or comment ignore whole line. */
4390 if (bp[-1] != ' ' || !ISALNUM (bp[0]))
4391 continue;
4393 for (ep = bp; ISALNUM (*ep) || *ep == '-'; ep++)
4394 continue;
4395 if (*ep++ == '.')
4396 make_tag (bp, ep - bp, TRUE,
4397 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
4403 * Makefile support
4404 * Ideas by Assar Westerlund <assar@sics.se> (2001)
4406 static void
4407 Makefile_targets (inf)
4408 FILE *inf;
4410 register char *bp;
4412 LOOP_ON_INPUT_LINES (inf, lb, bp)
4414 if (*bp == '\t' || *bp == '#')
4415 continue;
4416 while (*bp != '\0' && *bp != '=' && *bp != ':')
4417 bp++;
4418 if (*bp == ':' || (globals && *bp == '='))
4419 make_tag (lb.buffer, bp - lb.buffer, TRUE,
4420 lb.buffer, bp - lb.buffer + 1, lineno, linecharno);
4426 * Pascal parsing
4427 * Original code by Mosur K. Mohan (1989)
4429 * Locates tags for procedures & functions. Doesn't do any type- or
4430 * var-definitions. It does look for the keyword "extern" or
4431 * "forward" immediately following the procedure statement; if found,
4432 * the tag is skipped.
4434 static void
4435 Pascal_functions (inf)
4436 FILE *inf;
4438 linebuffer tline; /* mostly copied from C_entries */
4439 long save_lcno;
4440 int save_lineno, namelen, taglen;
4441 char c, *name;
4443 bool /* each of these flags is TRUE iff: */
4444 incomment, /* point is inside a comment */
4445 inquote, /* point is inside '..' string */
4446 get_tagname, /* point is after PROCEDURE/FUNCTION
4447 keyword, so next item = potential tag */
4448 found_tag, /* point is after a potential tag */
4449 inparms, /* point is within parameter-list */
4450 verify_tag; /* point has passed the parm-list, so the
4451 next token will determine whether this
4452 is a FORWARD/EXTERN to be ignored, or
4453 whether it is a real tag */
4455 save_lcno = save_lineno = namelen = taglen = 0; /* keep compiler quiet */
4456 name = NULL; /* keep compiler quiet */
4457 dbp = lb.buffer;
4458 *dbp = '\0';
4459 initbuffer (&tline);
4461 incomment = inquote = FALSE;
4462 found_tag = FALSE; /* have a proc name; check if extern */
4463 get_tagname = FALSE; /* found "procedure" keyword */
4464 inparms = FALSE; /* found '(' after "proc" */
4465 verify_tag = FALSE; /* check if "extern" is ahead */
4468 while (!feof (inf)) /* long main loop to get next char */
4470 c = *dbp++;
4471 if (c == '\0') /* if end of line */
4473 readline (&lb, inf);
4474 dbp = lb.buffer;
4475 if (*dbp == '\0')
4476 continue;
4477 if (!((found_tag && verify_tag)
4478 || get_tagname))
4479 c = *dbp++; /* only if don't need *dbp pointing
4480 to the beginning of the name of
4481 the procedure or function */
4483 if (incomment)
4485 if (c == '}') /* within { } comments */
4486 incomment = FALSE;
4487 else if (c == '*' && *dbp == ')') /* within (* *) comments */
4489 dbp++;
4490 incomment = FALSE;
4492 continue;
4494 else if (inquote)
4496 if (c == '\'')
4497 inquote = FALSE;
4498 continue;
4500 else
4501 switch (c)
4503 case '\'':
4504 inquote = TRUE; /* found first quote */
4505 continue;
4506 case '{': /* found open { comment */
4507 incomment = TRUE;
4508 continue;
4509 case '(':
4510 if (*dbp == '*') /* found open (* comment */
4512 incomment = TRUE;
4513 dbp++;
4515 else if (found_tag) /* found '(' after tag, i.e., parm-list */
4516 inparms = TRUE;
4517 continue;
4518 case ')': /* end of parms list */
4519 if (inparms)
4520 inparms = FALSE;
4521 continue;
4522 case ';':
4523 if (found_tag && !inparms) /* end of proc or fn stmt */
4525 verify_tag = TRUE;
4526 break;
4528 continue;
4530 if (found_tag && verify_tag && (*dbp != ' '))
4532 /* Check if this is an "extern" declaration. */
4533 if (*dbp == '\0')
4534 continue;
4535 if (lowcase (*dbp == 'e'))
4537 if (nocase_tail ("extern")) /* superfluous, really! */
4539 found_tag = FALSE;
4540 verify_tag = FALSE;
4543 else if (lowcase (*dbp) == 'f')
4545 if (nocase_tail ("forward")) /* check for forward reference */
4547 found_tag = FALSE;
4548 verify_tag = FALSE;
4551 if (found_tag && verify_tag) /* not external proc, so make tag */
4553 found_tag = FALSE;
4554 verify_tag = FALSE;
4555 make_tag (name, namelen, TRUE,
4556 tline.buffer, taglen, save_lineno, save_lcno);
4557 continue;
4560 if (get_tagname) /* grab name of proc or fn */
4562 char *cp;
4564 if (*dbp == '\0')
4565 continue;
4567 /* Find block name. */
4568 for (cp = dbp + 1; *cp != '\0' && !endtoken (*cp); cp++)
4569 continue;
4571 /* Save all values for later tagging. */
4572 linebuffer_setlen (&tline, lb.len);
4573 strcpy (tline.buffer, lb.buffer);
4574 save_lineno = lineno;
4575 save_lcno = linecharno;
4576 name = tline.buffer + (dbp - lb.buffer);
4577 namelen = cp - dbp;
4578 taglen = cp - lb.buffer + 1;
4580 dbp = cp; /* set dbp to e-o-token */
4581 get_tagname = FALSE;
4582 found_tag = TRUE;
4583 continue;
4585 /* And proceed to check for "extern". */
4587 else if (!incomment && !inquote && !found_tag)
4589 /* Check for proc/fn keywords. */
4590 switch (lowcase (c))
4592 case 'p':
4593 if (nocase_tail ("rocedure")) /* c = 'p', dbp has advanced */
4594 get_tagname = TRUE;
4595 continue;
4596 case 'f':
4597 if (nocase_tail ("unction"))
4598 get_tagname = TRUE;
4599 continue;
4602 } /* while not eof */
4604 free (tline.buffer);
4609 * Lisp tag functions
4610 * look for (def or (DEF, quote or QUOTE
4613 static void L_getit __P((void));
4615 static void
4616 L_getit ()
4618 if (*dbp == '\'') /* Skip prefix quote */
4619 dbp++;
4620 else if (*dbp == '(')
4622 dbp++;
4623 /* Try to skip "(quote " */
4624 if (!LOOKING_AT (dbp, "quote") && !LOOKING_AT (dbp, "QUOTE"))
4625 /* Ok, then skip "(" before name in (defstruct (foo)) */
4626 dbp = skip_spaces (dbp);
4628 get_tag (dbp, NULL);
4631 static void
4632 Lisp_functions (inf)
4633 FILE *inf;
4635 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4637 if (dbp[0] != '(')
4638 continue;
4640 if (strneq (dbp+1, "def", 3) || strneq (dbp+1, "DEF", 3))
4642 dbp = skip_non_spaces (dbp);
4643 dbp = skip_spaces (dbp);
4644 L_getit ();
4646 else
4648 /* Check for (foo::defmumble name-defined ... */
4650 dbp++;
4651 while (!notinname (*dbp) && *dbp != ':');
4652 if (*dbp == ':')
4655 dbp++;
4656 while (*dbp == ':');
4658 if (strneq (dbp, "def", 3) || strneq (dbp, "DEF", 3))
4660 dbp = skip_non_spaces (dbp);
4661 dbp = skip_spaces (dbp);
4662 L_getit ();
4671 * Postscript tag functions
4672 * Just look for lines where the first character is '/'
4673 * Also look at "defineps" for PSWrap
4674 * Ideas by:
4675 * Richard Mlynarik <mly@adoc.xerox.com> (1997)
4676 * Masatake Yamato <masata-y@is.aist-nara.ac.jp> (1999)
4678 static void
4679 Postscript_functions (inf)
4680 FILE *inf;
4682 register char *bp, *ep;
4684 LOOP_ON_INPUT_LINES (inf, lb, bp)
4686 if (bp[0] == '/')
4688 for (ep = bp+1;
4689 *ep != '\0' && *ep != ' ' && *ep != '{';
4690 ep++)
4691 continue;
4692 make_tag (bp, ep - bp, TRUE,
4693 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
4695 else if (LOOKING_AT (bp, "defineps"))
4696 get_tag (bp, NULL);
4702 * Scheme tag functions
4703 * look for (def... xyzzy
4704 * (def... (xyzzy
4705 * (def ... ((...(xyzzy ....
4706 * (set! xyzzy
4707 * Original code by Ken Haase (1985?)
4710 static void
4711 Scheme_functions (inf)
4712 FILE *inf;
4714 register char *bp;
4716 LOOP_ON_INPUT_LINES (inf, lb, bp)
4718 if (strneq (bp, "(def", 4) || strneq (bp, "(DEF", 4))
4720 bp = skip_non_spaces (bp+4);
4721 /* Skip over open parens and white space */
4722 while (notinname (*bp))
4723 bp++;
4724 get_tag (bp, NULL);
4726 if (LOOKING_AT (bp, "(SET!") || LOOKING_AT (bp, "(set!"))
4727 get_tag (bp, NULL);
4732 /* Find tags in TeX and LaTeX input files. */
4734 /* TEX_toktab is a table of TeX control sequences that define tags.
4735 * Each entry records one such control sequence.
4737 * Original code from who knows whom.
4738 * Ideas by:
4739 * Stefan Monnier (2002)
4742 static linebuffer *TEX_toktab = NULL; /* Table with tag tokens */
4744 /* Default set of control sequences to put into TEX_toktab.
4745 The value of environment var TEXTAGS is prepended to this. */
4746 static char *TEX_defenv = "\
4747 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4748 :part:appendix:entry:index:def\
4749 :newcommand:renewcommand:newenvironment:renewenvironment";
4751 static void TEX_mode __P((FILE *));
4752 static void TEX_decode_env __P((char *, char *));
4754 static char TEX_esc = '\\';
4755 static char TEX_opgrp = '{';
4756 static char TEX_clgrp = '}';
4759 * TeX/LaTeX scanning loop.
4761 static void
4762 TeX_commands (inf)
4763 FILE *inf;
4765 char *cp;
4766 linebuffer *key;
4768 /* Select either \ or ! as escape character. */
4769 TEX_mode (inf);
4771 /* Initialize token table once from environment. */
4772 if (TEX_toktab == NULL)
4773 TEX_decode_env ("TEXTAGS", TEX_defenv);
4775 LOOP_ON_INPUT_LINES (inf, lb, cp)
4777 /* Look at each TEX keyword in line. */
4778 for (;;)
4780 /* Look for a TEX escape. */
4781 while (*cp++ != TEX_esc)
4782 if (cp[-1] == '\0' || cp[-1] == '%')
4783 goto tex_next_line;
4785 for (key = TEX_toktab; key->buffer != NULL; key++)
4786 if (strneq (cp, key->buffer, key->len))
4788 register char *p;
4789 int namelen, linelen;
4790 bool opgrp = FALSE;
4792 cp = skip_spaces (cp + key->len);
4793 if (*cp == TEX_opgrp)
4795 opgrp = TRUE;
4796 cp++;
4798 for (p = cp;
4799 (!iswhite (*p) && *p != '#' &&
4800 *p != TEX_opgrp && *p != TEX_clgrp);
4801 p++)
4802 continue;
4803 namelen = p - cp;
4804 linelen = lb.len;
4805 if (!opgrp || *p == TEX_clgrp)
4807 while (*p != '\0' && *p != TEX_opgrp && *p != TEX_clgrp)
4808 *p++;
4809 linelen = p - lb.buffer + 1;
4811 make_tag (cp, namelen, TRUE,
4812 lb.buffer, linelen, lineno, linecharno);
4813 goto tex_next_line; /* We only tag a line once */
4816 tex_next_line:
4821 #define TEX_LESC '\\'
4822 #define TEX_SESC '!'
4824 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4825 chars accordingly. */
4826 static void
4827 TEX_mode (inf)
4828 FILE *inf;
4830 int c;
4832 while ((c = getc (inf)) != EOF)
4834 /* Skip to next line if we hit the TeX comment char. */
4835 if (c == '%')
4836 while (c != '\n')
4837 c = getc (inf);
4838 else if (c == TEX_LESC || c == TEX_SESC )
4839 break;
4842 if (c == TEX_LESC)
4844 TEX_esc = TEX_LESC;
4845 TEX_opgrp = '{';
4846 TEX_clgrp = '}';
4848 else
4850 TEX_esc = TEX_SESC;
4851 TEX_opgrp = '<';
4852 TEX_clgrp = '>';
4854 /* If the input file is compressed, inf is a pipe, and rewind may fail.
4855 No attempt is made to correct the situation. */
4856 rewind (inf);
4859 /* Read environment and prepend it to the default string.
4860 Build token table. */
4861 static void
4862 TEX_decode_env (evarname, defenv)
4863 char *evarname;
4864 char *defenv;
4866 register char *env, *p;
4867 int i, len;
4869 /* Append default string to environment. */
4870 env = getenv (evarname);
4871 if (!env)
4872 env = defenv;
4873 else
4875 char *oldenv = env;
4876 env = concat (oldenv, defenv, "");
4879 /* Allocate a token table */
4880 for (len = 1, p = env; p;)
4881 if ((p = etags_strchr (p, ':')) && *++p != '\0')
4882 len++;
4883 TEX_toktab = xnew (len, linebuffer);
4885 /* Unpack environment string into token table. Be careful about */
4886 /* zero-length strings (leading ':', "::" and trailing ':') */
4887 for (i = 0; *env != '\0';)
4889 p = etags_strchr (env, ':');
4890 if (!p) /* End of environment string. */
4891 p = env + strlen (env);
4892 if (p - env > 0)
4893 { /* Only non-zero strings. */
4894 TEX_toktab[i].buffer = savenstr (env, p - env);
4895 TEX_toktab[i].len = p - env;
4896 i++;
4898 if (*p)
4899 env = p + 1;
4900 else
4902 TEX_toktab[i].buffer = NULL; /* Mark end of table. */
4903 TEX_toktab[i].len = 0;
4904 break;
4910 /* Texinfo support. Dave Love, Mar. 2000. */
4911 static void
4912 Texinfo_nodes (inf)
4913 FILE * inf;
4915 char *cp, *start;
4916 LOOP_ON_INPUT_LINES (inf, lb, cp)
4917 if (LOOKING_AT (cp, "@node"))
4919 start = cp;
4920 while (*cp != '\0' && *cp != ',')
4921 cp++;
4922 make_tag (start, cp - start, TRUE,
4923 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4929 * Prolog support
4931 * Assumes that the predicate or rule starts at column 0.
4932 * Only the first clause of a predicate or rule is added.
4933 * Original code by Sunichirou Sugou (1989)
4934 * Rewritten by Anders Lindgren (1996)
4936 static int prolog_pr __P((char *, char *));
4937 static void prolog_skip_comment __P((linebuffer *, FILE *));
4938 static int prolog_atom __P((char *, int));
4940 static void
4941 Prolog_functions (inf)
4942 FILE *inf;
4944 char *cp, *last;
4945 int len;
4946 int allocated;
4948 allocated = 0;
4949 len = 0;
4950 last = NULL;
4952 LOOP_ON_INPUT_LINES (inf, lb, cp)
4954 if (cp[0] == '\0') /* Empty line */
4955 continue;
4956 else if (iswhite (cp[0])) /* Not a predicate */
4957 continue;
4958 else if (cp[0] == '/' && cp[1] == '*') /* comment. */
4959 prolog_skip_comment (&lb, inf);
4960 else if ((len = prolog_pr (cp, last)) > 0)
4962 /* Predicate or rule. Store the function name so that we
4963 only generate a tag for the first clause. */
4964 if (last == NULL)
4965 last = xnew(len + 1, char);
4966 else if (len + 1 > allocated)
4967 xrnew (last, len + 1, char);
4968 allocated = len + 1;
4969 strncpy (last, cp, len);
4970 last[len] = '\0';
4976 static void
4977 prolog_skip_comment (plb, inf)
4978 linebuffer *plb;
4979 FILE *inf;
4981 char *cp;
4985 for (cp = plb->buffer; *cp != '\0'; cp++)
4986 if (cp[0] == '*' && cp[1] == '/')
4987 return;
4988 readline (plb, inf);
4990 while (!feof(inf));
4994 * A predicate or rule definition is added if it matches:
4995 * <beginning of line><Prolog Atom><whitespace>(
4996 * or <beginning of line><Prolog Atom><whitespace>:-
4998 * It is added to the tags database if it doesn't match the
4999 * name of the previous clause header.
5001 * Return the size of the name of the predicate or rule, or 0 if no
5002 * header was found.
5004 static int
5005 prolog_pr (s, last)
5006 char *s;
5007 char *last; /* Name of last clause. */
5009 int pos;
5010 int len;
5012 pos = prolog_atom (s, 0);
5013 if (pos < 1)
5014 return 0;
5016 len = pos;
5017 pos = skip_spaces (s + pos) - s;
5019 if ((s[pos] == '.'
5020 || (s[pos] == '(' && (pos += 1))
5021 || (s[pos] == ':' && s[pos + 1] == '-' && (pos += 2)))
5022 && (last == NULL /* save only the first clause */
5023 || len != strlen (last)
5024 || !strneq (s, last, len)))
5026 make_tag (s, len, TRUE, s, pos, lineno, linecharno);
5027 return len;
5029 else
5030 return 0;
5034 * Consume a Prolog atom.
5035 * Return the number of bytes consumed, or -1 if there was an error.
5037 * A prolog atom, in this context, could be one of:
5038 * - An alphanumeric sequence, starting with a lower case letter.
5039 * - A quoted arbitrary string. Single quotes can escape themselves.
5040 * Backslash quotes everything.
5042 static int
5043 prolog_atom (s, pos)
5044 char *s;
5045 int pos;
5047 int origpos;
5049 origpos = pos;
5051 if (ISLOWER(s[pos]) || (s[pos] == '_'))
5053 /* The atom is unquoted. */
5054 pos++;
5055 while (ISALNUM(s[pos]) || (s[pos] == '_'))
5057 pos++;
5059 return pos - origpos;
5061 else if (s[pos] == '\'')
5063 pos++;
5065 for (;;)
5067 if (s[pos] == '\'')
5069 pos++;
5070 if (s[pos] != '\'')
5071 break;
5072 pos++; /* A double quote */
5074 else if (s[pos] == '\0')
5075 /* Multiline quoted atoms are ignored. */
5076 return -1;
5077 else if (s[pos] == '\\')
5079 if (s[pos+1] == '\0')
5080 return -1;
5081 pos += 2;
5083 else
5084 pos++;
5086 return pos - origpos;
5088 else
5089 return -1;
5094 * Support for Erlang
5096 * Generates tags for functions, defines, and records.
5097 * Assumes that Erlang functions start at column 0.
5098 * Original code by Anders Lindgren (1996)
5100 static int erlang_func __P((char *, char *));
5101 static void erlang_attribute __P((char *));
5102 static int erlang_atom __P((char *));
5104 static void
5105 Erlang_functions (inf)
5106 FILE *inf;
5108 char *cp, *last;
5109 int len;
5110 int allocated;
5112 allocated = 0;
5113 len = 0;
5114 last = NULL;
5116 LOOP_ON_INPUT_LINES (inf, lb, cp)
5118 if (cp[0] == '\0') /* Empty line */
5119 continue;
5120 else if (iswhite (cp[0])) /* Not function nor attribute */
5121 continue;
5122 else if (cp[0] == '%') /* comment */
5123 continue;
5124 else if (cp[0] == '"') /* Sometimes, strings start in column one */
5125 continue;
5126 else if (cp[0] == '-') /* attribute, e.g. "-define" */
5128 erlang_attribute (cp);
5129 last = NULL;
5131 else if ((len = erlang_func (cp, last)) > 0)
5134 * Function. Store the function name so that we only
5135 * generates a tag for the first clause.
5137 if (last == NULL)
5138 last = xnew (len + 1, char);
5139 else if (len + 1 > allocated)
5140 xrnew (last, len + 1, char);
5141 allocated = len + 1;
5142 strncpy (last, cp, len);
5143 last[len] = '\0';
5150 * A function definition is added if it matches:
5151 * <beginning of line><Erlang Atom><whitespace>(
5153 * It is added to the tags database if it doesn't match the
5154 * name of the previous clause header.
5156 * Return the size of the name of the function, or 0 if no function
5157 * was found.
5159 static int
5160 erlang_func (s, last)
5161 char *s;
5162 char *last; /* Name of last clause. */
5164 int pos;
5165 int len;
5167 pos = erlang_atom (s);
5168 if (pos < 1)
5169 return 0;
5171 len = pos;
5172 pos = skip_spaces (s + pos) - s;
5174 /* Save only the first clause. */
5175 if (s[pos++] == '('
5176 && (last == NULL
5177 || len != (int)strlen (last)
5178 || !strneq (s, last, len)))
5180 make_tag (s, len, TRUE, s, pos, lineno, linecharno);
5181 return len;
5184 return 0;
5189 * Handle attributes. Currently, tags are generated for defines
5190 * and records.
5192 * They are on the form:
5193 * -define(foo, bar).
5194 * -define(Foo(M, N), M+N).
5195 * -record(graph, {vtab = notable, cyclic = true}).
5197 static void
5198 erlang_attribute (s)
5199 char *s;
5201 char *cp = s;
5203 if ((LOOKING_AT (cp, "-define") || LOOKING_AT (cp, "-record"))
5204 && *cp++ == '(')
5206 int len = erlang_atom (skip_spaces (cp));
5207 if (len > 0)
5208 make_tag (cp, len, TRUE, s, cp + len - s, lineno, linecharno);
5210 return;
5215 * Consume an Erlang atom (or variable).
5216 * Return the number of bytes consumed, or -1 if there was an error.
5218 static int
5219 erlang_atom (s)
5220 char *s;
5222 int pos = 0;
5224 if (ISALPHA (s[pos]) || s[pos] == '_')
5226 /* The atom is unquoted. */
5228 pos++;
5229 while (ISALNUM (s[pos]) || s[pos] == '_');
5231 else if (s[pos] == '\'')
5233 for (pos++; s[pos] != '\''; pos++)
5234 if (s[pos] == '\0' /* multiline quoted atoms are ignored */
5235 || (s[pos] == '\\' && s[++pos] == '\0'))
5236 return 0;
5237 pos++;
5240 return pos;
5244 #ifdef ETAGS_REGEXPS
5246 static char *scan_separators __P((char *));
5247 static void add_regex __P((char *, language *));
5248 static char *substitute __P((char *, char *, struct re_registers *));
5251 * Take a string like "/blah/" and turn it into "blah", verifying
5252 * that the first and last characters are the same, and handling
5253 * quoted separator characters. Actually, stops on the occurrence of
5254 * an unquoted separator. Also process \t, \n, etc. and turn into
5255 * appropriate characters. Works in place. Null terminates name string.
5256 * Returns pointer to terminating separator, or NULL for
5257 * unterminated regexps.
5259 static char *
5260 scan_separators (name)
5261 char *name;
5263 char sep = name[0];
5264 char *copyto = name;
5265 bool quoted = FALSE;
5267 for (++name; *name != '\0'; ++name)
5269 if (quoted)
5271 switch (*name)
5273 case 'a': *copyto++ = '\007'; break; /* BEL (bell) */
5274 case 'b': *copyto++ = '\b'; break; /* BS (back space) */
5275 case 'd': *copyto++ = 0177; break; /* DEL (delete) */
5276 case 'e': *copyto++ = 033; break; /* ESC (delete) */
5277 case 'f': *copyto++ = '\f'; break; /* FF (form feed) */
5278 case 'n': *copyto++ = '\n'; break; /* NL (new line) */
5279 case 'r': *copyto++ = '\r'; break; /* CR (carriage return) */
5280 case 't': *copyto++ = '\t'; break; /* TAB (horizontal tab) */
5281 case 'v': *copyto++ = '\v'; break; /* VT (vertical tab) */
5282 default:
5283 if (*name == sep)
5284 *copyto++ = sep;
5285 else
5287 /* Something else is quoted, so preserve the quote. */
5288 *copyto++ = '\\';
5289 *copyto++ = *name;
5291 break;
5293 quoted = FALSE;
5295 else if (*name == '\\')
5296 quoted = TRUE;
5297 else if (*name == sep)
5298 break;
5299 else
5300 *copyto++ = *name;
5302 if (*name != sep)
5303 name = NULL; /* signal unterminated regexp */
5305 /* Terminate copied string. */
5306 *copyto = '\0';
5307 return name;
5310 /* Look at the argument of --regex or --no-regex and do the right
5311 thing. Same for each line of a regexp file. */
5312 static void
5313 analyse_regex (regex_arg)
5314 char *regex_arg;
5316 if (regex_arg == NULL)
5318 free_patterns (); /* --no-regex: remove existing regexps */
5319 return;
5322 /* A real --regexp option or a line in a regexp file. */
5323 switch (regex_arg[0])
5325 /* Comments in regexp file or null arg to --regex. */
5326 case '\0':
5327 case ' ':
5328 case '\t':
5329 break;
5331 /* Read a regex file. This is recursive and may result in a
5332 loop, which will stop when the file descriptors are exhausted. */
5333 case '@':
5335 FILE *regexfp;
5336 linebuffer regexbuf;
5337 char *regexfile = regex_arg + 1;
5339 /* regexfile is a file containing regexps, one per line. */
5340 regexfp = fopen (regexfile, "r");
5341 if (regexfp == NULL)
5343 pfatal (regexfile);
5344 return;
5346 initbuffer (&regexbuf);
5347 while (readline_internal (&regexbuf, regexfp) > 0)
5348 analyse_regex (regexbuf.buffer);
5349 free (regexbuf.buffer);
5350 fclose (regexfp);
5352 break;
5354 /* Regexp to be used for a specific language only. */
5355 case '{':
5357 language *lang;
5358 char *lang_name = regex_arg + 1;
5359 char *cp;
5361 for (cp = lang_name; *cp != '}'; cp++)
5362 if (*cp == '\0')
5364 error ("unterminated language name in regex: %s", regex_arg);
5365 return;
5367 *cp++ = '\0';
5368 lang = get_language_from_langname (lang_name);
5369 if (lang == NULL)
5370 return;
5371 add_regex (cp, lang);
5373 break;
5375 /* Regexp to be used for any language. */
5376 default:
5377 add_regex (regex_arg, NULL);
5378 break;
5382 /* Turn a name, which is an ed-style (but Emacs syntax) regular
5383 expression, into a real regular expression by compiling it. */
5384 static void
5385 add_regex (regexp_pattern, lang)
5386 char *regexp_pattern;
5387 language *lang;
5389 static struct re_pattern_buffer zeropattern;
5390 char sep, *pat, *name, *modifiers;
5391 const char *err;
5392 struct re_pattern_buffer *patbuf;
5393 pattern *pp;
5394 bool ignore_case, multi_line, single_line;
5397 if (strlen(regexp_pattern) < 3)
5399 error ("null regexp", (char *)NULL);
5400 return;
5402 sep = regexp_pattern[0];
5403 name = scan_separators (regexp_pattern);
5404 if (name == NULL)
5406 error ("%s: unterminated regexp", regexp_pattern);
5407 return;
5409 if (name[1] == sep)
5411 error ("null name for regexp \"%s\"", regexp_pattern);
5412 return;
5414 modifiers = scan_separators (name);
5415 if (modifiers == NULL) /* no terminating separator --> no name */
5417 modifiers = name;
5418 name = "";
5420 else
5421 modifiers += 1; /* skip separator */
5423 /* Parse regex modifiers. */
5424 ignore_case = FALSE; /* case is significant */
5425 multi_line = FALSE; /* matches are done one line at a time */
5426 single_line = FALSE; /* dot does not match newline */
5427 for (; modifiers[0] != '\0'; modifiers++)
5428 switch (modifiers[0])
5430 case 'i':
5431 ignore_case = TRUE;
5432 break;
5433 case 's':
5434 single_line = TRUE;
5435 /* FALLTHRU */
5436 case 'm':
5437 multi_line = TRUE;
5438 need_filebuf = TRUE;
5439 break;
5440 default:
5442 char wrongmod [2];
5443 wrongmod[0] = modifiers[0];
5444 wrongmod[1] = '\0';
5445 error ("invalid regexp modifier `%s', ignoring", wrongmod);
5447 break;
5450 patbuf = xnew (1, struct re_pattern_buffer);
5451 *patbuf = zeropattern;
5452 if (ignore_case)
5454 static char lc_trans[CHARS];
5455 int i;
5456 for (i = 0; i < CHARS; i++)
5457 lc_trans[i] = lowcase (i);
5458 patbuf->translate = lc_trans; /* translation table to fold case */
5461 if (multi_line)
5462 pat = concat ("^", regexp_pattern, ""); /* anchor to beginning of line */
5463 else
5464 pat = regexp_pattern;
5466 if (single_line)
5467 re_set_syntax (RE_SYNTAX_EMACS | RE_DOT_NEWLINE);
5468 else
5469 re_set_syntax (RE_SYNTAX_EMACS);
5471 err = re_compile_pattern (pat, strlen (regexp_pattern), patbuf);
5472 if (multi_line)
5473 free (pat);
5474 if (err != NULL)
5476 error ("%s while compiling pattern", err);
5477 return;
5480 pp = p_head;
5481 p_head = xnew (1, pattern);
5482 p_head->regex = savestr (regexp_pattern);
5483 p_head->p_next = pp;
5484 p_head->lang = lang;
5485 p_head->pat = patbuf;
5486 p_head->name_pattern = savestr (name);
5487 p_head->error_signaled = FALSE;
5488 p_head->ignore_case = ignore_case;
5489 p_head->multi_line = multi_line;
5493 * Do the substitutions indicated by the regular expression and
5494 * arguments.
5496 static char *
5497 substitute (in, out, regs)
5498 char *in, *out;
5499 struct re_registers *regs;
5501 char *result, *t;
5502 int size, dig, diglen;
5504 result = NULL;
5505 size = strlen (out);
5507 /* Pass 1: figure out how much to allocate by finding all \N strings. */
5508 if (out[size - 1] == '\\')
5509 fatal ("pattern error in \"%s\"", out);
5510 for (t = etags_strchr (out, '\\');
5511 t != NULL;
5512 t = etags_strchr (t + 2, '\\'))
5513 if (ISDIGIT (t[1]))
5515 dig = t[1] - '0';
5516 diglen = regs->end[dig] - regs->start[dig];
5517 size += diglen - 2;
5519 else
5520 size -= 1;
5522 /* Allocate space and do the substitutions. */
5523 result = xnew (size + 1, char);
5525 for (t = result; *out != '\0'; out++)
5526 if (*out == '\\' && ISDIGIT (*++out))
5528 dig = *out - '0';
5529 diglen = regs->end[dig] - regs->start[dig];
5530 strncpy (t, in + regs->start[dig], diglen);
5531 t += diglen;
5533 else
5534 *t++ = *out;
5535 *t = '\0';
5537 assert (t <= result + size && t - result == (int)strlen (result));
5539 return result;
5542 /* Deallocate all patterns. */
5543 static void
5544 free_patterns ()
5546 pattern *pp;
5547 while (p_head != NULL)
5549 pp = p_head->p_next;
5550 free (p_head->regex);
5551 free (p_head->name_pattern);
5552 free (p_head);
5553 p_head = pp;
5555 return;
5559 * Reads the whole file as a single string from `filebuf' and looks for
5560 * multi-line regular expressions, creating tags on matches.
5561 * readline already dealt with normal regexps.
5563 * Idea by Ben Wing <ben@666.com> (2002).
5565 static void
5566 regex_tag_multiline ()
5568 char *buffer = filebuf.buffer;
5569 pattern *pp;
5571 for (pp = p_head; pp != NULL; pp = pp->p_next)
5573 int match = 0;
5575 if (!pp->multi_line)
5576 continue; /* skip normal regexps */
5578 /* Generic initialisations before parsing file from memory. */
5579 lineno = 1; /* reset global line number */
5580 charno = 0; /* reset global char number */
5581 linecharno = 0; /* reset global char number of line start */
5583 /* Only use generic regexps or those for the current language. */
5584 if (pp->lang != NULL && pp->lang != curfdp->lang)
5585 continue;
5587 while (match >= 0 && match < filebuf.len)
5589 match = re_search (pp->pat, buffer, filebuf.len, charno,
5590 filebuf.len - match, &pp->regs);
5591 switch (match)
5593 case -2:
5594 /* Some error. */
5595 if (!pp->error_signaled)
5597 error ("regexp stack overflow while matching \"%s\"",
5598 pp->regex);
5599 pp->error_signaled = TRUE;
5601 break;
5602 case -1:
5603 /* No match. */
5604 break;
5605 default:
5606 if (match == pp->regs.end[0])
5608 if (!pp->error_signaled)
5610 error ("regexp matches the empty string: \"%s\"",
5611 pp->regex);
5612 pp->error_signaled = TRUE;
5614 match = -3; /* exit from while loop */
5615 break;
5618 /* Match occurred. Construct a tag. */
5619 while (charno < pp->regs.end[0])
5620 if (buffer[charno++] == '\n')
5621 lineno++, linecharno = charno;
5622 if (pp->name_pattern[0] != '\0')
5624 /* Make a named tag.
5625 Do not use make_tag here, as it would make the name
5626 implicit if possible, while we want to respect the user's
5627 request to create an explicit tag name. */
5628 char *name = substitute (buffer,
5629 pp->name_pattern, &pp->regs);
5630 if (name != NULL)
5631 pfnote (name, TRUE, buffer + linecharno,
5632 charno - linecharno + 1, lineno, linecharno);
5634 else
5636 /* Make an unnamed tag. */
5637 pfnote ((char *)NULL, TRUE, buffer + linecharno,
5638 charno - linecharno + 1, lineno, linecharno);
5640 break;
5646 #endif /* ETAGS_REGEXPS */
5649 static bool
5650 nocase_tail (cp)
5651 char *cp;
5653 register int len = 0;
5655 while (*cp != '\0' && lowcase (*cp) == lowcase (dbp[len]))
5656 cp++, len++;
5657 if (*cp == '\0' && !intoken (dbp[len]))
5659 dbp += len;
5660 return TRUE;
5662 return FALSE;
5665 static void
5666 get_tag (bp, namepp)
5667 register char *bp;
5668 char **namepp;
5670 register char *cp = bp;
5672 if (*bp != '\0')
5674 /* Go till you get to white space or a syntactic break */
5675 for (cp = bp + 1; !notinname (*cp); cp++)
5676 continue;
5677 make_tag (bp, cp - bp, TRUE,
5678 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
5681 if (namepp != NULL)
5682 *namepp = savenstr (bp, cp - bp);
5685 /* Initialize a linebuffer for use */
5686 static void
5687 initbuffer (lbp)
5688 linebuffer *lbp;
5690 lbp->size = (DEBUG) ? 3 : 200;
5691 lbp->buffer = xnew (lbp->size, char);
5692 lbp->buffer[0] = '\0';
5693 lbp->len = 0;
5697 * Read a line of text from `stream' into `lbp', excluding the
5698 * newline or CR-NL, if any. Return the number of characters read from
5699 * `stream', which is the length of the line including the newline.
5701 * On DOS or Windows we do not count the CR character, if any before the
5702 * NL, in the returned length; this mirrors the behavior of Emacs on those
5703 * platforms (for text files, it translates CR-NL to NL as it reads in the
5704 * file).
5706 * If multi-line regular expressions are requested, each line read is
5707 * appended to `filebuf'.
5709 static long
5710 readline_internal (lbp, stream)
5711 linebuffer *lbp;
5712 register FILE *stream;
5714 char *buffer = lbp->buffer;
5715 register char *p = lbp->buffer;
5716 register char *pend;
5717 int chars_deleted;
5719 pend = p + lbp->size; /* Separate to avoid 386/IX compiler bug. */
5721 for (;;)
5723 register int c = getc (stream);
5724 if (p == pend)
5726 /* We're at the end of linebuffer: expand it. */
5727 lbp->size *= 2;
5728 xrnew (buffer, lbp->size, char);
5729 p += buffer - lbp->buffer;
5730 pend = buffer + lbp->size;
5731 lbp->buffer = buffer;
5733 if (c == EOF)
5735 *p = '\0';
5736 chars_deleted = 0;
5737 break;
5739 if (c == '\n')
5741 if (p > buffer && p[-1] == '\r')
5743 p -= 1;
5744 #ifdef DOS_NT
5745 /* Assume CRLF->LF translation will be performed by Emacs
5746 when loading this file, so CRs won't appear in the buffer.
5747 It would be cleaner to compensate within Emacs;
5748 however, Emacs does not know how many CRs were deleted
5749 before any given point in the file. */
5750 chars_deleted = 1;
5751 #else
5752 chars_deleted = 2;
5753 #endif
5755 else
5757 chars_deleted = 1;
5759 *p = '\0';
5760 break;
5762 *p++ = c;
5764 lbp->len = p - buffer;
5766 if (need_filebuf /* we need filebuf for multi-line regexps */
5767 && chars_deleted > 0) /* not at EOF */
5769 while (filebuf.size <= filebuf.len + lbp->len + 1) /* +1 for \n */
5771 /* Expand filebuf. */
5772 filebuf.size *= 2;
5773 xrnew (filebuf.buffer, filebuf.size, char);
5775 strncpy (filebuf.buffer + filebuf.len, lbp->buffer, lbp->len);
5776 filebuf.len += lbp->len;
5777 filebuf.buffer[filebuf.len++] = '\n';
5778 filebuf.buffer[filebuf.len] = '\0';
5781 return lbp->len + chars_deleted;
5785 * Like readline_internal, above, but in addition try to match the
5786 * input line against relevant regular expressions and manage #line
5787 * directives.
5789 static void
5790 readline (lbp, stream)
5791 linebuffer *lbp;
5792 FILE *stream;
5794 long result;
5796 linecharno = charno; /* update global char number of line start */
5797 result = readline_internal (lbp, stream); /* read line */
5798 lineno += 1; /* increment global line number */
5799 charno += result; /* increment global char number */
5801 /* Honour #line directives. */
5802 if (!no_line_directive)
5804 static bool discard_until_line_directive;
5806 /* Check whether this is a #line directive. */
5807 if (result > 12 && strneq (lbp->buffer, "#line ", 6))
5809 int start, lno;
5811 if (DEBUG) start = 0; /* shut up the compiler */
5812 if (sscanf (lbp->buffer, "#line %d \"%n", &lno, &start) == 1)
5814 char *endp = lbp->buffer + start;
5816 assert (start > 0);
5817 while ((endp = etags_strchr (endp, '"')) != NULL
5818 && endp[-1] == '\\')
5819 endp++;
5820 if (endp != NULL)
5821 /* Ok, this is a real #line directive. Let's deal with it. */
5823 char *taggedabsname; /* absolute name of original file */
5824 char *taggedfname; /* name of original file as given */
5825 char *name; /* temp var */
5827 discard_until_line_directive = FALSE; /* found it */
5828 name = lbp->buffer + start;
5829 *endp = '\0';
5830 canonicalize_filename (name); /* for DOS */
5831 taggedabsname = absolute_filename (name, curfdp->infabsdir);
5832 if (filename_is_absolute (name)
5833 || filename_is_absolute (curfdp->infname))
5834 taggedfname = savestr (taggedabsname);
5835 else
5836 taggedfname = relative_filename (taggedabsname,tagfiledir);
5838 if (streq (curfdp->taggedfname, taggedfname))
5839 /* The #line directive is only a line number change. We
5840 deal with this afterwards. */
5841 free (taggedfname);
5842 else
5843 /* The tags following this #line directive should be
5844 attributed to taggedfname. In order to do this, set
5845 curfdp accordingly. */
5847 fdesc *fdp; /* file description pointer */
5849 /* Go look for a file description already set up for the
5850 file indicated in the #line directive. If there is
5851 one, use it from now until the next #line
5852 directive. */
5853 for (fdp = fdhead; fdp != NULL; fdp = fdp->next)
5854 if (streq (fdp->infname, curfdp->infname)
5855 && streq (fdp->taggedfname, taggedfname))
5856 /* If we remove the second test above (after the &&)
5857 then all entries pertaining to the same file are
5858 coalesced in the tags file. If we use it, then
5859 entries pertaining to the same file but generated
5860 from different files (via #line directives) will
5861 go into separate sections in the tags file. These
5862 alternatives look equivalent. The first one
5863 destroys some apparently useless information. */
5865 curfdp = fdp;
5866 free (taggedfname);
5867 break;
5869 /* Else, if we already tagged the real file, skip all
5870 input lines until the next #line directive. */
5871 if (fdp == NULL) /* not found */
5872 for (fdp = fdhead; fdp != NULL; fdp = fdp->next)
5873 if (streq (fdp->infabsname, taggedabsname))
5875 discard_until_line_directive = TRUE;
5876 free (taggedfname);
5877 break;
5879 /* Else create a new file description and use that from
5880 now on, until the next #line directive. */
5881 if (fdp == NULL) /* not found */
5883 fdp = fdhead;
5884 fdhead = xnew (1, fdesc);
5885 *fdhead = *curfdp; /* copy curr. file description */
5886 fdhead->next = fdp;
5887 fdhead->infname = savestr (curfdp->infname);
5888 fdhead->infabsname = savestr (curfdp->infabsname);
5889 fdhead->infabsdir = savestr (curfdp->infabsdir);
5890 fdhead->taggedfname = taggedfname;
5891 fdhead->usecharno = FALSE;
5892 curfdp = fdhead;
5895 free (taggedabsname);
5896 lineno = lno - 1;
5897 readline (lbp, stream);
5898 return;
5899 } /* if a real #line directive */
5900 } /* if #line is followed by a a number */
5901 } /* if line begins with "#line " */
5903 /* If we are here, no #line directive was found. */
5904 if (discard_until_line_directive)
5906 if (result > 0)
5908 /* Do a tail recursion on ourselves, thus discarding the contents
5909 of the line buffer. */
5910 readline (lbp, stream);
5911 return;
5913 /* End of file. */
5914 discard_until_line_directive = FALSE;
5915 return;
5917 } /* if #line directives should be considered */
5919 #ifdef ETAGS_REGEXPS
5921 int match;
5922 pattern *pp;
5924 /* Match against relevant patterns. */
5925 if (lbp->len > 0)
5926 for (pp = p_head; pp != NULL; pp = pp->p_next)
5928 /* Only use generic regexps or those for the current language.
5929 Also do not use multiline regexps, which is the job of
5930 regex_tag_multiline. */
5931 if ((pp->lang != NULL && pp->lang != fdhead->lang)
5932 || pp->multi_line)
5933 continue;
5935 match = re_match (pp->pat, lbp->buffer, lbp->len, 0, &pp->regs);
5936 switch (match)
5938 case -2:
5939 /* Some error. */
5940 if (!pp->error_signaled)
5942 error ("regexp stack overflow while matching \"%s\"",
5943 pp->regex);
5944 pp->error_signaled = TRUE;
5946 break;
5947 case -1:
5948 /* No match. */
5949 break;
5950 case 0:
5951 /* Empty string matched. */
5952 if (!pp->error_signaled)
5954 error ("regexp matches the empty string: \"%s\"",
5955 pp->regex);
5956 pp->error_signaled = TRUE;
5958 break;
5959 default:
5960 /* Match occurred. Construct a tag. */
5961 if (pp->name_pattern[0] != '\0')
5963 /* Make a named tag.
5964 Do not use make_tag here, as it would make the name
5965 implicit if possible, while we want to respect the user's
5966 request to create an explicit tag name. */
5967 char *name = substitute (lbp->buffer,
5968 pp->name_pattern, &pp->regs);
5969 if (name != NULL)
5970 pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);
5972 else
5974 /* Make an unnamed tag. */
5975 pfnote ((char *)NULL, TRUE,
5976 lbp->buffer, match, lineno, linecharno);
5978 break;
5982 #endif /* ETAGS_REGEXPS */
5987 * Return a pointer to a space of size strlen(cp)+1 allocated
5988 * with xnew where the string CP has been copied.
5990 static char *
5991 savestr (cp)
5992 char *cp;
5994 return savenstr (cp, strlen (cp));
5998 * Return a pointer to a space of size LEN+1 allocated with xnew where
5999 * the string CP has been copied for at most the first LEN characters.
6001 static char *
6002 savenstr (cp, len)
6003 char *cp;
6004 int len;
6006 register char *dp;
6008 dp = xnew (len + 1, char);
6009 strncpy (dp, cp, len);
6010 dp[len] = '\0';
6011 return dp;
6015 * Return the ptr in sp at which the character c last
6016 * appears; NULL if not found
6018 * Identical to POSIX strrchr, included for portability.
6020 static char *
6021 etags_strrchr (sp, c)
6022 register const char *sp;
6023 register int c;
6025 register const char *r;
6027 r = NULL;
6030 if (*sp == c)
6031 r = sp;
6032 } while (*sp++);
6033 return (char *)r;
6037 * Return the ptr in sp at which the character c first
6038 * appears; NULL if not found
6040 * Identical to POSIX strchr, included for portability.
6042 static char *
6043 etags_strchr (sp, c)
6044 register const char *sp;
6045 register int c;
6049 if (*sp == c)
6050 return (char *)sp;
6051 } while (*sp++);
6052 return NULL;
6056 * Return TRUE if the two strings are equal, ignoring case for alphabetic
6057 * characters.
6059 * Analogous to BSD's strcasecmp, included for portability.
6061 static bool
6062 strcaseeq (s1, s2)
6063 register const char *s1;
6064 register const char *s2;
6066 while (*s1 != '\0'
6067 && (ISALPHA (*s1) && ISALPHA (*s2)
6068 ? lowcase (*s1) == lowcase (*s2)
6069 : *s1 == *s2))
6070 s1++, s2++;
6072 return (*s1 == *s2);
6075 /* Skip spaces, return new pointer. */
6076 static char *
6077 skip_spaces (cp)
6078 char *cp;
6080 while (iswhite (*cp))
6081 cp++;
6082 return cp;
6085 /* Skip non spaces, return new pointer. */
6086 static char *
6087 skip_non_spaces (cp)
6088 char *cp;
6090 while (*cp != '\0' && !iswhite (*cp))
6091 cp++;
6092 return cp;
6095 /* Print error message and exit. */
6096 void
6097 fatal (s1, s2)
6098 char *s1, *s2;
6100 error (s1, s2);
6101 exit (BAD);
6104 static void
6105 pfatal (s1)
6106 char *s1;
6108 perror (s1);
6109 exit (BAD);
6112 static void
6113 suggest_asking_for_help ()
6115 fprintf (stderr, "\tTry `%s %s' for a complete list of options.\n",
6116 progname,
6117 #ifdef LONG_OPTIONS
6118 "--help"
6119 #else
6120 "-h"
6121 #endif
6123 exit (BAD);
6126 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
6127 static void
6128 error (s1, s2)
6129 const char *s1, *s2;
6131 fprintf (stderr, "%s: ", progname);
6132 fprintf (stderr, s1, s2);
6133 fprintf (stderr, "\n");
6136 /* Return a newly-allocated string whose contents
6137 concatenate those of s1, s2, s3. */
6138 static char *
6139 concat (s1, s2, s3)
6140 char *s1, *s2, *s3;
6142 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
6143 char *result = xnew (len1 + len2 + len3 + 1, char);
6145 strcpy (result, s1);
6146 strcpy (result + len1, s2);
6147 strcpy (result + len1 + len2, s3);
6148 result[len1 + len2 + len3] = '\0';
6150 return result;
6154 /* Does the same work as the system V getcwd, but does not need to
6155 guess the buffer size in advance. */
6156 static char *
6157 etags_getcwd ()
6159 #ifdef HAVE_GETCWD
6160 int bufsize = 200;
6161 char *path = xnew (bufsize, char);
6163 while (getcwd (path, bufsize) == NULL)
6165 if (errno != ERANGE)
6166 pfatal ("getcwd");
6167 bufsize *= 2;
6168 free (path);
6169 path = xnew (bufsize, char);
6172 canonicalize_filename (path);
6173 return path;
6175 #else /* not HAVE_GETCWD */
6176 #if MSDOS
6178 char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */
6180 getwd (path);
6182 for (p = path; *p != '\0'; p++)
6183 if (*p == '\\')
6184 *p = '/';
6185 else
6186 *p = lowcase (*p);
6188 return strdup (path);
6189 #else /* not MSDOS */
6190 linebuffer path;
6191 FILE *pipe;
6193 initbuffer (&path);
6194 pipe = (FILE *) popen ("pwd 2>/dev/null", "r");
6195 if (pipe == NULL || readline_internal (&path, pipe) == 0)
6196 pfatal ("pwd");
6197 pclose (pipe);
6199 return path.buffer;
6200 #endif /* not MSDOS */
6201 #endif /* not HAVE_GETCWD */
6204 /* Return a newly allocated string containing the file name of FILE
6205 relative to the absolute directory DIR (which should end with a slash). */
6206 static char *
6207 relative_filename (file, dir)
6208 char *file, *dir;
6210 char *fp, *dp, *afn, *res;
6211 int i;
6213 /* Find the common root of file and dir (with a trailing slash). */
6214 afn = absolute_filename (file, cwd);
6215 fp = afn;
6216 dp = dir;
6217 while (*fp++ == *dp++)
6218 continue;
6219 fp--, dp--; /* back to the first differing char */
6220 #ifdef DOS_NT
6221 if (fp == afn && afn[0] != '/') /* cannot build a relative name */
6222 return afn;
6223 #endif
6224 do /* look at the equal chars until '/' */
6225 fp--, dp--;
6226 while (*fp != '/');
6228 /* Build a sequence of "../" strings for the resulting relative file name. */
6229 i = 0;
6230 while ((dp = etags_strchr (dp + 1, '/')) != NULL)
6231 i += 1;
6232 res = xnew (3*i + strlen (fp + 1) + 1, char);
6233 res[0] = '\0';
6234 while (i-- > 0)
6235 strcat (res, "../");
6237 /* Add the file name relative to the common root of file and dir. */
6238 strcat (res, fp + 1);
6239 free (afn);
6241 return res;
6244 /* Return a newly allocated string containing the absolute file name
6245 of FILE given DIR (which should end with a slash). */
6246 static char *
6247 absolute_filename (file, dir)
6248 char *file, *dir;
6250 char *slashp, *cp, *res;
6252 if (filename_is_absolute (file))
6253 res = savestr (file);
6254 #ifdef DOS_NT
6255 /* We don't support non-absolute file names with a drive
6256 letter, like `d:NAME' (it's too much hassle). */
6257 else if (file[1] == ':')
6258 fatal ("%s: relative file names with drive letters not supported", file);
6259 #endif
6260 else
6261 res = concat (dir, file, "");
6263 /* Delete the "/dirname/.." and "/." substrings. */
6264 slashp = etags_strchr (res, '/');
6265 while (slashp != NULL && slashp[0] != '\0')
6267 if (slashp[1] == '.')
6269 if (slashp[2] == '.'
6270 && (slashp[3] == '/' || slashp[3] == '\0'))
6272 cp = slashp;
6274 cp--;
6275 while (cp >= res && !filename_is_absolute (cp));
6276 if (cp < res)
6277 cp = slashp; /* the absolute name begins with "/.." */
6278 #ifdef DOS_NT
6279 /* Under MSDOS and NT we get `d:/NAME' as absolute
6280 file name, so the luser could say `d:/../NAME'.
6281 We silently treat this as `d:/NAME'. */
6282 else if (cp[0] != '/')
6283 cp = slashp;
6284 #endif
6285 strcpy (cp, slashp + 3);
6286 slashp = cp;
6287 continue;
6289 else if (slashp[2] == '/' || slashp[2] == '\0')
6291 strcpy (slashp, slashp + 2);
6292 continue;
6296 slashp = etags_strchr (slashp + 1, '/');
6299 if (res[0] == '\0')
6300 return savestr ("/");
6301 else
6302 return res;
6305 /* Return a newly allocated string containing the absolute
6306 file name of dir where FILE resides given DIR (which should
6307 end with a slash). */
6308 static char *
6309 absolute_dirname (file, dir)
6310 char *file, *dir;
6312 char *slashp, *res;
6313 char save;
6315 canonicalize_filename (file);
6316 slashp = etags_strrchr (file, '/');
6317 if (slashp == NULL)
6318 return savestr (dir);
6319 save = slashp[1];
6320 slashp[1] = '\0';
6321 res = absolute_filename (file, dir);
6322 slashp[1] = save;
6324 return res;
6327 /* Whether the argument string is an absolute file name. The argument
6328 string must have been canonicalized with canonicalize_filename. */
6329 static bool
6330 filename_is_absolute (fn)
6331 char *fn;
6333 return (fn[0] == '/'
6334 #ifdef DOS_NT
6335 || (ISALPHA(fn[0]) && fn[1] == ':' && fn[2] == '/')
6336 #endif
6340 /* Translate backslashes into slashes. Works in place. */
6341 static void
6342 canonicalize_filename (fn)
6343 register char *fn;
6345 #ifdef DOS_NT
6346 /* Canonicalize drive letter case. */
6347 if (fn[0] != '\0' && fn[1] == ':' && ISLOWER (fn[0]))
6348 fn[0] = upcase (fn[0]);
6349 /* Convert backslashes to slashes. */
6350 for (; *fn != '\0'; fn++)
6351 if (*fn == '\\')
6352 *fn = '/';
6353 #else
6354 /* No action. */
6355 fn = NULL; /* shut up the compiler */
6356 #endif
6359 /* Set the minimum size of a string contained in a linebuffer. */
6360 static void
6361 linebuffer_setlen (lbp, toksize)
6362 linebuffer *lbp;
6363 int toksize;
6365 while (lbp->size <= toksize)
6367 lbp->size *= 2;
6368 xrnew (lbp->buffer, lbp->size, char);
6370 lbp->len = toksize;
6373 /* Like malloc but get fatal error if memory is exhausted. */
6374 static PTR
6375 xmalloc (size)
6376 unsigned int size;
6378 PTR result = (PTR) malloc (size);
6379 if (result == NULL)
6380 fatal ("virtual memory exhausted", (char *)NULL);
6381 return result;
6384 static PTR
6385 xrealloc (ptr, size)
6386 char *ptr;
6387 unsigned int size;
6389 PTR result = (PTR) realloc (ptr, size);
6390 if (result == NULL)
6391 fatal ("virtual memory exhausted", (char *)NULL);
6392 return result;
6396 * Local Variables:
6397 * c-indentation-style: gnu
6398 * indent-tabs-mode: t
6399 * tab-width: 8
6400 * fill-column: 79
6401 * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node" "pattern")
6402 * End: