1 /* Tags file maker to go with GNU Emacs -*- coding: latin-1 -*-
2 Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2001, 2002
3 Free Software Foundation, Inc. and Ken Arnold
5 This file is not considered part of GNU Emacs.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 * Ctags originally by Ken Arnold.
24 * Fortran added by Jim Kleckner.
25 * Ed Pelegri-Llopart added C typedefs.
26 * Gnu Emacs TAGS format and modifications by RMS?
27 * 1989 Sam Kendall added C++.
28 * 1992 Joseph B. Wells improved C and C++ parsing.
29 * 1993 Francesco Potortì reorganised C and C++.
30 * 1994 Line-by-line regexp tags by Tom Tromey.
31 * 2001 Nested classes by Francesco Potortì (concept by Mykola Dzyuba).
32 * 2002 #line directives by Francesco Potortì.
34 * Francesco Potortì <pot@gnu.org> has maintained and improved it since 1993.
38 char pot_etags_version
[] = "@(#) pot revision number is 16.46";
48 # define NDEBUG /* disable assert */
53 /* On some systems, Emacs defines static as nothing for the sake
54 of unexec. We don't want that here since we don't use unexec. */
56 # define ETAGS_REGEXPS /* use the regexp features */
57 # define LONG_OPTIONS /* accept long options */
58 # ifndef PTR /* for Xemacs */
61 # ifndef __P /* for Xemacs */
62 # define __P(args) args
65 # if defined(__STDC__) && (__STDC__ || defined(__SUNPRO_C))
66 # define __P(args) args /* use prototypes */
67 # define PTR void * /* for generic pointers */
69 # define __P(args) () /* no prototypes */
70 # define const /* remove const for old compilers' sake */
71 # define PTR long * /* don't use void* */
73 #endif /* !HAVE_CONFIG_H */
76 # define _GNU_SOURCE 1 /* enables some compiler checks on GNU */
79 /* WIN32_NATIVE is for Xemacs.
80 MSDOS, WINDOWSNT, DOS_NT are for Emacs. */
85 #endif /* WIN32_NATIVE */
91 # include <sys/param.h>
93 # ifndef HAVE_CONFIG_H
95 # include <sys/config.h>
107 # define MAXPATHLEN _MAX_PATH
113 # endif /* undef HAVE_GETCWD */
114 #else /* !WINDOWSNT */
119 extern char *getenv ();
121 #endif /* !WINDOWSNT */
126 # if defined (HAVE_GETCWD) && !defined (WINDOWSNT)
127 extern char *getcwd (char *buf
, size_t size
);
129 #endif /* HAVE_UNISTD_H */
137 #include <sys/types.h>
138 #include <sys/stat.h>
142 # undef assert /* some systems have a buggy assert.h */
143 # define assert(x) ((void) 0)
146 #if !defined (S_ISREG) && defined (S_IFREG)
147 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
153 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
155 extern int optind
, opterr
;
156 #endif /* LONG_OPTIONS */
159 # ifndef HAVE_CONFIG_H /* this is a standalone compilation */
160 # ifdef __CYGWIN__ /* compiling on Cygwin */
162 the regex
.h distributed with Cygwin is
not compatible with etags
, alas
!
163 If you want regular expression support
, you should
delete this notice
and
164 arrange to use the GNU regex
.h
and regex
.c
.
168 #endif /* ETAGS_REGEXPS */
170 /* Define CTAGS to make the program "ctags" compatible with the usual one.
171 Leave it undefined to make the program "etags", which makes emacs-style
172 tag tables and tags typedefs, #defines and struct/union/enum by default. */
180 /* Exit codes for success and failure. */
189 #define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t))
190 #define strcaseeq(s,t) (assert((s)!=NULL && (t)!=NULL), !etags_strcasecmp (s, t))
191 #define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
192 #define strncaseeq(s,t,n) (assert((s)!=NULL && (t)!=NULL), !etags_strncasecmp (s, t, n))
194 #define CHARS 256 /* 2^sizeof(char) */
195 #define CHAR(x) ((unsigned int)(x) & (CHARS - 1))
196 #define iswhite(c) (_wht[CHAR(c)]) /* c is white (see white) */
197 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name (see nonam) */
198 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token (see begtk) */
199 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token (see midtk) */
200 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens (see endtk) */
202 #define ISALNUM(c) isalnum (CHAR(c))
203 #define ISALPHA(c) isalpha (CHAR(c))
204 #define ISDIGIT(c) isdigit (CHAR(c))
205 #define ISLOWER(c) islower (CHAR(c))
207 #define lowcase(c) tolower (CHAR(c))
208 #define upcase(c) toupper (CHAR(c))
212 * xnew, xrnew -- allocate, reallocate storage
214 * SYNOPSIS: Type *xnew (int n, Type);
215 * void xrnew (OldPointer, int n, Type);
218 # include "chkmalloc.h"
219 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
220 (n) * sizeof (Type)))
221 # define xrnew(op,n,Type) ((op) = (Type *) trace_realloc (__FILE__, __LINE__, \
222 (char *) (op), (n) * sizeof (Type)))
224 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
225 # define xrnew(op,n,Type) ((op) = (Type *) xrealloc ( \
226 (char *) (op), (n) * sizeof (Type)))
231 typedef void Lang_function
__P((FILE *));
235 char *suffix
; /* file name suffix for this compressor */
236 char *command
; /* takes one arg and decompresses to stdout */
241 char *name
; /* language name */
242 bool metasource
; /* source used to generate other sources */
243 Lang_function
*function
; /* parse function */
244 char **filenames
; /* names of this language's files */
245 char **suffixes
; /* name suffixes of this language's files */
246 char **interpreters
; /* interpreters for this language */
251 struct fdesc
*next
; /* for the linked list */
252 char *infname
; /* uncompressed input file name */
253 char *infabsname
; /* absolute uncompressed input file name */
254 char *infabsdir
; /* absolute dir of input file */
255 char *taggedfname
; /* file name to write in tagfile */
256 language
*lang
; /* language of file */
257 char *prop
; /* file properties to write in tagfile */
258 bool usecharno
; /* etags tags shall contain char number */
259 bool written
; /* entry written in the tags file */
262 typedef struct node_st
263 { /* sorting structure */
264 struct node_st
*left
, *right
; /* left and right sons */
265 fdesc
*fdp
; /* description of file to whom tag belongs */
266 char *name
; /* tag name */
267 char *regex
; /* search regexp */
268 bool valid
; /* write this tag on the tag file */
269 bool is_func
; /* function tag: use regexp in CTAGS mode */
270 bool been_warned
; /* warning already given for duplicated tag */
271 int lno
; /* line number tag is on */
272 long cno
; /* character number line starts on */
276 * A `linebuffer' is a structure which holds a line of text.
277 * `readline_internal' reads a line from a stream into a linebuffer
278 * and works regardless of the length of the line.
279 * SIZE is the size of BUFFER, LEN is the length of the string in
280 * BUFFER after readline reads it.
289 /* Used to support mixing of --lang and file names. */
293 at_language
, /* a language specification */
294 at_regexp
, /* a regular expression */
295 at_filename
, /* a file name */
296 at_stdin
/* read from stdin here */
297 } arg_type
; /* argument type */
298 language
*lang
; /* language associated with the argument */
299 char *what
; /* the argument itself */
303 /* Structure defining a regular expression. */
304 typedef struct regexp
306 struct regexp
*p_next
; /* pointer to next in list */
307 language
*lang
; /* if set, use only for this language */
308 char *pattern
; /* the regexp pattern */
309 char *name
; /* tag name */
310 struct re_pattern_buffer
*pat
; /* the compiled pattern */
311 struct re_registers regs
; /* re registers */
312 bool error_signaled
; /* already signaled for this regexp */
313 bool force_explicit_name
; /* do not allow implict tag name */
314 bool ignore_case
; /* ignore case when matching */
315 bool multi_line
; /* do a multi-line match on the whole file */
317 #endif /* ETAGS_REGEXPS */
320 /* Many compilers barf on this:
321 Lang_function Ada_funcs;
322 so let's write it this way */
323 static void Ada_funcs
__P((FILE *));
324 static void Asm_labels
__P((FILE *));
325 static void C_entries
__P((int c_ext
, FILE *));
326 static void default_C_entries
__P((FILE *));
327 static void plain_C_entries
__P((FILE *));
328 static void Cjava_entries
__P((FILE *));
329 static void Cobol_paragraphs
__P((FILE *));
330 static void Cplusplus_entries
__P((FILE *));
331 static void Cstar_entries
__P((FILE *));
332 static void Erlang_functions
__P((FILE *));
333 static void Fortran_functions
__P((FILE *));
334 static void HTML_labels
__P((FILE *));
335 static void Lisp_functions
__P((FILE *));
336 static void Makefile_targets
__P((FILE *));
337 static void Pascal_functions
__P((FILE *));
338 static void Perl_functions
__P((FILE *));
339 static void PHP_functions
__P((FILE *));
340 static void Postscript_functions
__P((FILE *));
341 static void Prolog_functions
__P((FILE *));
342 static void Python_functions
__P((FILE *));
343 static void Scheme_functions
__P((FILE *));
344 static void TeX_commands
__P((FILE *));
345 static void Texinfo_nodes
__P((FILE *));
346 static void Yacc_entries
__P((FILE *));
347 static void just_read_file
__P((FILE *));
349 static void print_language_names
__P((void));
350 static void print_version
__P((void));
351 static void print_help
__P((void));
352 int main
__P((int, char **));
354 static compressor
*get_compressor_from_suffix
__P((char *, char **));
355 static language
*get_language_from_langname
__P((const char *));
356 static language
*get_language_from_interpreter
__P((char *));
357 static language
*get_language_from_filename
__P((char *, bool));
358 static void readline
__P((linebuffer
*, FILE *));
359 static long readline_internal
__P((linebuffer
*, FILE *));
360 static bool nocase_tail
__P((char *));
361 static void get_tag
__P((char *, char **));
364 static void analyse_regex
__P((char *));
365 static void free_regexps
__P((void));
366 static void regex_tag_multiline
__P((void));
367 #endif /* ETAGS_REGEXPS */
368 static void error
__P((const char *, const char *));
369 static void suggest_asking_for_help
__P((void));
370 void fatal
__P((char *, char *));
371 static void pfatal
__P((char *));
372 static void add_node
__P((node
*, node
**));
374 static void init
__P((void));
375 static void process_file_name
__P((char *, language
*));
376 static void process_file
__P((FILE *, char *, language
*));
377 static void find_entries
__P((FILE *));
378 static void free_tree
__P((node
*));
379 static void free_fdesc
__P((fdesc
*));
380 static void pfnote
__P((char *, bool, char *, int, int, long));
381 static void make_tag
__P((char *, int, bool, char *, int, int, long));
382 static void invalidate_nodes
__P((fdesc
*, node
**));
383 static void put_entries
__P((node
*));
385 static char *concat
__P((char *, char *, char *));
386 static char *skip_spaces
__P((char *));
387 static char *skip_non_spaces
__P((char *));
388 static char *savenstr
__P((char *, int));
389 static char *savestr
__P((char *));
390 static char *etags_strchr
__P((const char *, int));
391 static char *etags_strrchr
__P((const char *, int));
392 static int etags_strcasecmp
__P((const char *, const char *));
393 static int etags_strncasecmp
__P((const char *, const char *, int));
394 static char *etags_getcwd
__P((void));
395 static char *relative_filename
__P((char *, char *));
396 static char *absolute_filename
__P((char *, char *));
397 static char *absolute_dirname
__P((char *, char *));
398 static bool filename_is_absolute
__P((char *f
));
399 static void canonicalize_filename
__P((char *));
400 static void linebuffer_init
__P((linebuffer
*));
401 static void linebuffer_setlen
__P((linebuffer
*, int));
402 static PTR xmalloc
__P((unsigned int));
403 static PTR xrealloc
__P((char *, unsigned int));
406 static char searchar
= '/'; /* use /.../ searches */
408 static char *tagfile
; /* output file */
409 static char *progname
; /* name this program was invoked with */
410 static char *cwd
; /* current working directory */
411 static char *tagfiledir
; /* directory of tagfile */
412 static FILE *tagf
; /* ioptr for tags file */
414 static fdesc
*fdhead
; /* head of file description list */
415 static fdesc
*curfdp
; /* current file description */
416 static int lineno
; /* line number of current line */
417 static long charno
; /* current character number */
418 static long linecharno
; /* charno of start of current line */
419 static char *dbp
; /* pointer to start of current tag */
421 static const int invalidcharno
= -1;
423 static node
*nodehead
; /* the head of the binary tree of tags */
424 static node
*last_node
; /* the last node created */
426 static linebuffer lb
; /* the current line */
427 static linebuffer filebuf
; /* a buffer containing the whole file */
428 static linebuffer token_name
; /* a buffer containing a tag name */
430 /* boolean "functions" (see init) */
431 static bool _wht
[CHARS
], _nin
[CHARS
], _itk
[CHARS
], _btk
[CHARS
], _etk
[CHARS
];
434 *white
= " \f\t\n\r\v",
436 *nonam
= " \f\t\n\r()=,;", /* look at make_tag before modifying! */
437 /* token ending chars */
438 *endtk
= " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
439 /* token starting chars */
440 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
441 /* valid in-token chars */
442 *midtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
444 static bool append_to_tagfile
; /* -a: append to tags */
445 /* The next four default to TRUE for etags, but to FALSE for ctags. */
446 static bool typedefs
; /* -t: create tags for C and Ada typedefs */
447 static bool typedefs_or_cplusplus
; /* -T: create tags for C typedefs, level */
448 /* 0 struct/enum/union decls, and C++ */
449 /* member functions. */
450 static bool constantypedefs
; /* -d: create tags for C #define, enum */
451 /* constants and variables. */
452 /* -D: opposite of -d. Default under ctags. */
453 static bool globals
; /* create tags for global variables */
454 static bool declarations
; /* --declarations: tag them and extern in C&Co*/
455 static bool members
; /* create tags for C member variables */
456 static bool no_line_directive
; /* ignore #line directives (undocumented) */
457 static bool update
; /* -u: update tags */
458 static bool vgrind_style
; /* -v: create vgrind style index output */
459 static bool no_warnings
; /* -w: suppress warnings */
460 static bool cxref_style
; /* -x: create cxref style output */
461 static bool cplusplus
; /* .[hc] means C++, not C */
462 static bool ignoreindent
; /* -I: ignore indentation in C */
463 static bool packages_only
; /* --packages-only: in Ada, only tag packages*/
465 #define STDIN 0x1001 /* returned by getopt_long on --parse-stdin */
466 static bool parsing_stdin
; /* --parse-stdin used */
469 static regexp
*p_head
; /* list of all regexps */
470 static bool need_filebuf
; /* some regexes are multi-line */
472 # define need_filebuf FALSE
473 #endif /* ETAGS_REGEXPS */
476 static struct option longopts
[] =
478 { "packages-only", no_argument
, &packages_only
, TRUE
},
479 { "c++", no_argument
, NULL
, 'C' },
480 { "declarations", no_argument
, &declarations
, TRUE
},
481 { "no-line-directive", no_argument
, &no_line_directive
, TRUE
},
482 { "help", no_argument
, NULL
, 'h' },
483 { "help", no_argument
, NULL
, 'H' },
484 { "ignore-indentation", no_argument
, NULL
, 'I' },
485 { "language", required_argument
, NULL
, 'l' },
486 { "members", no_argument
, &members
, TRUE
},
487 { "no-members", no_argument
, &members
, FALSE
},
488 { "output", required_argument
, NULL
, 'o' },
490 { "regex", required_argument
, NULL
, 'r' },
491 { "no-regex", no_argument
, NULL
, 'R' },
492 { "ignore-case-regex", required_argument
, NULL
, 'c' },
493 #endif /* ETAGS_REGEXPS */
494 { "parse-stdin", required_argument
, NULL
, STDIN
},
495 { "version", no_argument
, NULL
, 'V' },
497 #if CTAGS /* Etags options */
498 { "backward-search", no_argument
, NULL
, 'B' },
499 { "cxref", no_argument
, NULL
, 'x' },
500 { "defines", no_argument
, NULL
, 'd' },
501 { "globals", no_argument
, &globals
, TRUE
},
502 { "typedefs", no_argument
, NULL
, 't' },
503 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
504 { "update", no_argument
, NULL
, 'u' },
505 { "vgrind", no_argument
, NULL
, 'v' },
506 { "no-warn", no_argument
, NULL
, 'w' },
508 #else /* Ctags options */
509 { "append", no_argument
, NULL
, 'a' },
510 { "no-defines", no_argument
, NULL
, 'D' },
511 { "no-globals", no_argument
, &globals
, FALSE
},
512 { "include", required_argument
, NULL
, 'i' },
516 #endif /* LONG_OPTIONS */
518 static compressor compressors
[] =
520 { "z", "gzip -d -c"},
521 { "Z", "gzip -d -c"},
522 { "gz", "gzip -d -c"},
523 { "GZ", "gzip -d -c"},
524 { "bz2", "bzip2 -d -c" },
533 static char *Ada_suffixes
[] =
534 { "ads", "adb", "ada", NULL
};
537 static char *Asm_suffixes
[] =
538 { "a", /* Unix assembler */
539 "asm", /* Microcontroller assembly */
540 "def", /* BSO/Tasking definition includes */
541 "inc", /* Microcontroller include files */
542 "ins", /* Microcontroller include files */
543 "s", "sa", /* Unix assembler */
544 "S", /* cpp-processed Unix assembler */
545 "src", /* BSO/Tasking C compiler output */
549 /* Note that .c and .h can be considered C++, if the --c++ flag was
550 given, or if the `class' keyowrd is met inside the file.
551 That is why default_C_entries is called for these. */
552 static char *default_C_suffixes
[] =
555 static char *Cplusplus_suffixes
[] =
556 { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
557 "M", /* Objective C++ */
558 "pdb", /* Postscript with C syntax */
561 static char *Cjava_suffixes
[] =
564 static char *Cobol_suffixes
[] =
565 { "COB", "cob", NULL
};
567 static char *Cstar_suffixes
[] =
568 { "cs", "hs", NULL
};
570 static char *Erlang_suffixes
[] =
571 { "erl", "hrl", NULL
};
573 static char *Fortran_suffixes
[] =
574 { "F", "f", "f90", "for", NULL
};
576 static char *HTML_suffixes
[] =
577 { "htm", "html", "shtml", NULL
};
579 static char *Lisp_suffixes
[] =
580 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL
};
582 static char *Makefile_filenames
[] =
583 { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL
};
585 static char *Pascal_suffixes
[] =
586 { "p", "pas", NULL
};
588 static char *Perl_suffixes
[] =
589 { "pl", "pm", NULL
};
591 static char *Perl_interpreters
[] =
592 { "perl", "@PERL@", NULL
};
594 static char *PHP_suffixes
[] =
595 { "php", "php3", "php4", NULL
};
597 static char *plain_C_suffixes
[] =
598 { "lm", /* Objective lex file */
599 "m", /* Objective C file */
600 "pc", /* Pro*C file */
603 static char *Postscript_suffixes
[] =
604 { "ps", "psw", NULL
}; /* .psw is for PSWrap */
606 static char *Prolog_suffixes
[] =
609 static char *Python_suffixes
[] =
612 /* Can't do the `SCM' or `scm' prefix with a version number. */
613 static char *Scheme_suffixes
[] =
614 { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL
};
616 static char *TeX_suffixes
[] =
617 { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL
};
619 static char *Texinfo_suffixes
[] =
620 { "texi", "texinfo", "txi", NULL
};
622 static char *Yacc_suffixes
[] =
623 { "y", "y++", "ym", "yxx", "yy", NULL
}; /* .ym is Objective yacc file */
626 * Table of languages.
628 * It is ok for a given function to be listed under more than one
629 * name. I just didn't.
632 static language lang_names
[] =
634 { "ada", FALSE
, Ada_funcs
, NULL
, Ada_suffixes
, NULL
},
635 { "asm", FALSE
, Asm_labels
, NULL
, Asm_suffixes
, NULL
},
636 { "c", FALSE
, default_C_entries
, NULL
, default_C_suffixes
, NULL
},
637 { "c++", FALSE
, Cplusplus_entries
, NULL
, Cplusplus_suffixes
, NULL
},
638 { "c*", FALSE
, Cstar_entries
, NULL
, Cstar_suffixes
, NULL
},
639 { "cobol", FALSE
, Cobol_paragraphs
, NULL
, Cobol_suffixes
, NULL
},
640 { "erlang", FALSE
, Erlang_functions
, NULL
, Erlang_suffixes
, NULL
},
641 { "fortran", FALSE
, Fortran_functions
, NULL
, Fortran_suffixes
, NULL
},
642 { "html", FALSE
, HTML_labels
, NULL
, HTML_suffixes
, NULL
},
643 { "java", FALSE
, Cjava_entries
, NULL
, Cjava_suffixes
, NULL
},
644 { "lisp", FALSE
, Lisp_functions
, NULL
, Lisp_suffixes
, NULL
},
645 { "makefile", FALSE
, Makefile_targets
, Makefile_filenames
, NULL
, NULL
},
646 { "pascal", FALSE
, Pascal_functions
, NULL
, Pascal_suffixes
, NULL
},
647 { "perl", FALSE
, Perl_functions
,NULL
, Perl_suffixes
, Perl_interpreters
},
648 { "php", FALSE
, PHP_functions
, NULL
, PHP_suffixes
, NULL
},
649 { "postscript",FALSE
, Postscript_functions
,NULL
, Postscript_suffixes
, NULL
},
650 { "proc", FALSE
, plain_C_entries
, NULL
, plain_C_suffixes
, NULL
},
651 { "prolog", FALSE
, Prolog_functions
, NULL
, Prolog_suffixes
, NULL
},
652 { "python", FALSE
, Python_functions
, NULL
, Python_suffixes
, NULL
},
653 { "scheme", FALSE
, Scheme_functions
, NULL
, Scheme_suffixes
, NULL
},
654 { "tex", FALSE
, TeX_commands
, NULL
, TeX_suffixes
, NULL
},
655 { "texinfo", FALSE
, Texinfo_nodes
, NULL
, Texinfo_suffixes
, NULL
},
656 { "yacc", TRUE
, Yacc_entries
, NULL
, Yacc_suffixes
, NULL
},
657 { "auto", FALSE
, NULL
}, /* default guessing scheme */
658 { "none", FALSE
, just_read_file
}, /* regexp matching only */
659 { NULL
, FALSE
, NULL
} /* end of list */
664 print_language_names ()
669 puts ("\nThese are the currently supported languages, along with the\n\
670 default file names and dot suffixes:");
671 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
673 printf (" %-*s", 10, lang
->name
);
674 if (lang
->filenames
!= NULL
)
675 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
676 printf (" %s", *name
);
677 if (lang
->suffixes
!= NULL
)
678 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
679 printf (" .%s", *ext
);
682 puts ("Where `auto' means use default language for files based on file\n\
683 name suffix, and `none' means only do regexp processing on files.\n\
684 If no language is specified and no matching suffix is found,\n\
685 the first line of the file is read for a sharp-bang (#!) sequence\n\
686 followed by the name of an interpreter. If no such sequence is found,\n\
687 Fortran is tried first; if no tags are found, C is tried next.\n\
688 When parsing any C file, a \"class\" keyword switches to C++.\n\
689 Compressed files are supported using gzip and bzip2.");
693 # define EMACS_NAME "standalone"
696 # define VERSION "version"
701 printf ("%s (%s %s)\n", (CTAGS
) ? "ctags" : "etags", EMACS_NAME
, VERSION
);
702 puts ("Copyright (C) 2002 Free Software Foundation, Inc. and Ken Arnold");
703 puts ("This program is distributed under the same terms as Emacs");
711 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
713 These are the options accepted by %s.\n", progname
, progname
);
715 puts ("You may use unambiguous abbreviations for the long option names.");
717 puts ("Long option names do not work with this executable, as it is not\n\
718 linked with GNU getopt.");
719 #endif /* LONG_OPTIONS */
720 puts (" A - as file name means read names from stdin (one per line).\n\
721 Absolute names are stored in the output file as they are.\n\
722 Relative ones are stored relative to the output file's directory.\n");
725 puts ("-a, --append\n\
726 Append tag entries to existing tags file.");
728 puts ("--packages-only\n\
729 For Ada files, only generate tags for packages.");
732 puts ("-B, --backward-search\n\
733 Write the search commands for the tag entries using '?', the\n\
734 backward-search command instead of '/', the forward-search command.");
736 /* This option is mostly obsolete, because etags can now automatically
737 detect C++. Retained for backward compatibility and for debugging and
738 experimentation. In principle, we could want to tag as C++ even
739 before any "class" keyword.
741 Treat files whose name suffix defaults to C language as C++ files.");
744 puts ("--declarations\n\
745 In C and derived languages, create tags for function declarations,");
747 puts ("\tand create tags for extern variables if --globals is used.");
750 ("\tand create tags for extern variables unless --no-globals is used.");
753 puts ("-d, --defines\n\
754 Create tag entries for C #define constants and enum constants, too.");
756 puts ("-D, --no-defines\n\
757 Don't create tag entries for C #define constants and enum constants.\n\
758 This makes the tags file smaller.");
761 puts ("-i FILE, --include=FILE\n\
762 Include a note in tag file indicating that, when searching for\n\
763 a tag, one should also consult the tags file FILE after\n\
764 checking the current file.");
766 puts ("-l LANG, --language=LANG\n\
767 Force the following files to be considered as written in the\n\
768 named language up to the next --language=LANG option.");
772 Create tag entries for global variables in some languages.");
774 puts ("--no-globals\n\
775 Do not create tag entries for global variables in some\n\
776 languages. This makes the tags file smaller.");
778 Create tag entries for member variables in some languages.");
781 puts ("-r REGEXP, --regex=REGEXP or --regex=@regexfile\n\
782 Make a tag for each line matching a regular expression pattern\n\
783 in the following files. {LANGUAGE}REGEXP uses REGEXP for LANGUAGE\n\
784 files only. REGEXFILE is a file containing one REGEXP per line.\n\
785 REGEXP takes the form /TAGREGEXP/TAGNAME/MODS, where TAGNAME/ is\n\
786 optional. The TAGREGEXP pattern is anchored (as if preceded by ^).");
787 puts (" If TAGNAME/ is present, the tags created are named.\n\
788 For example Tcl named tags can be created with:\n\
789 --regex=\"/proc[ \\t]+\\([^ \\t]+\\)/\\1/.\".\n\
790 MODS are optional one-letter modifiers: `i' means to ignore case,\n\
791 `m' means to allow multi-line matches, `s' implies `m' and\n\
792 causes dot to match any character, including newline.");
793 puts ("-R, --no-regex\n\
794 Don't create tags from regexps for the following files.");
795 #endif /* ETAGS_REGEXPS */
796 puts ("-I, --ignore-indentation\n\
797 In C and C++ do not assume that a closing brace in the first\n\
798 column is the final brace of a function or structure definition.");
799 puts ("-o FILE, --output=FILE\n\
800 Write the tags to FILE.");
801 puts ("--parse-stdin=NAME\n\
802 Read from standard input and record tags as belonging to file NAME.");
806 puts ("-t, --typedefs\n\
807 Generate tag entries for C and Ada typedefs.");
808 puts ("-T, --typedefs-and-c++\n\
809 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
810 and C++ member functions.");
814 puts ("-u, --update\n\
815 Update the tag entries for the given files, leaving tag\n\
816 entries for other files in place. Currently, this is\n\
817 implemented by deleting the existing entries for the given\n\
818 files and then rewriting the new entries at the end of the\n\
819 tags file. It is often faster to simply rebuild the entire\n\
820 tag file than to use this.");
824 puts ("-v, --vgrind\n\
825 Generates an index of items intended for human consumption,\n\
826 similar to the output of vgrind. The index is sorted, and\n\
827 gives the page number of each item.");
828 puts ("-w, --no-warn\n\
829 Suppress warning messages about entries defined in multiple\n\
831 puts ("-x, --cxref\n\
832 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
833 The output uses line numbers instead of page numbers, but\n\
834 beyond that the differences are cosmetic; try both to see\n\
838 puts ("-V, --version\n\
839 Print the version of the program.\n\
841 Print this help message.");
843 print_language_names ();
846 puts ("Report bugs to bug-gnu-emacs@gnu.org");
852 #ifdef VMS /* VMS specific functions */
856 /* This is a BUG! ANY arbitrary limit is a BUG!
857 Won't someone please fix this? */
858 #define MAX_FILE_SPEC_LEN 255
861 char body
[MAX_FILE_SPEC_LEN
+ 1];
865 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
866 returning in each successive call the next file name matching the input
867 spec. The function expects that each in_spec passed
868 to it will be processed to completion; in particular, up to and
869 including the call following that in which the last matching name
870 is returned, the function ignores the value of in_spec, and will
871 only start processing a new spec with the following call.
872 If an error occurs, on return out_spec contains the value
873 of in_spec when the error occurred.
875 With each successive file name returned in out_spec, the
876 function's return value is one. When there are no more matching
877 names the function returns zero. If on the first call no file
878 matches in_spec, or there is any other error, -1 is returned.
883 #define OUTSIZE MAX_FILE_SPEC_LEN
889 static long context
= 0;
890 static struct dsc$descriptor_s o
;
891 static struct dsc$descriptor_s i
;
892 static bool pass1
= TRUE
;
899 o
.dsc$a_pointer
= (char *) out
;
900 o
.dsc$w_length
= (short)OUTSIZE
;
901 i
.dsc$a_pointer
= in
;
902 i
.dsc$w_length
= (short)strlen(in
);
903 i
.dsc$b_dtype
= DSC$K_DTYPE_T
;
904 i
.dsc$b_class
= DSC$K_CLASS_S
;
905 o
.dsc$b_dtype
= DSC$K_DTYPE_VT
;
906 o
.dsc$b_class
= DSC$K_CLASS_VS
;
908 if ((status
= lib$
find_file(&i
, &o
, &context
, 0, 0)) == RMS$_NORMAL
)
910 out
->body
[out
->curlen
] = EOS
;
913 else if (status
== RMS$_NMF
)
917 strcpy(out
->body
, in
);
920 lib$
find_file_end(&context
);
926 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
927 name of each file specified by the provided arg expanding wildcards.
930 gfnames (arg
, p_error
)
934 static vspec filename
= {MAX_FILE_SPEC_LEN
, "\0"};
936 switch (fn_exp (&filename
, arg
))
940 return filename
.body
;
946 return filename
.body
;
950 #ifndef OLD /* Newer versions of VMS do provide `system'. */
954 error ("%s", "system() function not implemented under VMS");
958 #define VERSION_DELIM ';'
959 char *massage_name (s
)
965 if (*s
== VERSION_DELIM
)
983 unsigned int nincluded_files
;
984 char **included_files
;
986 int current_arg
, file_count
;
987 linebuffer filename_lb
;
996 _fmode
= O_BINARY
; /* all of files are treated as binary files */
1000 nincluded_files
= 0;
1001 included_files
= xnew (argc
, char *);
1005 /* Allocate enough no matter what happens. Overkill, but each one
1007 argbuffer
= xnew (argc
, argument
);
1010 * If etags, always find typedefs and structure tags. Why not?
1011 * Also default to find macro constants, enum constants and
1016 typedefs
= typedefs_or_cplusplus
= constantypedefs
= TRUE
;
1021 #ifdef ETAGS_REGEXPS
1022 optstring
= "-r:Rc:";
1023 #endif /* ETAGS_REGEXPS */
1024 #ifndef LONG_OPTIONS
1025 optstring
= optstring
+ 1;
1026 #endif /* LONG_OPTIONS */
1027 optstring
= concat (optstring
,
1029 (CTAGS
) ? "BxdtTuvw" : "aDi:");
1031 while ((opt
= getopt_long (argc
, argv
, optstring
, longopts
, 0)) != EOF
)
1035 /* If getopt returns 0, then it has already processed a
1036 long-named option. We should do nothing. */
1040 /* This means that a file name has been seen. Record it. */
1041 argbuffer
[current_arg
].arg_type
= at_filename
;
1042 argbuffer
[current_arg
].what
= optarg
;
1048 /* Parse standard input. Idea by Vivek <vivek@etla.org>. */
1049 argbuffer
[current_arg
].arg_type
= at_stdin
;
1050 argbuffer
[current_arg
].what
= optarg
;
1054 fatal ("cannot parse standard input more than once", (char *)NULL
);
1055 parsing_stdin
= TRUE
;
1058 /* Common options. */
1059 case 'C': cplusplus
= TRUE
; break;
1060 case 'f': /* for compatibility with old makefiles */
1064 error ("-o option may only be given once.", (char *)NULL
);
1065 suggest_asking_for_help ();
1070 case 'S': /* for backward compatibility */
1071 ignoreindent
= TRUE
;
1075 language
*lang
= get_language_from_langname (optarg
);
1078 argbuffer
[current_arg
].lang
= lang
;
1079 argbuffer
[current_arg
].arg_type
= at_language
;
1085 /* Backward compatibility: support obsolete --ignore-case-regexp. */
1086 optarg
= concat (optarg
, "i", ""); /* memory leak here */
1089 argbuffer
[current_arg
].arg_type
= at_regexp
;
1090 argbuffer
[current_arg
].what
= optarg
;
1094 argbuffer
[current_arg
].arg_type
= at_regexp
;
1095 argbuffer
[current_arg
].what
= NULL
;
1107 case 'a': append_to_tagfile
= TRUE
; break;
1108 case 'D': constantypedefs
= FALSE
; break;
1109 case 'i': included_files
[nincluded_files
++] = optarg
; break;
1111 /* Ctags options. */
1112 case 'B': searchar
= '?'; break;
1113 case 'd': constantypedefs
= TRUE
; break;
1114 case 't': typedefs
= TRUE
; break;
1115 case 'T': typedefs
= typedefs_or_cplusplus
= TRUE
; break;
1116 case 'u': update
= TRUE
; break;
1117 case 'v': vgrind_style
= TRUE
; /*FALLTHRU*/
1118 case 'x': cxref_style
= TRUE
; break;
1119 case 'w': no_warnings
= TRUE
; break;
1121 suggest_asking_for_help ();
1124 for (; optind
< argc
; ++optind
)
1126 argbuffer
[current_arg
].arg_type
= at_filename
;
1127 argbuffer
[current_arg
].what
= argv
[optind
];
1132 if (nincluded_files
== 0 && file_count
== 0)
1134 error ("no input files specified.", (char *)NULL
);
1135 suggest_asking_for_help ();
1138 if (tagfile
== NULL
)
1139 tagfile
= CTAGS
? "tags" : "TAGS";
1140 cwd
= etags_getcwd (); /* the current working directory */
1141 if (cwd
[strlen (cwd
) - 1] != '/')
1144 cwd
= concat (oldcwd
, "/", "");
1147 if (streq (tagfile
, "-"))
1150 tagfiledir
= absolute_dirname (tagfile
, cwd
);
1152 init (); /* set up boolean "functions" */
1154 linebuffer_init (&lb
);
1155 linebuffer_init (&filename_lb
);
1156 linebuffer_init (&filebuf
);
1157 linebuffer_init (&token_name
);
1161 if (streq (tagfile
, "-"))
1165 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1166 doesn't take effect until after `stdout' is already open). */
1167 if (!isatty (fileno (stdout
)))
1168 setmode (fileno (stdout
), O_BINARY
);
1172 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1178 * Loop through files finding functions.
1180 for (i
= 0; i
< current_arg
; ++i
)
1182 static language
*lang
; /* non-NULL if language is forced */
1185 switch (argbuffer
[i
].arg_type
)
1188 lang
= argbuffer
[i
].lang
;
1190 #ifdef ETAGS_REGEXPS
1192 analyse_regex (argbuffer
[i
].what
);
1197 while ((this_file
= gfnames (argbuffer
[i
].what
, &got_err
)) != NULL
)
1201 error ("can't find file %s\n", this_file
);
1206 this_file
= massage_name (this_file
);
1209 this_file
= argbuffer
[i
].what
;
1211 /* Input file named "-" means read file names from stdin
1212 (one per line) and use them. */
1213 if (streq (this_file
, "-"))
1216 fatal ("cannot parse standard input AND read file names from it",
1218 while (readline_internal (&filename_lb
, stdin
) > 0)
1219 process_file_name (filename_lb
.buffer
, lang
);
1222 process_file_name (this_file
, lang
);
1228 this_file
= argbuffer
[i
].what
;
1229 process_file (stdin
, this_file
, lang
);
1234 #ifdef ETAGS_REGEXPS
1236 #endif /* ETAGS_REGEXPS */
1238 free (filebuf
.buffer
);
1239 free (token_name
.buffer
);
1241 if (!CTAGS
|| cxref_style
)
1243 put_entries (nodehead
); /* write the remainig tags (ETAGS) */
1244 free_tree (nodehead
);
1250 /* Output file entries that have no tags. */
1251 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
1253 fprintf (tagf
, "\f\n%s,0\n", fdp
->taggedfname
);
1255 while (nincluded_files
-- > 0)
1256 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
1259 if (fclose (tagf
) == EOF
)
1267 for (i
= 0; i
< current_arg
; ++i
)
1269 switch (argbuffer
[i
].arg_type
)
1275 continue; /* the for loop */
1278 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1279 tagfile
, argbuffer
[i
].what
, tagfile
);
1280 if (system (cmd
) != GOOD
)
1281 fatal ("failed to execute shell command", (char *)NULL
);
1283 append_to_tagfile
= TRUE
;
1286 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1289 put_entries (nodehead
); /* write all the tags (CTAGS) */
1290 free_tree (nodehead
);
1292 if (fclose (tagf
) == EOF
)
1297 char cmd
[2*BUFSIZ
+10];
1298 sprintf (cmd
, "sort -o %.*s %.*s", BUFSIZ
, tagfile
, BUFSIZ
, tagfile
);
1299 exit (system (cmd
));
1306 * Return a compressor given the file name. If EXTPTR is non-zero,
1307 * return a pointer into FILE where the compressor-specific
1308 * extension begins. If no compressor is found, NULL is returned
1309 * and EXTPTR is not significant.
1310 * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca> (1998)
1313 get_compressor_from_suffix (file
, extptr
)
1318 char *slash
, *suffix
;
1320 /* This relies on FN to be after canonicalize_filename,
1321 so we don't need to consider backslashes on DOS_NT. */
1322 slash
= etags_strrchr (file
, '/');
1323 suffix
= etags_strrchr (file
, '.');
1324 if (suffix
== NULL
|| suffix
< slash
)
1329 /* Let those poor souls who live with DOS 8+3 file name limits get
1330 some solace by treating foo.cgz as if it were foo.c.gz, etc.
1331 Only the first do loop is run if not MSDOS */
1334 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1335 if (streq (compr
->suffix
, suffix
))
1338 break; /* do it only once: not really a loop */
1341 } while (*suffix
!= '\0');
1348 * Return a language given the name.
1351 get_language_from_langname (name
)
1357 error ("empty language name", (char *)NULL
);
1360 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1361 if (streq (name
, lang
->name
))
1363 error ("unknown language \"%s\"", name
);
1371 * Return a language given the interpreter name.
1374 get_language_from_interpreter (interpreter
)
1380 if (interpreter
== NULL
)
1382 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1383 if (lang
->interpreters
!= NULL
)
1384 for (iname
= lang
->interpreters
; *iname
!= NULL
; iname
++)
1385 if (streq (*iname
, interpreter
))
1394 * Return a language given the file name.
1397 get_language_from_filename (file
, case_sensitive
)
1399 bool case_sensitive
;
1402 char **name
, **ext
, *suffix
;
1404 /* Try whole file name first. */
1405 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1406 if (lang
->filenames
!= NULL
)
1407 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
1408 if ((case_sensitive
)
1409 ? streq (*name
, file
)
1410 : strcaseeq (*name
, file
))
1413 /* If not found, try suffix after last dot. */
1414 suffix
= etags_strrchr (file
, '.');
1418 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1419 if (lang
->suffixes
!= NULL
)
1420 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
1421 if ((case_sensitive
)
1422 ? streq (*ext
, suffix
)
1423 : strcaseeq (*ext
, suffix
))
1430 * This routine is called on each file argument.
1433 process_file_name (file
, lang
)
1437 struct stat stat_buf
;
1441 char *compressed_name
, *uncompressed_name
;
1442 char *ext
, *real_name
;
1445 canonicalize_filename (file
);
1446 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
1448 error ("skipping inclusion of %s in self.", file
);
1451 if ((compr
= get_compressor_from_suffix (file
, &ext
)) == NULL
)
1453 compressed_name
= NULL
;
1454 real_name
= uncompressed_name
= savestr (file
);
1458 real_name
= compressed_name
= savestr (file
);
1459 uncompressed_name
= savenstr (file
, ext
- file
);
1462 /* If the canonicalized uncompressed name
1463 has already been dealt with, skip it silently. */
1464 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
1466 assert (fdp
->infname
!= NULL
);
1467 if (streq (uncompressed_name
, fdp
->infname
))
1471 if (stat (real_name
, &stat_buf
) != 0)
1473 /* Reset real_name and try with a different name. */
1475 if (compressed_name
!= NULL
) /* try with the given suffix */
1477 if (stat (uncompressed_name
, &stat_buf
) == 0)
1478 real_name
= uncompressed_name
;
1480 else /* try all possible suffixes */
1482 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1484 compressed_name
= concat (file
, ".", compr
->suffix
);
1485 if (stat (compressed_name
, &stat_buf
) != 0)
1489 char *suf
= compressed_name
+ strlen (file
);
1490 size_t suflen
= strlen (compr
->suffix
) + 1;
1491 for ( ; suf
[1]; suf
++, suflen
--)
1493 memmove (suf
, suf
+ 1, suflen
);
1494 if (stat (compressed_name
, &stat_buf
) == 0)
1496 real_name
= compressed_name
;
1500 if (real_name
!= NULL
)
1503 free (compressed_name
);
1504 compressed_name
= NULL
;
1508 real_name
= compressed_name
;
1513 if (real_name
== NULL
)
1518 } /* try with a different name */
1520 if (!S_ISREG (stat_buf
.st_mode
))
1522 error ("skipping %s: it is not a regular file.", real_name
);
1525 if (real_name
== compressed_name
)
1527 char *cmd
= concat (compr
->command
, " ", real_name
);
1528 inf
= (FILE *) popen (cmd
, "r");
1532 inf
= fopen (real_name
, "r");
1539 process_file (inf
, uncompressed_name
, lang
);
1541 if (real_name
== compressed_name
)
1542 retval
= pclose (inf
);
1544 retval
= fclose (inf
);
1549 if (compressed_name
) free (compressed_name
);
1550 if (uncompressed_name
) free (uncompressed_name
);
1557 process_file (fh
, fn
, lang
)
1562 static const fdesc emptyfdesc
;
1565 /* Create a new input file description entry. */
1566 fdp
= xnew (1, fdesc
);
1569 fdp
->infname
= savestr (fn
);
1571 fdp
->infabsname
= absolute_filename (fn
, cwd
);
1572 fdp
->infabsdir
= absolute_dirname (fn
, cwd
);
1573 if (filename_is_absolute (fn
))
1575 /* An absolute file name. Canonicalize it. */
1576 fdp
->taggedfname
= absolute_filename (fn
, NULL
);
1580 /* A file name relative to cwd. Make it relative
1581 to the directory of the tags file. */
1582 fdp
->taggedfname
= relative_filename (fn
, tagfiledir
);
1584 fdp
->usecharno
= TRUE
; /* use char position when making tags */
1586 fdp
->written
= FALSE
; /* not written on tags file yet */
1589 curfdp
= fdhead
; /* the current file description */
1593 /* If not Ctags, and if this is not metasource and if it contained no #line
1594 directives, we can write the tags and free all nodes pointing to
1597 && curfdp
->usecharno
/* no #line directives in this file */
1598 && !curfdp
->lang
->metasource
)
1602 /* Look for the head of the sublist relative to this file. See add_node
1603 for the structure of the node tree. */
1605 for (np
= nodehead
; np
!= NULL
; prev
= np
, np
= np
->left
)
1606 if (np
->fdp
== curfdp
)
1609 /* If we generated tags for this file, write and delete them. */
1612 /* This is the head of the last sublist, if any. The following
1613 instructions depend on this being true. */
1614 assert (np
->left
== NULL
);
1616 assert (fdhead
== curfdp
);
1617 assert (last_node
->fdp
== curfdp
);
1618 put_entries (np
); /* write tags for file curfdp->taggedfname */
1619 free_tree (np
); /* remove the written nodes */
1621 nodehead
= NULL
; /* no nodes left */
1623 prev
->left
= NULL
; /* delete the pointer to the sublist */
1629 * This routine sets up the boolean pseudo-functions which work
1630 * by setting boolean flags dependent upon the corresponding character.
1631 * Every char which is NOT in that string is not a white char. Therefore,
1632 * all of the array "_wht" is set to FALSE, and then the elements
1633 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1634 * of a char is TRUE if it is the string "white", else FALSE.
1642 for (i
= 0; i
< CHARS
; i
++)
1643 iswhite(i
) = notinname(i
) = begtoken(i
) = intoken(i
) = endtoken(i
) = FALSE
;
1644 for (sp
= white
; *sp
!= '\0'; sp
++) iswhite (*sp
) = TRUE
;
1645 for (sp
= nonam
; *sp
!= '\0'; sp
++) notinname (*sp
) = TRUE
;
1646 notinname('\0') = notinname('\n');
1647 for (sp
= begtk
; *sp
!= '\0'; sp
++) begtoken (*sp
) = TRUE
;
1648 begtoken('\0') = begtoken('\n');
1649 for (sp
= midtk
; *sp
!= '\0'; sp
++) intoken (*sp
) = TRUE
;
1650 intoken('\0') = intoken('\n');
1651 for (sp
= endtk
; *sp
!= '\0'; sp
++) endtoken (*sp
) = TRUE
;
1652 endtoken('\0') = endtoken('\n');
1656 * This routine opens the specified file and calls the function
1657 * which finds the function and type definitions.
1664 language
*lang
= curfdp
->lang
;
1665 Lang_function
*parser
= NULL
;
1667 /* If user specified a language, use it. */
1668 if (lang
!= NULL
&& lang
->function
!= NULL
)
1670 parser
= lang
->function
;
1673 /* Else try to guess the language given the file name. */
1676 lang
= get_language_from_filename (curfdp
->infname
, TRUE
);
1677 if (lang
!= NULL
&& lang
->function
!= NULL
)
1679 curfdp
->lang
= lang
;
1680 parser
= lang
->function
;
1684 /* Else look for sharp-bang as the first two characters. */
1686 && readline_internal (&lb
, inf
) > 0
1688 && lb
.buffer
[0] == '#'
1689 && lb
.buffer
[1] == '!')
1693 /* Set lp to point at the first char after the last slash in the
1694 line or, if no slashes, at the first nonblank. Then set cp to
1695 the first successive blank and terminate the string. */
1696 lp
= etags_strrchr (lb
.buffer
+2, '/');
1700 lp
= skip_spaces (lb
.buffer
+ 2);
1701 cp
= skip_non_spaces (lp
);
1704 if (strlen (lp
) > 0)
1706 lang
= get_language_from_interpreter (lp
);
1707 if (lang
!= NULL
&& lang
->function
!= NULL
)
1709 curfdp
->lang
= lang
;
1710 parser
= lang
->function
;
1715 /* We rewind here, even if inf may be a pipe. We fail if the
1716 length of the first line is longer than the pipe block size,
1717 which is unlikely. */
1720 /* Else try to guess the language given the case insensitive file name. */
1723 lang
= get_language_from_filename (curfdp
->infname
, FALSE
);
1724 if (lang
!= NULL
&& lang
->function
!= NULL
)
1726 curfdp
->lang
= lang
;
1727 parser
= lang
->function
;
1731 /* Else try Fortran or C. */
1734 node
*old_last_node
= last_node
;
1736 curfdp
->lang
= get_language_from_langname ("fortran");
1739 if (old_last_node
== last_node
)
1740 /* No Fortran entries found. Try C. */
1742 /* We do not tag if rewind fails.
1743 Only the file name will be recorded in the tags file. */
1745 curfdp
->lang
= get_language_from_langname (cplusplus
? "c++" : "c");
1751 if (!no_line_directive
1752 && curfdp
->lang
!= NULL
&& curfdp
->lang
->metasource
)
1753 /* It may be that this is a bingo.y file, and we already parsed a bingo.c
1754 file, or anyway we parsed a file that is automatically generated from
1755 this one. If this is the case, the bingo.c file contained #line
1756 directives that generated tags pointing to this file. Let's delete
1757 them all before parsing this file, which is the real source. */
1759 fdesc
**fdpp
= &fdhead
;
1760 while (*fdpp
!= NULL
)
1762 && streq ((*fdpp
)->taggedfname
, curfdp
->taggedfname
))
1763 /* We found one of those! We must delete both the file description
1764 and all tags referring to it. */
1766 fdesc
*badfdp
= *fdpp
;
1770 "Removing references to \"%s\" obtained from \"%s\"\n",
1771 badfdp
->taggedfname
, badfdp
->infname
);
1773 /* Delete the tags referring to badfdp. */
1774 invalidate_nodes (badfdp
, &nodehead
);
1776 *fdpp
= badfdp
->next
; /* remove the bad description from the list */
1777 free_fdesc (badfdp
);
1780 fdpp
= &(*fdpp
)->next
; /* advance the list pointer */
1783 assert (parser
!= NULL
);
1785 /* Generic initialisations before reading from file. */
1786 linebuffer_setlen (&filebuf
, 0); /* reset the file buffer */
1788 /* Generic initialisations before parsing file with readline. */
1789 lineno
= 0; /* reset global line number */
1790 charno
= 0; /* reset global char number */
1791 linecharno
= 0; /* reset global char number of line start */
1795 #ifdef ETAGS_REGEXPS
1796 regex_tag_multiline ();
1797 #endif /* ETAGS_REGEXPS */
1802 * Check whether an implicitly named tag should be created,
1803 * then call `pfnote'.
1804 * NAME is a string that is internally copied by this function.
1806 * TAGS format specification
1807 * Idea by Sam Kendall <kendall@mv.mv.com> (1997)
1808 * The following is explained in some more detail in etc/ETAGS.EBNF.
1810 * make_tag creates tags with "implicit tag names" (unnamed tags)
1811 * if the following are all true, assuming NONAM=" \f\t\n\r()=,;":
1812 * 1. NAME does not contain any of the characters in NONAM;
1813 * 2. LINESTART contains name as either a rightmost, or rightmost but
1814 * one character, substring;
1815 * 3. the character, if any, immediately before NAME in LINESTART must
1816 * be a character in NONAM;
1817 * 4. the character, if any, immediately after NAME in LINESTART must
1818 * also be a character in NONAM.
1820 * The implementation uses the notinname() macro, which recognises the
1821 * characters stored in the string `nonam'.
1822 * etags.el needs to use the same characters that are in NONAM.
1825 make_tag (name
, namelen
, is_func
, linestart
, linelen
, lno
, cno
)
1826 char *name
; /* tag name, or NULL if unnamed */
1827 int namelen
; /* tag length */
1828 bool is_func
; /* tag is a function */
1829 char *linestart
; /* start of the line where tag is */
1830 int linelen
; /* length of the line where tag is */
1831 int lno
; /* line number */
1832 long cno
; /* character number */
1834 bool named
= (name
!= NULL
&& namelen
> 0);
1836 if (!CTAGS
&& named
) /* maybe set named to false */
1837 /* Let's try to make an implicit tag name, that is, create an unnamed tag
1838 such that etags.el can guess a name from it. */
1841 register char *cp
= name
;
1843 for (i
= 0; i
< namelen
; i
++)
1844 if (notinname (*cp
++))
1846 if (i
== namelen
) /* rule #1 */
1848 cp
= linestart
+ linelen
- namelen
;
1849 if (notinname (linestart
[linelen
-1]))
1850 cp
-= 1; /* rule #4 */
1851 if (cp
>= linestart
/* rule #2 */
1853 || notinname (cp
[-1])) /* rule #3 */
1854 && strneq (name
, cp
, namelen
)) /* rule #2 */
1855 named
= FALSE
; /* use implicit tag name */
1860 name
= savenstr (name
, namelen
);
1863 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
);
1868 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
)
1869 char *name
; /* tag name, or NULL if unnamed */
1870 bool is_func
; /* tag is a function */
1871 char *linestart
; /* start of the line where tag is */
1872 int linelen
; /* length of the line where tag is */
1873 int lno
; /* line number */
1874 long cno
; /* character number */
1878 if (CTAGS
&& name
== NULL
)
1881 np
= xnew (1, node
);
1883 /* If ctags mode, change name "main" to M<thisfilename>. */
1884 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
1886 register char *fp
= etags_strrchr (curfdp
->taggedfname
, '/');
1887 np
->name
= concat ("M", fp
== NULL
? curfdp
->taggedfname
: fp
+ 1, "");
1888 fp
= etags_strrchr (np
->name
, '.');
1889 if (fp
!= NULL
&& fp
[1] != '\0' && fp
[2] == '\0')
1895 np
->been_warned
= FALSE
;
1897 np
->is_func
= is_func
;
1899 if (np
->fdp
->usecharno
)
1900 /* Our char numbers are 0-base, because of C language tradition?
1901 ctags compatibility? old versions compatibility? I don't know.
1902 Anyway, since emacs's are 1-base we expect etags.el to take care
1903 of the difference. If we wanted to have 1-based numbers, we would
1904 uncomment the +1 below. */
1905 np
->cno
= cno
/* + 1 */ ;
1907 np
->cno
= invalidcharno
;
1908 np
->left
= np
->right
= NULL
;
1909 if (CTAGS
&& !cxref_style
)
1911 if (strlen (linestart
) < 50)
1912 np
->regex
= concat (linestart
, "$", "");
1914 np
->regex
= savenstr (linestart
, 50);
1917 np
->regex
= savenstr (linestart
, linelen
);
1919 add_node (np
, &nodehead
);
1924 * recurse on left children, iterate on right children.
1932 register node
*node_right
= np
->right
;
1933 free_tree (np
->left
);
1934 if (np
->name
!= NULL
)
1944 * delete a file description
1948 register fdesc
*fdp
;
1950 if (fdp
->infname
!= NULL
) free (fdp
->infname
);
1951 if (fdp
->infabsname
!= NULL
) free (fdp
->infabsname
);
1952 if (fdp
->infabsdir
!= NULL
) free (fdp
->infabsdir
);
1953 if (fdp
->taggedfname
!= NULL
) free (fdp
->taggedfname
);
1954 if (fdp
->prop
!= NULL
) free (fdp
->prop
);
1960 * Adds a node to the tree of nodes. In etags mode, sort by file
1961 * name. In ctags mode, sort by tag name. Make no attempt at
1964 * add_node is the only function allowed to add nodes, so it can
1968 add_node (np
, cur_node_p
)
1969 node
*np
, **cur_node_p
;
1972 register node
*cur_node
= *cur_node_p
;
1974 if (cur_node
== NULL
)
1984 /* For each file name, tags are in a linked sublist on the right
1985 pointer. The first tags of different files are a linked list
1986 on the left pointer. last_node points to the end of the last
1988 if (last_node
!= NULL
&& last_node
->fdp
== np
->fdp
)
1990 /* Let's use the same sublist as the last added node. */
1991 assert (last_node
->right
== NULL
);
1992 last_node
->right
= np
;
1995 else if (cur_node
->fdp
== np
->fdp
)
1997 /* Scanning the list we found the head of a sublist which is
1998 good for us. Let's scan this sublist. */
1999 add_node (np
, &cur_node
->right
);
2002 /* The head of this sublist is not good for us. Let's try the
2004 add_node (np
, &cur_node
->left
);
2005 } /* if ETAGS mode */
2010 dif
= strcmp (np
->name
, cur_node
->name
);
2013 * If this tag name matches an existing one, then
2014 * do not add the node, but maybe print a warning.
2018 if (np
->fdp
== cur_node
->fdp
)
2022 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
2023 np
->fdp
->infname
, lineno
, np
->name
);
2024 fprintf (stderr
, "Second entry ignored\n");
2027 else if (!cur_node
->been_warned
&& !no_warnings
)
2031 "Duplicate entry in files %s and %s: %s (Warning only)\n",
2032 np
->fdp
->infname
, cur_node
->fdp
->infname
, np
->name
);
2033 cur_node
->been_warned
= TRUE
;
2038 /* Actually add the node */
2039 add_node (np
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
2040 } /* if CTAGS mode */
2044 * invalidate_nodes ()
2045 * Scan the node tree and invalidate all nodes pointing to the
2046 * given file description (CTAGS case) or free them (ETAGS case).
2049 invalidate_nodes (badfdp
, npp
)
2060 if (np
->left
!= NULL
)
2061 invalidate_nodes (badfdp
, &np
->left
);
2062 if (np
->fdp
== badfdp
)
2064 if (np
->right
!= NULL
)
2065 invalidate_nodes (badfdp
, &np
->right
);
2069 assert (np
->fdp
!= NULL
);
2070 if (np
->fdp
== badfdp
)
2072 *npp
= np
->left
; /* detach the sublist from the list */
2073 np
->left
= NULL
; /* isolate it */
2074 free_tree (np
); /* free it */
2075 invalidate_nodes (badfdp
, npp
);
2078 invalidate_nodes (badfdp
, &np
->left
);
2083 static int total_size_of_entries
__P((node
*));
2084 static int number_len
__P((long));
2086 /* Length of a non-negative number's decimal representation. */
2092 while ((num
/= 10) > 0)
2098 * Return total number of characters that put_entries will output for
2099 * the nodes in the linked list at the right of the specified node.
2100 * This count is irrelevant with etags.el since emacs 19.34 at least,
2101 * but is still supplied for backward compatibility.
2104 total_size_of_entries (np
)
2107 register int total
= 0;
2109 for (; np
!= NULL
; np
= np
->right
)
2112 total
+= strlen (np
->regex
) + 1; /* pat\177 */
2113 if (np
->name
!= NULL
)
2114 total
+= strlen (np
->name
) + 1; /* name\001 */
2115 total
+= number_len ((long) np
->lno
) + 1; /* lno, */
2116 if (np
->cno
!= invalidcharno
) /* cno */
2117 total
+= number_len (np
->cno
);
2118 total
+= 1; /* newline */
2129 static fdesc
*fdp
= NULL
;
2134 /* Output subentries that precede this one */
2136 put_entries (np
->left
);
2138 /* Output this entry */
2147 fprintf (tagf
, "\f\n%s,%d\n",
2148 fdp
->taggedfname
, total_size_of_entries (np
));
2149 fdp
->written
= TRUE
;
2151 fputs (np
->regex
, tagf
);
2152 fputc ('\177', tagf
);
2153 if (np
->name
!= NULL
)
2155 fputs (np
->name
, tagf
);
2156 fputc ('\001', tagf
);
2158 fprintf (tagf
, "%d,", np
->lno
);
2159 if (np
->cno
!= invalidcharno
)
2160 fprintf (tagf
, "%ld", np
->cno
);
2166 if (np
->name
== NULL
)
2167 error ("internal error: NULL name in ctags mode.", (char *)NULL
);
2172 fprintf (stdout
, "%s %s %d\n",
2173 np
->name
, np
->fdp
->taggedfname
, (np
->lno
+ 63) / 64);
2175 fprintf (stdout
, "%-16s %3d %-16s %s\n",
2176 np
->name
, np
->lno
, np
->fdp
->taggedfname
, np
->regex
);
2180 fprintf (tagf
, "%s\t%s\t", np
->name
, np
->fdp
->taggedfname
);
2183 { /* function or #define macro with args */
2184 putc (searchar
, tagf
);
2187 for (sp
= np
->regex
; *sp
; sp
++)
2189 if (*sp
== '\\' || *sp
== searchar
)
2193 putc (searchar
, tagf
);
2196 { /* anything else; text pattern inadequate */
2197 fprintf (tagf
, "%d", np
->lno
);
2202 } /* if this node contains a valid tag */
2204 /* Output subentries that follow this one */
2205 put_entries (np
->right
);
2207 put_entries (np
->left
);
2212 #define C_EXT 0x00fff /* C extensions */
2213 #define C_PLAIN 0x00000 /* C */
2214 #define C_PLPL 0x00001 /* C++ */
2215 #define C_STAR 0x00003 /* C* */
2216 #define C_JAVA 0x00005 /* JAVA */
2217 #define C_AUTO 0x01000 /* C, but switch to C++ if `class' is met */
2218 #define YACC 0x10000 /* yacc file */
2221 * The C symbol tables.
2226 st_C_objprot
, st_C_objimpl
, st_C_objend
,
2231 st_C_class
, st_C_template
,
2232 st_C_struct
, st_C_extern
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
2235 static unsigned int hash
__P((const char *, unsigned int));
2236 static struct C_stab_entry
* in_word_set
__P((const char *, unsigned int));
2237 static enum sym_type C_symtype
__P((char *, int, int));
2239 /* Feed stuff between (but not including) %[ and %] lines to:
2240 gperf -c -k 1,3 -o -p -r -t
2242 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
2246 while, 0, st_C_ignore
2247 switch, 0, st_C_ignore
2248 return, 0, st_C_ignore
2249 @interface, 0, st_C_objprot
2250 @protocol, 0, st_C_objprot
2251 @implementation,0, st_C_objimpl
2252 @end, 0, st_C_objend
2253 import, C_JAVA, st_C_ignore
2254 package, C_JAVA, st_C_ignore
2255 friend, C_PLPL, st_C_ignore
2256 extends, C_JAVA, st_C_javastruct
2257 implements, C_JAVA, st_C_javastruct
2258 interface, C_JAVA, st_C_struct
2259 class, 0, st_C_class
2260 namespace, C_PLPL, st_C_struct
2261 domain, C_STAR, st_C_struct
2262 union, 0, st_C_struct
2263 struct, 0, st_C_struct
2264 extern, 0, st_C_extern
2266 typedef, 0, st_C_typedef
2267 define, 0, st_C_define
2268 operator, C_PLPL, st_C_operator
2269 template, 0, st_C_template
2270 bool, C_PLPL, st_C_typespec
2271 long, 0, st_C_typespec
2272 short, 0, st_C_typespec
2273 int, 0, st_C_typespec
2274 char, 0, st_C_typespec
2275 float, 0, st_C_typespec
2276 double, 0, st_C_typespec
2277 signed, 0, st_C_typespec
2278 unsigned, 0, st_C_typespec
2279 auto, 0, st_C_typespec
2280 void, 0, st_C_typespec
2281 static, 0, st_C_typespec
2282 const, 0, st_C_typespec
2283 volatile, 0, st_C_typespec
2284 explicit, C_PLPL, st_C_typespec
2285 mutable, C_PLPL, st_C_typespec
2286 typename, C_PLPL, st_C_typespec
2287 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
2288 DEFUN, 0, st_C_gnumacro
2289 SYSCALL, 0, st_C_gnumacro
2290 ENTRY, 0, st_C_gnumacro
2291 PSEUDO, 0, st_C_gnumacro
2292 # These are defined inside C functions, so currently they are not met.
2293 # EXFUN used in glibc, DEFVAR_* in emacs.
2294 #EXFUN, 0, st_C_gnumacro
2295 #DEFVAR_, 0, st_C_gnumacro
2297 and replace lines between %< and %> with its output,
2298 then make in_word_set and C_stab_entry static. */
2300 /* C code produced by gperf version 2.7.1 (19981006 egcs) */
2301 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
2302 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
2304 #define TOTAL_KEYWORDS 47
2305 #define MIN_WORD_LENGTH 2
2306 #define MAX_WORD_LENGTH 15
2307 #define MIN_HASH_VALUE 18
2308 #define MAX_HASH_VALUE 138
2309 /* maximum key range = 121, duplicates = 0 */
2316 register const char *str
;
2317 register unsigned int len
;
2319 static unsigned char asso_values
[] =
2321 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2322 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2323 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2324 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2325 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2326 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2327 139, 139, 139, 139, 63, 139, 139, 139, 33, 44,
2328 62, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2329 42, 139, 139, 12, 32, 139, 139, 139, 139, 139,
2330 139, 139, 139, 139, 139, 139, 139, 34, 59, 37,
2331 24, 58, 33, 3, 139, 16, 139, 139, 42, 60,
2332 18, 11, 39, 139, 23, 57, 4, 63, 6, 20,
2333 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2334 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2335 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2336 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2337 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2338 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2339 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2340 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2341 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2342 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2343 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2344 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2345 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2346 139, 139, 139, 139, 139, 139
2348 register int hval
= len
;
2354 hval
+= asso_values
[(unsigned char)str
[2]];
2357 hval
+= asso_values
[(unsigned char)str
[0]];
2366 static struct C_stab_entry
*
2367 in_word_set (str
, len
)
2368 register const char *str
;
2369 register unsigned int len
;
2371 static struct C_stab_entry wordlist
[] =
2373 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2374 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2375 {"if", 0, st_C_ignore
},
2376 {""}, {""}, {""}, {""},
2377 {"int", 0, st_C_typespec
},
2379 {"void", 0, st_C_typespec
},
2381 {"interface", C_JAVA
, st_C_struct
},
2383 {"SYSCALL", 0, st_C_gnumacro
},
2385 {"return", 0, st_C_ignore
},
2386 {""}, {""}, {""}, {""}, {""}, {""}, {""},
2387 {"while", 0, st_C_ignore
},
2388 {"auto", 0, st_C_typespec
},
2389 {""}, {""}, {""}, {""}, {""}, {""},
2390 {"float", 0, st_C_typespec
},
2391 {"typedef", 0, st_C_typedef
},
2392 {"typename", C_PLPL
, st_C_typespec
},
2394 {"friend", C_PLPL
, st_C_ignore
},
2395 {"volatile", 0, st_C_typespec
},
2397 {"for", 0, st_C_ignore
},
2398 {"const", 0, st_C_typespec
},
2399 {"import", C_JAVA
, st_C_ignore
},
2401 {"define", 0, st_C_define
},
2402 {"long", 0, st_C_typespec
},
2403 {"implements", C_JAVA
, st_C_javastruct
},
2404 {"signed", 0, st_C_typespec
},
2406 {"extern", 0, st_C_extern
},
2407 {"extends", C_JAVA
, st_C_javastruct
},
2409 {"mutable", C_PLPL
, st_C_typespec
},
2410 {"template", 0, st_C_template
},
2411 {"short", 0, st_C_typespec
},
2412 {"bool", C_PLPL
, st_C_typespec
},
2413 {"char", 0, st_C_typespec
},
2414 {"class", 0, st_C_class
},
2415 {"operator", C_PLPL
, st_C_operator
},
2417 {"switch", 0, st_C_ignore
},
2419 {"ENTRY", 0, st_C_gnumacro
},
2421 {"package", C_JAVA
, st_C_ignore
},
2422 {"union", 0, st_C_struct
},
2423 {"@end", 0, st_C_objend
},
2424 {"struct", 0, st_C_struct
},
2425 {"namespace", C_PLPL
, st_C_struct
},
2427 {"domain", C_STAR
, st_C_struct
},
2428 {"@interface", 0, st_C_objprot
},
2429 {"PSEUDO", 0, st_C_gnumacro
},
2430 {"double", 0, st_C_typespec
},
2432 {"@protocol", 0, st_C_objprot
},
2434 {"static", 0, st_C_typespec
},
2436 {"DEFUN", 0, st_C_gnumacro
},
2437 {""}, {""}, {""}, {""},
2438 {"explicit", C_PLPL
, st_C_typespec
},
2439 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2440 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2442 {"enum", 0, st_C_enum
},
2444 {"unsigned", 0, st_C_typespec
},
2445 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2446 {"@implementation",0, st_C_objimpl
}
2449 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
2451 register int key
= hash (str
, len
);
2453 if (key
<= MAX_HASH_VALUE
&& key
>= 0)
2455 register const char *s
= wordlist
[key
].name
;
2457 if (*str
== *s
&& !strncmp (str
+ 1, s
+ 1, len
- 1))
2458 return &wordlist
[key
];
2465 static enum sym_type
2466 C_symtype (str
, len
, c_ext
)
2471 register struct C_stab_entry
*se
= in_word_set (str
, len
);
2473 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
2480 * C functions and variables are recognized using a simple
2481 * finite automaton. fvdef is its state variable.
2485 fvnone
, /* nothing seen */
2486 fdefunkey
, /* Emacs DEFUN keyword seen */
2487 fdefunname
, /* Emacs DEFUN name seen */
2488 foperator
, /* func: operator keyword seen (cplpl) */
2489 fvnameseen
, /* function or variable name seen */
2490 fstartlist
, /* func: just after open parenthesis */
2491 finlist
, /* func: in parameter list */
2492 flistseen
, /* func: after parameter list */
2493 fignore
, /* func: before open brace */
2494 vignore
/* var-like: ignore until ';' */
2497 static bool fvextern
; /* func or var: extern keyword seen; */
2500 * typedefs are recognized using a simple finite automaton.
2501 * typdef is its state variable.
2505 tnone
, /* nothing seen */
2506 tkeyseen
, /* typedef keyword seen */
2507 ttypeseen
, /* defined type seen */
2508 tinbody
, /* inside typedef body */
2509 tend
, /* just before typedef tag */
2510 tignore
/* junk after typedef tag */
2514 * struct-like structures (enum, struct and union) are recognized
2515 * using another simple finite automaton. `structdef' is its state
2520 snone
, /* nothing seen yet,
2521 or in struct body if cblev > 0 */
2522 skeyseen
, /* struct-like keyword seen */
2523 stagseen
, /* struct-like tag seen */
2524 sintemplate
, /* inside template (ignore) */
2525 scolonseen
/* colon seen after struct-like tag */
2529 * When objdef is different from onone, objtag is the name of the class.
2531 static char *objtag
= "<uninited>";
2534 * Yet another little state machine to deal with preprocessor lines.
2538 dnone
, /* nothing seen */
2539 dsharpseen
, /* '#' seen as first char on line */
2540 ddefineseen
, /* '#' and 'define' seen */
2541 dignorerest
/* ignore rest of line */
2545 * State machine for Objective C protocols and implementations.
2546 * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995)
2550 onone
, /* nothing seen */
2551 oprotocol
, /* @interface or @protocol seen */
2552 oimplementation
, /* @implementations seen */
2553 otagseen
, /* class name seen */
2554 oparenseen
, /* parenthesis before category seen */
2555 ocatseen
, /* category name seen */
2556 oinbody
, /* in @implementation body */
2557 omethodsign
, /* in @implementation body, after +/- */
2558 omethodtag
, /* after method name */
2559 omethodcolon
, /* after method colon */
2560 omethodparm
, /* after method parameter */
2561 oignore
/* wait for @end */
2566 * Use this structure to keep info about the token read, and how it
2567 * should be tagged. Used by the make_C_tag function to build a tag.
2578 } token
; /* latest token read */
2581 * Variables and functions for dealing with nested structures.
2582 * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001)
2584 static void pushclass_above
__P((int, char *, int));
2585 static void popclass_above
__P((int));
2586 static void write_classname
__P((linebuffer
*, char *qualifier
));
2589 char **cname
; /* nested class names */
2590 int *cblev
; /* nested class curly brace level */
2591 int nl
; /* class nesting level (elements used) */
2592 int size
; /* length of the array */
2593 } cstack
; /* stack for nested declaration tags */
2594 /* Current struct nesting depth (namespace, class, struct, union, enum). */
2595 #define nestlev (cstack.nl)
2596 /* After struct keyword or in struct body, not inside a nested function. */
2597 #define instruct (structdef == snone && nestlev > 0 \
2598 && cblev == cstack.cblev[nestlev-1] + 1)
2601 pushclass_above (cblev
, str
, len
)
2608 popclass_above (cblev
);
2610 if (nl
>= cstack
.size
)
2612 int size
= cstack
.size
*= 2;
2613 xrnew (cstack
.cname
, size
, char *);
2614 xrnew (cstack
.cblev
, size
, int);
2616 assert (nl
== 0 || cstack
.cblev
[nl
-1] < cblev
);
2617 cstack
.cname
[nl
] = (str
== NULL
) ? NULL
: savenstr (str
, len
);
2618 cstack
.cblev
[nl
] = cblev
;
2623 popclass_above (cblev
)
2628 for (nl
= cstack
.nl
- 1;
2629 nl
>= 0 && cstack
.cblev
[nl
] >= cblev
;
2632 if (cstack
.cname
[nl
] != NULL
)
2633 free (cstack
.cname
[nl
]);
2639 write_classname (cn
, qualifier
)
2644 int qlen
= strlen (qualifier
);
2646 if (cstack
.nl
== 0 || cstack
.cname
[0] == NULL
)
2650 cn
->buffer
[0] = '\0';
2654 len
= strlen (cstack
.cname
[0]);
2655 linebuffer_setlen (cn
, len
);
2656 strcpy (cn
->buffer
, cstack
.cname
[0]);
2658 for (i
= 1; i
< cstack
.nl
; i
++)
2663 s
= cstack
.cname
[i
];
2668 linebuffer_setlen (cn
, len
);
2669 strncat (cn
->buffer
, qualifier
, qlen
);
2670 strncat (cn
->buffer
, s
, slen
);
2675 static bool consider_token
__P((char *, int, int, int *, int, int, bool *));
2676 static void make_C_tag
__P((bool));
2680 * checks to see if the current token is at the start of a
2681 * function or variable, or corresponds to a typedef, or
2682 * is a struct/union/enum tag, or #define, or an enum constant.
2684 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2685 * with args. C_EXTP points to which language we are looking at.
2696 consider_token (str
, len
, c
, c_extp
, cblev
, parlev
, is_func_or_var
)
2697 register char *str
; /* IN: token pointer */
2698 register int len
; /* IN: token length */
2699 register int c
; /* IN: first char after the token */
2700 int *c_extp
; /* IN, OUT: C extensions mask */
2701 int cblev
; /* IN: curly brace level */
2702 int parlev
; /* IN: parenthesis level */
2703 bool *is_func_or_var
; /* OUT: function or variable found */
2705 /* When structdef is stagseen, scolonseen, or snone with cblev > 0,
2706 structtype is the type of the preceding struct-like keyword, and
2707 structcblev is the curly brace level where it has been seen. */
2708 static enum sym_type structtype
;
2709 static int structcblev
;
2710 static enum sym_type toktype
;
2713 toktype
= C_symtype (str
, len
, *c_extp
);
2716 * Advance the definedef state machine.
2721 /* We're not on a preprocessor line. */
2722 if (toktype
== st_C_gnumacro
)
2729 if (toktype
== st_C_define
)
2731 definedef
= ddefineseen
;
2735 definedef
= dignorerest
;
2740 * Make a tag for any macro, unless it is a constant
2741 * and constantypedefs is FALSE.
2743 definedef
= dignorerest
;
2744 *is_func_or_var
= (c
== '(');
2745 if (!*is_func_or_var
&& !constantypedefs
)
2752 error ("internal error: definedef value.", (char *)NULL
);
2761 if (toktype
== st_C_typedef
)
2783 if (structdef
== snone
&& fvdef
== fvnone
)
2802 * This structdef business is NOT invoked when we are ctags and the
2803 * file is plain C. This is because a struct tag may have the same
2804 * name as another tag, and this loses with ctags.
2808 case st_C_javastruct
:
2809 if (structdef
== stagseen
)
2810 structdef
= scolonseen
;
2815 && (*c_extp
& C_AUTO
) /* automatic detection of C++ language */
2816 && definedef
== dnone
&& structdef
== snone
2817 && typdef
== tnone
&& fvdef
== fvnone
)
2818 *c_extp
= (*c_extp
| C_PLPL
) & ~C_AUTO
;
2819 if (toktype
== st_C_template
)
2826 && (typdef
== tkeyseen
2827 || (typedefs_or_cplusplus
&& structdef
== snone
)))
2829 structdef
= skeyseen
;
2830 structtype
= toktype
;
2831 structcblev
= cblev
;
2836 if (structdef
== skeyseen
)
2838 structdef
= stagseen
;
2842 if (typdef
!= tnone
)
2845 /* Detect Objective C constructs. */
2855 objdef
= oimplementation
;
2859 case oimplementation
:
2860 /* Save the class tag for functions or variables defined inside. */
2861 objtag
= savenstr (str
, len
);
2865 /* Save the class tag for categories. */
2866 objtag
= savenstr (str
, len
);
2868 *is_func_or_var
= TRUE
;
2872 *is_func_or_var
= TRUE
;
2879 objdef
= omethodtag
;
2880 linebuffer_setlen (&token_name
, len
);
2881 strncpy (token_name
.buffer
, str
, len
);
2882 token_name
.buffer
[len
] = '\0';
2888 objdef
= omethodparm
;
2893 objdef
= omethodtag
;
2894 linebuffer_setlen (&token_name
, token_name
.len
+ len
);
2895 strncat (token_name
.buffer
, str
, len
);
2900 if (toktype
== st_C_objend
)
2902 /* Memory leakage here: the string pointed by objtag is
2903 never released, because many tests would be needed to
2904 avoid breaking on incorrect input code. The amount of
2905 memory leaked here is the sum of the lengths of the
2913 /* A function, variable or enum constant? */
2920 if (fvdef
!= finlist
&& fvdef
!= fignore
&& fvdef
!= vignore
)
2921 fvdef
= fvnone
; /* should be useless */
2929 *is_func_or_var
= TRUE
;
2933 && structdef
== snone
2934 && structtype
== st_C_enum
&& cblev
> structcblev
)
2935 return TRUE
; /* enum constant */
2941 fvdef
= fdefunname
; /* GNU macro */
2942 *is_func_or_var
= TRUE
;
2945 if ((strneq (str
, "asm", 3) && endtoken (str
[3]))
2946 || (strneq (str
, "__asm__", 7) && endtoken (str
[7])))
2951 if ((*c_extp
& C_PLPL
) && strneq (str
+len
-10, "::operator", 10))
2954 *is_func_or_var
= TRUE
;
2957 if (cblev
> 0 && !instruct
)
2959 fvdef
= fvnameseen
; /* function or variable */
2960 *is_func_or_var
= TRUE
;
2971 * C_entries often keeps pointers to tokens or lines which are older than
2972 * the line currently read. By keeping two line buffers, and switching
2973 * them at end of line, it is possible to use those pointers.
2981 #define current_lb_is_new (newndx == curndx)
2982 #define switch_line_buffers() (curndx = 1 - curndx)
2984 #define curlb (lbs[curndx].lb)
2985 #define newlb (lbs[newndx].lb)
2986 #define curlinepos (lbs[curndx].linepos)
2987 #define newlinepos (lbs[newndx].linepos)
2989 #define cplpl ((c_ext & C_PLPL) == C_PLPL)
2990 #define cjava ((c_ext & C_JAVA) == C_JAVA)
2992 #define CNL_SAVE_DEFINEDEF() \
2994 curlinepos = charno; \
2995 readline (&curlb, inf); \
2996 lp = curlb.buffer; \
3003 CNL_SAVE_DEFINEDEF(); \
3004 if (savetoken.valid) \
3006 token = savetoken; \
3007 savetoken.valid = FALSE; \
3009 definedef = dnone; \
3017 /* This function should never be called when token.valid is FALSE, but
3018 we must protect against invalid input or internal errors. */
3019 if (!DEBUG
&& !token
.valid
)
3022 if (!token
.valid
) /* this case is optimised away if !DEBUG */
3023 make_tag (concat (token_name
.buffer
, "##invalid token##", ""),
3024 token_name
.len
+ 17, isfun
, token
.line
,
3025 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
3027 make_tag (token_name
.buffer
, token_name
.len
, isfun
, token
.line
,
3028 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
3030 token
.valid
= FALSE
;
3036 * This routine finds functions, variables, typedefs,
3037 * #define's, enum constants and struct/union/enum definitions in
3038 * C syntax and adds them to the list.
3041 C_entries (c_ext
, inf
)
3042 int c_ext
; /* extension of C */
3043 FILE *inf
; /* input file */
3045 register char c
; /* latest char read; '\0' for end of line */
3046 register char *lp
; /* pointer one beyond the character `c' */
3047 int curndx
, newndx
; /* indices for current and new lb */
3048 register int tokoff
; /* offset in line of start of current token */
3049 register int toklen
; /* length of current token */
3050 char *qualifier
; /* string used to qualify names */
3051 int qlen
; /* length of qualifier */
3052 int cblev
; /* current curly brace level */
3053 int parlev
; /* current parenthesis level */
3054 int typdefcblev
; /* cblev where a typedef struct body begun */
3055 bool incomm
, inquote
, inchar
, quotednl
, midtoken
;
3056 bool yacc_rules
; /* in the rules part of a yacc file */
3057 struct tok savetoken
; /* token saved during preprocessor handling */
3060 linebuffer_init (&lbs
[0].lb
);
3061 linebuffer_init (&lbs
[1].lb
);
3062 if (cstack
.size
== 0)
3064 cstack
.size
= (DEBUG
) ? 1 : 4;
3066 cstack
.cname
= xnew (cstack
.size
, char *);
3067 cstack
.cblev
= xnew (cstack
.size
, int);
3070 tokoff
= toklen
= typdefcblev
= 0; /* keep compiler quiet */
3071 curndx
= newndx
= 0;
3075 fvdef
= fvnone
; fvextern
= FALSE
; typdef
= tnone
;
3076 structdef
= snone
; definedef
= dnone
; objdef
= onone
;
3078 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3079 token
.valid
= savetoken
.valid
= FALSE
;
3083 { qualifier
= "."; qlen
= 1; }
3085 { qualifier
= "::"; qlen
= 2; }
3093 /* If we're at the end of the line, the next character is a
3094 '\0'; don't skip it, because it's the thing that tells us
3095 to read the next line. */
3116 /* Newlines inside comments do not end macro definitions in
3118 CNL_SAVE_DEFINEDEF ();
3131 /* Newlines inside strings do not end macro definitions
3132 in traditional cpp, even though compilers don't
3133 usually accept them. */
3134 CNL_SAVE_DEFINEDEF ();
3144 /* Hmmm, something went wrong. */
3173 if (fvdef
!= finlist
&& fvdef
!= fignore
&& fvdef
!=vignore
)
3186 else if (/* cplpl && */ *lp
== '/')
3194 if ((c_ext
& YACC
) && *lp
== '%')
3196 /* Entering or exiting rules section in yacc file. */
3198 definedef
= dnone
; fvdef
= fvnone
; fvextern
= FALSE
;
3199 typdef
= tnone
; structdef
= snone
;
3200 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3202 yacc_rules
= !yacc_rules
;
3208 if (definedef
== dnone
)
3211 bool cpptoken
= TRUE
;
3213 /* Look back on this line. If all blanks, or nonblanks
3214 followed by an end of comment, this is a preprocessor
3216 for (cp
= newlb
.buffer
; cp
< lp
-1; cp
++)
3219 if (*cp
== '*' && *(cp
+1) == '/')
3228 definedef
= dsharpseen
;
3229 } /* if (definedef == dnone) */
3235 /* Consider token only if some involved conditions are satisfied. */
3236 if (typdef
!= tignore
3237 && definedef
!= dignorerest
3239 && structdef
!= sintemplate
3240 && (definedef
!= dnone
3241 || structdef
!= scolonseen
))
3247 if (c
== ':' && cplpl
&& *lp
== ':' && begtoken (lp
[1]))
3250 * This handles :: in the middle, but not at the
3251 * beginning of an identifier. Also, space-separated
3252 * :: is not recognised.
3257 goto still_in_token
;
3261 bool funorvar
= FALSE
;
3264 || consider_token (newlb
.buffer
+ tokoff
, toklen
, c
,
3265 &c_ext
, cblev
, parlev
, &funorvar
))
3267 if (fvdef
== foperator
)
3270 lp
= skip_spaces (lp
-1);
3274 && !iswhite (*lp
) && *lp
!= '(')
3277 toklen
+= lp
- oldlp
;
3279 token
.named
= FALSE
;
3280 if ((c_ext
& C_EXT
) /* not pure C */
3281 && nestlev
> 0 && definedef
== dnone
)
3282 /* in struct body */
3284 write_classname (&token_name
, qualifier
);
3285 linebuffer_setlen (&token_name
,
3286 token_name
.len
+qlen
+toklen
);
3287 strcat (token_name
.buffer
, qualifier
);
3288 strncat (token_name
.buffer
,
3289 newlb
.buffer
+ tokoff
, toklen
);
3292 else if (objdef
== ocatseen
)
3293 /* Objective C category */
3295 int len
= strlen (objtag
) + 2 + toklen
;
3296 linebuffer_setlen (&token_name
, len
);
3297 strcpy (token_name
.buffer
, objtag
);
3298 strcat (token_name
.buffer
, "(");
3299 strncat (token_name
.buffer
,
3300 newlb
.buffer
+ tokoff
, toklen
);
3301 strcat (token_name
.buffer
, ")");
3304 else if (objdef
== omethodtag
3305 || objdef
== omethodparm
)
3306 /* Objective C method */
3310 else if (fvdef
== fdefunname
)
3311 /* GNU DEFUN and similar macros */
3313 bool defun
= (newlb
.buffer
[tokoff
] == 'F');
3317 /* Rewrite the tag so that emacs lisp DEFUNs
3318 can be found by their elisp name */
3325 linebuffer_setlen (&token_name
, len
);
3326 strncpy (token_name
.buffer
,
3327 newlb
.buffer
+ off
, len
);
3328 token_name
.buffer
[len
] = '\0';
3331 if (token_name
.buffer
[len
] == '_')
3332 token_name
.buffer
[len
] = '-';
3333 token
.named
= defun
;
3337 linebuffer_setlen (&token_name
, toklen
);
3338 strncpy (token_name
.buffer
,
3339 newlb
.buffer
+ tokoff
, toklen
);
3340 token_name
.buffer
[toklen
] = '\0';
3341 /* Name macros and members. */
3342 token
.named
= (structdef
== stagseen
3343 || typdef
== ttypeseen
3346 && definedef
== dignorerest
)
3348 && definedef
== dnone
3349 && structdef
== snone
3352 token
.lineno
= lineno
;
3353 token
.offset
= tokoff
;
3354 token
.length
= toklen
;
3355 token
.line
= newlb
.buffer
;
3356 token
.linepos
= newlinepos
;
3359 if (definedef
== dnone
3360 && (fvdef
== fvnameseen
3361 || fvdef
== foperator
3362 || structdef
== stagseen
3364 || typdef
== ttypeseen
3365 || objdef
!= onone
))
3367 if (current_lb_is_new
)
3368 switch_line_buffers ();
3370 else if (definedef
!= dnone
3371 || fvdef
== fdefunname
3373 make_C_tag (funorvar
);
3377 } /* if (endtoken (c)) */
3378 else if (intoken (c
))
3384 } /* if (midtoken) */
3385 else if (begtoken (c
))
3397 if (!instruct
|| members
)
3399 make_C_tag (TRUE
); /* a function */
3406 if (structdef
== stagseen
&& !cjava
)
3408 popclass_above (cblev
);
3416 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
3418 tokoff
= lp
- 1 - newlb
.buffer
;
3423 } /* if (begtoken) */
3424 } /* if must look at token */
3427 /* Detect end of line, colon, comma, semicolon and various braces
3428 after having handled a token.*/
3432 if (yacc_rules
&& token
.offset
== 0 && token
.valid
)
3434 make_C_tag (FALSE
); /* a yacc function */
3437 if (definedef
!= dnone
)
3443 make_C_tag (TRUE
); /* an Objective C class */
3447 objdef
= omethodcolon
;
3448 linebuffer_setlen (&token_name
, token_name
.len
+ 1);
3449 strcat (token_name
.buffer
, ":");
3452 if (structdef
== stagseen
)
3454 structdef
= scolonseen
;
3458 if (cplpl
&& fvdef
== flistseen
)
3460 make_C_tag (TRUE
); /* a function */
3467 if (definedef
!= dnone
)
3473 make_C_tag (FALSE
); /* a typedef */
3483 if (typdef
== tignore
|| cplpl
)
3487 if ((globals
&& cblev
== 0 && (!fvextern
|| declarations
))
3488 || (members
&& instruct
))
3489 make_C_tag (FALSE
); /* a variable */
3492 token
.valid
= FALSE
;
3495 if ((declarations
&& typdef
== tnone
&& !instruct
)
3496 || (members
&& typdef
!= tignore
&& instruct
))
3497 make_C_tag (TRUE
); /* a function declaration */
3503 && structdef
== stagseen
&& (c_ext
& C_PLPL
))
3504 make_C_tag (FALSE
); /* forward declaration */
3506 /* The following instruction invalidates the token.
3507 Probably the token should be invalidated in all other
3508 cases where some state machine is reset prematurely. */
3509 token
.valid
= FALSE
;
3510 } /* switch (fvdef) */
3516 if (structdef
== stagseen
)
3520 if (definedef
!= dnone
)
3526 make_C_tag (TRUE
); /* an Objective C method */
3542 case fvnameseen
: /* a variable */
3543 if ((globals
&& cblev
== 0 && (!fvextern
|| declarations
))
3544 || (members
&& instruct
))
3547 case flistseen
: /* a function */
3548 if ((declarations
&& typdef
== tnone
&& !instruct
)
3549 || (members
&& typdef
!= tignore
&& instruct
))
3551 make_C_tag (TRUE
); /* a function declaration */
3554 else if (!declarations
)
3556 token
.valid
= FALSE
;
3561 if (structdef
== stagseen
)
3565 if (definedef
!= dnone
)
3567 if (structdef
== stagseen
)
3574 make_C_tag (FALSE
); /* a typedef */
3586 if ((members
&& cblev
== 1)
3587 || (globals
&& cblev
== 0
3588 && (!fvextern
|| declarations
)))
3589 make_C_tag (FALSE
); /* a variable */
3598 if (definedef
!= dnone
)
3600 if (objdef
== otagseen
&& parlev
== 0)
3601 objdef
= oparenseen
;
3605 if (typdef
== ttypeseen
3609 /* This handles constructs like:
3610 typedef void OperatorFun (int fun); */
3627 if (definedef
!= dnone
)
3629 if (objdef
== ocatseen
&& parlev
== 1)
3631 make_C_tag (TRUE
); /* an Objective C category */
3645 || typdef
== ttypeseen
))
3648 make_C_tag (FALSE
); /* a typedef */
3651 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
3655 if (definedef
!= dnone
)
3657 if (typdef
== ttypeseen
)
3659 /* Whenever typdef is set to tinbody (currently only
3660 here), typdefcblev should be set to cblev. */
3662 typdefcblev
= cblev
;
3667 make_C_tag (TRUE
); /* a function */
3676 make_C_tag (TRUE
); /* an Objective C class */
3681 make_C_tag (TRUE
); /* an Objective C method */
3685 /* Neutralize `extern "C" {' grot. */
3686 if (cblev
== 0 && structdef
== snone
&& nestlev
== 0
3694 case skeyseen
: /* unnamed struct */
3695 pushclass_above (cblev
, NULL
, 0);
3698 case stagseen
: /* named struct or enum */
3699 case scolonseen
: /* a class */
3700 pushclass_above (cblev
, token
.line
+token
.offset
, token
.length
);
3702 make_C_tag (FALSE
); /* a struct or enum */
3708 if (definedef
!= dnone
)
3710 if (fvdef
== fstartlist
)
3711 fvdef
= fvnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
3714 if (definedef
!= dnone
)
3716 if (!ignoreindent
&& lp
== newlb
.buffer
+ 1)
3718 cblev
= 0; /* reset curly brace level if first column */
3719 parlev
= 0; /* also reset paren level, just in case... */
3723 popclass_above (cblev
);
3725 /* Only if typdef == tinbody is typdefcblev significant. */
3726 if (typdef
== tinbody
&& cblev
<= typdefcblev
)
3728 assert (cblev
== typdefcblev
);
3733 if (definedef
!= dnone
)
3743 if ((members
&& cblev
== 1)
3744 || (globals
&& cblev
== 0 && (!fvextern
|| declarations
)))
3745 make_C_tag (FALSE
); /* a variable */
3752 if (cplpl
&& structdef
== stagseen
)
3754 structdef
= sintemplate
;
3759 if (structdef
== sintemplate
)
3761 structdef
= stagseen
;
3767 if (objdef
== oinbody
&& cblev
== 0)
3769 objdef
= omethodsign
;
3774 case '#': case '~': case '&': case '%': case '/': case '|':
3775 case '^': case '!': case '.': case '?': case ']':
3776 if (definedef
!= dnone
)
3778 /* These surely cannot follow a function tag in C. */
3791 if (objdef
== otagseen
)
3793 make_C_tag (TRUE
); /* an Objective C class */
3796 /* If a macro spans multiple lines don't reset its state. */
3798 CNL_SAVE_DEFINEDEF ();
3804 } /* while not eof */
3806 free (lbs
[0].lb
.buffer
);
3807 free (lbs
[1].lb
.buffer
);
3811 * Process either a C++ file or a C file depending on the setting
3815 default_C_entries (inf
)
3818 C_entries (cplusplus
? C_PLPL
: C_AUTO
, inf
);
3821 /* Always do plain C. */
3823 plain_C_entries (inf
)
3829 /* Always do C++. */
3831 Cplusplus_entries (inf
)
3834 C_entries (C_PLPL
, inf
);
3837 /* Always do Java. */
3842 C_entries (C_JAVA
, inf
);
3850 C_entries (C_STAR
, inf
);
3853 /* Always do Yacc. */
3858 C_entries (YACC
, inf
);
3862 /* Useful macros. */
3863 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3864 for (; /* loop initialization */ \
3865 !feof (file_pointer) /* loop test */ \
3866 && /* instructions at start of loop */ \
3867 (readline (&line_buffer, file_pointer), \
3868 char_pointer = line_buffer.buffer, \
3871 #define LOOKING_AT(cp, keyword) /* keyword is a constant string */ \
3872 (strneq ((cp), keyword, sizeof(keyword)-1) /* cp points at keyword */ \
3873 && notinname ((cp)[sizeof(keyword)-1]) /* end of keyword */ \
3874 && ((cp) = skip_spaces((cp)+sizeof(keyword)-1))) /* skip spaces */
3877 * Read a file, but do no processing. This is used to do regexp
3878 * matching on files that have no language defined.
3881 just_read_file (inf
)
3884 register char *dummy
;
3886 LOOP_ON_INPUT_LINES (inf
, lb
, dummy
)
3891 /* Fortran parsing */
3893 static void F_takeprec
__P((void));
3894 static void F_getit
__P((FILE *));
3899 dbp
= skip_spaces (dbp
);
3903 dbp
= skip_spaces (dbp
);
3904 if (strneq (dbp
, "(*)", 3))
3909 if (!ISDIGIT (*dbp
))
3911 --dbp
; /* force failure */
3916 while (ISDIGIT (*dbp
));
3925 dbp
= skip_spaces (dbp
);
3928 readline (&lb
, inf
);
3933 dbp
= skip_spaces (dbp
);
3935 if (!ISALPHA (*dbp
) && *dbp
!= '_' && *dbp
!= '$')
3937 for (cp
= dbp
+ 1; *cp
!= '\0' && intoken (*cp
); cp
++)
3939 make_tag (dbp
, cp
-dbp
, TRUE
,
3940 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
3945 Fortran_functions (inf
)
3948 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
3951 dbp
++; /* Ratfor escape to fortran */
3952 dbp
= skip_spaces (dbp
);
3955 switch (lowcase (*dbp
))
3958 if (nocase_tail ("integer"))
3962 if (nocase_tail ("real"))
3966 if (nocase_tail ("logical"))
3970 if (nocase_tail ("complex") || nocase_tail ("character"))
3974 if (nocase_tail ("double"))
3976 dbp
= skip_spaces (dbp
);
3979 if (nocase_tail ("precision"))
3985 dbp
= skip_spaces (dbp
);
3988 switch (lowcase (*dbp
))
3991 if (nocase_tail ("function"))
3995 if (nocase_tail ("subroutine"))
3999 if (nocase_tail ("entry"))
4003 if (nocase_tail ("blockdata") || nocase_tail ("block data"))
4005 dbp
= skip_spaces (dbp
);
4006 if (*dbp
== '\0') /* assume un-named */
4007 make_tag ("blockdata", 9, TRUE
,
4008 lb
.buffer
, dbp
- lb
.buffer
, lineno
, linecharno
);
4010 F_getit (inf
); /* look for name */
4021 * Philippe Waroquiers <philippe.waroquiers@eurocontrol.int> (1998)
4024 static void Ada_getit
__P((FILE *, char *));
4026 /* Once we are positioned after an "interesting" keyword, let's get
4027 the real tag value necessary. */
4029 Ada_getit (inf
, name_qualifier
)
4031 char *name_qualifier
;
4039 dbp
= skip_spaces (dbp
);
4041 || (dbp
[0] == '-' && dbp
[1] == '-'))
4043 readline (&lb
, inf
);
4046 switch (lowcase(*dbp
))
4049 if (nocase_tail ("body"))
4051 /* Skipping body of procedure body or package body or ....
4052 resetting qualifier to body instead of spec. */
4053 name_qualifier
= "/b";
4058 /* Skipping type of task type or protected type ... */
4059 if (nocase_tail ("type"))
4066 for (cp
= dbp
; *cp
!= '\0' && *cp
!= '"'; cp
++)
4071 dbp
= skip_spaces (dbp
);
4074 && (ISALPHA (*cp
) || ISDIGIT (*cp
) || *cp
== '_' || *cp
== '.'));
4082 name
= concat (dbp
, name_qualifier
, "");
4084 make_tag (name
, strlen (name
), TRUE
,
4085 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4097 bool inquote
= FALSE
;
4098 bool skip_till_semicolumn
= FALSE
;
4100 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4102 while (*dbp
!= '\0')
4104 /* Skip a string i.e. "abcd". */
4105 if (inquote
|| (*dbp
== '"'))
4107 dbp
= etags_strchr ((inquote
) ? dbp
: dbp
+1, '"');
4112 continue; /* advance char */
4117 break; /* advance line */
4121 /* Skip comments. */
4122 if (dbp
[0] == '-' && dbp
[1] == '-')
4123 break; /* advance line */
4125 /* Skip character enclosed in single quote i.e. 'a'
4126 and skip single quote starting an attribute i.e. 'Image. */
4135 if (skip_till_semicolumn
)
4138 skip_till_semicolumn
= FALSE
;
4140 continue; /* advance char */
4143 /* Search for beginning of a token. */
4144 if (!begtoken (*dbp
))
4147 continue; /* advance char */
4150 /* We are at the beginning of a token. */
4151 switch (lowcase(*dbp
))
4154 if (!packages_only
&& nocase_tail ("function"))
4155 Ada_getit (inf
, "/f");
4157 break; /* from switch */
4158 continue; /* advance char */
4160 if (!packages_only
&& nocase_tail ("procedure"))
4161 Ada_getit (inf
, "/p");
4162 else if (nocase_tail ("package"))
4163 Ada_getit (inf
, "/s");
4164 else if (nocase_tail ("protected")) /* protected type */
4165 Ada_getit (inf
, "/t");
4167 break; /* from switch */
4168 continue; /* advance char */
4171 if (typedefs
&& !packages_only
&& nocase_tail ("use"))
4173 /* when tagging types, avoid tagging use type Pack.Typename;
4174 for this, we will skip everything till a ; */
4175 skip_till_semicolumn
= TRUE
;
4176 continue; /* advance char */
4180 if (!packages_only
&& nocase_tail ("task"))
4181 Ada_getit (inf
, "/k");
4182 else if (typedefs
&& !packages_only
&& nocase_tail ("type"))
4184 Ada_getit (inf
, "/t");
4185 while (*dbp
!= '\0')
4189 break; /* from switch */
4190 continue; /* advance char */
4193 /* Look for the end of the token. */
4194 while (!endtoken (*dbp
))
4197 } /* advance char */
4198 } /* advance line */
4203 * Unix and microcontroller assembly tag handling
4204 * Labels: /^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]/
4205 * Idea by Bob Weiner, Motorola Inc. (1994)
4213 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4215 /* If first char is alphabetic or one of [_.$], test for colon
4216 following identifier. */
4217 if (ISALPHA (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4219 /* Read past label. */
4221 while (ISALNUM (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4223 if (*cp
== ':' || iswhite (*cp
))
4224 /* Found end of label, so copy it and add it to the table. */
4225 make_tag (lb
.buffer
, cp
- lb
.buffer
, TRUE
,
4226 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4234 * Perl sub names: /^sub[ \t\n]+[^ \t\n{]+/
4235 * Perl variable names: /^(my|local).../
4236 * Original code by Bart Robinson <lomew@cs.utah.edu> (1995)
4237 * Additions by Michael Ernst <mernst@alum.mit.edu> (1997)
4238 * Ideas by Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE> (2001)
4241 Perl_functions (inf
)
4244 char *package
= savestr ("main"); /* current package name */
4247 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4251 if (LOOKING_AT (cp
, "package"))
4254 get_tag (cp
, &package
);
4256 else if (LOOKING_AT (cp
, "sub"))
4261 while (!notinname (*cp
))
4264 continue; /* nothing found */
4265 if ((pos
= etags_strchr (sp
, ':')) != NULL
4266 && pos
< cp
&& pos
[1] == ':')
4267 /* The name is already qualified. */
4268 make_tag (sp
, cp
- sp
, TRUE
,
4269 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4273 char savechar
, *name
;
4277 name
= concat (package
, "::", sp
);
4279 make_tag (name
, strlen(name
), TRUE
,
4280 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4284 else if (globals
) /* only if we are tagging global vars */
4286 /* Skip a qualifier, if any. */
4287 bool qual
= LOOKING_AT (cp
, "my") || LOOKING_AT (cp
, "local");
4288 /* After "my" or "local", but before any following paren or space. */
4289 char *varstart
= cp
;
4291 if (qual
/* should this be removed? If yes, how? */
4292 && (*cp
== '$' || *cp
== '@' || *cp
== '%'))
4297 while (ISALNUM (*cp
) || *cp
== '_');
4301 /* Should be examining a variable list at this point;
4302 could insist on seeing an open parenthesis. */
4303 while (*cp
!= '\0' && *cp
!= ';' && *cp
!= '=' && *cp
!= ')')
4309 make_tag (varstart
, cp
- varstart
, FALSE
,
4310 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4318 * Look for /^[\t]*def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
4319 * Idea by Eric S. Raymond <esr@thyrsus.com> (1997)
4320 * More ideas by seb bacon <seb@jamkit.com> (2002)
4323 Python_functions (inf
)
4328 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4330 cp
= skip_spaces (cp
);
4331 if (LOOKING_AT (cp
, "def") || LOOKING_AT (cp
, "class"))
4334 while (!notinname (*cp
) && *cp
!= ':')
4336 make_tag (name
, cp
- name
, TRUE
,
4337 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4346 * - /^[ \t]*function[ \t\n]+[^ \t\n(]+/
4347 * - /^[ \t]*class[ \t\n]+[^ \t\n]+/
4348 * - /^[ \t]*define\(\"[^\"]+/
4349 * Only with --members:
4350 * - /^[ \t]*var[ \t\n]+\$[^ \t\n=;]/
4351 * Idea by Diez B. Roggisch (2001)
4357 register char *cp
, *name
;
4358 bool search_identifier
= FALSE
;
4360 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4362 cp
= skip_spaces (cp
);
4364 if (search_identifier
4367 while (!notinname (*cp
))
4369 make_tag (name
, cp
- name
, TRUE
,
4370 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4371 search_identifier
= FALSE
;
4373 else if (LOOKING_AT (cp
, "function"))
4376 cp
= skip_spaces (cp
+1);
4380 while (!notinname (*cp
))
4382 make_tag (name
, cp
- name
, TRUE
,
4383 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4386 search_identifier
= TRUE
;
4388 else if (LOOKING_AT (cp
, "class"))
4393 while (*cp
!= '\0' && !iswhite (*cp
))
4395 make_tag (name
, cp
- name
, FALSE
,
4396 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4399 search_identifier
= TRUE
;
4401 else if (strneq (cp
, "define", 6)
4402 && (cp
= skip_spaces (cp
+6))
4404 && (*cp
== '"' || *cp
== '\''))
4408 while (*cp
!= quote
&& *cp
!= '\0')
4410 make_tag (name
, cp
- name
, FALSE
,
4411 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4414 && LOOKING_AT (cp
, "var")
4418 while (!notinname(*cp
))
4420 make_tag (name
, cp
- name
, FALSE
,
4421 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4428 * Cobol tag functions
4429 * We could look for anything that could be a paragraph name.
4430 * i.e. anything that starts in column 8 is one word and ends in a full stop.
4431 * Idea by Corny de Souza (1993)
4434 Cobol_paragraphs (inf
)
4437 register char *bp
, *ep
;
4439 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4445 /* If eoln, compiler option or comment ignore whole line. */
4446 if (bp
[-1] != ' ' || !ISALNUM (bp
[0]))
4449 for (ep
= bp
; ISALNUM (*ep
) || *ep
== '-'; ep
++)
4452 make_tag (bp
, ep
- bp
, TRUE
,
4453 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
4460 * Ideas by Assar Westerlund <assar@sics.se> (2001)
4463 Makefile_targets (inf
)
4468 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4470 if (*bp
== '\t' || *bp
== '#')
4472 while (*bp
!= '\0' && *bp
!= '=' && *bp
!= ':')
4474 if (*bp
== ':' || (globals
&& *bp
== '='))
4475 make_tag (lb
.buffer
, bp
- lb
.buffer
, TRUE
,
4476 lb
.buffer
, bp
- lb
.buffer
+ 1, lineno
, linecharno
);
4483 * Original code by Mosur K. Mohan (1989)
4485 * Locates tags for procedures & functions. Doesn't do any type- or
4486 * var-definitions. It does look for the keyword "extern" or
4487 * "forward" immediately following the procedure statement; if found,
4488 * the tag is skipped.
4491 Pascal_functions (inf
)
4494 linebuffer tline
; /* mostly copied from C_entries */
4496 int save_lineno
, namelen
, taglen
;
4499 bool /* each of these flags is TRUE iff: */
4500 incomment
, /* point is inside a comment */
4501 inquote
, /* point is inside '..' string */
4502 get_tagname
, /* point is after PROCEDURE/FUNCTION
4503 keyword, so next item = potential tag */
4504 found_tag
, /* point is after a potential tag */
4505 inparms
, /* point is within parameter-list */
4506 verify_tag
; /* point has passed the parm-list, so the
4507 next token will determine whether this
4508 is a FORWARD/EXTERN to be ignored, or
4509 whether it is a real tag */
4511 save_lcno
= save_lineno
= namelen
= taglen
= 0; /* keep compiler quiet */
4512 name
= NULL
; /* keep compiler quiet */
4515 linebuffer_init (&tline
);
4517 incomment
= inquote
= FALSE
;
4518 found_tag
= FALSE
; /* have a proc name; check if extern */
4519 get_tagname
= FALSE
; /* found "procedure" keyword */
4520 inparms
= FALSE
; /* found '(' after "proc" */
4521 verify_tag
= FALSE
; /* check if "extern" is ahead */
4524 while (!feof (inf
)) /* long main loop to get next char */
4527 if (c
== '\0') /* if end of line */
4529 readline (&lb
, inf
);
4533 if (!((found_tag
&& verify_tag
)
4535 c
= *dbp
++; /* only if don't need *dbp pointing
4536 to the beginning of the name of
4537 the procedure or function */
4541 if (c
== '}') /* within { } comments */
4543 else if (c
== '*' && *dbp
== ')') /* within (* *) comments */
4560 inquote
= TRUE
; /* found first quote */
4562 case '{': /* found open { comment */
4566 if (*dbp
== '*') /* found open (* comment */
4571 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
4574 case ')': /* end of parms list */
4579 if (found_tag
&& !inparms
) /* end of proc or fn stmt */
4586 if (found_tag
&& verify_tag
&& (*dbp
!= ' '))
4588 /* Check if this is an "extern" declaration. */
4591 if (lowcase (*dbp
== 'e'))
4593 if (nocase_tail ("extern")) /* superfluous, really! */
4599 else if (lowcase (*dbp
) == 'f')
4601 if (nocase_tail ("forward")) /* check for forward reference */
4607 if (found_tag
&& verify_tag
) /* not external proc, so make tag */
4611 make_tag (name
, namelen
, TRUE
,
4612 tline
.buffer
, taglen
, save_lineno
, save_lcno
);
4616 if (get_tagname
) /* grab name of proc or fn */
4623 /* Find block name. */
4624 for (cp
= dbp
+ 1; *cp
!= '\0' && !endtoken (*cp
); cp
++)
4627 /* Save all values for later tagging. */
4628 linebuffer_setlen (&tline
, lb
.len
);
4629 strcpy (tline
.buffer
, lb
.buffer
);
4630 save_lineno
= lineno
;
4631 save_lcno
= linecharno
;
4632 name
= tline
.buffer
+ (dbp
- lb
.buffer
);
4634 taglen
= cp
- lb
.buffer
+ 1;
4636 dbp
= cp
; /* set dbp to e-o-token */
4637 get_tagname
= FALSE
;
4641 /* And proceed to check for "extern". */
4643 else if (!incomment
&& !inquote
&& !found_tag
)
4645 /* Check for proc/fn keywords. */
4646 switch (lowcase (c
))
4649 if (nocase_tail ("rocedure")) /* c = 'p', dbp has advanced */
4653 if (nocase_tail ("unction"))
4658 } /* while not eof */
4660 free (tline
.buffer
);
4665 * Lisp tag functions
4666 * look for (def or (DEF, quote or QUOTE
4669 static void L_getit
__P((void));
4674 if (*dbp
== '\'') /* Skip prefix quote */
4676 else if (*dbp
== '(')
4679 /* Try to skip "(quote " */
4680 if (!LOOKING_AT (dbp
, "quote") && !LOOKING_AT (dbp
, "QUOTE"))
4681 /* Ok, then skip "(" before name in (defstruct (foo)) */
4682 dbp
= skip_spaces (dbp
);
4684 get_tag (dbp
, NULL
);
4688 Lisp_functions (inf
)
4691 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4696 if (strneq (dbp
+1, "def", 3) || strneq (dbp
+1, "DEF", 3))
4698 dbp
= skip_non_spaces (dbp
);
4699 dbp
= skip_spaces (dbp
);
4704 /* Check for (foo::defmumble name-defined ... */
4707 while (!notinname (*dbp
) && *dbp
!= ':');
4712 while (*dbp
== ':');
4714 if (strneq (dbp
, "def", 3) || strneq (dbp
, "DEF", 3))
4716 dbp
= skip_non_spaces (dbp
);
4717 dbp
= skip_spaces (dbp
);
4727 * Postscript tag functions
4728 * Just look for lines where the first character is '/'
4729 * Also look at "defineps" for PSWrap
4731 * Richard Mlynarik <mly@adoc.xerox.com> (1997)
4732 * Masatake Yamato <masata-y@is.aist-nara.ac.jp> (1999)
4735 Postscript_functions (inf
)
4738 register char *bp
, *ep
;
4740 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4745 *ep
!= '\0' && *ep
!= ' ' && *ep
!= '{';
4748 make_tag (bp
, ep
- bp
, TRUE
,
4749 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
4751 else if (LOOKING_AT (bp
, "defineps"))
4758 * Scheme tag functions
4759 * look for (def... xyzzy
4761 * (def ... ((...(xyzzy ....
4763 * Original code by Ken Haase (1985?)
4767 Scheme_functions (inf
)
4772 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4774 if (strneq (bp
, "(def", 4) || strneq (bp
, "(DEF", 4))
4776 bp
= skip_non_spaces (bp
+4);
4777 /* Skip over open parens and white space */
4778 while (notinname (*bp
))
4782 if (LOOKING_AT (bp
, "(SET!") || LOOKING_AT (bp
, "(set!"))
4788 /* Find tags in TeX and LaTeX input files. */
4790 /* TEX_toktab is a table of TeX control sequences that define tags.
4791 * Each entry records one such control sequence.
4793 * Original code from who knows whom.
4795 * Stefan Monnier (2002)
4798 static linebuffer
*TEX_toktab
= NULL
; /* Table with tag tokens */
4800 /* Default set of control sequences to put into TEX_toktab.
4801 The value of environment var TEXTAGS is prepended to this. */
4802 static char *TEX_defenv
= "\
4803 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4804 :part:appendix:entry:index:def\
4805 :newcommand:renewcommand:newenvironment:renewenvironment";
4807 static void TEX_mode
__P((FILE *));
4808 static void TEX_decode_env
__P((char *, char *));
4810 static char TEX_esc
= '\\';
4811 static char TEX_opgrp
= '{';
4812 static char TEX_clgrp
= '}';
4815 * TeX/LaTeX scanning loop.
4824 /* Select either \ or ! as escape character. */
4827 /* Initialize token table once from environment. */
4828 if (TEX_toktab
== NULL
)
4829 TEX_decode_env ("TEXTAGS", TEX_defenv
);
4831 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4833 /* Look at each TEX keyword in line. */
4836 /* Look for a TEX escape. */
4837 while (*cp
++ != TEX_esc
)
4838 if (cp
[-1] == '\0' || cp
[-1] == '%')
4841 for (key
= TEX_toktab
; key
->buffer
!= NULL
; key
++)
4842 if (strneq (cp
, key
->buffer
, key
->len
))
4845 int namelen
, linelen
;
4848 cp
= skip_spaces (cp
+ key
->len
);
4849 if (*cp
== TEX_opgrp
)
4855 (!iswhite (*p
) && *p
!= '#' &&
4856 *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
);
4861 if (!opgrp
|| *p
== TEX_clgrp
)
4863 while (*p
!= '\0' && *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
)
4865 linelen
= p
- lb
.buffer
+ 1;
4867 make_tag (cp
, namelen
, TRUE
,
4868 lb
.buffer
, linelen
, lineno
, linecharno
);
4869 goto tex_next_line
; /* We only tag a line once */
4877 #define TEX_LESC '\\'
4878 #define TEX_SESC '!'
4880 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4881 chars accordingly. */
4888 while ((c
= getc (inf
)) != EOF
)
4890 /* Skip to next line if we hit the TeX comment char. */
4894 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
4910 /* If the input file is compressed, inf is a pipe, and rewind may fail.
4911 No attempt is made to correct the situation. */
4915 /* Read environment and prepend it to the default string.
4916 Build token table. */
4918 TEX_decode_env (evarname
, defenv
)
4922 register char *env
, *p
;
4925 /* Append default string to environment. */
4926 env
= getenv (evarname
);
4932 env
= concat (oldenv
, defenv
, "");
4935 /* Allocate a token table */
4936 for (len
= 1, p
= env
; p
;)
4937 if ((p
= etags_strchr (p
, ':')) && *++p
!= '\0')
4939 TEX_toktab
= xnew (len
, linebuffer
);
4941 /* Unpack environment string into token table. Be careful about */
4942 /* zero-length strings (leading ':', "::" and trailing ':') */
4943 for (i
= 0; *env
!= '\0';)
4945 p
= etags_strchr (env
, ':');
4946 if (!p
) /* End of environment string. */
4947 p
= env
+ strlen (env
);
4949 { /* Only non-zero strings. */
4950 TEX_toktab
[i
].buffer
= savenstr (env
, p
- env
);
4951 TEX_toktab
[i
].len
= p
- env
;
4958 TEX_toktab
[i
].buffer
= NULL
; /* Mark end of table. */
4959 TEX_toktab
[i
].len
= 0;
4966 /* Texinfo support. Dave Love, Mar. 2000. */
4972 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4973 if (LOOKING_AT (cp
, "@node"))
4976 while (*cp
!= '\0' && *cp
!= ',')
4978 make_tag (start
, cp
- start
, TRUE
,
4979 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4984 /* Similar to LOOKING_AT but does not use notinname, does not skip */
4985 #define LOOKING_AT_NOCASE(cp, kw) /* kw is a constant string */ \
4986 (strncaseeq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \
4987 && ((cp) += sizeof(kw)-1)) /* skip spaces */
4991 * Contents of <title>, <h1>, <h2>, <h3> are tags.
4992 * Contents of <a name=xxx> are tags with name xxx.
4994 * Francesco Potortì, 2002.
5000 bool getnext
= FALSE
; /* next text outside of HTML tags is a tag */
5001 bool skiptag
= FALSE
; /* skip to the end of the current HTML tag */
5002 bool intag
= FALSE
; /* inside an html tag, looking for ID= */
5003 bool inanchor
= FALSE
; /* when INTAG, is an anchor, look for NAME= */
5007 linebuffer_setlen (&token_name
, 0); /* no name in buffer */
5009 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
5010 for (;;) /* loop on the same line */
5012 if (skiptag
) /* skip HTML tag */
5014 while (*dbp
!= '\0' && *dbp
!= '>')
5020 continue; /* look on the same line */
5022 break; /* go to next line */
5025 else if (intag
) /* look for "name=" or "id=" */
5027 while (*dbp
!= '\0' && *dbp
!= '>'
5028 && lowcase (*dbp
) != 'n' && lowcase (*dbp
) != 'i')
5031 break; /* go to next line */
5036 continue; /* look on the same line */
5038 if ((inanchor
&& LOOKING_AT_NOCASE (dbp
, "name="))
5039 || LOOKING_AT_NOCASE (dbp
, "id="))
5041 bool quoted
= (dbp
[0] == '"');
5044 for (end
= ++dbp
; *end
!= '\0' && *end
!= '"'; end
++)
5047 for (end
= dbp
; *end
!= '\0' && intoken (*end
); end
++)
5049 linebuffer_setlen (&token_name
, end
- dbp
);
5050 strncpy (token_name
.buffer
, dbp
, end
- dbp
);
5051 token_name
.buffer
[end
- dbp
] = '\0';
5054 intag
= FALSE
; /* we found what we looked for */
5055 skiptag
= TRUE
; /* skip to the end of the tag */
5056 getnext
= TRUE
; /* then grab the text */
5057 continue; /* look on the same line */
5062 else if (getnext
) /* grab next tokens and tag them */
5064 dbp
= skip_spaces (dbp
);
5066 break; /* go to next line */
5070 inanchor
= (lowcase (dbp
[1]) == 'a' && !intoken (dbp
[2]));
5071 continue; /* look on the same line */
5074 for (end
= dbp
+ 1; *end
!= '\0' && *end
!= '<'; end
++)
5076 make_tag (token_name
.buffer
, token_name
.len
, TRUE
,
5077 dbp
, end
- dbp
, lineno
, linecharno
);
5078 linebuffer_setlen (&token_name
, 0); /* no name in buffer */
5080 break; /* go to next line */
5083 else /* look for an interesting HTML tag */
5085 while (*dbp
!= '\0' && *dbp
!= '<')
5088 break; /* go to next line */
5090 if (lowcase (dbp
[1]) == 'a' && !intoken (dbp
[2]))
5093 continue; /* look on the same line */
5095 else if (LOOKING_AT_NOCASE (dbp
, "<title>")
5096 || LOOKING_AT_NOCASE (dbp
, "<h1>")
5097 || LOOKING_AT_NOCASE (dbp
, "<h2>")
5098 || LOOKING_AT_NOCASE (dbp
, "<h3>"))
5102 continue; /* look on the same line */
5113 * Assumes that the predicate or rule starts at column 0.
5114 * Only the first clause of a predicate or rule is added.
5115 * Original code by Sunichirou Sugou (1989)
5116 * Rewritten by Anders Lindgren (1996)
5118 static int prolog_pr
__P((char *, char *));
5119 static void prolog_skip_comment
__P((linebuffer
*, FILE *));
5120 static int prolog_atom
__P((char *, int));
5123 Prolog_functions (inf
)
5134 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5136 if (cp
[0] == '\0') /* Empty line */
5138 else if (iswhite (cp
[0])) /* Not a predicate */
5140 else if (cp
[0] == '/' && cp
[1] == '*') /* comment. */
5141 prolog_skip_comment (&lb
, inf
);
5142 else if ((len
= prolog_pr (cp
, last
)) > 0)
5144 /* Predicate or rule. Store the function name so that we
5145 only generate a tag for the first clause. */
5147 last
= xnew(len
+ 1, char);
5148 else if (len
+ 1 > allocated
)
5149 xrnew (last
, len
+ 1, char);
5150 allocated
= len
+ 1;
5151 strncpy (last
, cp
, len
);
5159 prolog_skip_comment (plb
, inf
)
5167 for (cp
= plb
->buffer
; *cp
!= '\0'; cp
++)
5168 if (cp
[0] == '*' && cp
[1] == '/')
5170 readline (plb
, inf
);
5176 * A predicate or rule definition is added if it matches:
5177 * <beginning of line><Prolog Atom><whitespace>(
5178 * or <beginning of line><Prolog Atom><whitespace>:-
5180 * It is added to the tags database if it doesn't match the
5181 * name of the previous clause header.
5183 * Return the size of the name of the predicate or rule, or 0 if no
5189 char *last
; /* Name of last clause. */
5194 pos
= prolog_atom (s
, 0);
5199 pos
= skip_spaces (s
+ pos
) - s
;
5202 || (s
[pos
] == '(' && (pos
+= 1))
5203 || (s
[pos
] == ':' && s
[pos
+ 1] == '-' && (pos
+= 2)))
5204 && (last
== NULL
/* save only the first clause */
5205 || len
!= strlen (last
)
5206 || !strneq (s
, last
, len
)))
5208 make_tag (s
, len
, TRUE
, s
, pos
, lineno
, linecharno
);
5216 * Consume a Prolog atom.
5217 * Return the number of bytes consumed, or -1 if there was an error.
5219 * A prolog atom, in this context, could be one of:
5220 * - An alphanumeric sequence, starting with a lower case letter.
5221 * - A quoted arbitrary string. Single quotes can escape themselves.
5222 * Backslash quotes everything.
5225 prolog_atom (s
, pos
)
5233 if (ISLOWER(s
[pos
]) || (s
[pos
] == '_'))
5235 /* The atom is unquoted. */
5237 while (ISALNUM(s
[pos
]) || (s
[pos
] == '_'))
5241 return pos
- origpos
;
5243 else if (s
[pos
] == '\'')
5254 pos
++; /* A double quote */
5256 else if (s
[pos
] == '\0')
5257 /* Multiline quoted atoms are ignored. */
5259 else if (s
[pos
] == '\\')
5261 if (s
[pos
+1] == '\0')
5268 return pos
- origpos
;
5276 * Support for Erlang
5278 * Generates tags for functions, defines, and records.
5279 * Assumes that Erlang functions start at column 0.
5280 * Original code by Anders Lindgren (1996)
5282 static int erlang_func
__P((char *, char *));
5283 static void erlang_attribute
__P((char *));
5284 static int erlang_atom
__P((char *));
5287 Erlang_functions (inf
)
5298 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5300 if (cp
[0] == '\0') /* Empty line */
5302 else if (iswhite (cp
[0])) /* Not function nor attribute */
5304 else if (cp
[0] == '%') /* comment */
5306 else if (cp
[0] == '"') /* Sometimes, strings start in column one */
5308 else if (cp
[0] == '-') /* attribute, e.g. "-define" */
5310 erlang_attribute (cp
);
5313 else if ((len
= erlang_func (cp
, last
)) > 0)
5316 * Function. Store the function name so that we only
5317 * generates a tag for the first clause.
5320 last
= xnew (len
+ 1, char);
5321 else if (len
+ 1 > allocated
)
5322 xrnew (last
, len
+ 1, char);
5323 allocated
= len
+ 1;
5324 strncpy (last
, cp
, len
);
5332 * A function definition is added if it matches:
5333 * <beginning of line><Erlang Atom><whitespace>(
5335 * It is added to the tags database if it doesn't match the
5336 * name of the previous clause header.
5338 * Return the size of the name of the function, or 0 if no function
5342 erlang_func (s
, last
)
5344 char *last
; /* Name of last clause. */
5349 pos
= erlang_atom (s
);
5354 pos
= skip_spaces (s
+ pos
) - s
;
5356 /* Save only the first clause. */
5359 || len
!= (int)strlen (last
)
5360 || !strneq (s
, last
, len
)))
5362 make_tag (s
, len
, TRUE
, s
, pos
, lineno
, linecharno
);
5371 * Handle attributes. Currently, tags are generated for defines
5374 * They are on the form:
5375 * -define(foo, bar).
5376 * -define(Foo(M, N), M+N).
5377 * -record(graph, {vtab = notable, cyclic = true}).
5380 erlang_attribute (s
)
5385 if ((LOOKING_AT (cp
, "-define") || LOOKING_AT (cp
, "-record"))
5388 int len
= erlang_atom (skip_spaces (cp
));
5390 make_tag (cp
, len
, TRUE
, s
, cp
+ len
- s
, lineno
, linecharno
);
5397 * Consume an Erlang atom (or variable).
5398 * Return the number of bytes consumed, or -1 if there was an error.
5406 if (ISALPHA (s
[pos
]) || s
[pos
] == '_')
5408 /* The atom is unquoted. */
5411 while (ISALNUM (s
[pos
]) || s
[pos
] == '_');
5413 else if (s
[pos
] == '\'')
5415 for (pos
++; s
[pos
] != '\''; pos
++)
5416 if (s
[pos
] == '\0' /* multiline quoted atoms are ignored */
5417 || (s
[pos
] == '\\' && s
[++pos
] == '\0'))
5426 #ifdef ETAGS_REGEXPS
5428 static char *scan_separators
__P((char *));
5429 static void add_regex
__P((char *, language
*));
5430 static char *substitute
__P((char *, char *, struct re_registers
*));
5433 * Take a string like "/blah/" and turn it into "blah", verifying
5434 * that the first and last characters are the same, and handling
5435 * quoted separator characters. Actually, stops on the occurrence of
5436 * an unquoted separator. Also process \t, \n, etc. and turn into
5437 * appropriate characters. Works in place. Null terminates name string.
5438 * Returns pointer to terminating separator, or NULL for
5439 * unterminated regexps.
5442 scan_separators (name
)
5446 char *copyto
= name
;
5447 bool quoted
= FALSE
;
5449 for (++name
; *name
!= '\0'; ++name
)
5455 case 'a': *copyto
++ = '\007'; break; /* BEL (bell) */
5456 case 'b': *copyto
++ = '\b'; break; /* BS (back space) */
5457 case 'd': *copyto
++ = 0177; break; /* DEL (delete) */
5458 case 'e': *copyto
++ = 033; break; /* ESC (delete) */
5459 case 'f': *copyto
++ = '\f'; break; /* FF (form feed) */
5460 case 'n': *copyto
++ = '\n'; break; /* NL (new line) */
5461 case 'r': *copyto
++ = '\r'; break; /* CR (carriage return) */
5462 case 't': *copyto
++ = '\t'; break; /* TAB (horizontal tab) */
5463 case 'v': *copyto
++ = '\v'; break; /* VT (vertical tab) */
5469 /* Something else is quoted, so preserve the quote. */
5477 else if (*name
== '\\')
5479 else if (*name
== sep
)
5485 name
= NULL
; /* signal unterminated regexp */
5487 /* Terminate copied string. */
5492 /* Look at the argument of --regex or --no-regex and do the right
5493 thing. Same for each line of a regexp file. */
5495 analyse_regex (regex_arg
)
5498 if (regex_arg
== NULL
)
5500 free_regexps (); /* --no-regex: remove existing regexps */
5504 /* A real --regexp option or a line in a regexp file. */
5505 switch (regex_arg
[0])
5507 /* Comments in regexp file or null arg to --regex. */
5513 /* Read a regex file. This is recursive and may result in a
5514 loop, which will stop when the file descriptors are exhausted. */
5518 linebuffer regexbuf
;
5519 char *regexfile
= regex_arg
+ 1;
5521 /* regexfile is a file containing regexps, one per line. */
5522 regexfp
= fopen (regexfile
, "r");
5523 if (regexfp
== NULL
)
5528 linebuffer_init (®exbuf
);
5529 while (readline_internal (®exbuf
, regexfp
) > 0)
5530 analyse_regex (regexbuf
.buffer
);
5531 free (regexbuf
.buffer
);
5536 /* Regexp to be used for a specific language only. */
5540 char *lang_name
= regex_arg
+ 1;
5543 for (cp
= lang_name
; *cp
!= '}'; cp
++)
5546 error ("unterminated language name in regex: %s", regex_arg
);
5550 lang
= get_language_from_langname (lang_name
);
5553 add_regex (cp
, lang
);
5557 /* Regexp to be used for any language. */
5559 add_regex (regex_arg
, NULL
);
5564 /* Separate the regexp pattern, compile it,
5565 and care for optional name and modifiers. */
5567 add_regex (regexp_pattern
, lang
)
5568 char *regexp_pattern
;
5571 static struct re_pattern_buffer zeropattern
;
5572 char sep
, *pat
, *name
, *modifiers
;
5574 struct re_pattern_buffer
*patbuf
;
5577 force_explicit_name
= TRUE
, /* do not use implicit tag names */
5578 ignore_case
= FALSE
, /* case is significant */
5579 multi_line
= FALSE
, /* matches are done one line at a time */
5580 single_line
= FALSE
; /* dot does not match newline */
5583 if (strlen(regexp_pattern
) < 3)
5585 error ("null regexp", (char *)NULL
);
5588 sep
= regexp_pattern
[0];
5589 name
= scan_separators (regexp_pattern
);
5592 error ("%s: unterminated regexp", regexp_pattern
);
5597 error ("null name for regexp \"%s\"", regexp_pattern
);
5600 modifiers
= scan_separators (name
);
5601 if (modifiers
== NULL
) /* no terminating separator --> no name */
5607 modifiers
+= 1; /* skip separator */
5609 /* Parse regex modifiers. */
5610 for (; modifiers
[0] != '\0'; modifiers
++)
5611 switch (modifiers
[0])
5614 if (modifiers
== name
)
5615 error ("forcing explicit tag name but no name, ignoring", NULL
);
5616 force_explicit_name
= TRUE
;
5626 need_filebuf
= TRUE
;
5631 wrongmod
[0] = modifiers
[0];
5633 error ("invalid regexp modifier `%s', ignoring", wrongmod
);
5638 patbuf
= xnew (1, struct re_pattern_buffer
);
5639 *patbuf
= zeropattern
;
5642 static char lc_trans
[CHARS
];
5644 for (i
= 0; i
< CHARS
; i
++)
5645 lc_trans
[i
] = lowcase (i
);
5646 patbuf
->translate
= lc_trans
; /* translation table to fold case */
5650 pat
= concat ("^", regexp_pattern
, ""); /* anchor to beginning of line */
5652 pat
= regexp_pattern
;
5655 re_set_syntax (RE_SYNTAX_EMACS
| RE_DOT_NEWLINE
);
5657 re_set_syntax (RE_SYNTAX_EMACS
);
5659 err
= re_compile_pattern (pat
, strlen (regexp_pattern
), patbuf
);
5664 error ("%s while compiling pattern", err
);
5669 p_head
= xnew (1, regexp
);
5670 p_head
->pattern
= savestr (regexp_pattern
);
5671 p_head
->p_next
= rp
;
5672 p_head
->lang
= lang
;
5673 p_head
->pat
= patbuf
;
5674 p_head
->name
= savestr (name
);
5675 p_head
->error_signaled
= FALSE
;
5676 p_head
->force_explicit_name
= force_explicit_name
;
5677 p_head
->ignore_case
= ignore_case
;
5678 p_head
->multi_line
= multi_line
;
5682 * Do the substitutions indicated by the regular expression and
5686 substitute (in
, out
, regs
)
5688 struct re_registers
*regs
;
5691 int size
, dig
, diglen
;
5694 size
= strlen (out
);
5696 /* Pass 1: figure out how much to allocate by finding all \N strings. */
5697 if (out
[size
- 1] == '\\')
5698 fatal ("pattern error in \"%s\"", out
);
5699 for (t
= etags_strchr (out
, '\\');
5701 t
= etags_strchr (t
+ 2, '\\'))
5705 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
5711 /* Allocate space and do the substitutions. */
5712 result
= xnew (size
+ 1, char);
5714 for (t
= result
; *out
!= '\0'; out
++)
5715 if (*out
== '\\' && ISDIGIT (*++out
))
5718 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
5719 strncpy (t
, in
+ regs
->start
[dig
], diglen
);
5726 assert (t
<= result
+ size
&& t
- result
== (int)strlen (result
));
5731 /* Deallocate all regexps. */
5736 while (p_head
!= NULL
)
5738 rp
= p_head
->p_next
;
5739 free (p_head
->pattern
);
5740 free (p_head
->name
);
5748 * Reads the whole file as a single string from `filebuf' and looks for
5749 * multi-line regular expressions, creating tags on matches.
5750 * readline already dealt with normal regexps.
5752 * Idea by Ben Wing <ben@666.com> (2002).
5755 regex_tag_multiline ()
5757 char *buffer
= filebuf
.buffer
;
5761 for (rp
= p_head
; rp
!= NULL
; rp
= rp
->p_next
)
5765 if (!rp
->multi_line
)
5766 continue; /* skip normal regexps */
5768 /* Generic initialisations before parsing file from memory. */
5769 lineno
= 1; /* reset global line number */
5770 charno
= 0; /* reset global char number */
5771 linecharno
= 0; /* reset global char number of line start */
5773 /* Only use generic regexps or those for the current language. */
5774 if (rp
->lang
!= NULL
&& rp
->lang
!= curfdp
->lang
)
5777 while (match
>= 0 && match
< filebuf
.len
)
5779 match
= re_search (rp
->pat
, buffer
, filebuf
.len
, charno
,
5780 filebuf
.len
- match
, &rp
->regs
);
5785 if (!rp
->error_signaled
)
5787 error ("regexp stack overflow while matching \"%s\"",
5789 rp
->error_signaled
= TRUE
;
5796 if (match
== rp
->regs
.end
[0])
5798 if (!rp
->error_signaled
)
5800 error ("regexp matches the empty string: \"%s\"",
5802 rp
->error_signaled
= TRUE
;
5804 match
= -3; /* exit from while loop */
5808 /* Match occurred. Construct a tag. */
5809 while (charno
< rp
->regs
.end
[0])
5810 if (buffer
[charno
++] == '\n')
5811 lineno
++, linecharno
= charno
;
5813 if (name
[0] != '\0')
5814 /* Make a named tag. */
5815 name
= substitute (buffer
, rp
->name
, &rp
->regs
);
5816 if (rp
->force_explicit_name
)
5817 /* Force explicit tag name, if a name is there. */
5818 pfnote (name
, TRUE
, buffer
+ linecharno
,
5819 charno
- linecharno
+ 1, lineno
, linecharno
);
5821 make_tag (name
, strlen (name
), TRUE
, buffer
+ linecharno
,
5822 charno
- linecharno
+ 1, lineno
, linecharno
);
5829 #endif /* ETAGS_REGEXPS */
5836 register int len
= 0;
5838 while (*cp
!= '\0' && lowcase (*cp
) == lowcase (dbp
[len
]))
5840 if (*cp
== '\0' && !intoken (dbp
[len
]))
5849 get_tag (bp
, namepp
)
5853 register char *cp
= bp
;
5857 /* Go till you get to white space or a syntactic break */
5858 for (cp
= bp
+ 1; !notinname (*cp
); cp
++)
5860 make_tag (bp
, cp
- bp
, TRUE
,
5861 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
5865 *namepp
= savenstr (bp
, cp
- bp
);
5869 * Read a line of text from `stream' into `lbp', excluding the
5870 * newline or CR-NL, if any. Return the number of characters read from
5871 * `stream', which is the length of the line including the newline.
5873 * On DOS or Windows we do not count the CR character, if any before the
5874 * NL, in the returned length; this mirrors the behavior of Emacs on those
5875 * platforms (for text files, it translates CR-NL to NL as it reads in the
5878 * If multi-line regular expressions are requested, each line read is
5879 * appended to `filebuf'.
5882 readline_internal (lbp
, stream
)
5884 register FILE *stream
;
5886 char *buffer
= lbp
->buffer
;
5887 register char *p
= lbp
->buffer
;
5888 register char *pend
;
5891 pend
= p
+ lbp
->size
; /* Separate to avoid 386/IX compiler bug. */
5895 register int c
= getc (stream
);
5898 /* We're at the end of linebuffer: expand it. */
5900 xrnew (buffer
, lbp
->size
, char);
5901 p
+= buffer
- lbp
->buffer
;
5902 pend
= buffer
+ lbp
->size
;
5903 lbp
->buffer
= buffer
;
5913 if (p
> buffer
&& p
[-1] == '\r')
5917 /* Assume CRLF->LF translation will be performed by Emacs
5918 when loading this file, so CRs won't appear in the buffer.
5919 It would be cleaner to compensate within Emacs;
5920 however, Emacs does not know how many CRs were deleted
5921 before any given point in the file. */
5936 lbp
->len
= p
- buffer
;
5938 if (need_filebuf
/* we need filebuf for multi-line regexps */
5939 && chars_deleted
> 0) /* not at EOF */
5941 while (filebuf
.size
<= filebuf
.len
+ lbp
->len
+ 1) /* +1 for \n */
5943 /* Expand filebuf. */
5945 xrnew (filebuf
.buffer
, filebuf
.size
, char);
5947 strncpy (filebuf
.buffer
+ filebuf
.len
, lbp
->buffer
, lbp
->len
);
5948 filebuf
.len
+= lbp
->len
;
5949 filebuf
.buffer
[filebuf
.len
++] = '\n';
5950 filebuf
.buffer
[filebuf
.len
] = '\0';
5953 return lbp
->len
+ chars_deleted
;
5957 * Like readline_internal, above, but in addition try to match the
5958 * input line against relevant regular expressions and manage #line
5962 readline (lbp
, stream
)
5968 linecharno
= charno
; /* update global char number of line start */
5969 result
= readline_internal (lbp
, stream
); /* read line */
5970 lineno
+= 1; /* increment global line number */
5971 charno
+= result
; /* increment global char number */
5973 /* Honour #line directives. */
5974 if (!no_line_directive
)
5976 static bool discard_until_line_directive
;
5978 /* Check whether this is a #line directive. */
5979 if (result
> 12 && strneq (lbp
->buffer
, "#line ", 6))
5983 if (DEBUG
) start
= 0; /* shut up the compiler */
5984 if (sscanf (lbp
->buffer
, "#line %d \"%n", &lno
, &start
) == 1)
5986 char *endp
= lbp
->buffer
+ start
;
5989 while ((endp
= etags_strchr (endp
, '"')) != NULL
5990 && endp
[-1] == '\\')
5993 /* Ok, this is a real #line directive. Let's deal with it. */
5995 char *taggedabsname
; /* absolute name of original file */
5996 char *taggedfname
; /* name of original file as given */
5997 char *name
; /* temp var */
5999 discard_until_line_directive
= FALSE
; /* found it */
6000 name
= lbp
->buffer
+ start
;
6002 canonicalize_filename (name
); /* for DOS */
6003 taggedabsname
= absolute_filename (name
, curfdp
->infabsdir
);
6004 if (filename_is_absolute (name
)
6005 || filename_is_absolute (curfdp
->infname
))
6006 taggedfname
= savestr (taggedabsname
);
6008 taggedfname
= relative_filename (taggedabsname
,tagfiledir
);
6010 if (streq (curfdp
->taggedfname
, taggedfname
))
6011 /* The #line directive is only a line number change. We
6012 deal with this afterwards. */
6015 /* The tags following this #line directive should be
6016 attributed to taggedfname. In order to do this, set
6017 curfdp accordingly. */
6019 fdesc
*fdp
; /* file description pointer */
6021 /* Go look for a file description already set up for the
6022 file indicated in the #line directive. If there is
6023 one, use it from now until the next #line
6025 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
6026 if (streq (fdp
->infname
, curfdp
->infname
)
6027 && streq (fdp
->taggedfname
, taggedfname
))
6028 /* If we remove the second test above (after the &&)
6029 then all entries pertaining to the same file are
6030 coalesced in the tags file. If we use it, then
6031 entries pertaining to the same file but generated
6032 from different files (via #line directives) will
6033 go into separate sections in the tags file. These
6034 alternatives look equivalent. The first one
6035 destroys some apparently useless information. */
6041 /* Else, if we already tagged the real file, skip all
6042 input lines until the next #line directive. */
6043 if (fdp
== NULL
) /* not found */
6044 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
6045 if (streq (fdp
->infabsname
, taggedabsname
))
6047 discard_until_line_directive
= TRUE
;
6051 /* Else create a new file description and use that from
6052 now on, until the next #line directive. */
6053 if (fdp
== NULL
) /* not found */
6056 fdhead
= xnew (1, fdesc
);
6057 *fdhead
= *curfdp
; /* copy curr. file description */
6059 fdhead
->infname
= savestr (curfdp
->infname
);
6060 fdhead
->infabsname
= savestr (curfdp
->infabsname
);
6061 fdhead
->infabsdir
= savestr (curfdp
->infabsdir
);
6062 fdhead
->taggedfname
= taggedfname
;
6063 fdhead
->usecharno
= FALSE
;
6064 fdhead
->prop
= NULL
;
6065 fdhead
->written
= FALSE
;
6069 free (taggedabsname
);
6071 readline (lbp
, stream
);
6073 } /* if a real #line directive */
6074 } /* if #line is followed by a a number */
6075 } /* if line begins with "#line " */
6077 /* If we are here, no #line directive was found. */
6078 if (discard_until_line_directive
)
6082 /* Do a tail recursion on ourselves, thus discarding the contents
6083 of the line buffer. */
6084 readline (lbp
, stream
);
6088 discard_until_line_directive
= FALSE
;
6091 } /* if #line directives should be considered */
6093 #ifdef ETAGS_REGEXPS
6099 /* Match against relevant regexps. */
6101 for (rp
= p_head
; rp
!= NULL
; rp
= rp
->p_next
)
6103 /* Only use generic regexps or those for the current language.
6104 Also do not use multiline regexps, which is the job of
6105 regex_tag_multiline. */
6106 if ((rp
->lang
!= NULL
&& rp
->lang
!= fdhead
->lang
)
6110 match
= re_match (rp
->pat
, lbp
->buffer
, lbp
->len
, 0, &rp
->regs
);
6115 if (!rp
->error_signaled
)
6117 error ("regexp stack overflow while matching \"%s\"",
6119 rp
->error_signaled
= TRUE
;
6126 /* Empty string matched. */
6127 if (!rp
->error_signaled
)
6129 error ("regexp matches the empty string: \"%s\"", rp
->pattern
);
6130 rp
->error_signaled
= TRUE
;
6134 /* Match occurred. Construct a tag. */
6136 if (name
[0] != '\0')
6137 /* Make a named tag. */
6138 name
= substitute (lbp
->buffer
, rp
->name
, &rp
->regs
);
6139 if (rp
->force_explicit_name
)
6140 /* Force explicit tag name, if a name is there. */
6141 pfnote (name
, TRUE
, lbp
->buffer
, match
, lineno
, linecharno
);
6143 make_tag (name
, strlen (name
), TRUE
,
6144 lbp
->buffer
, match
, lineno
, linecharno
);
6149 #endif /* ETAGS_REGEXPS */
6154 * Return a pointer to a space of size strlen(cp)+1 allocated
6155 * with xnew where the string CP has been copied.
6161 return savenstr (cp
, strlen (cp
));
6165 * Return a pointer to a space of size LEN+1 allocated with xnew where
6166 * the string CP has been copied for at most the first LEN characters.
6175 dp
= xnew (len
+ 1, char);
6176 strncpy (dp
, cp
, len
);
6182 * Return the ptr in sp at which the character c last
6183 * appears; NULL if not found
6185 * Identical to POSIX strrchr, included for portability.
6188 etags_strrchr (sp
, c
)
6189 register const char *sp
;
6192 register const char *r
;
6204 * Return the ptr in sp at which the character c first
6205 * appears; NULL if not found
6207 * Identical to POSIX strchr, included for portability.
6210 etags_strchr (sp
, c
)
6211 register const char *sp
;
6223 * Compare two strings, ignoring case for alphabetic characters.
6225 * Same as BSD's strcasecmp, included for portability.
6228 etags_strcasecmp (s1
, s2
)
6229 register const char *s1
;
6230 register const char *s2
;
6233 && (ISALPHA (*s1
) && ISALPHA (*s2
)
6234 ? lowcase (*s1
) == lowcase (*s2
)
6238 return (ISALPHA (*s1
) && ISALPHA (*s2
)
6239 ? lowcase (*s1
) - lowcase (*s2
)
6244 * Compare two strings, ignoring case for alphabetic characters.
6245 * Stop after a given number of characters
6247 * Same as BSD's strncasecmp, included for portability.
6250 etags_strncasecmp (s1
, s2
, n
)
6251 register const char *s1
;
6252 register const char *s2
;
6255 while (*s1
!= '\0' && n
-- > 0
6256 && (ISALPHA (*s1
) && ISALPHA (*s2
)
6257 ? lowcase (*s1
) == lowcase (*s2
)
6264 return (ISALPHA (*s1
) && ISALPHA (*s2
)
6265 ? lowcase (*s1
) - lowcase (*s2
)
6269 /* Skip spaces, return new pointer. */
6274 while (iswhite (*cp
))
6279 /* Skip non spaces, return new pointer. */
6281 skip_non_spaces (cp
)
6284 while (*cp
!= '\0' && !iswhite (*cp
))
6289 /* Print error message and exit. */
6307 suggest_asking_for_help ()
6309 fprintf (stderr
, "\tTry `%s %s' for a complete list of options.\n",
6320 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
6323 const char *s1
, *s2
;
6325 fprintf (stderr
, "%s: ", progname
);
6326 fprintf (stderr
, s1
, s2
);
6327 fprintf (stderr
, "\n");
6330 /* Return a newly-allocated string whose contents
6331 concatenate those of s1, s2, s3. */
6336 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
6337 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
6339 strcpy (result
, s1
);
6340 strcpy (result
+ len1
, s2
);
6341 strcpy (result
+ len1
+ len2
, s3
);
6342 result
[len1
+ len2
+ len3
] = '\0';
6348 /* Does the same work as the system V getcwd, but does not need to
6349 guess the buffer size in advance. */
6355 char *path
= xnew (bufsize
, char);
6357 while (getcwd (path
, bufsize
) == NULL
)
6359 if (errno
!= ERANGE
)
6363 path
= xnew (bufsize
, char);
6366 canonicalize_filename (path
);
6369 #else /* not HAVE_GETCWD */
6372 char *p
, path
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
6376 for (p
= path
; *p
!= '\0'; p
++)
6382 return strdup (path
);
6383 #else /* not MSDOS */
6387 linebuffer_init (&path
);
6388 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
6389 if (pipe
== NULL
|| readline_internal (&path
, pipe
) == 0)
6394 #endif /* not MSDOS */
6395 #endif /* not HAVE_GETCWD */
6398 /* Return a newly allocated string containing the file name of FILE
6399 relative to the absolute directory DIR (which should end with a slash). */
6401 relative_filename (file
, dir
)
6404 char *fp
, *dp
, *afn
, *res
;
6407 /* Find the common root of file and dir (with a trailing slash). */
6408 afn
= absolute_filename (file
, cwd
);
6411 while (*fp
++ == *dp
++)
6413 fp
--, dp
--; /* back to the first differing char */
6415 if (fp
== afn
&& afn
[0] != '/') /* cannot build a relative name */
6418 do /* look at the equal chars until '/' */
6422 /* Build a sequence of "../" strings for the resulting relative file name. */
6424 while ((dp
= etags_strchr (dp
+ 1, '/')) != NULL
)
6426 res
= xnew (3*i
+ strlen (fp
+ 1) + 1, char);
6429 strcat (res
, "../");
6431 /* Add the file name relative to the common root of file and dir. */
6432 strcat (res
, fp
+ 1);
6438 /* Return a newly allocated string containing the absolute file name
6439 of FILE given DIR (which should end with a slash). */
6441 absolute_filename (file
, dir
)
6444 char *slashp
, *cp
, *res
;
6446 if (filename_is_absolute (file
))
6447 res
= savestr (file
);
6449 /* We don't support non-absolute file names with a drive
6450 letter, like `d:NAME' (it's too much hassle). */
6451 else if (file
[1] == ':')
6452 fatal ("%s: relative file names with drive letters not supported", file
);
6455 res
= concat (dir
, file
, "");
6457 /* Delete the "/dirname/.." and "/." substrings. */
6458 slashp
= etags_strchr (res
, '/');
6459 while (slashp
!= NULL
&& slashp
[0] != '\0')
6461 if (slashp
[1] == '.')
6463 if (slashp
[2] == '.'
6464 && (slashp
[3] == '/' || slashp
[3] == '\0'))
6469 while (cp
>= res
&& !filename_is_absolute (cp
));
6471 cp
= slashp
; /* the absolute name begins with "/.." */
6473 /* Under MSDOS and NT we get `d:/NAME' as absolute
6474 file name, so the luser could say `d:/../NAME'.
6475 We silently treat this as `d:/NAME'. */
6476 else if (cp
[0] != '/')
6479 strcpy (cp
, slashp
+ 3);
6483 else if (slashp
[2] == '/' || slashp
[2] == '\0')
6485 strcpy (slashp
, slashp
+ 2);
6490 slashp
= etags_strchr (slashp
+ 1, '/');
6494 return savestr ("/");
6499 /* Return a newly allocated string containing the absolute
6500 file name of dir where FILE resides given DIR (which should
6501 end with a slash). */
6503 absolute_dirname (file
, dir
)
6509 canonicalize_filename (file
);
6510 slashp
= etags_strrchr (file
, '/');
6512 return savestr (dir
);
6515 res
= absolute_filename (file
, dir
);
6521 /* Whether the argument string is an absolute file name. The argument
6522 string must have been canonicalized with canonicalize_filename. */
6524 filename_is_absolute (fn
)
6527 return (fn
[0] == '/'
6529 || (ISALPHA(fn
[0]) && fn
[1] == ':' && fn
[2] == '/')
6534 /* Translate backslashes into slashes. Works in place. */
6536 canonicalize_filename (fn
)
6540 /* Canonicalize drive letter case. */
6541 if (fn
[0] != '\0' && fn
[1] == ':' && ISLOWER (fn
[0]))
6542 fn
[0] = upcase (fn
[0]);
6543 /* Convert backslashes to slashes. */
6544 for (; *fn
!= '\0'; fn
++)
6549 fn
= NULL
; /* shut up the compiler */
6554 /* Initialize a linebuffer for use */
6556 linebuffer_init (lbp
)
6559 lbp
->size
= (DEBUG
) ? 3 : 200;
6560 lbp
->buffer
= xnew (lbp
->size
, char);
6561 lbp
->buffer
[0] = '\0';
6565 /* Set the minimum size of a string contained in a linebuffer. */
6567 linebuffer_setlen (lbp
, toksize
)
6571 while (lbp
->size
<= toksize
)
6574 xrnew (lbp
->buffer
, lbp
->size
, char);
6579 /* Like malloc but get fatal error if memory is exhausted. */
6584 PTR result
= (PTR
) malloc (size
);
6586 fatal ("virtual memory exhausted", (char *)NULL
);
6591 xrealloc (ptr
, size
)
6595 PTR result
= (PTR
) realloc (ptr
, size
);
6597 fatal ("virtual memory exhausted", (char *)NULL
);
6603 * c-indentation-style: gnu
6604 * indent-tabs-mode: t
6607 * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node" "regexp")