Avoid doubly tagging parse.y when both parse.c and parse.y are given on
[bpt/emacs.git] / lib-src / etags.c
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
4
5 This file is not considered part of GNU Emacs.
6
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.
11
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.
16
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. */
20
21 /*
22 * Authors:
23 * Ctags originally by Ken Arnold.
24 * Fortran added by Jim Kleckner.
25 * Ed Pelegri-Llopart added C typedefs.
26 * Gnu Emacs TAGS format and modifications by RMS?
27 * 1989 Sam Kendall added C++.
28 * 1992 Joseph B. Wells improved C and C++ parsing.
29 * 1993 Francesco Potortì reorganised C and C++.
30 * 1994 Regexp tags by Tom Tromey.
31 * 2001 Nested classes by Francesco Potortì (ideas by Mykola Dzyuba).
32 *
33 * Francesco Potortì <pot@gnu.org> has maintained it since 1993.
34 */
35
36 char pot_etags_version[] = "@(#) pot revision number is 15.10";
37
38 #define TRUE 1
39 #define FALSE 0
40
41 #ifdef DEBUG
42 # undef DEBUG
43 # define DEBUG TRUE
44 #else
45 # define DEBUG FALSE
46 # define NDEBUG /* disable assert */
47 #endif
48
49 #ifdef HAVE_CONFIG_H
50 # include <config.h>
51 /* On some systems, Emacs defines static as nothing for the sake
52 of unexec. We don't want that here since we don't use unexec. */
53 # undef static
54 # define ETAGS_REGEXPS /* use the regexp features */
55 # define LONG_OPTIONS /* accept long options */
56 # ifndef PTR /* for Xemacs */
57 # define PTR void *
58 # endif
59 # ifndef __P /* for Xemacs */
60 # define __P(args) args
61 # endif
62 #else
63 # if defined(__STDC__) && (__STDC__ || defined(__SUNPRO_C))
64 # define __P(args) args /* use prototypes */
65 # define PTR void * /* for generic pointers */
66 # else
67 # define __P(args) () /* no prototypes */
68 # define const /* remove const for old compilers' sake */
69 # define PTR long * /* don't use void* */
70 # endif
71 #endif /* !HAVE_CONFIG_H */
72
73 #ifndef _GNU_SOURCE
74 # define _GNU_SOURCE 1 /* enables some compiler checks on GNU */
75 #endif
76
77 /* WIN32_NATIVE is for Xemacs.
78 MSDOS, WINDOWSNT, DOS_NT are for Emacs. */
79 #ifdef WIN32_NATIVE
80 # undef MSDOS
81 # undef WINDOWSNT
82 # define WINDOWSNT
83 #endif /* WIN32_NATIVE */
84
85 #ifdef MSDOS
86 # undef MSDOS
87 # define MSDOS TRUE
88 # include <fcntl.h>
89 # include <sys/param.h>
90 # include <io.h>
91 # ifndef HAVE_CONFIG_H
92 # define DOS_NT
93 # include <sys/config.h>
94 # endif
95 #else
96 # define MSDOS FALSE
97 #endif /* MSDOS */
98
99 #ifdef WINDOWSNT
100 # include <stdlib.h>
101 # include <fcntl.h>
102 # include <string.h>
103 # include <direct.h>
104 # include <io.h>
105 # define MAXPATHLEN _MAX_PATH
106 # undef HAVE_NTGUI
107 # undef DOS_NT
108 # define DOS_NT
109 # ifndef HAVE_GETCWD
110 # define HAVE_GETCWD
111 # endif /* undef HAVE_GETCWD */
112 #else /* !WINDOWSNT */
113 # ifdef STDC_HEADERS
114 # include <stdlib.h>
115 # include <string.h>
116 # else
117 extern char *getenv ();
118 # endif
119 #endif /* !WINDOWSNT */
120
121 #ifdef HAVE_UNISTD_H
122 # include <unistd.h>
123 #else
124 # if defined (HAVE_GETCWD) && !defined (WINDOWSNT)
125 extern char *getcwd (char *buf, size_t size);
126 # endif
127 #endif /* HAVE_UNISTD_H */
128
129 #include <stdio.h>
130 #include <ctype.h>
131 #include <errno.h>
132 #ifndef errno
133 extern int errno;
134 #endif
135 #include <sys/types.h>
136 #include <sys/stat.h>
137
138 #include <assert.h>
139 #ifdef NDEBUG
140 # undef assert /* some systems have a buggy assert.h */
141 # define assert(x) ((void) 0)
142 #endif
143
144 #if !defined (S_ISREG) && defined (S_IFREG)
145 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
146 #endif
147
148 #ifdef LONG_OPTIONS
149 # include <getopt.h>
150 #else
151 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
152 extern char *optarg;
153 extern int optind, opterr;
154 #endif /* LONG_OPTIONS */
155
156 #ifdef ETAGS_REGEXPS
157 # ifndef HAVE_CONFIG_H /* this is a standalone compilation */
158 # ifdef __CYGWIN__ /* compiling on Cygwin */
159 !!! NOTICE !!!
160 the regex.h distributed with Cygwin is not compatible with etags, alas!
161 If you want regular expression support, you should delete this notice and
162 arrange to use the GNU regex.h and regex.c.
163 # endif
164 # endif
165 # include <regex.h>
166 #endif /* ETAGS_REGEXPS */
167
168 /* Define CTAGS to make the program "ctags" compatible with the usual one.
169 Leave it undefined to make the program "etags", which makes emacs-style
170 tag tables and tags typedefs, #defines and struct/union/enum by default. */
171 #ifdef CTAGS
172 # undef CTAGS
173 # define CTAGS TRUE
174 #else
175 # define CTAGS FALSE
176 #endif
177
178 /* Exit codes for success and failure. */
179 #ifdef VMS
180 # define GOOD 1
181 # define BAD 0
182 #else
183 # define GOOD 0
184 # define BAD 1
185 #endif
186
187 #define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t))
188 #define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
189
190 #define CHARS 256 /* 2^sizeof(char) */
191 #define CHAR(x) ((unsigned int)(x) & (CHARS - 1))
192 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */
193 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
194 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
195 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
196 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
197
198 #define ISALNUM(c) isalnum (CHAR(c))
199 #define ISALPHA(c) isalpha (CHAR(c))
200 #define ISDIGIT(c) isdigit (CHAR(c))
201 #define ISLOWER(c) islower (CHAR(c))
202
203 #define lowcase(c) tolower (CHAR(c))
204 #define upcase(c) toupper (CHAR(c))
205
206
207 /*
208 * xnew, xrnew -- allocate, reallocate storage
209 *
210 * SYNOPSIS: Type *xnew (int n, Type);
211 * void xrnew (OldPointer, int n, Type);
212 */
213 #if DEBUG
214 # include "chkmalloc.h"
215 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
216 (n) * sizeof (Type)))
217 # define xrnew(op,n,Type) ((op) = (Type *) trace_realloc (__FILE__, __LINE__, \
218 (char *) (op), (n) * sizeof (Type)))
219 #else
220 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
221 # define xrnew(op,n,Type) ((op) = (Type *) xrealloc ( \
222 (char *) (op), (n) * sizeof (Type)))
223 #endif
224
225 #define bool int
226
227 typedef void Lang_function __P((FILE *));
228
229 typedef struct
230 {
231 char *suffix; /* file name suffix for this compressor */
232 char *command; /* takes one arg and decompresses to stdout */
233 } compressor;
234
235 typedef struct
236 {
237 char *name; /* language name */
238 bool metasource; /* source used to generate other sources */
239 Lang_function *function; /* parse function */
240 char **filenames; /* names of this language's files */
241 char **suffixes; /* name suffixes of this language's files */
242 char **interpreters; /* interpreters for this language */
243 } language;
244
245 typedef struct fdesc
246 {
247 struct fdesc *next; /* for the linked list */
248 char *infname; /* uncompressed input file name */
249 char *infabsname; /* absolute uncompressed input file name */
250 char *infabsdir; /* absolute dir of input file */
251 char *taggedfname; /* file name to write in tagfile */
252 language *lang; /* language of file */
253 char *prop; /* file properties to write in tagfile */
254 bool usecharno; /* etags tags shall contain char number */
255 } fdesc;
256
257 typedef struct node_st
258 { /* sorting structure */
259 struct node_st *left, *right; /* left and right sons */
260 fdesc *fdp; /* description of file to whom tag belongs */
261 char *name; /* tag name */
262 char *pat; /* search pattern */
263 bool valid; /* write this tag on the tag file */
264 bool is_func; /* function tag: use pattern in CTAGS mode */
265 bool been_warned; /* warning already given for duplicated tag */
266 int lno; /* line number tag is on */
267 long cno; /* character number line starts on */
268 } node;
269
270 /*
271 * A `linebuffer' is a structure which holds a line of text.
272 * `readline_internal' reads a line from a stream into a linebuffer
273 * and works regardless of the length of the line.
274 * SIZE is the size of BUFFER, LEN is the length of the string in
275 * BUFFER after readline reads it.
276 */
277 typedef struct
278 {
279 long size;
280 int len;
281 char *buffer;
282 } linebuffer;
283
284 /* Used to support mixing of --lang and file names. */
285 typedef struct
286 {
287 enum {
288 at_language, /* a language specification */
289 at_regexp, /* a regular expression */
290 at_icregexp, /* same, but with case ignored */
291 at_filename /* a file name */
292 } arg_type; /* argument type */
293 language *lang; /* language associated with the argument */
294 char *what; /* the argument itself */
295 } argument;
296
297 #ifdef ETAGS_REGEXPS
298 /* Structure defining a regular expression. */
299 typedef struct pattern
300 {
301 struct pattern *p_next;
302 language *lang;
303 char *regex;
304 struct re_pattern_buffer *pat;
305 struct re_registers regs;
306 char *name_pattern;
307 bool error_signaled;
308 bool ignore_case;
309 } pattern;
310 #endif /* ETAGS_REGEXPS */
311
312
313 /* Many compilers barf on this:
314 Lang_function Ada_funcs;
315 so let's write it this way */
316 static void Ada_funcs __P((FILE *));
317 static void Asm_labels __P((FILE *));
318 static void C_entries __P((int c_ext, FILE *));
319 static void default_C_entries __P((FILE *));
320 static void plain_C_entries __P((FILE *));
321 static void Cjava_entries __P((FILE *));
322 static void Cobol_paragraphs __P((FILE *));
323 static void Cplusplus_entries __P((FILE *));
324 static void Cstar_entries __P((FILE *));
325 static void Erlang_functions __P((FILE *));
326 static void Fortran_functions __P((FILE *));
327 static void Yacc_entries __P((FILE *));
328 static void Lisp_functions __P((FILE *));
329 static void Makefile_targets __P((FILE *));
330 static void Pascal_functions __P((FILE *));
331 static void Perl_functions __P((FILE *));
332 static void PHP_functions __P((FILE *));
333 static void Postscript_functions __P((FILE *));
334 static void Prolog_functions __P((FILE *));
335 static void Python_functions __P((FILE *));
336 static void Scheme_functions __P((FILE *));
337 static void TeX_commands __P((FILE *));
338 static void Texinfo_nodes __P((FILE *));
339 static void just_read_file __P((FILE *));
340
341 static void print_language_names __P((void));
342 static void print_version __P((void));
343 static void print_help __P((void));
344 int main __P((int, char **));
345
346 static compressor *get_compressor_from_suffix __P((char *, char **));
347 static language *get_language_from_langname __P((const char *));
348 static language *get_language_from_interpreter __P((char *));
349 static language *get_language_from_filename __P((char *));
350 static long readline __P((linebuffer *, FILE *));
351 static long readline_internal __P((linebuffer *, FILE *));
352 static bool nocase_tail __P((char *));
353 static char *get_tag __P((char *));
354
355 #ifdef ETAGS_REGEXPS
356 static void analyse_regex __P((char *, bool));
357 static void add_regex __P((char *, bool, language *));
358 static void free_patterns __P((void));
359 #endif /* ETAGS_REGEXPS */
360 static void error __P((const char *, const char *));
361 static void suggest_asking_for_help __P((void));
362 void fatal __P((char *, char *));
363 static void pfatal __P((char *));
364 static void add_node __P((node *, node **));
365
366 static void init __P((void));
367 static void initbuffer __P((linebuffer *));
368 static void process_file __P((char *, language *));
369 static void find_entries __P((FILE *));
370 static void free_tree __P((node *));
371 static void pfnote __P((char *, bool, char *, int, int, long));
372 static void new_pfnote __P((char *, int, bool, char *, int, int, long));
373 static void invalidate_nodes __P((fdesc *, node *));
374 static void put_entries __P((node *));
375
376 static char *concat __P((char *, char *, char *));
377 static char *skip_spaces __P((char *));
378 static char *skip_non_spaces __P((char *));
379 static char *savenstr __P((char *, int));
380 static char *savestr __P((char *));
381 static char *etags_strchr __P((const char *, int));
382 static char *etags_strrchr __P((const char *, int));
383 static char *etags_getcwd __P((void));
384 static char *relative_filename __P((char *, char *));
385 static char *absolute_filename __P((char *, char *));
386 static char *absolute_dirname __P((char *, char *));
387 static bool filename_is_absolute __P((char *f));
388 static void canonicalize_filename __P((char *));
389 static void linebuffer_setlen __P((linebuffer *, int));
390 static PTR xmalloc __P((unsigned int));
391 static PTR xrealloc __P((char *, unsigned int));
392
393 \f
394 static char searchar = '/'; /* use /.../ searches */
395
396 static char *tagfile; /* output file */
397 static char *progname; /* name this program was invoked with */
398 static char *cwd; /* current working directory */
399 static char *tagfiledir; /* directory of tagfile */
400 static FILE *tagf; /* ioptr for tags file */
401
402 static fdesc *fdhead; /* head of file description list */
403 static fdesc *curfdp; /* current file description */
404 static int lineno; /* line number of current line */
405 static long charno; /* current character number */
406 static long linecharno; /* charno of start of current line */
407 static char *dbp; /* pointer to start of current tag */
408
409 static const int invalidcharno = -1;
410
411 static node *nodehead; /* the head of the binary tree of tags */
412
413 static linebuffer lb; /* the current line */
414
415 /* boolean "functions" (see init) */
416 static bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
417 static char
418 /* white chars */
419 *white = " \f\t\n\r\v",
420 /* not in a name */
421 *nonam = " \f\t\n\r()=,;",
422 /* token ending chars */
423 *endtk = " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
424 /* token starting chars */
425 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
426 /* valid in-token chars */
427 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
428
429 static bool append_to_tagfile; /* -a: append to tags */
430 /* The next four default to TRUE for etags, but to FALSE for ctags. */
431 static bool typedefs; /* -t: create tags for C and Ada typedefs */
432 static bool typedefs_or_cplusplus; /* -T: create tags for C typedefs, level */
433 /* 0 struct/enum/union decls, and C++ */
434 /* member functions. */
435 static bool constantypedefs; /* -d: create tags for C #define, enum */
436 /* constants and variables. */
437 /* -D: opposite of -d. Default under ctags. */
438 static bool globals; /* create tags for global variables */
439 static bool declarations; /* --declarations: tag them and extern in C&Co*/
440 static bool members; /* create tags for C member variables */
441 static bool no_line_directive; /* ignore #line directives */
442 static bool update; /* -u: update tags */
443 static bool vgrind_style; /* -v: create vgrind style index output */
444 static bool no_warnings; /* -w: suppress warnings */
445 static bool cxref_style; /* -x: create cxref style output */
446 static bool cplusplus; /* .[hc] means C++, not C */
447 static bool noindentypedefs; /* -I: ignore indentation in C */
448 static bool packages_only; /* --packages-only: in Ada, only tag packages*/
449
450 #ifdef ETAGS_REGEXPS
451 /* List of all regexps. */
452 static pattern *p_head;
453
454 /* How many characters in the character set. (From regex.c.) */
455 #define CHAR_SET_SIZE 256
456 /* Translation table for case-insensitive matching. */
457 static char lc_trans[CHAR_SET_SIZE];
458 #endif /* ETAGS_REGEXPS */
459
460 #ifdef LONG_OPTIONS
461 static struct option longopts[] =
462 {
463 { "packages-only", no_argument, &packages_only, TRUE },
464 { "c++", no_argument, NULL, 'C' },
465 { "declarations", no_argument, &declarations, TRUE },
466 { "no-line-directive", no_argument, &no_line_directive, TRUE },
467 { "help", no_argument, NULL, 'h' },
468 { "help", no_argument, NULL, 'H' },
469 { "ignore-indentation", no_argument, NULL, 'I' },
470 { "language", required_argument, NULL, 'l' },
471 { "members", no_argument, &members, TRUE },
472 { "no-members", no_argument, &members, FALSE },
473 { "output", required_argument, NULL, 'o' },
474 #ifdef ETAGS_REGEXPS
475 { "regex", required_argument, NULL, 'r' },
476 { "no-regex", no_argument, NULL, 'R' },
477 { "ignore-case-regex", required_argument, NULL, 'c' },
478 #endif /* ETAGS_REGEXPS */
479 { "version", no_argument, NULL, 'V' },
480
481 #if CTAGS /* Etags options */
482 { "backward-search", no_argument, NULL, 'B' },
483 { "cxref", no_argument, NULL, 'x' },
484 { "defines", no_argument, NULL, 'd' },
485 { "globals", no_argument, &globals, TRUE },
486 { "typedefs", no_argument, NULL, 't' },
487 { "typedefs-and-c++", no_argument, NULL, 'T' },
488 { "update", no_argument, NULL, 'u' },
489 { "vgrind", no_argument, NULL, 'v' },
490 { "no-warn", no_argument, NULL, 'w' },
491
492 #else /* Ctags options */
493 { "append", no_argument, NULL, 'a' },
494 { "no-defines", no_argument, NULL, 'D' },
495 { "no-globals", no_argument, &globals, FALSE },
496 { "include", required_argument, NULL, 'i' },
497 #endif
498 { NULL }
499 };
500 #endif /* LONG_OPTIONS */
501
502 static compressor compressors[] =
503 {
504 { "z", "gzip -d -c"},
505 { "Z", "gzip -d -c"},
506 { "gz", "gzip -d -c"},
507 { "GZ", "gzip -d -c"},
508 { "bz2", "bzip2 -d -c" },
509 { NULL }
510 };
511
512 /*
513 * Language stuff.
514 */
515
516 /* Ada code */
517 static char *Ada_suffixes [] =
518 { "ads", "adb", "ada", NULL };
519
520 /* Assembly code */
521 static char *Asm_suffixes [] =
522 { "a", /* Unix assembler */
523 "asm", /* Microcontroller assembly */
524 "def", /* BSO/Tasking definition includes */
525 "inc", /* Microcontroller include files */
526 "ins", /* Microcontroller include files */
527 "s", "sa", /* Unix assembler */
528 "S", /* cpp-processed Unix assembler */
529 "src", /* BSO/Tasking C compiler output */
530 NULL
531 };
532
533 /* Note that .c and .h can be considered C++, if the --c++ flag was
534 given, or if the `class' keyowrd is met inside the file.
535 That is why default_C_entries is called for these. */
536 static char *default_C_suffixes [] =
537 { "c", "h", NULL };
538
539 static char *Cplusplus_suffixes [] =
540 { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
541 "M", /* Objective C++ */
542 "pdb", /* Postscript with C syntax */
543 NULL };
544
545 static char *Cjava_suffixes [] =
546 { "java", NULL };
547
548 static char *Cobol_suffixes [] =
549 { "COB", "cob", NULL };
550
551 static char *Cstar_suffixes [] =
552 { "cs", "hs", NULL };
553
554 static char *Erlang_suffixes [] =
555 { "erl", "hrl", NULL };
556
557 static char *Fortran_suffixes [] =
558 { "F", "f", "f90", "for", NULL };
559
560 static char *Lisp_suffixes [] =
561 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL };
562
563 static char *Makefile_filenames [] =
564 { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL};
565
566 static char *Pascal_suffixes [] =
567 { "p", "pas", NULL };
568
569 static char *Perl_suffixes [] =
570 { "pl", "pm", NULL };
571
572 static char *Perl_interpreters [] =
573 { "perl", "@PERL@", NULL };
574
575 static char *PHP_suffixes [] =
576 { "php", "php3", "php4", NULL };
577
578 static char *plain_C_suffixes [] =
579 { "lm", /* Objective lex file */
580 "m", /* Objective C file */
581 "pc", /* Pro*C file */
582 NULL };
583
584 static char *Postscript_suffixes [] =
585 { "ps", "psw", NULL }; /* .psw is for PSWrap */
586
587 static char *Prolog_suffixes [] =
588 { "prolog", NULL };
589
590 static char *Python_suffixes [] =
591 { "py", NULL };
592
593 /* Can't do the `SCM' or `scm' prefix with a version number. */
594 static char *Scheme_suffixes [] =
595 { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL };
596
597 static char *TeX_suffixes [] =
598 { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL };
599
600 static char *Texinfo_suffixes [] =
601 { "texi", "texinfo", "txi", NULL };
602
603 static char *Yacc_suffixes [] =
604 { "y", "y++", "ym", "yxx", "yy", NULL }; /* .ym is Objective yacc file */
605
606 /*
607 * Table of languages.
608 *
609 * It is ok for a given function to be listed under more than one
610 * name. I just didn't.
611 */
612
613 static language lang_names [] =
614 {
615 { "ada", FALSE, Ada_funcs, NULL, Ada_suffixes, NULL },
616 { "asm", FALSE, Asm_labels, NULL, Asm_suffixes, NULL },
617 { "c", FALSE, default_C_entries, NULL, default_C_suffixes, NULL },
618 { "c++", FALSE, Cplusplus_entries, NULL, Cplusplus_suffixes, NULL },
619 { "c*", FALSE, Cstar_entries, NULL, Cstar_suffixes, NULL },
620 { "cobol", FALSE, Cobol_paragraphs, NULL, Cobol_suffixes, NULL },
621 { "erlang", FALSE, Erlang_functions, NULL, Erlang_suffixes, NULL },
622 { "fortran", FALSE, Fortran_functions, NULL, Fortran_suffixes, NULL },
623 { "java", FALSE, Cjava_entries, NULL, Cjava_suffixes, NULL },
624 { "lisp", FALSE, Lisp_functions, NULL, Lisp_suffixes, NULL },
625 { "makefile", FALSE, Makefile_targets, Makefile_filenames, NULL, NULL },
626 { "pascal", FALSE, Pascal_functions, NULL, Pascal_suffixes, NULL },
627 { "perl", FALSE, Perl_functions,NULL, Perl_suffixes, Perl_interpreters },
628 { "php", FALSE, PHP_functions, NULL, PHP_suffixes, NULL },
629 { "postscript",FALSE, Postscript_functions,NULL, Postscript_suffixes, NULL },
630 { "proc", FALSE, plain_C_entries, NULL, plain_C_suffixes, NULL },
631 { "prolog", FALSE, Prolog_functions, NULL, Prolog_suffixes, NULL },
632 { "python", FALSE, Python_functions, NULL, Python_suffixes, NULL },
633 { "scheme", FALSE, Scheme_functions, NULL, Scheme_suffixes, NULL },
634 { "tex", FALSE, TeX_commands, NULL, TeX_suffixes, NULL },
635 { "texinfo", FALSE, Texinfo_nodes, NULL, Texinfo_suffixes, NULL },
636 { "yacc", TRUE, Yacc_entries, NULL, Yacc_suffixes, NULL },
637 { "auto", FALSE, NULL }, /* default guessing scheme */
638 { "none", FALSE, just_read_file }, /* regexp matching only */
639 { NULL, FALSE, NULL } /* end of list */
640 };
641
642 \f
643 static void
644 print_language_names ()
645 {
646 language *lang;
647 char **name, **ext;
648
649 puts ("\nThese are the currently supported languages, along with the\n\
650 default file names and dot suffixes:");
651 for (lang = lang_names; lang->name != NULL; lang++)
652 {
653 printf (" %-*s", 10, lang->name);
654 if (lang->filenames != NULL)
655 for (name = lang->filenames; *name != NULL; name++)
656 printf (" %s", *name);
657 if (lang->suffixes != NULL)
658 for (ext = lang->suffixes; *ext != NULL; ext++)
659 printf (" .%s", *ext);
660 puts ("");
661 }
662 puts ("Where `auto' means use default language for files based on file\n\
663 name suffix, and `none' means only do regexp processing on files.\n\
664 If no language is specified and no matching suffix is found,\n\
665 the first line of the file is read for a sharp-bang (#!) sequence\n\
666 followed by the name of an interpreter. If no such sequence is found,\n\
667 Fortran is tried first; if no tags are found, C is tried next.\n\
668 When parsing any C file, a \"class\" keyword switches to C++.\n\
669 Compressed files are supported using gzip and bzip2.");
670 }
671
672 #ifndef EMACS_NAME
673 # define EMACS_NAME "GNU Emacs"
674 #endif
675 #ifndef VERSION
676 # define VERSION "21"
677 #endif
678 static void
679 print_version ()
680 {
681 printf ("%s (%s %s)\n", (CTAGS) ? "ctags" : "etags", EMACS_NAME, VERSION);
682 puts ("Copyright (C) 2002 Free Software Foundation, Inc. and Ken Arnold");
683 puts ("This program is distributed under the same terms as Emacs");
684
685 exit (GOOD);
686 }
687
688 static void
689 print_help ()
690 {
691 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
692 \n\
693 These are the options accepted by %s.\n", progname, progname);
694 #ifdef LONG_OPTIONS
695 puts ("You may use unambiguous abbreviations for the long option names.");
696 #else
697 puts ("Long option names do not work with this executable, as it is not\n\
698 linked with GNU getopt.");
699 #endif /* LONG_OPTIONS */
700 puts (" A - as file name means read names from stdin (one per line).\n\
701 Absolute names are stored in the output file as they are.\n\
702 Relative ones are stored relative to the output file's directory.\n");
703
704 if (!CTAGS)
705 puts ("-a, --append\n\
706 Append tag entries to existing tags file.");
707
708 puts ("--packages-only\n\
709 For Ada files, only generate tags for packages.");
710
711 if (CTAGS)
712 puts ("-B, --backward-search\n\
713 Write the search commands for the tag entries using '?', the\n\
714 backward-search command instead of '/', the forward-search command.");
715
716 /* This option is mostly obsolete, because etags can now automatically
717 detect C++. Retained for backward compatibility and for debugging and
718 experimentation. In principle, we could want to tag as C++ even
719 before any "class" keyword.
720 puts ("-C, --c++\n\
721 Treat files whose name suffix defaults to C language as C++ files.");
722 */
723
724 puts ("--declarations\n\
725 In C and derived languages, create tags for function declarations,");
726 if (CTAGS)
727 puts ("\tand create tags for extern variables if --globals is used.");
728 else
729 puts
730 ("\tand create tags for extern variables unless --no-globals is used.");
731
732 if (CTAGS)
733 puts ("-d, --defines\n\
734 Create tag entries for C #define constants and enum constants, too.");
735 else
736 puts ("-D, --no-defines\n\
737 Don't create tag entries for C #define constants and enum constants.\n\
738 This makes the tags file smaller.");
739
740 if (!CTAGS)
741 puts ("-i FILE, --include=FILE\n\
742 Include a note in tag file indicating that, when searching for\n\
743 a tag, one should also consult the tags file FILE after\n\
744 checking the current file.");
745
746 puts ("-l LANG, --language=LANG\n\
747 Force the following files to be considered as written in the\n\
748 named language up to the next --language=LANG option.");
749
750 if (CTAGS)
751 puts ("--globals\n\
752 Create tag entries for global variables in some languages.");
753 else
754 puts ("--no-globals\n\
755 Do not create tag entries for global variables in some\n\
756 languages. This makes the tags file smaller.");
757 puts ("--members\n\
758 Create tag entries for member variables in C and derived languages.");
759
760 #ifdef ETAGS_REGEXPS
761 puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
762 Make a tag for each line matching pattern REGEXP in the following\n\
763 files. {LANGUAGE}/REGEXP/ uses REGEXP for LANGUAGE files only.\n\
764 regexfile is a file containing one REGEXP per line.\n\
765 REGEXP is anchored (as if preceded by ^).\n\
766 The form /REGEXP/NAME/ creates a named tag.\n\
767 For example Tcl named tags can be created with:\n\
768 --regex=\"/proc[ \\t]+\\([^ \\t]+\\)/\\1/.\"");
769 puts ("-c /REGEXP/, --ignore-case-regex=/REGEXP/ or --ignore-case-regex=@regexfile\n\
770 Like -r, --regex but ignore case when matching expressions.");
771 puts ("-R, --no-regex\n\
772 Don't create tags from regexps for the following files.");
773 #endif /* ETAGS_REGEXPS */
774 puts ("-o FILE, --output=FILE\n\
775 Write the tags to FILE.");
776 puts ("-I, --ignore-indentation\n\
777 Don't rely on indentation quite as much as normal. Currently,\n\
778 this means not to assume that a closing brace in the first\n\
779 column is the final brace of a function or structure\n\
780 definition in C and C++.");
781
782 if (CTAGS)
783 {
784 puts ("-t, --typedefs\n\
785 Generate tag entries for C and Ada typedefs.");
786 puts ("-T, --typedefs-and-c++\n\
787 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
788 and C++ member functions.");
789 }
790
791 if (CTAGS)
792 puts ("-u, --update\n\
793 Update the tag entries for the given files, leaving tag\n\
794 entries for other files in place. Currently, this is\n\
795 implemented by deleting the existing entries for the given\n\
796 files and then rewriting the new entries at the end of the\n\
797 tags file. It is often faster to simply rebuild the entire\n\
798 tag file than to use this.");
799
800 if (CTAGS)
801 {
802 puts ("-v, --vgrind\n\
803 Generates an index of items intended for human consumption,\n\
804 similar to the output of vgrind. The index is sorted, and\n\
805 gives the page number of each item.");
806 puts ("-w, --no-warn\n\
807 Suppress warning messages about entries defined in multiple\n\
808 files.");
809 puts ("-x, --cxref\n\
810 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
811 The output uses line numbers instead of page numbers, but\n\
812 beyond that the differences are cosmetic; try both to see\n\
813 which you like.");
814 }
815
816 puts ("-V, --version\n\
817 Print the version of the program.\n\
818 -h, --help\n\
819 Print this help message.");
820
821 print_language_names ();
822
823 puts ("");
824 puts ("Report bugs to bug-gnu-emacs@gnu.org");
825
826 exit (GOOD);
827 }
828
829 \f
830 #ifdef VMS /* VMS specific functions */
831
832 #define EOS '\0'
833
834 /* This is a BUG! ANY arbitrary limit is a BUG!
835 Won't someone please fix this? */
836 #define MAX_FILE_SPEC_LEN 255
837 typedef struct {
838 short curlen;
839 char body[MAX_FILE_SPEC_LEN + 1];
840 } vspec;
841
842 /*
843 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
844 returning in each successive call the next file name matching the input
845 spec. The function expects that each in_spec passed
846 to it will be processed to completion; in particular, up to and
847 including the call following that in which the last matching name
848 is returned, the function ignores the value of in_spec, and will
849 only start processing a new spec with the following call.
850 If an error occurs, on return out_spec contains the value
851 of in_spec when the error occurred.
852
853 With each successive file name returned in out_spec, the
854 function's return value is one. When there are no more matching
855 names the function returns zero. If on the first call no file
856 matches in_spec, or there is any other error, -1 is returned.
857 */
858
859 #include <rmsdef.h>
860 #include <descrip.h>
861 #define OUTSIZE MAX_FILE_SPEC_LEN
862 static short
863 fn_exp (out, in)
864 vspec *out;
865 char *in;
866 {
867 static long context = 0;
868 static struct dsc$descriptor_s o;
869 static struct dsc$descriptor_s i;
870 static bool pass1 = TRUE;
871 long status;
872 short retval;
873
874 if (pass1)
875 {
876 pass1 = FALSE;
877 o.dsc$a_pointer = (char *) out;
878 o.dsc$w_length = (short)OUTSIZE;
879 i.dsc$a_pointer = in;
880 i.dsc$w_length = (short)strlen(in);
881 i.dsc$b_dtype = DSC$K_DTYPE_T;
882 i.dsc$b_class = DSC$K_CLASS_S;
883 o.dsc$b_dtype = DSC$K_DTYPE_VT;
884 o.dsc$b_class = DSC$K_CLASS_VS;
885 }
886 if ((status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL)
887 {
888 out->body[out->curlen] = EOS;
889 return 1;
890 }
891 else if (status == RMS$_NMF)
892 retval = 0;
893 else
894 {
895 strcpy(out->body, in);
896 retval = -1;
897 }
898 lib$find_file_end(&context);
899 pass1 = TRUE;
900 return retval;
901 }
902
903 /*
904 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
905 name of each file specified by the provided arg expanding wildcards.
906 */
907 static char *
908 gfnames (arg, p_error)
909 char *arg;
910 bool *p_error;
911 {
912 static vspec filename = {MAX_FILE_SPEC_LEN, "\0"};
913
914 switch (fn_exp (&filename, arg))
915 {
916 case 1:
917 *p_error = FALSE;
918 return filename.body;
919 case 0:
920 *p_error = FALSE;
921 return NULL;
922 default:
923 *p_error = TRUE;
924 return filename.body;
925 }
926 }
927
928 #ifndef OLD /* Newer versions of VMS do provide `system'. */
929 system (cmd)
930 char *cmd;
931 {
932 error ("%s", "system() function not implemented under VMS");
933 }
934 #endif
935
936 #define VERSION_DELIM ';'
937 char *massage_name (s)
938 char *s;
939 {
940 char *start = s;
941
942 for ( ; *s; s++)
943 if (*s == VERSION_DELIM)
944 {
945 *s = EOS;
946 break;
947 }
948 else
949 *s = lowcase (*s);
950 return start;
951 }
952 #endif /* VMS */
953
954 \f
955 int
956 main (argc, argv)
957 int argc;
958 char *argv[];
959 {
960 int i;
961 unsigned int nincluded_files;
962 char **included_files;
963 argument *argbuffer;
964 int current_arg, file_count;
965 linebuffer filename_lb;
966 #ifdef VMS
967 bool got_err;
968 #endif
969
970 #ifdef DOS_NT
971 _fmode = O_BINARY; /* all of files are treated as binary files */
972 #endif /* DOS_NT */
973
974 progname = argv[0];
975 nincluded_files = 0;
976 included_files = xnew (argc, char *);
977 current_arg = 0;
978 file_count = 0;
979
980 /* Allocate enough no matter what happens. Overkill, but each one
981 is small. */
982 argbuffer = xnew (argc, argument);
983
984 #ifdef ETAGS_REGEXPS
985 /* Set syntax for regular expression routines. */
986 re_set_syntax (RE_SYNTAX_EMACS | RE_INTERVALS);
987 /* Translation table for case-insensitive search. */
988 for (i = 0; i < CHAR_SET_SIZE; i++)
989 lc_trans[i] = lowcase (i);
990 #endif /* ETAGS_REGEXPS */
991
992 /*
993 * If etags, always find typedefs and structure tags. Why not?
994 * Also default to find macro constants, enum constants and
995 * global variables.
996 */
997 if (!CTAGS)
998 {
999 typedefs = typedefs_or_cplusplus = constantypedefs = TRUE;
1000 globals = TRUE;
1001 }
1002
1003 while (1)
1004 {
1005 int opt;
1006 char *optstring = "-";
1007
1008 #ifdef ETAGS_REGEXPS
1009 optstring = "-r:Rc:";
1010 #endif /* ETAGS_REGEXPS */
1011
1012 #ifndef LONG_OPTIONS
1013 optstring = optstring + 1;
1014 #endif /* LONG_OPTIONS */
1015
1016 optstring = concat (optstring,
1017 "Cf:Il:o:SVhH",
1018 (CTAGS) ? "BxdtTuvw" : "aDi:");
1019
1020 opt = getopt_long (argc, argv, optstring, longopts, 0);
1021 if (opt == EOF)
1022 break;
1023
1024 switch (opt)
1025 {
1026 case 0:
1027 /* If getopt returns 0, then it has already processed a
1028 long-named option. We should do nothing. */
1029 break;
1030
1031 case 1:
1032 /* This means that a file name has been seen. Record it. */
1033 argbuffer[current_arg].arg_type = at_filename;
1034 argbuffer[current_arg].what = optarg;
1035 ++current_arg;
1036 ++file_count;
1037 break;
1038
1039 /* Common options. */
1040 case 'C': cplusplus = TRUE; break;
1041 case 'f': /* for compatibility with old makefiles */
1042 case 'o':
1043 if (tagfile)
1044 {
1045 error ("-o option may only be given once.", (char *)NULL);
1046 suggest_asking_for_help ();
1047 }
1048 tagfile = optarg;
1049 break;
1050 case 'I':
1051 case 'S': /* for backward compatibility */
1052 noindentypedefs = TRUE;
1053 break;
1054 case 'l':
1055 {
1056 language *lang = get_language_from_langname (optarg);
1057 if (lang != NULL)
1058 {
1059 argbuffer[current_arg].lang = lang;
1060 argbuffer[current_arg].arg_type = at_language;
1061 ++current_arg;
1062 }
1063 }
1064 break;
1065 case 'r':
1066 argbuffer[current_arg].arg_type = at_regexp;
1067 argbuffer[current_arg].what = optarg;
1068 ++current_arg;
1069 break;
1070 case 'R':
1071 argbuffer[current_arg].arg_type = at_regexp;
1072 argbuffer[current_arg].what = NULL;
1073 ++current_arg;
1074 break;
1075 case 'c':
1076 argbuffer[current_arg].arg_type = at_icregexp;
1077 argbuffer[current_arg].what = optarg;
1078 ++current_arg;
1079 break;
1080 case 'V':
1081 print_version ();
1082 break;
1083 case 'h':
1084 case 'H':
1085 print_help ();
1086 break;
1087
1088 /* Etags options */
1089 case 'a': append_to_tagfile = TRUE; break;
1090 case 'D': constantypedefs = FALSE; break;
1091 case 'i': included_files[nincluded_files++] = optarg; break;
1092
1093 /* Ctags options. */
1094 case 'B': searchar = '?'; break;
1095 case 'd': constantypedefs = TRUE; break;
1096 case 't': typedefs = TRUE; break;
1097 case 'T': typedefs = typedefs_or_cplusplus = TRUE; break;
1098 case 'u': update = TRUE; break;
1099 case 'v': vgrind_style = TRUE; /*FALLTHRU*/
1100 case 'x': cxref_style = TRUE; break;
1101 case 'w': no_warnings = TRUE; break;
1102 default:
1103 suggest_asking_for_help ();
1104 }
1105 }
1106
1107 for (; optind < argc; ++optind)
1108 {
1109 argbuffer[current_arg].arg_type = at_filename;
1110 argbuffer[current_arg].what = argv[optind];
1111 ++current_arg;
1112 ++file_count;
1113 }
1114
1115 if (nincluded_files == 0 && file_count == 0)
1116 {
1117 error ("no input files specified.", (char *)NULL);
1118 suggest_asking_for_help ();
1119 }
1120
1121 if (tagfile == NULL)
1122 tagfile = CTAGS ? "tags" : "TAGS";
1123 cwd = etags_getcwd (); /* the current working directory */
1124 if (cwd[strlen (cwd) - 1] != '/')
1125 {
1126 char *oldcwd = cwd;
1127 cwd = concat (oldcwd, "/", "");
1128 free (oldcwd);
1129 }
1130 if (streq (tagfile, "-"))
1131 tagfiledir = cwd;
1132 else
1133 tagfiledir = absolute_dirname (tagfile, cwd);
1134
1135 init (); /* set up boolean "functions" */
1136
1137 initbuffer (&lb);
1138 initbuffer (&filename_lb);
1139
1140 if (!CTAGS)
1141 {
1142 if (streq (tagfile, "-"))
1143 {
1144 tagf = stdout;
1145 #ifdef DOS_NT
1146 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1147 doesn't take effect until after `stdout' is already open). */
1148 if (!isatty (fileno (stdout)))
1149 setmode (fileno (stdout), O_BINARY);
1150 #endif /* DOS_NT */
1151 }
1152 else
1153 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1154 if (tagf == NULL)
1155 pfatal (tagfile);
1156 }
1157
1158 /*
1159 * Loop through files finding functions.
1160 */
1161 for (i = 0; i < current_arg; ++i)
1162 {
1163 static language *lang; /* non-NULL if language is forced */
1164 char *this_file;
1165
1166 switch (argbuffer[i].arg_type)
1167 {
1168 case at_language:
1169 lang = argbuffer[i].lang;
1170 break;
1171 #ifdef ETAGS_REGEXPS
1172 case at_regexp:
1173 analyse_regex (argbuffer[i].what, FALSE);
1174 break;
1175 case at_icregexp:
1176 analyse_regex (argbuffer[i].what, TRUE);
1177 break;
1178 #endif
1179 case at_filename:
1180 #ifdef VMS
1181 while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL)
1182 {
1183 if (got_err)
1184 {
1185 error ("can't find file %s\n", this_file);
1186 argc--, argv++;
1187 }
1188 else
1189 {
1190 this_file = massage_name (this_file);
1191 }
1192 #else
1193 this_file = argbuffer[i].what;
1194 #endif
1195 /* Input file named "-" means read file names from stdin
1196 (one per line) and use them. */
1197 if (streq (this_file, "-"))
1198 while (readline_internal (&filename_lb, stdin) > 0)
1199 process_file (filename_lb.buffer, lang);
1200 else
1201 process_file (this_file, lang);
1202 #ifdef VMS
1203 }
1204 #endif
1205 break;
1206 }
1207 }
1208
1209 #ifdef ETAGS_REGEXPS
1210 free_patterns ();
1211 #endif /* ETAGS_REGEXPS */
1212
1213 if (!CTAGS || cxref_style)
1214 {
1215 put_entries (nodehead);
1216 free_tree (nodehead);
1217 nodehead = NULL;
1218 if (!CTAGS)
1219 while (nincluded_files-- > 0)
1220 fprintf (tagf, "\f\n%s,include\n", *included_files++);
1221
1222 if (fclose (tagf) == EOF)
1223 pfatal (tagfile);
1224 exit (GOOD);
1225 }
1226
1227 if (update)
1228 {
1229 char cmd[BUFSIZ];
1230 for (i = 0; i < current_arg; ++i)
1231 {
1232 if (argbuffer[i].arg_type != at_filename)
1233 continue;
1234 sprintf (cmd,
1235 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1236 tagfile, argbuffer[i].what, tagfile);
1237 if (system (cmd) != GOOD)
1238 fatal ("failed to execute shell command", (char *)NULL);
1239 }
1240 append_to_tagfile = TRUE;
1241 }
1242
1243 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1244 if (tagf == NULL)
1245 pfatal (tagfile);
1246 put_entries (nodehead);
1247 free_tree (nodehead);
1248 nodehead = NULL;
1249 if (fclose (tagf) == EOF)
1250 pfatal (tagfile);
1251
1252 if (update)
1253 {
1254 char cmd[BUFSIZ];
1255 sprintf (cmd, "sort %s -o %s", tagfile, tagfile);
1256 exit (system (cmd));
1257 }
1258 return GOOD;
1259 }
1260
1261
1262 /*
1263 * Return a compressor given the file name. If EXTPTR is non-zero,
1264 * return a pointer into FILE where the compressor-specific
1265 * extension begins. If no compressor is found, NULL is returned
1266 * and EXTPTR is not significant.
1267 * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca> (1998)
1268 */
1269 static compressor *
1270 get_compressor_from_suffix (file, extptr)
1271 char *file;
1272 char **extptr;
1273 {
1274 compressor *compr;
1275 char *slash, *suffix;
1276
1277 /* This relies on FN to be after canonicalize_filename,
1278 so we don't need to consider backslashes on DOS_NT. */
1279 slash = etags_strrchr (file, '/');
1280 suffix = etags_strrchr (file, '.');
1281 if (suffix == NULL || suffix < slash)
1282 return NULL;
1283 if (extptr != NULL)
1284 *extptr = suffix;
1285 suffix += 1;
1286 /* Let those poor souls who live with DOS 8+3 file name limits get
1287 some solace by treating foo.cgz as if it were foo.c.gz, etc.
1288 Only the first do loop is run if not MSDOS */
1289 do
1290 {
1291 for (compr = compressors; compr->suffix != NULL; compr++)
1292 if (streq (compr->suffix, suffix))
1293 return compr;
1294 if (!MSDOS)
1295 break; /* do it only once: not really a loop */
1296 if (extptr != NULL)
1297 *extptr = ++suffix;
1298 } while (*suffix != '\0');
1299 return NULL;
1300 }
1301
1302
1303
1304 /*
1305 * Return a language given the name.
1306 */
1307 static language *
1308 get_language_from_langname (name)
1309 const char *name;
1310 {
1311 language *lang;
1312
1313 if (name == NULL)
1314 error ("empty language name", (char *)NULL);
1315 else
1316 {
1317 for (lang = lang_names; lang->name != NULL; lang++)
1318 if (streq (name, lang->name))
1319 return lang;
1320 error ("unknown language \"%s\"", name);
1321 }
1322
1323 return NULL;
1324 }
1325
1326
1327 /*
1328 * Return a language given the interpreter name.
1329 */
1330 static language *
1331 get_language_from_interpreter (interpreter)
1332 char *interpreter;
1333 {
1334 language *lang;
1335 char **iname;
1336
1337 if (interpreter == NULL)
1338 return NULL;
1339 for (lang = lang_names; lang->name != NULL; lang++)
1340 if (lang->interpreters != NULL)
1341 for (iname = lang->interpreters; *iname != NULL; iname++)
1342 if (streq (*iname, interpreter))
1343 return lang;
1344
1345 return NULL;
1346 }
1347
1348
1349
1350 /*
1351 * Return a language given the file name.
1352 */
1353 static language *
1354 get_language_from_filename (file)
1355 char *file;
1356 {
1357 language *lang;
1358 char **name, **ext, *suffix;
1359
1360 /* Try whole file name first. */
1361 for (lang = lang_names; lang->name != NULL; lang++)
1362 if (lang->filenames != NULL)
1363 for (name = lang->filenames; *name != NULL; name++)
1364 if (streq (*name, file))
1365 return lang;
1366
1367 /* If not found, try suffix after last dot. */
1368 suffix = etags_strrchr (file, '.');
1369 if (suffix == NULL)
1370 return NULL;
1371 suffix += 1;
1372 for (lang = lang_names; lang->name != NULL; lang++)
1373 if (lang->suffixes != NULL)
1374 for (ext = lang->suffixes; *ext != NULL; ext++)
1375 if (streq (*ext, suffix))
1376 return lang;
1377 return NULL;
1378 }
1379
1380 \f
1381 /*
1382 * This routine is called on each file argument.
1383 */
1384 static void
1385 process_file (file, lang)
1386 char *file;
1387 language *lang;
1388 {
1389 struct stat stat_buf;
1390 FILE *inf;
1391 static const fdesc emptyfdesc;
1392 fdesc *fdp;
1393 compressor *compr;
1394 char *compressed_name, *uncompressed_name;
1395 char *ext, *real_name;
1396 int retval;
1397
1398
1399 canonicalize_filename (file);
1400 if (streq (file, tagfile) && !streq (tagfile, "-"))
1401 {
1402 error ("skipping inclusion of %s in self.", file);
1403 return;
1404 }
1405 if ((compr = get_compressor_from_suffix (file, &ext)) == NULL)
1406 {
1407 compressed_name = NULL;
1408 real_name = uncompressed_name = savestr (file);
1409 }
1410 else
1411 {
1412 real_name = compressed_name = savestr (file);
1413 uncompressed_name = savenstr (file, ext - file);
1414 }
1415
1416 /* If the canonicalized uncompressed name
1417 has already been dealt with, skip it silently. */
1418 for (fdp = fdhead; fdp != NULL; fdp = fdp->next)
1419 {
1420 assert (fdp->infname != NULL);
1421 if (streq (uncompressed_name, fdp->infname))
1422 goto cleanup;
1423 }
1424
1425 /* Create a new input file description entry. */
1426 fdp = fdhead;
1427 fdhead = xnew (1, fdesc);
1428 *fdhead = emptyfdesc;
1429 fdhead->next = fdp;
1430
1431 if (stat (real_name, &stat_buf) != 0)
1432 {
1433 /* Reset real_name and try with a different name. */
1434 real_name = NULL;
1435 if (compressed_name != NULL) /* try with the given suffix */
1436 {
1437 if (stat (uncompressed_name, &stat_buf) == 0)
1438 real_name = uncompressed_name;
1439 }
1440 else /* try all possible suffixes */
1441 {
1442 for (compr = compressors; compr->suffix != NULL; compr++)
1443 {
1444 compressed_name = concat (file, ".", compr->suffix);
1445 if (stat (compressed_name, &stat_buf) != 0)
1446 {
1447 if (MSDOS)
1448 {
1449 char *suf = compressed_name + strlen (file);
1450 size_t suflen = strlen (compr->suffix) + 1;
1451 for ( ; suf[1]; suf++, suflen--)
1452 {
1453 memmove (suf, suf + 1, suflen);
1454 if (stat (compressed_name, &stat_buf) == 0)
1455 {
1456 real_name = compressed_name;
1457 break;
1458 }
1459 }
1460 if (real_name != NULL)
1461 break;
1462 } /* MSDOS */
1463 free (compressed_name);
1464 compressed_name = NULL;
1465 }
1466 else
1467 {
1468 real_name = compressed_name;
1469 break;
1470 }
1471 }
1472 }
1473 if (real_name == NULL)
1474 {
1475 perror (file);
1476 goto cleanup;
1477 }
1478 } /* try with a different name */
1479
1480 if (!S_ISREG (stat_buf.st_mode))
1481 {
1482 error ("skipping %s: it is not a regular file.", real_name);
1483 goto cleanup;
1484 }
1485 if (real_name == compressed_name)
1486 {
1487 char *cmd = concat (compr->command, " ", real_name);
1488 inf = (FILE *) popen (cmd, "r");
1489 free (cmd);
1490 }
1491 else
1492 inf = fopen (real_name, "r");
1493 if (inf == NULL)
1494 {
1495 perror (real_name);
1496 goto cleanup;
1497 }
1498
1499 fdhead->infname = savestr (uncompressed_name);
1500 fdhead->lang = lang;
1501 fdhead->infabsname = absolute_filename (uncompressed_name, cwd);
1502 fdhead->infabsdir = absolute_dirname (uncompressed_name, cwd);
1503 if (filename_is_absolute (uncompressed_name))
1504 {
1505 /* file is an absolute file name. Canonicalize it. */
1506 fdhead->taggedfname = absolute_filename (uncompressed_name, NULL);
1507 }
1508 else
1509 {
1510 /* file is a file name relative to cwd. Make it relative
1511 to the directory of the tags file. */
1512 fdhead->taggedfname = relative_filename (uncompressed_name, tagfiledir);
1513 }
1514 fdhead->usecharno = TRUE; /* use char position when making tags */
1515 fdhead->prop = NULL;
1516
1517 curfdp = fdhead; /* the current file description */
1518
1519 find_entries (inf);
1520
1521 if (real_name == compressed_name)
1522 retval = pclose (inf);
1523 else
1524 retval = fclose (inf);
1525 if (retval < 0)
1526 pfatal (file);
1527
1528 cleanup:
1529 /* XXX if no more useful, delete head of file description list */
1530 if (compressed_name) free (compressed_name);
1531 if (uncompressed_name) free (uncompressed_name);
1532 return;
1533 }
1534
1535 /*
1536 * This routine sets up the boolean pseudo-functions which work
1537 * by setting boolean flags dependent upon the corresponding character.
1538 * Every char which is NOT in that string is not a white char. Therefore,
1539 * all of the array "_wht" is set to FALSE, and then the elements
1540 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1541 * of a char is TRUE if it is the string "white", else FALSE.
1542 */
1543 static void
1544 init ()
1545 {
1546 register char *sp;
1547 register int i;
1548
1549 for (i = 0; i < CHARS; i++)
1550 iswhite(i) = notinname(i) = begtoken(i) = intoken(i) = endtoken(i) = FALSE;
1551 for (sp = white; *sp != '\0'; sp++) iswhite (*sp) = TRUE;
1552 for (sp = nonam; *sp != '\0'; sp++) notinname (*sp) = TRUE;
1553 notinname('\0') = notinname('\n');
1554 for (sp = begtk; *sp != '\0'; sp++) begtoken (*sp) = TRUE;
1555 begtoken('\0') = begtoken('\n');
1556 for (sp = midtk; *sp != '\0'; sp++) intoken (*sp) = TRUE;
1557 intoken('\0') = intoken('\n');
1558 for (sp = endtk; *sp != '\0'; sp++) endtoken (*sp) = TRUE;
1559 endtoken('\0') = endtoken('\n');
1560 }
1561
1562 /*
1563 * This routine opens the specified file and calls the function
1564 * which finds the function and type definitions.
1565 */
1566 static node *last_node = NULL;
1567
1568 static void
1569 find_entries (inf)
1570 FILE *inf;
1571 {
1572 char *cp;
1573 node *old_last_node;
1574 language *lang = curfdp->lang;
1575 Lang_function *parser = NULL;
1576
1577 /* If user specified a language, use it. */
1578 if (lang != NULL && lang->function != NULL)
1579 {
1580 parser = lang->function;
1581 }
1582
1583 /* Else try to guess the language given the file name. */
1584 if (parser == NULL)
1585 {
1586 lang = get_language_from_filename (curfdp->infname);
1587 if (lang != NULL && lang->function != NULL)
1588 {
1589 curfdp->lang = lang;
1590 parser = lang->function;
1591 }
1592 }
1593
1594 /* Else look for sharp-bang as the first two characters. */
1595 if (parser == NULL
1596 && readline_internal (&lb, inf) > 0
1597 && lb.len >= 2
1598 && lb.buffer[0] == '#'
1599 && lb.buffer[1] == '!')
1600 {
1601 char *lp;
1602
1603 /* Set lp to point at the first char after the last slash in the
1604 line or, if no slashes, at the first nonblank. Then set cp to
1605 the first successive blank and terminate the string. */
1606 lp = etags_strrchr (lb.buffer+2, '/');
1607 if (lp != NULL)
1608 lp += 1;
1609 else
1610 lp = skip_spaces (lb.buffer + 2);
1611 cp = skip_non_spaces (lp);
1612 *cp = '\0';
1613
1614 if (strlen (lp) > 0)
1615 {
1616 lang = get_language_from_interpreter (lp);
1617 if (lang != NULL && lang->function != NULL)
1618 {
1619 curfdp->lang = lang;
1620 parser = lang->function;
1621 }
1622 }
1623 }
1624
1625 if (!no_line_directive
1626 && curfdp->lang != NULL && curfdp->lang->metasource)
1627 /* It may be that this is an xxx.y file, and we already parsed an xxx.c
1628 file, or anyway we parsed a file that is automatically generated from
1629 this one. If this is the case, the xxx.c file contained #line
1630 directives that generated tags pointing to this file. Let's delete
1631 them all before parsing this file, which is the real source. */
1632 {
1633 fdesc **fdpp = &fdhead;
1634 while (*fdpp != NULL)
1635 if (*fdpp != curfdp
1636 && streq ((*fdpp)->taggedfname, curfdp->taggedfname))
1637 /* We found one of those! We must delete both the file description
1638 and all tags referring to it. */
1639 {
1640 fdesc *badfdp = *fdpp;
1641
1642 *fdpp = badfdp->next; /* remove the bad description from the list */
1643 fdpp = &badfdp->next; /* advance the list pointer */
1644
1645 fprintf (stderr, "Removing references to \"%s\" obtained from \"%s\"\n",
1646 badfdp->taggedfname, badfdp->infname);
1647 /* Delete the tags referring to badfdp. */
1648 invalidate_nodes (badfdp, nodehead);
1649
1650 /* Delete badfdp. */
1651 if (badfdp->infname != NULL) free (badfdp->infname);
1652 if (badfdp->infabsname != NULL) free (badfdp->infabsname);
1653 if (badfdp->infabsdir != NULL) free (badfdp->infabsdir);
1654 if (badfdp->taggedfname != NULL) free (badfdp->taggedfname);
1655 if (badfdp->prop != NULL) free (badfdp->prop);
1656 free (badfdp);
1657 }
1658 else
1659 fdpp = &(*fdpp)->next; /* advance the list pointer */
1660 }
1661
1662 if (parser != NULL)
1663 {
1664 parser (inf);
1665 return;
1666 }
1667
1668 /* We rewind here, even if inf may be a pipe. We fail if the
1669 length of the first line is longer than the pipe block size,
1670 which is unlikely. */
1671 rewind (inf);
1672
1673 /* Else try Fortran. */
1674 old_last_node = last_node;
1675 curfdp->lang = get_language_from_langname ("fortran");
1676 Fortran_functions (inf);
1677
1678 if (old_last_node == last_node)
1679 /* No Fortran entries found. Try C. */
1680 {
1681 /* We do not tag if rewind fails.
1682 Only the file name will be recorded in the tags file. */
1683 rewind (inf);
1684 curfdp->lang = get_language_from_langname (cplusplus ? "c++" : "c");
1685 default_C_entries (inf);
1686 }
1687 return;
1688 }
1689
1690 \f
1691 /* Record a tag. */
1692 static void
1693 pfnote (name, is_func, linestart, linelen, lno, cno)
1694 char *name; /* tag name, or NULL if unnamed */
1695 bool is_func; /* tag is a function */
1696 char *linestart; /* start of the line where tag is */
1697 int linelen; /* length of the line where tag is */
1698 int lno; /* line number */
1699 long cno; /* character number */
1700 {
1701 register node *np;
1702
1703 if (CTAGS && name == NULL)
1704 return;
1705
1706 np = xnew (1, node);
1707
1708 /* If ctags mode, change name "main" to M<thisfilename>. */
1709 if (CTAGS && !cxref_style && streq (name, "main"))
1710 {
1711 register char *fp = etags_strrchr (curfdp->taggedfname, '/');
1712 np->name = concat ("M", fp == NULL ? curfdp->taggedfname : fp + 1, "");
1713 fp = etags_strrchr (np->name, '.');
1714 if (fp != NULL && fp[1] != '\0' && fp[2] == '\0')
1715 fp[0] = '\0';
1716 }
1717 else
1718 np->name = name;
1719 np->valid = TRUE;
1720 np->been_warned = FALSE;
1721 np->fdp = curfdp;
1722 np->is_func = is_func;
1723 np->lno = lno;
1724 if (np->fdp->usecharno)
1725 /* Our char numbers are 0-base, because of C language tradition?
1726 ctags compatibility? old versions compatibility? I don't know.
1727 Anyway, since emacs's are 1-base we expect etags.el to take care
1728 of the difference. If we wanted to have 1-based numbers, we would
1729 uncomment the +1 below. */
1730 np->cno = cno /* + 1 */ ;
1731 else
1732 np->cno = invalidcharno;
1733 np->left = np->right = NULL;
1734 if (CTAGS && !cxref_style)
1735 {
1736 if (strlen (linestart) < 50)
1737 np->pat = concat (linestart, "$", "");
1738 else
1739 np->pat = savenstr (linestart, 50);
1740 }
1741 else
1742 np->pat = savenstr (linestart, linelen);
1743
1744 add_node (np, &nodehead);
1745 }
1746
1747 /*
1748 * TAGS format specification
1749 * Idea by Sam Kendall <kendall@mv.mv.com> (1997)
1750 *
1751 * pfnote should emit the optimized form [unnamed tag] only if:
1752 * 1. name does not contain any of the characters " \t\r\n(),;";
1753 * 2. linestart contains name as either a rightmost, or rightmost but
1754 * one character, substring;
1755 * 3. the character, if any, immediately before name in linestart must
1756 * be one of the characters " \t(),;";
1757 * 4. the character, if any, immediately after name in linestart must
1758 * also be one of the characters " \t(),;".
1759 *
1760 * The real implementation uses the notinname() macro, which recognises
1761 * characters slightly different from " \t\r\n(),;". See the variable
1762 * `nonam'.
1763 */
1764 #define traditional_tag_style TRUE
1765 static void
1766 new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno)
1767 char *name; /* tag name, or NULL if unnamed */
1768 int namelen; /* tag length */
1769 bool is_func; /* tag is a function */
1770 char *linestart; /* start of the line where tag is */
1771 int linelen; /* length of the line where tag is */
1772 int lno; /* line number */
1773 long cno; /* character number */
1774 {
1775 register char *cp;
1776 bool named;
1777
1778 named = TRUE;
1779 if (!CTAGS)
1780 {
1781 for (cp = name; !notinname (*cp); cp++)
1782 continue;
1783 if (*cp == '\0') /* rule #1 */
1784 {
1785 cp = linestart + linelen - namelen;
1786 if (notinname (linestart[linelen-1]))
1787 cp -= 1; /* rule #4 */
1788 if (cp >= linestart /* rule #2 */
1789 && (cp == linestart
1790 || notinname (cp[-1])) /* rule #3 */
1791 && strneq (name, cp, namelen)) /* rule #2 */
1792 named = FALSE; /* use unnamed tag */
1793 }
1794 }
1795
1796 if (named)
1797 name = savenstr (name, namelen);
1798 else
1799 name = NULL;
1800 pfnote (name, is_func, linestart, linelen, lno, cno);
1801 }
1802
1803 /*
1804 * free_tree ()
1805 * recurse on left children, iterate on right children.
1806 */
1807 static void
1808 free_tree (np)
1809 register node *np;
1810 {
1811 while (np)
1812 {
1813 register node *node_right = np->right;
1814 free_tree (np->left);
1815 if (np->name != NULL)
1816 free (np->name);
1817 free (np->pat);
1818 free (np);
1819 np = node_right;
1820 }
1821 }
1822
1823 /*
1824 * add_node ()
1825 * Adds a node to the tree of nodes. In etags mode, sort by file
1826 * name. In ctags mode, sort by tag name. Make no attempt at
1827 * balancing.
1828 *
1829 * add_node is the only function allowed to add nodes, so it can
1830 * maintain state.
1831 */
1832 static void
1833 add_node (np, cur_node_p)
1834 node *np, **cur_node_p;
1835 {
1836 register int dif;
1837 register node *cur_node = *cur_node_p;
1838
1839 if (cur_node == NULL)
1840 {
1841 *cur_node_p = np;
1842 last_node = np;
1843 return;
1844 }
1845
1846 if (!CTAGS)
1847 {
1848 /* Etags Mode */
1849 assert (last_node != NULL);
1850 /* For each file name, tags are in a linked sublist on the right
1851 pointer. The first tags of different files are a linked list
1852 on the left pointer. last_node points to the end of the last
1853 used sublist. */
1854 if (last_node->fdp == np->fdp)
1855 {
1856 /* Let's use the same sublist as the last added node. */
1857 last_node->right = np;
1858 last_node = np;
1859 }
1860 else if (cur_node->fdp == np->fdp)
1861 {
1862 /* Scanning the list we found the head of a sublist which is
1863 good for us. Let's scan this sublist. */
1864 add_node (np, &cur_node->right);
1865 }
1866 else
1867 /* The head of this sublist is not good for us. Let's try the
1868 next one. */
1869 add_node (np, &cur_node->left);
1870 }
1871 else
1872 {
1873 /* Ctags Mode */
1874 dif = strcmp (np->name, cur_node->name);
1875
1876 /*
1877 * If this tag name matches an existing one, then
1878 * do not add the node, but maybe print a warning.
1879 */
1880 if (!dif)
1881 {
1882 if (np->fdp == cur_node->fdp)
1883 {
1884 if (!no_warnings)
1885 {
1886 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1887 np->fdp->infname, lineno, np->name);
1888 fprintf (stderr, "Second entry ignored\n");
1889 }
1890 }
1891 else if (!cur_node->been_warned && !no_warnings)
1892 {
1893 fprintf
1894 (stderr,
1895 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1896 np->fdp->infname, cur_node->fdp->infname, np->name);
1897 cur_node->been_warned = TRUE;
1898 }
1899 return;
1900 }
1901
1902 /* Actually add the node */
1903 add_node (np, dif < 0 ? &cur_node->left : &cur_node->right);
1904 }
1905 }
1906
1907 /*
1908 * invalidate_nodes ()
1909 * Scan the node tree and invalidate all nodes pointing to the
1910 * given file description.
1911 */
1912 static void
1913 invalidate_nodes (badfdp, np)
1914 fdesc *badfdp;
1915 node *np;
1916 {
1917 if (np->left != NULL)
1918 invalidate_nodes (badfdp, np->left);
1919 if (np->fdp == badfdp)
1920 np-> valid = FALSE;
1921 if (np->right != NULL)
1922 invalidate_nodes (badfdp, np->right);
1923 }
1924
1925 \f
1926 static int total_size_of_entries __P((node *));
1927 static int number_len __P((long));
1928
1929 /* Length of a non-negative number's decimal representation. */
1930 static int
1931 number_len (num)
1932 long num;
1933 {
1934 int len = 1;
1935 while ((num /= 10) > 0)
1936 len += 1;
1937 return len;
1938 }
1939
1940 /*
1941 * Return total number of characters that put_entries will output for
1942 * the nodes in the linked list at the right of the specified node.
1943 * This count is irrelevant with etags.el since emacs 19.34 at least,
1944 * but is still supplied for backward compatibility.
1945 */
1946 static int
1947 total_size_of_entries (np)
1948 register node *np;
1949 {
1950 register int total = 0;
1951
1952 for (; np != NULL; np = np->right)
1953 {
1954 total += strlen (np->pat) + 1; /* pat\177 */
1955 if (np->name != NULL)
1956 total += strlen (np->name) + 1; /* name\001 */
1957 total += number_len ((long) np->lno) + 1; /* lno, */
1958 if (np->cno != invalidcharno) /* cno */
1959 total += number_len (np->cno);
1960 total += 1; /* newline */
1961 }
1962
1963 return total;
1964 }
1965
1966 static void
1967 put_entries (np)
1968 register node *np;
1969 {
1970 register char *sp;
1971 static fdesc *fdp = NULL;
1972
1973 if (np == NULL)
1974 return;
1975
1976 /* Output subentries that precede this one */
1977 if (CTAGS)
1978 put_entries (np->left);
1979
1980 /* Output this entry */
1981 if (np->valid)
1982 {
1983 if (!CTAGS)
1984 {
1985 /* Etags mode */
1986 if (fdp != np->fdp)
1987 {
1988 fdp = np->fdp;
1989 fprintf (tagf, "\f\n%s,%d\n",
1990 fdp->taggedfname, total_size_of_entries (np));
1991 }
1992 fputs (np->pat, tagf);
1993 fputc ('\177', tagf);
1994 if (np->name != NULL)
1995 {
1996 fputs (np->name, tagf);
1997 fputc ('\001', tagf);
1998 }
1999 fprintf (tagf, "%d,", np->lno);
2000 if (np->cno != invalidcharno)
2001 fprintf (tagf, "%ld", np->cno);
2002 fputs ("\n", tagf);
2003 }
2004 else
2005 {
2006 /* Ctags mode */
2007 if (np->name == NULL)
2008 error ("internal error: NULL name in ctags mode.", (char *)NULL);
2009
2010 if (cxref_style)
2011 {
2012 if (vgrind_style)
2013 fprintf (stdout, "%s %s %d\n",
2014 np->name, np->fdp->taggedfname, (np->lno + 63) / 64);
2015 else
2016 fprintf (stdout, "%-16s %3d %-16s %s\n",
2017 np->name, np->lno, np->fdp->taggedfname, np->pat);
2018 }
2019 else
2020 {
2021 fprintf (tagf, "%s\t%s\t", np->name, np->fdp->taggedfname);
2022
2023 if (np->is_func)
2024 { /* function or #define macro with args */
2025 putc (searchar, tagf);
2026 putc ('^', tagf);
2027
2028 for (sp = np->pat; *sp; sp++)
2029 {
2030 if (*sp == '\\' || *sp == searchar)
2031 putc ('\\', tagf);
2032 putc (*sp, tagf);
2033 }
2034 putc (searchar, tagf);
2035 }
2036 else
2037 { /* anything else; text pattern inadequate */
2038 fprintf (tagf, "%d", np->lno);
2039 }
2040 putc ('\n', tagf);
2041 }
2042 }
2043 } /* if this node contains a valid tag */
2044
2045 /* Output subentries that follow this one */
2046 put_entries (np->right);
2047 if (!CTAGS)
2048 put_entries (np->left);
2049 }
2050
2051 \f
2052 /* C extensions. */
2053 #define C_EXT 0x00fff /* C extensions */
2054 #define C_PLAIN 0x00000 /* C */
2055 #define C_PLPL 0x00001 /* C++ */
2056 #define C_STAR 0x00003 /* C* */
2057 #define C_JAVA 0x00005 /* JAVA */
2058 #define C_AUTO 0x01000 /* C, but switch to C++ if `class' is met */
2059 #define YACC 0x10000 /* yacc file */
2060
2061 /*
2062 * The C symbol tables.
2063 */
2064 enum sym_type
2065 {
2066 st_none,
2067 st_C_objprot, st_C_objimpl, st_C_objend,
2068 st_C_gnumacro,
2069 st_C_ignore,
2070 st_C_javastruct,
2071 st_C_operator,
2072 st_C_class, st_C_template,
2073 st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
2074 };
2075
2076 static unsigned int hash __P((const char *, unsigned int));
2077 static struct C_stab_entry * in_word_set __P((const char *, unsigned int));
2078 static enum sym_type C_symtype __P((char *, int, int));
2079
2080 /* Feed stuff between (but not including) %[ and %] lines to:
2081 gperf -c -k 1,3 -o -p -r -t
2082 %[
2083 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
2084 %%
2085 if, 0, st_C_ignore
2086 for, 0, st_C_ignore
2087 while, 0, st_C_ignore
2088 switch, 0, st_C_ignore
2089 return, 0, st_C_ignore
2090 @interface, 0, st_C_objprot
2091 @protocol, 0, st_C_objprot
2092 @implementation,0, st_C_objimpl
2093 @end, 0, st_C_objend
2094 import, C_JAVA, st_C_ignore
2095 package, C_JAVA, st_C_ignore
2096 friend, C_PLPL, st_C_ignore
2097 extends, C_JAVA, st_C_javastruct
2098 implements, C_JAVA, st_C_javastruct
2099 interface, C_JAVA, st_C_struct
2100 class, 0, st_C_class
2101 namespace, C_PLPL, st_C_struct
2102 domain, C_STAR, st_C_struct
2103 union, 0, st_C_struct
2104 struct, 0, st_C_struct
2105 extern, 0, st_C_extern
2106 enum, 0, st_C_enum
2107 typedef, 0, st_C_typedef
2108 define, 0, st_C_define
2109 operator, C_PLPL, st_C_operator
2110 template, 0, st_C_template
2111 bool, C_PLPL, st_C_typespec
2112 long, 0, st_C_typespec
2113 short, 0, st_C_typespec
2114 int, 0, st_C_typespec
2115 char, 0, st_C_typespec
2116 float, 0, st_C_typespec
2117 double, 0, st_C_typespec
2118 signed, 0, st_C_typespec
2119 unsigned, 0, st_C_typespec
2120 auto, 0, st_C_typespec
2121 void, 0, st_C_typespec
2122 static, 0, st_C_typespec
2123 const, 0, st_C_typespec
2124 volatile, 0, st_C_typespec
2125 explicit, C_PLPL, st_C_typespec
2126 mutable, C_PLPL, st_C_typespec
2127 typename, C_PLPL, st_C_typespec
2128 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
2129 DEFUN, 0, st_C_gnumacro
2130 SYSCALL, 0, st_C_gnumacro
2131 ENTRY, 0, st_C_gnumacro
2132 PSEUDO, 0, st_C_gnumacro
2133 # These are defined inside C functions, so currently they are not met.
2134 # EXFUN used in glibc, DEFVAR_* in emacs.
2135 #EXFUN, 0, st_C_gnumacro
2136 #DEFVAR_, 0, st_C_gnumacro
2137 %]
2138 and replace lines between %< and %> with its output,
2139 then make in_word_set and C_stab_entry static. */
2140 /*%<*/
2141 /* C code produced by gperf version 2.7.1 (19981006 egcs) */
2142 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
2143 struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
2144
2145 #define TOTAL_KEYWORDS 47
2146 #define MIN_WORD_LENGTH 2
2147 #define MAX_WORD_LENGTH 15
2148 #define MIN_HASH_VALUE 18
2149 #define MAX_HASH_VALUE 138
2150 /* maximum key range = 121, duplicates = 0 */
2151
2152 #ifdef __GNUC__
2153 __inline
2154 #endif
2155 static unsigned int
2156 hash (str, len)
2157 register const char *str;
2158 register unsigned int len;
2159 {
2160 static unsigned char asso_values[] =
2161 {
2162 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2163 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2164 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2165 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2166 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2167 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2168 139, 139, 139, 139, 63, 139, 139, 139, 33, 44,
2169 62, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2170 42, 139, 139, 12, 32, 139, 139, 139, 139, 139,
2171 139, 139, 139, 139, 139, 139, 139, 34, 59, 37,
2172 24, 58, 33, 3, 139, 16, 139, 139, 42, 60,
2173 18, 11, 39, 139, 23, 57, 4, 63, 6, 20,
2174 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2175 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2176 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2177 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2178 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2179 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2180 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2181 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2182 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2183 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2184 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2185 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2186 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2187 139, 139, 139, 139, 139, 139
2188 };
2189 register int hval = len;
2190
2191 switch (hval)
2192 {
2193 default:
2194 case 3:
2195 hval += asso_values[(unsigned char)str[2]];
2196 case 2:
2197 case 1:
2198 hval += asso_values[(unsigned char)str[0]];
2199 break;
2200 }
2201 return hval;
2202 }
2203
2204 #ifdef __GNUC__
2205 __inline
2206 #endif
2207 static struct C_stab_entry *
2208 in_word_set (str, len)
2209 register const char *str;
2210 register unsigned int len;
2211 {
2212 static struct C_stab_entry wordlist[] =
2213 {
2214 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2215 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2216 {"if", 0, st_C_ignore},
2217 {""}, {""}, {""}, {""},
2218 {"int", 0, st_C_typespec},
2219 {""}, {""},
2220 {"void", 0, st_C_typespec},
2221 {""}, {""},
2222 {"interface", C_JAVA, st_C_struct},
2223 {""},
2224 {"SYSCALL", 0, st_C_gnumacro},
2225 {""},
2226 {"return", 0, st_C_ignore},
2227 {""}, {""}, {""}, {""}, {""}, {""}, {""},
2228 {"while", 0, st_C_ignore},
2229 {"auto", 0, st_C_typespec},
2230 {""}, {""}, {""}, {""}, {""}, {""},
2231 {"float", 0, st_C_typespec},
2232 {"typedef", 0, st_C_typedef},
2233 {"typename", C_PLPL, st_C_typespec},
2234 {""}, {""}, {""},
2235 {"friend", C_PLPL, st_C_ignore},
2236 {"volatile", 0, st_C_typespec},
2237 {""}, {""},
2238 {"for", 0, st_C_ignore},
2239 {"const", 0, st_C_typespec},
2240 {"import", C_JAVA, st_C_ignore},
2241 {""},
2242 {"define", 0, st_C_define},
2243 {"long", 0, st_C_typespec},
2244 {"implements", C_JAVA, st_C_javastruct},
2245 {"signed", 0, st_C_typespec},
2246 {""},
2247 {"extern", 0, st_C_extern},
2248 {"extends", C_JAVA, st_C_javastruct},
2249 {""},
2250 {"mutable", C_PLPL, st_C_typespec},
2251 {"template", 0, st_C_template},
2252 {"short", 0, st_C_typespec},
2253 {"bool", C_PLPL, st_C_typespec},
2254 {"char", 0, st_C_typespec},
2255 {"class", 0, st_C_class},
2256 {"operator", C_PLPL, st_C_operator},
2257 {""},
2258 {"switch", 0, st_C_ignore},
2259 {""},
2260 {"ENTRY", 0, st_C_gnumacro},
2261 {""},
2262 {"package", C_JAVA, st_C_ignore},
2263 {"union", 0, st_C_struct},
2264 {"@end", 0, st_C_objend},
2265 {"struct", 0, st_C_struct},
2266 {"namespace", C_PLPL, st_C_struct},
2267 {""}, {""},
2268 {"domain", C_STAR, st_C_struct},
2269 {"@interface", 0, st_C_objprot},
2270 {"PSEUDO", 0, st_C_gnumacro},
2271 {"double", 0, st_C_typespec},
2272 {""},
2273 {"@protocol", 0, st_C_objprot},
2274 {""},
2275 {"static", 0, st_C_typespec},
2276 {""}, {""},
2277 {"DEFUN", 0, st_C_gnumacro},
2278 {""}, {""}, {""}, {""},
2279 {"explicit", C_PLPL, st_C_typespec},
2280 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2281 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2282 {""},
2283 {"enum", 0, st_C_enum},
2284 {""}, {""},
2285 {"unsigned", 0, st_C_typespec},
2286 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2287 {"@implementation",0, st_C_objimpl}
2288 };
2289
2290 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
2291 {
2292 register int key = hash (str, len);
2293
2294 if (key <= MAX_HASH_VALUE && key >= 0)
2295 {
2296 register const char *s = wordlist[key].name;
2297
2298 if (*str == *s && !strncmp (str + 1, s + 1, len - 1))
2299 return &wordlist[key];
2300 }
2301 }
2302 return 0;
2303 }
2304 /*%>*/
2305
2306 static enum sym_type
2307 C_symtype (str, len, c_ext)
2308 char *str;
2309 int len;
2310 int c_ext;
2311 {
2312 register struct C_stab_entry *se = in_word_set (str, len);
2313
2314 if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
2315 return st_none;
2316 return se->type;
2317 }
2318
2319 \f
2320 /*
2321 * C functions and variables are recognized using a simple
2322 * finite automaton. fvdef is its state variable.
2323 */
2324 static enum
2325 {
2326 fvnone, /* nothing seen */
2327 fdefunkey, /* Emacs DEFUN keyword seen */
2328 fdefunname, /* Emacs DEFUN name seen */
2329 foperator, /* func: operator keyword seen (cplpl) */
2330 fvnameseen, /* function or variable name seen */
2331 fstartlist, /* func: just after open parenthesis */
2332 finlist, /* func: in parameter list */
2333 flistseen, /* func: after parameter list */
2334 fignore, /* func: before open brace */
2335 vignore /* var-like: ignore until ';' */
2336 } fvdef;
2337
2338 static bool fvextern; /* func or var: extern keyword seen; */
2339
2340 /*
2341 * typedefs are recognized using a simple finite automaton.
2342 * typdef is its state variable.
2343 */
2344 static enum
2345 {
2346 tnone, /* nothing seen */
2347 tkeyseen, /* typedef keyword seen */
2348 ttypeseen, /* defined type seen */
2349 tinbody, /* inside typedef body */
2350 tend, /* just before typedef tag */
2351 tignore /* junk after typedef tag */
2352 } typdef;
2353
2354 /*
2355 * struct-like structures (enum, struct and union) are recognized
2356 * using another simple finite automaton. `structdef' is its state
2357 * variable.
2358 */
2359 static enum
2360 {
2361 snone, /* nothing seen yet,
2362 or in struct body if cblev > 0 */
2363 skeyseen, /* struct-like keyword seen */
2364 stagseen, /* struct-like tag seen */
2365 sintemplate, /* inside template (ignore) */
2366 scolonseen /* colon seen after struct-like tag */
2367 } structdef;
2368
2369 /*
2370 * When objdef is different from onone, objtag is the name of the class.
2371 */
2372 static char *objtag = "<uninited>";
2373
2374 /*
2375 * Yet another little state machine to deal with preprocessor lines.
2376 */
2377 static enum
2378 {
2379 dnone, /* nothing seen */
2380 dsharpseen, /* '#' seen as first char on line */
2381 ddefineseen, /* '#' and 'define' seen */
2382 dignorerest /* ignore rest of line */
2383 } definedef;
2384
2385 /*
2386 * State machine for Objective C protocols and implementations.
2387 * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995)
2388 */
2389 static enum
2390 {
2391 onone, /* nothing seen */
2392 oprotocol, /* @interface or @protocol seen */
2393 oimplementation, /* @implementations seen */
2394 otagseen, /* class name seen */
2395 oparenseen, /* parenthesis before category seen */
2396 ocatseen, /* category name seen */
2397 oinbody, /* in @implementation body */
2398 omethodsign, /* in @implementation body, after +/- */
2399 omethodtag, /* after method name */
2400 omethodcolon, /* after method colon */
2401 omethodparm, /* after method parameter */
2402 oignore /* wait for @end */
2403 } objdef;
2404
2405
2406 /*
2407 * Use this structure to keep info about the token read, and how it
2408 * should be tagged. Used by the make_C_tag function to build a tag.
2409 */
2410 static struct tok
2411 {
2412 bool valid;
2413 bool named;
2414 int offset;
2415 int length;
2416 int lineno;
2417 long linepos;
2418 char *line;
2419 } token; /* latest token read */
2420 static linebuffer token_name; /* its name */
2421
2422 /*
2423 * Variables and functions for dealing with nested structures.
2424 * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001)
2425 */
2426 static void pushclass_above __P((int, char *, int));
2427 static void popclass_above __P((int));
2428 static void write_classname __P((linebuffer *, char *qualifier));
2429
2430 static struct {
2431 char **cname; /* nested class names */
2432 int *cblev; /* nested class curly brace level */
2433 int nl; /* class nesting level (elements used) */
2434 int size; /* length of the array */
2435 } cstack; /* stack for nested declaration tags */
2436 /* Current struct nesting depth (namespace, class, struct, union, enum). */
2437 #define nestlev (cstack.nl)
2438 /* After struct keyword or in struct body, not inside an nested function. */
2439 #define instruct (structdef == snone && nestlev > 0 \
2440 && cblev == cstack.cblev[nestlev-1] + 1)
2441
2442 static void
2443 pushclass_above (cblev, str, len)
2444 int cblev;
2445 char *str;
2446 int len;
2447 {
2448 int nl;
2449
2450 popclass_above (cblev);
2451 nl = cstack.nl;
2452 if (nl >= cstack.size)
2453 {
2454 int size = cstack.size *= 2;
2455 xrnew (cstack.cname, size, char *);
2456 xrnew (cstack.cblev, size, int);
2457 }
2458 assert (nl == 0 || cstack.cblev[nl-1] < cblev);
2459 cstack.cname[nl] = (str == NULL) ? NULL : savenstr (str, len);
2460 cstack.cblev[nl] = cblev;
2461 cstack.nl = nl + 1;
2462 }
2463
2464 static void
2465 popclass_above (cblev)
2466 int cblev;
2467 {
2468 int nl;
2469
2470 for (nl = cstack.nl - 1;
2471 nl >= 0 && cstack.cblev[nl] >= cblev;
2472 nl--)
2473 {
2474 if (cstack.cname[nl] != NULL)
2475 free (cstack.cname[nl]);
2476 cstack.nl = nl;
2477 }
2478 }
2479
2480 static void
2481 write_classname (cn, qualifier)
2482 linebuffer *cn;
2483 char *qualifier;
2484 {
2485 int i, len;
2486 int qlen = strlen (qualifier);
2487
2488 if (cstack.nl == 0 || cstack.cname[0] == NULL)
2489 {
2490 len = 0;
2491 cn->len = 0;
2492 cn->buffer[0] = '\0';
2493 }
2494 else
2495 {
2496 len = strlen (cstack.cname[0]);
2497 linebuffer_setlen (cn, len);
2498 strcpy (cn->buffer, cstack.cname[0]);
2499 }
2500 for (i = 1; i < cstack.nl; i++)
2501 {
2502 char *s;
2503 int slen;
2504
2505 s = cstack.cname[i];
2506 if (s == NULL)
2507 continue;
2508 slen = strlen (s);
2509 len += slen + qlen;
2510 linebuffer_setlen (cn, len);
2511 strncat (cn->buffer, qualifier, qlen);
2512 strncat (cn->buffer, s, slen);
2513 }
2514 }
2515
2516 \f
2517 static bool consider_token __P((char *, int, int, int *, int, int, bool *));
2518 static void make_C_tag __P((bool));
2519
2520 /*
2521 * consider_token ()
2522 * checks to see if the current token is at the start of a
2523 * function or variable, or corresponds to a typedef, or
2524 * is a struct/union/enum tag, or #define, or an enum constant.
2525 *
2526 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2527 * with args. C_EXTP points to which language we are looking at.
2528 *
2529 * Globals
2530 * fvdef IN OUT
2531 * structdef IN OUT
2532 * definedef IN OUT
2533 * typdef IN OUT
2534 * objdef IN OUT
2535 */
2536
2537 static bool
2538 consider_token (str, len, c, c_extp, cblev, parlev, is_func_or_var)
2539 register char *str; /* IN: token pointer */
2540 register int len; /* IN: token length */
2541 register int c; /* IN: first char after the token */
2542 int *c_extp; /* IN, OUT: C extensions mask */
2543 int cblev; /* IN: curly brace level */
2544 int parlev; /* IN: parenthesis level */
2545 bool *is_func_or_var; /* OUT: function or variable found */
2546 {
2547 /* When structdef is stagseen, scolonseen, or snone with cblev > 0,
2548 structtype is the type of the preceding struct-like keyword, and
2549 structcblev is the curly brace level where it has been seen. */
2550 static enum sym_type structtype;
2551 static int structcblev;
2552 static enum sym_type toktype;
2553
2554
2555 toktype = C_symtype (str, len, *c_extp);
2556
2557 /*
2558 * Advance the definedef state machine.
2559 */
2560 switch (definedef)
2561 {
2562 case dnone:
2563 /* We're not on a preprocessor line. */
2564 if (toktype == st_C_gnumacro)
2565 {
2566 fvdef = fdefunkey;
2567 return FALSE;
2568 }
2569 break;
2570 case dsharpseen:
2571 if (toktype == st_C_define)
2572 {
2573 definedef = ddefineseen;
2574 }
2575 else
2576 {
2577 definedef = dignorerest;
2578 }
2579 return FALSE;
2580 case ddefineseen:
2581 /*
2582 * Make a tag for any macro, unless it is a constant
2583 * and constantypedefs is FALSE.
2584 */
2585 definedef = dignorerest;
2586 *is_func_or_var = (c == '(');
2587 if (!*is_func_or_var && !constantypedefs)
2588 return FALSE;
2589 else
2590 return TRUE;
2591 case dignorerest:
2592 return FALSE;
2593 default:
2594 error ("internal error: definedef value.", (char *)NULL);
2595 }
2596
2597 /*
2598 * Now typedefs
2599 */
2600 switch (typdef)
2601 {
2602 case tnone:
2603 if (toktype == st_C_typedef)
2604 {
2605 if (typedefs)
2606 typdef = tkeyseen;
2607 fvextern = FALSE;
2608 fvdef = fvnone;
2609 return FALSE;
2610 }
2611 break;
2612 case tkeyseen:
2613 switch (toktype)
2614 {
2615 case st_none:
2616 case st_C_typespec:
2617 case st_C_class:
2618 case st_C_struct:
2619 case st_C_enum:
2620 typdef = ttypeseen;
2621 break;
2622 }
2623 break;
2624 case ttypeseen:
2625 if (structdef == snone && fvdef == fvnone)
2626 {
2627 fvdef = fvnameseen;
2628 return TRUE;
2629 }
2630 break;
2631 case tend:
2632 switch (toktype)
2633 {
2634 case st_C_typespec:
2635 case st_C_class:
2636 case st_C_struct:
2637 case st_C_enum:
2638 return FALSE;
2639 }
2640 return TRUE;
2641 }
2642
2643 /*
2644 * This structdef business is NOT invoked when we are ctags and the
2645 * file is plain C. This is because a struct tag may have the same
2646 * name as another tag, and this loses with ctags.
2647 */
2648 switch (toktype)
2649 {
2650 case st_C_javastruct:
2651 if (structdef == stagseen)
2652 structdef = scolonseen;
2653 return FALSE;
2654 case st_C_template:
2655 case st_C_class:
2656 if (cblev == 0
2657 && (*c_extp & C_AUTO) /* automatic detection of C++ language */
2658 && definedef == dnone && structdef == snone
2659 && typdef == tnone && fvdef == fvnone)
2660 *c_extp = (*c_extp | C_PLPL) & ~C_AUTO;
2661 if (toktype == st_C_template)
2662 break;
2663 /* FALLTHRU */
2664 case st_C_struct:
2665 case st_C_enum:
2666 if (parlev == 0
2667 && fvdef != vignore
2668 && (typdef == tkeyseen
2669 || (typedefs_or_cplusplus && structdef == snone)))
2670 {
2671 structdef = skeyseen;
2672 structtype = toktype;
2673 structcblev = cblev;
2674 }
2675 return FALSE;
2676 }
2677
2678 if (structdef == skeyseen)
2679 {
2680 structdef = stagseen;
2681 return TRUE;
2682 }
2683
2684 if (typdef != tnone)
2685 definedef = dnone;
2686
2687 /* Detect Objective C constructs. */
2688 switch (objdef)
2689 {
2690 case onone:
2691 switch (toktype)
2692 {
2693 case st_C_objprot:
2694 objdef = oprotocol;
2695 return FALSE;
2696 case st_C_objimpl:
2697 objdef = oimplementation;
2698 return FALSE;
2699 }
2700 break;
2701 case oimplementation:
2702 /* Save the class tag for functions or variables defined inside. */
2703 objtag = savenstr (str, len);
2704 objdef = oinbody;
2705 return FALSE;
2706 case oprotocol:
2707 /* Save the class tag for categories. */
2708 objtag = savenstr (str, len);
2709 objdef = otagseen;
2710 *is_func_or_var = TRUE;
2711 return TRUE;
2712 case oparenseen:
2713 objdef = ocatseen;
2714 *is_func_or_var = TRUE;
2715 return TRUE;
2716 case oinbody:
2717 break;
2718 case omethodsign:
2719 if (parlev == 0)
2720 {
2721 objdef = omethodtag;
2722 linebuffer_setlen (&token_name, len);
2723 strncpy (token_name.buffer, str, len);
2724 token_name.buffer[len] = '\0';
2725 return TRUE;
2726 }
2727 return FALSE;
2728 case omethodcolon:
2729 if (parlev == 0)
2730 objdef = omethodparm;
2731 return FALSE;
2732 case omethodparm:
2733 if (parlev == 0)
2734 {
2735 objdef = omethodtag;
2736 linebuffer_setlen (&token_name, token_name.len + len);
2737 strncat (token_name.buffer, str, len);
2738 return TRUE;
2739 }
2740 return FALSE;
2741 case oignore:
2742 if (toktype == st_C_objend)
2743 {
2744 /* Memory leakage here: the string pointed by objtag is
2745 never released, because many tests would be needed to
2746 avoid breaking on incorrect input code. The amount of
2747 memory leaked here is the sum of the lengths of the
2748 class tags.
2749 free (objtag); */
2750 objdef = onone;
2751 }
2752 return FALSE;
2753 }
2754
2755 /* A function, variable or enum constant? */
2756 switch (toktype)
2757 {
2758 case st_C_extern:
2759 fvextern = TRUE;
2760 /* FALLTHRU */
2761 case st_C_typespec:
2762 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2763 fvdef = fvnone; /* should be useless */
2764 return FALSE;
2765 case st_C_ignore:
2766 fvextern = FALSE;
2767 fvdef = vignore;
2768 return FALSE;
2769 case st_C_operator:
2770 fvdef = foperator;
2771 *is_func_or_var = TRUE;
2772 return TRUE;
2773 case st_none:
2774 if (constantypedefs
2775 && structdef == snone
2776 && structtype == st_C_enum && cblev > structcblev)
2777 return TRUE; /* enum constant */
2778 switch (fvdef)
2779 {
2780 case fdefunkey:
2781 if (cblev > 0)
2782 break;
2783 fvdef = fdefunname; /* GNU macro */
2784 *is_func_or_var = TRUE;
2785 return TRUE;
2786 case fvnone:
2787 if ((strneq (str, "asm", 3) && endtoken (str[3]))
2788 || (strneq (str, "__asm__", 7) && endtoken (str[7])))
2789 {
2790 fvdef = vignore;
2791 return FALSE;
2792 }
2793 if ((*c_extp & C_PLPL) && strneq (str+len-10, "::operator", 10))
2794 {
2795 fvdef = foperator;
2796 *is_func_or_var = TRUE;
2797 return TRUE;
2798 }
2799 if (cblev > 0 && !instruct)
2800 break;
2801 fvdef = fvnameseen; /* function or variable */
2802 *is_func_or_var = TRUE;
2803 return TRUE;
2804 }
2805 break;
2806 }
2807
2808 return FALSE;
2809 }
2810
2811 \f
2812 /*
2813 * C_entries often keeps pointers to tokens or lines which are older than
2814 * the line currently read. By keeping two line buffers, and switching
2815 * them at end of line, it is possible to use those pointers.
2816 */
2817 static struct
2818 {
2819 long linepos;
2820 linebuffer lb;
2821 } lbs[2];
2822
2823 #define current_lb_is_new (newndx == curndx)
2824 #define switch_line_buffers() (curndx = 1 - curndx)
2825
2826 #define curlb (lbs[curndx].lb)
2827 #define newlb (lbs[newndx].lb)
2828 #define curlinepos (lbs[curndx].linepos)
2829 #define newlinepos (lbs[newndx].linepos)
2830
2831 #define CNL_SAVE_DEFINEDEF() \
2832 do { \
2833 curlinepos = charno; \
2834 lineno++; \
2835 linecharno = charno; \
2836 charno += readline (&curlb, inf); \
2837 lp = curlb.buffer; \
2838 quotednl = FALSE; \
2839 newndx = curndx; \
2840 } while (0)
2841
2842 #define CNL() \
2843 do { \
2844 CNL_SAVE_DEFINEDEF(); \
2845 if (savetoken.valid) \
2846 { \
2847 token = savetoken; \
2848 savetoken.valid = FALSE; \
2849 } \
2850 definedef = dnone; \
2851 } while (0)
2852
2853
2854 static void
2855 make_C_tag (isfun)
2856 bool isfun;
2857 {
2858 /* This function should never be called when token.valid is FALSE, but
2859 we must protect against invalid input or internal errors. */
2860 if (DEBUG || token.valid)
2861 {
2862 if (traditional_tag_style)
2863 {
2864 /* This was the original code. Now we call new_pfnote instead,
2865 which uses the new method for naming tags (see new_pfnote). */
2866 char *name = NULL;
2867
2868 if (CTAGS || token.named)
2869 name = savestr (token_name.buffer);
2870 if (DEBUG && !token.valid)
2871 {
2872 if (token.named)
2873 name = concat (name, "##invalid##", "");
2874 else
2875 name = savestr ("##invalid##");
2876 }
2877 pfnote (name, isfun, token.line,
2878 token.offset+token.length+1, token.lineno, token.linepos);
2879 }
2880 else
2881 new_pfnote (token_name.buffer, token_name.len, isfun, token.line,
2882 token.offset+token.length+1, token.lineno, token.linepos);
2883 token.valid = FALSE;
2884 }
2885 }
2886
2887
2888 /*
2889 * C_entries ()
2890 * This routine finds functions, variables, typedefs,
2891 * #define's, enum constants and struct/union/enum definitions in
2892 * C syntax and adds them to the list.
2893 */
2894 static void
2895 C_entries (c_ext, inf)
2896 int c_ext; /* extension of C */
2897 FILE *inf; /* input file */
2898 {
2899 register char c; /* latest char read; '\0' for end of line */
2900 register char *lp; /* pointer one beyond the character `c' */
2901 int curndx, newndx; /* indices for current and new lb */
2902 register int tokoff; /* offset in line of start of current token */
2903 register int toklen; /* length of current token */
2904 char *qualifier; /* string used to qualify names */
2905 int qlen; /* length of qualifier */
2906 int cblev; /* current curly brace level */
2907 int parlev; /* current parenthesis level */
2908 int typdefcblev; /* cblev where a typedef struct body begun */
2909 bool incomm, inquote, inchar, quotednl, midtoken;
2910 bool cplpl, cjava;
2911 bool yacc_rules; /* in the rules part of a yacc file */
2912 struct tok savetoken; /* token saved during preprocessor handling */
2913
2914
2915 initbuffer (&token_name);
2916 initbuffer (&lbs[0].lb);
2917 initbuffer (&lbs[1].lb);
2918 if (cstack.size == 0)
2919 {
2920 cstack.size = (DEBUG) ? 1 : 4;
2921 cstack.nl = 0;
2922 cstack.cname = xnew (cstack.size, char *);
2923 cstack.cblev = xnew (cstack.size, int);
2924 }
2925
2926 tokoff = toklen = typdefcblev = 0; /* keep compiler quiet */
2927 curndx = newndx = 0;
2928 lineno = 0;
2929 charno = 0;
2930 lp = curlb.buffer;
2931 *lp = 0;
2932
2933 fvdef = fvnone; fvextern = FALSE; typdef = tnone;
2934 structdef = snone; definedef = dnone; objdef = onone;
2935 yacc_rules = FALSE;
2936 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2937 token.valid = savetoken.valid = FALSE;
2938 cblev = 0;
2939 parlev = 0;
2940 cplpl = (c_ext & C_PLPL) == C_PLPL;
2941 cjava = (c_ext & C_JAVA) == C_JAVA;
2942 if (cjava)
2943 { qualifier = "."; qlen = 1; }
2944 else
2945 { qualifier = "::"; qlen = 2; }
2946
2947
2948 while (!feof (inf))
2949 {
2950 c = *lp++;
2951 if (c == '\\')
2952 {
2953 /* If we're at the end of the line, the next character is a
2954 '\0'; don't skip it, because it's the thing that tells us
2955 to read the next line. */
2956 if (*lp == '\0')
2957 {
2958 quotednl = TRUE;
2959 continue;
2960 }
2961 lp++;
2962 c = ' ';
2963 }
2964 else if (incomm)
2965 {
2966 switch (c)
2967 {
2968 case '*':
2969 if (*lp == '/')
2970 {
2971 c = *lp++;
2972 incomm = FALSE;
2973 }
2974 break;
2975 case '\0':
2976 /* Newlines inside comments do not end macro definitions in
2977 traditional cpp. */
2978 CNL_SAVE_DEFINEDEF ();
2979 break;
2980 }
2981 continue;
2982 }
2983 else if (inquote)
2984 {
2985 switch (c)
2986 {
2987 case '"':
2988 inquote = FALSE;
2989 break;
2990 case '\0':
2991 /* Newlines inside strings do not end macro definitions
2992 in traditional cpp, even though compilers don't
2993 usually accept them. */
2994 CNL_SAVE_DEFINEDEF ();
2995 break;
2996 }
2997 continue;
2998 }
2999 else if (inchar)
3000 {
3001 switch (c)
3002 {
3003 case '\0':
3004 /* Hmmm, something went wrong. */
3005 CNL ();
3006 /* FALLTHRU */
3007 case '\'':
3008 inchar = FALSE;
3009 break;
3010 }
3011 continue;
3012 }
3013 else
3014 switch (c)
3015 {
3016 case '"':
3017 inquote = TRUE;
3018 switch (fvdef)
3019 {
3020 case fdefunkey:
3021 case fstartlist:
3022 case finlist:
3023 case fignore:
3024 case vignore:
3025 break;
3026 default:
3027 fvextern = FALSE;
3028 fvdef = fvnone;
3029 }
3030 continue;
3031 case '\'':
3032 inchar = TRUE;
3033 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
3034 {
3035 fvextern = FALSE;
3036 fvdef = fvnone;
3037 }
3038 continue;
3039 case '/':
3040 if (*lp == '*')
3041 {
3042 lp++;
3043 incomm = TRUE;
3044 continue;
3045 }
3046 else if (/* cplpl && */ *lp == '/')
3047 {
3048 c = '\0';
3049 break;
3050 }
3051 else
3052 break;
3053 case '%':
3054 if ((c_ext & YACC) && *lp == '%')
3055 {
3056 /* Entering or exiting rules section in yacc file. */
3057 lp++;
3058 definedef = dnone; fvdef = fvnone; fvextern = FALSE;
3059 typdef = tnone; structdef = snone;
3060 midtoken = inquote = inchar = incomm = quotednl = FALSE;
3061 cblev = 0;
3062 yacc_rules = !yacc_rules;
3063 continue;
3064 }
3065 else
3066 break;
3067 case '#':
3068 if (definedef == dnone)
3069 {
3070 char *cp;
3071 bool cpptoken = TRUE;
3072
3073 /* Look back on this line. If all blanks, or nonblanks
3074 followed by an end of comment, this is a preprocessor
3075 token. */
3076 for (cp = newlb.buffer; cp < lp-1; cp++)
3077 if (!iswhite (*cp))
3078 {
3079 if (*cp == '*' && *(cp+1) == '/')
3080 {
3081 cp++;
3082 cpptoken = TRUE;
3083 }
3084 else
3085 cpptoken = FALSE;
3086 }
3087 if (cpptoken)
3088 definedef = dsharpseen;
3089 } /* if (definedef == dnone) */
3090
3091 continue;
3092 } /* switch (c) */
3093
3094
3095 /* Consider token only if some involved conditions are satisfied. */
3096 if (typdef != tignore
3097 && definedef != dignorerest
3098 && fvdef != finlist
3099 && structdef != sintemplate
3100 && (definedef != dnone
3101 || structdef != scolonseen))
3102 {
3103 if (midtoken)
3104 {
3105 if (endtoken (c))
3106 {
3107 if (c == ':' && cplpl && *lp == ':' && begtoken (lp[1]))
3108 {
3109 /*
3110 * This handles :: in the middle, but not at the
3111 * beginning of an identifier. Also, space-separated
3112 * :: is not recognised.
3113 */
3114 lp += 2;
3115 toklen += 2;
3116 c = lp[-1];
3117 goto still_in_token;
3118 }
3119 else
3120 {
3121 bool funorvar = FALSE;
3122
3123 if (yacc_rules
3124 || consider_token (newlb.buffer + tokoff, toklen, c,
3125 &c_ext, cblev, parlev, &funorvar))
3126 {
3127 if (fvdef == foperator)
3128 {
3129 char *oldlp = lp;
3130 lp = skip_spaces (lp-1);
3131 if (*lp != '\0')
3132 lp += 1;
3133 while (*lp != '\0'
3134 && !iswhite (*lp) && *lp != '(')
3135 lp += 1;
3136 c = *lp++;
3137 toklen += lp - oldlp;
3138 }
3139 token.named = FALSE;
3140 if ((c_ext & C_EXT) /* not pure C */
3141 && nestlev > 0 && definedef == dnone)
3142 /* in struct body */
3143 {
3144 write_classname (&token_name, qualifier);
3145 linebuffer_setlen (&token_name,
3146 token_name.len+qlen+toklen);
3147 strcat (token_name.buffer, qualifier);
3148 strncat (token_name.buffer,
3149 newlb.buffer + tokoff, toklen);
3150 token.named = TRUE;
3151 }
3152 else if (objdef == ocatseen)
3153 /* Objective C category */
3154 {
3155 int len = strlen (objtag) + 2 + toklen;
3156 linebuffer_setlen (&token_name, len);
3157 strcpy (token_name.buffer, objtag);
3158 strcat (token_name.buffer, "(");
3159 strncat (token_name.buffer,
3160 newlb.buffer + tokoff, toklen);
3161 strcat (token_name.buffer, ")");
3162 token.named = TRUE;
3163 }
3164 else if (objdef == omethodtag
3165 || objdef == omethodparm)
3166 /* Objective C method */
3167 {
3168 token.named = TRUE;
3169 }
3170 else if (fvdef == fdefunname)
3171 /* GNU DEFUN and similar macros */
3172 {
3173 bool defun = (newlb.buffer[tokoff] == 'F');
3174 int off = tokoff;
3175 int len = toklen;
3176
3177 /* Rewrite the tag so that emacs lisp DEFUNs
3178 can be found by their elisp name */
3179 if (defun)
3180 {
3181 off += 1;
3182 len -= 1;
3183 }
3184 len = toklen;
3185 linebuffer_setlen (&token_name, len);
3186 strncpy (token_name.buffer,
3187 newlb.buffer + off, len);
3188 token_name.buffer[len] = '\0';
3189 if (defun)
3190 while (--len >= 0)
3191 if (token_name.buffer[len] == '_')
3192 token_name.buffer[len] = '-';
3193 token.named = defun;
3194 }
3195 else
3196 {
3197 linebuffer_setlen (&token_name, toklen);
3198 strncpy (token_name.buffer,
3199 newlb.buffer + tokoff, toklen);
3200 token_name.buffer[toklen] = '\0';
3201 /* Name macros and members. */
3202 token.named = (structdef == stagseen
3203 || typdef == ttypeseen
3204 || typdef == tend
3205 || (funorvar
3206 && definedef == dignorerest)
3207 || (funorvar
3208 && definedef == dnone
3209 && structdef == snone
3210 && cblev > 0));
3211 }
3212 token.lineno = lineno;
3213 token.offset = tokoff;
3214 token.length = toklen;
3215 token.line = newlb.buffer;
3216 token.linepos = newlinepos;
3217 token.valid = TRUE;
3218
3219 if (definedef == dnone
3220 && (fvdef == fvnameseen
3221 || fvdef == foperator
3222 || structdef == stagseen
3223 || typdef == tend
3224 || typdef == ttypeseen
3225 || objdef != onone))
3226 {
3227 if (current_lb_is_new)
3228 switch_line_buffers ();
3229 }
3230 else if (definedef != dnone
3231 || fvdef == fdefunname
3232 || instruct)
3233 make_C_tag (funorvar);
3234 }
3235 midtoken = FALSE;
3236 }
3237 } /* if (endtoken (c)) */
3238 else if (intoken (c))
3239 still_in_token:
3240 {
3241 toklen++;
3242 continue;
3243 }
3244 } /* if (midtoken) */
3245 else if (begtoken (c))
3246 {
3247 switch (definedef)
3248 {
3249 case dnone:
3250 switch (fvdef)
3251 {
3252 case fstartlist:
3253 fvdef = finlist;
3254 continue;
3255 case flistseen:
3256 make_C_tag (TRUE); /* a function */
3257 fvdef = fignore;
3258 break;
3259 case fvnameseen:
3260 fvdef = fvnone;
3261 break;
3262 }
3263 if (structdef == stagseen && !cjava)
3264 {
3265 popclass_above (cblev);
3266 structdef = snone;
3267 }
3268 break;
3269 case dsharpseen:
3270 savetoken = token;
3271 }
3272 if (!yacc_rules || lp == newlb.buffer + 1)
3273 {
3274 tokoff = lp - 1 - newlb.buffer;
3275 toklen = 1;
3276 midtoken = TRUE;
3277 }
3278 continue;
3279 } /* if (begtoken) */
3280 } /* if must look at token */
3281
3282
3283 /* Detect end of line, colon, comma, semicolon and various braces
3284 after having handled a token.*/
3285 switch (c)
3286 {
3287 case ':':
3288 if (yacc_rules && token.offset == 0 && token.valid)
3289 {
3290 make_C_tag (FALSE); /* a yacc function */
3291 break;
3292 }
3293 if (definedef != dnone)
3294 break;
3295 switch (objdef)
3296 {
3297 case otagseen:
3298 objdef = oignore;
3299 make_C_tag (TRUE); /* an Objective C class */
3300 break;
3301 case omethodtag:
3302 case omethodparm:
3303 objdef = omethodcolon;
3304 linebuffer_setlen (&token_name, token_name.len + 1);
3305 strcat (token_name.buffer, ":");
3306 break;
3307 }
3308 if (structdef == stagseen)
3309 structdef = scolonseen;
3310 break;
3311 case ';':
3312 if (definedef != dnone)
3313 break;
3314 switch (typdef)
3315 {
3316 case tend:
3317 case ttypeseen:
3318 make_C_tag (FALSE); /* a typedef */
3319 typdef = tnone;
3320 fvdef = fvnone;
3321 break;
3322 case tnone:
3323 case tinbody:
3324 case tignore:
3325 switch (fvdef)
3326 {
3327 case fignore:
3328 if (typdef == tignore)
3329 fvdef = fvnone;
3330 break;
3331 case fvnameseen:
3332 if ((globals && cblev == 0 && (!fvextern || declarations))
3333 || (members && instruct))
3334 make_C_tag (FALSE); /* a variable */
3335 fvextern = FALSE;
3336 fvdef = fvnone;
3337 token.valid = FALSE;
3338 break;
3339 case flistseen:
3340 if ((declarations && typdef == tnone && !instruct)
3341 || (members && typdef != tignore && instruct))
3342 make_C_tag (TRUE); /* a function declaration */
3343 /* FALLTHRU */
3344 default:
3345 fvextern = FALSE;
3346 fvdef = fvnone;
3347 if (declarations
3348 && structdef == stagseen && (c_ext & C_PLPL))
3349 make_C_tag (FALSE); /* forward declaration */
3350 else
3351 /* The following instruction invalidates the token.
3352 Probably the token should be invalidated in all other
3353 cases where some state machine is reset prematurely. */
3354 token.valid = FALSE;
3355 } /* switch (fvdef) */
3356 /* FALLTHRU */
3357 default:
3358 if (!instruct)
3359 typdef = tnone;
3360 }
3361 if (structdef == stagseen)
3362 structdef = snone;
3363 break;
3364 case ',':
3365 if (definedef != dnone)
3366 break;
3367 switch (objdef)
3368 {
3369 case omethodtag:
3370 case omethodparm:
3371 make_C_tag (TRUE); /* an Objective C method */
3372 objdef = oinbody;
3373 break;
3374 }
3375 switch (fvdef)
3376 {
3377 case fdefunkey:
3378 case foperator:
3379 case fstartlist:
3380 case finlist:
3381 case fignore:
3382 case vignore:
3383 break;
3384 case fdefunname:
3385 fvdef = fignore;
3386 break;
3387 case fvnameseen: /* a variable */
3388 if ((globals && cblev == 0 && (!fvextern || declarations))
3389 || (members && instruct))
3390 make_C_tag (FALSE);
3391 break;
3392 case flistseen: /* a function */
3393 if ((declarations && typdef == tnone && !instruct)
3394 || (members && typdef != tignore && instruct))
3395 {
3396 make_C_tag (TRUE); /* a function declaration */
3397 fvdef = fvnameseen;
3398 }
3399 else if (!declarations)
3400 fvdef = fvnone;
3401 token.valid = FALSE;
3402 break;
3403 default:
3404 fvdef = fvnone;
3405 }
3406 if (structdef == stagseen)
3407 structdef = snone;
3408 break;
3409 case '[':
3410 if (definedef != dnone)
3411 break;
3412 if (structdef == stagseen)
3413 structdef = snone;
3414 switch (typdef)
3415 {
3416 case ttypeseen:
3417 case tend:
3418 typdef = tignore;
3419 make_C_tag (FALSE); /* a typedef */
3420 break;
3421 case tnone:
3422 case tinbody:
3423 switch (fvdef)
3424 {
3425 case foperator:
3426 case finlist:
3427 case fignore:
3428 case vignore:
3429 break;
3430 case fvnameseen:
3431 if ((members && cblev == 1)
3432 || (globals && cblev == 0
3433 && (!fvextern || declarations)))
3434 make_C_tag (FALSE); /* a variable */
3435 /* FALLTHRU */
3436 default:
3437 fvdef = fvnone;
3438 }
3439 break;
3440 }
3441 break;
3442 case '(':
3443 if (definedef != dnone)
3444 break;
3445 if (objdef == otagseen && parlev == 0)
3446 objdef = oparenseen;
3447 switch (fvdef)
3448 {
3449 case fvnameseen:
3450 if (typdef == ttypeseen
3451 && *lp != '*'
3452 && !instruct)
3453 {
3454 /* This handles constructs like:
3455 typedef void OperatorFun (int fun); */
3456 make_C_tag (FALSE);
3457 typdef = tignore;
3458 fvdef = fignore;
3459 break;
3460 }
3461 /* FALLTHRU */
3462 case foperator:
3463 fvdef = fstartlist;
3464 break;
3465 case flistseen:
3466 fvdef = finlist;
3467 break;
3468 }
3469 parlev++;
3470 break;
3471 case ')':
3472 if (definedef != dnone)
3473 break;
3474 if (objdef == ocatseen && parlev == 1)
3475 {
3476 make_C_tag (TRUE); /* an Objective C category */
3477 objdef = oignore;
3478 }
3479 if (--parlev == 0)
3480 {
3481 switch (fvdef)
3482 {
3483 case fstartlist:
3484 case finlist:
3485 fvdef = flistseen;
3486 break;
3487 }
3488 if (!instruct
3489 && (typdef == tend
3490 || typdef == ttypeseen))
3491 {
3492 typdef = tignore;
3493 make_C_tag (FALSE); /* a typedef */
3494 }
3495 }
3496 else if (parlev < 0) /* can happen due to ill-conceived #if's. */
3497 parlev = 0;
3498 break;
3499 case '{':
3500 if (definedef != dnone)
3501 break;
3502 if (typdef == ttypeseen)
3503 {
3504 /* Whenever typdef is set to tinbody (currently only
3505 here), typdefcblev should be set to cblev. */
3506 typdef = tinbody;
3507 typdefcblev = cblev;
3508 }
3509 switch (fvdef)
3510 {
3511 case flistseen:
3512 make_C_tag (TRUE); /* a function */
3513 /* FALLTHRU */
3514 case fignore:
3515 fvdef = fvnone;
3516 break;
3517 case fvnone:
3518 switch (objdef)
3519 {
3520 case otagseen:
3521 make_C_tag (TRUE); /* an Objective C class */
3522 objdef = oignore;
3523 break;
3524 case omethodtag:
3525 case omethodparm:
3526 make_C_tag (TRUE); /* an Objective C method */
3527 objdef = oinbody;
3528 break;
3529 default:
3530 /* Neutralize `extern "C" {' grot. */
3531 if (cblev == 0 && structdef == snone && nestlev == 0
3532 && typdef == tnone)
3533 cblev = -1;
3534 }
3535 }
3536 switch (structdef)
3537 {
3538 case skeyseen: /* unnamed struct */
3539 pushclass_above (cblev, NULL, 0);
3540 structdef = snone;
3541 break;
3542 case stagseen: /* named struct or enum */
3543 case scolonseen: /* a class */
3544 pushclass_above (cblev, token.line+token.offset, token.length);
3545 structdef = snone;
3546 make_C_tag (FALSE); /* a struct or enum */
3547 break;
3548 }
3549 cblev++;
3550 break;
3551 case '*':
3552 if (definedef != dnone)
3553 break;
3554 if (fvdef == fstartlist)
3555 fvdef = fvnone; /* avoid tagging `foo' in `foo (*bar()) ()' */
3556 break;
3557 case '}':
3558 if (definedef != dnone)
3559 break;
3560 if (!noindentypedefs && lp == newlb.buffer + 1)
3561 {
3562 cblev = 0; /* reset curly brace level if first column */
3563 parlev = 0; /* also reset paren level, just in case... */
3564 }
3565 else if (cblev > 0)
3566 cblev--;
3567 popclass_above (cblev);
3568 structdef = snone;
3569 /* Only if typdef == tinbody is typdefcblev significant. */
3570 if (typdef == tinbody && cblev <= typdefcblev)
3571 {
3572 assert (cblev == typdefcblev);
3573 typdef = tend;
3574 }
3575 break;
3576 case '=':
3577 if (definedef != dnone)
3578 break;
3579 switch (fvdef)
3580 {
3581 case foperator:
3582 case finlist:
3583 case fignore:
3584 case vignore:
3585 break;
3586 case fvnameseen:
3587 if ((members && cblev == 1)
3588 || (globals && cblev == 0 && (!fvextern || declarations)))
3589 make_C_tag (FALSE); /* a variable */
3590 /* FALLTHRU */
3591 default:
3592 fvdef = vignore;
3593 }
3594 break;
3595 case '<':
3596 if (cplpl && structdef == stagseen)
3597 {
3598 structdef = sintemplate;
3599 break;
3600 }
3601 goto resetfvdef;
3602 case '>':
3603 if (structdef == sintemplate)
3604 {
3605 structdef = stagseen;
3606 break;
3607 }
3608 goto resetfvdef;
3609 case '+':
3610 case '-':
3611 if (objdef == oinbody && cblev == 0)
3612 {
3613 objdef = omethodsign;
3614 break;
3615 }
3616 /* FALLTHRU */
3617 resetfvdef:
3618 case '#': case '~': case '&': case '%': case '/': case '|':
3619 case '^': case '!': case '.': case '?': case ']':
3620 if (definedef != dnone)
3621 break;
3622 /* These surely cannot follow a function tag in C. */
3623 switch (fvdef)
3624 {
3625 case foperator:
3626 case finlist:
3627 case fignore:
3628 case vignore:
3629 break;
3630 default:
3631 fvdef = fvnone;
3632 }
3633 break;
3634 case '\0':
3635 if (objdef == otagseen)
3636 {
3637 make_C_tag (TRUE); /* an Objective C class */
3638 objdef = oignore;
3639 }
3640 /* If a macro spans multiple lines don't reset its state. */
3641 if (quotednl)
3642 CNL_SAVE_DEFINEDEF ();
3643 else
3644 CNL ();
3645 break;
3646 } /* switch (c) */
3647
3648 } /* while not eof */
3649
3650 free (token_name.buffer);
3651 free (lbs[0].lb.buffer);
3652 free (lbs[1].lb.buffer);
3653 }
3654
3655 /*
3656 * Process either a C++ file or a C file depending on the setting
3657 * of a global flag.
3658 */
3659 static void
3660 default_C_entries (inf)
3661 FILE *inf;
3662 {
3663 C_entries (cplusplus ? C_PLPL : C_AUTO, inf);
3664 }
3665
3666 /* Always do plain C. */
3667 static void
3668 plain_C_entries (inf)
3669 FILE *inf;
3670 {
3671 C_entries (0, inf);
3672 }
3673
3674 /* Always do C++. */
3675 static void
3676 Cplusplus_entries (inf)
3677 FILE *inf;
3678 {
3679 C_entries (C_PLPL, inf);
3680 }
3681
3682 /* Always do Java. */
3683 static void
3684 Cjava_entries (inf)
3685 FILE *inf;
3686 {
3687 C_entries (C_JAVA, inf);
3688 }
3689
3690 /* Always do C*. */
3691 static void
3692 Cstar_entries (inf)
3693 FILE *inf;
3694 {
3695 C_entries (C_STAR, inf);
3696 }
3697
3698 /* Always do Yacc. */
3699 static void
3700 Yacc_entries (inf)
3701 FILE *inf;
3702 {
3703 C_entries (YACC, inf);
3704 }
3705
3706 \f
3707 /* Useful macros. */
3708 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3709 for (lineno = charno = 0; /* loop initialization */ \
3710 !feof (file_pointer) /* loop test */ \
3711 && (lineno++, /* instructions at start of loop */ \
3712 linecharno = charno, \
3713 charno += readline (&line_buffer, file_pointer), \
3714 char_pointer = lb.buffer, \
3715 TRUE); \
3716 )
3717 #define LOOKING_AT(cp, keyword) /* keyword is a constant string */ \
3718 (strneq ((cp), keyword, sizeof(keyword)-1) /* cp points at keyword */ \
3719 && notinname ((cp)[sizeof(keyword)-1]) /* end of keyword */ \
3720 && ((cp) = skip_spaces((cp)+sizeof(keyword)-1))) /* skip spaces */
3721
3722 /*
3723 * Read a file, but do no processing. This is used to do regexp
3724 * matching on files that have no language defined.
3725 */
3726 static void
3727 just_read_file (inf)
3728 FILE *inf;
3729 {
3730 register char *dummy;
3731
3732 LOOP_ON_INPUT_LINES (inf, lb, dummy)
3733 continue;
3734 }
3735
3736 \f
3737 /* Fortran parsing */
3738
3739 static void F_takeprec __P((void));
3740 static void F_getit __P((FILE *));
3741
3742 static void
3743 F_takeprec ()
3744 {
3745 dbp = skip_spaces (dbp);
3746 if (*dbp != '*')
3747 return;
3748 dbp++;
3749 dbp = skip_spaces (dbp);
3750 if (strneq (dbp, "(*)", 3))
3751 {
3752 dbp += 3;
3753 return;
3754 }
3755 if (!ISDIGIT (*dbp))
3756 {
3757 --dbp; /* force failure */
3758 return;
3759 }
3760 do
3761 dbp++;
3762 while (ISDIGIT (*dbp));
3763 }
3764
3765 static void
3766 F_getit (inf)
3767 FILE *inf;
3768 {
3769 register char *cp;
3770
3771 dbp = skip_spaces (dbp);
3772 if (*dbp == '\0')
3773 {
3774 lineno++;
3775 linecharno = charno;
3776 charno += readline (&lb, inf);
3777 dbp = lb.buffer;
3778 if (dbp[5] != '&')
3779 return;
3780 dbp += 6;
3781 dbp = skip_spaces (dbp);
3782 }
3783 if (!ISALPHA (*dbp) && *dbp != '_' && *dbp != '$')
3784 return;
3785 for (cp = dbp + 1; *cp != '\0' && intoken (*cp); cp++)
3786 continue;
3787 pfnote (savenstr (dbp, cp-dbp), TRUE,
3788 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3789 }
3790
3791
3792 static void
3793 Fortran_functions (inf)
3794 FILE *inf;
3795 {
3796 LOOP_ON_INPUT_LINES (inf, lb, dbp)
3797 {
3798 if (*dbp == '%')
3799 dbp++; /* Ratfor escape to fortran */
3800 dbp = skip_spaces (dbp);
3801 if (*dbp == '\0')
3802 continue;
3803 switch (lowcase (*dbp))
3804 {
3805 case 'i':
3806 if (nocase_tail ("integer"))
3807 F_takeprec ();
3808 break;
3809 case 'r':
3810 if (nocase_tail ("real"))
3811 F_takeprec ();
3812 break;
3813 case 'l':
3814 if (nocase_tail ("logical"))
3815 F_takeprec ();
3816 break;
3817 case 'c':
3818 if (nocase_tail ("complex") || nocase_tail ("character"))
3819 F_takeprec ();
3820 break;
3821 case 'd':
3822 if (nocase_tail ("double"))
3823 {
3824 dbp = skip_spaces (dbp);
3825 if (*dbp == '\0')
3826 continue;
3827 if (nocase_tail ("precision"))
3828 break;
3829 continue;
3830 }
3831 break;
3832 }
3833 dbp = skip_spaces (dbp);
3834 if (*dbp == '\0')
3835 continue;
3836 switch (lowcase (*dbp))
3837 {
3838 case 'f':
3839 if (nocase_tail ("function"))
3840 F_getit (inf);
3841 continue;
3842 case 's':
3843 if (nocase_tail ("subroutine"))
3844 F_getit (inf);
3845 continue;
3846 case 'e':
3847 if (nocase_tail ("entry"))
3848 F_getit (inf);
3849 continue;
3850 case 'b':
3851 if (nocase_tail ("blockdata") || nocase_tail ("block data"))
3852 {
3853 dbp = skip_spaces (dbp);
3854 if (*dbp == '\0') /* assume un-named */
3855 pfnote (savestr ("blockdata"), TRUE,
3856 lb.buffer, dbp - lb.buffer, lineno, linecharno);
3857 else
3858 F_getit (inf); /* look for name */
3859 }
3860 continue;
3861 }
3862 }
3863 }
3864
3865 \f
3866 /*
3867 * Ada parsing
3868 * Original code by
3869 * Philippe Waroquiers <philippe.waroquiers@eurocontrol.be> (1998)
3870 */
3871
3872 static void Ada_getit __P((FILE *, char *));
3873
3874 /* Once we are positioned after an "interesting" keyword, let's get
3875 the real tag value necessary. */
3876 static void
3877 Ada_getit (inf, name_qualifier)
3878 FILE *inf;
3879 char *name_qualifier;
3880 {
3881 register char *cp;
3882 char *name;
3883 char c;
3884
3885 while (!feof (inf))
3886 {
3887 dbp = skip_spaces (dbp);
3888 if (*dbp == '\0'
3889 || (dbp[0] == '-' && dbp[1] == '-'))
3890 {
3891 lineno++;
3892 linecharno = charno;
3893 charno += readline (&lb, inf);
3894 dbp = lb.buffer;
3895 }
3896 switch (lowcase(*dbp))
3897 {
3898 case 'b':
3899 if (nocase_tail ("body"))
3900 {
3901 /* Skipping body of procedure body or package body or ....
3902 resetting qualifier to body instead of spec. */
3903 name_qualifier = "/b";
3904 continue;
3905 }
3906 break;
3907 case 't':
3908 /* Skipping type of task type or protected type ... */
3909 if (nocase_tail ("type"))
3910 continue;
3911 break;
3912 }
3913 if (*dbp == '"')
3914 {
3915 dbp += 1;
3916 for (cp = dbp; *cp != '\0' && *cp != '"'; cp++)
3917 continue;
3918 }
3919 else
3920 {
3921 dbp = skip_spaces (dbp);
3922 for (cp = dbp;
3923 (*cp != '\0'
3924 && (ISALPHA (*cp) || ISDIGIT (*cp) || *cp == '_' || *cp == '.'));
3925 cp++)
3926 continue;
3927 if (cp == dbp)
3928 return;
3929 }
3930 c = *cp;
3931 *cp = '\0';
3932 name = concat (dbp, name_qualifier, "");
3933 *cp = c;
3934 pfnote (name, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3935 if (c == '"')
3936 dbp = cp + 1;
3937 return;
3938 }
3939 }
3940
3941 static void
3942 Ada_funcs (inf)
3943 FILE *inf;
3944 {
3945 bool inquote = FALSE;
3946
3947 LOOP_ON_INPUT_LINES (inf, lb, dbp)
3948 {
3949 while (*dbp != '\0')
3950 {
3951 /* Skip a string i.e. "abcd". */
3952 if (inquote || (*dbp == '"'))
3953 {
3954 dbp = etags_strchr ((inquote) ? dbp : dbp+1, '"');
3955 if (dbp != NULL)
3956 {
3957 inquote = FALSE;
3958 dbp += 1;
3959 continue; /* advance char */
3960 }
3961 else
3962 {
3963 inquote = TRUE;
3964 break; /* advance line */
3965 }
3966 }
3967
3968 /* Skip comments. */
3969 if (dbp[0] == '-' && dbp[1] == '-')
3970 break; /* advance line */
3971
3972 /* Skip character enclosed in single quote i.e. 'a'
3973 and skip single quote starting an attribute i.e. 'Image. */
3974 if (*dbp == '\'')
3975 {
3976 dbp++ ;
3977 if (*dbp != '\0')
3978 dbp++;
3979 continue;
3980 }
3981
3982 /* Search for beginning of a token. */
3983 if (!begtoken (*dbp))
3984 {
3985 dbp++;
3986 continue; /* advance char */
3987 }
3988
3989 /* We are at the beginning of a token. */
3990 switch (lowcase(*dbp))
3991 {
3992 case 'f':
3993 if (!packages_only && nocase_tail ("function"))
3994 Ada_getit (inf, "/f");
3995 else
3996 break; /* from switch */
3997 continue; /* advance char */
3998 case 'p':
3999 if (!packages_only && nocase_tail ("procedure"))
4000 Ada_getit (inf, "/p");
4001 else if (nocase_tail ("package"))
4002 Ada_getit (inf, "/s");
4003 else if (nocase_tail ("protected")) /* protected type */
4004 Ada_getit (inf, "/t");
4005 else
4006 break; /* from switch */
4007 continue; /* advance char */
4008 case 't':
4009 if (!packages_only && nocase_tail ("task"))
4010 Ada_getit (inf, "/k");
4011 else if (typedefs && !packages_only && nocase_tail ("type"))
4012 {
4013 Ada_getit (inf, "/t");
4014 while (*dbp != '\0')
4015 dbp += 1;
4016 }
4017 else
4018 break; /* from switch */
4019 continue; /* advance char */
4020 }
4021
4022 /* Look for the end of the token. */
4023 while (!endtoken (*dbp))
4024 dbp++;
4025
4026 } /* advance char */
4027 } /* advance line */
4028 }
4029
4030 \f
4031 /*
4032 * Unix and microcontroller assembly tag handling
4033 * Labels: /^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]/
4034 * Idea by Bob Weiner, Motorola Inc. (1994)
4035 */
4036 static void
4037 Asm_labels (inf)
4038 FILE *inf;
4039 {
4040 register char *cp;
4041
4042 LOOP_ON_INPUT_LINES (inf, lb, cp)
4043 {
4044 /* If first char is alphabetic or one of [_.$], test for colon
4045 following identifier. */
4046 if (ISALPHA (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
4047 {
4048 /* Read past label. */
4049 cp++;
4050 while (ISALNUM (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
4051 cp++;
4052 if (*cp == ':' || iswhite (*cp))
4053 {
4054 /* Found end of label, so copy it and add it to the table. */
4055 pfnote (savenstr(lb.buffer, cp-lb.buffer), TRUE,
4056 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4057 }
4058 }
4059 }
4060 }
4061
4062 \f
4063 /*
4064 * Perl support
4065 * Perl sub names: /^sub[ \t\n]+[^ \t\n{]+/
4066 * Perl variable names: /^(my|local).../
4067 * Original code by Bart Robinson <lomew@cs.utah.edu> (1995)
4068 * Additions by Michael Ernst <mernst@alum.mit.edu> (1997)
4069 * Ideas by Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE> (2001)
4070 */
4071 static void
4072 Perl_functions (inf)
4073 FILE *inf;
4074 {
4075 char *package = savestr ("main"); /* current package name */
4076 register char *cp;
4077
4078 LOOP_ON_INPUT_LINES (inf, lb, cp)
4079 {
4080 skip_spaces(cp);
4081
4082 if (LOOKING_AT (cp, "package"))
4083 {
4084 free (package);
4085 package = get_tag (cp);
4086 if (package == NULL) /* can't parse package name */
4087 package = savestr ("");
4088 else
4089 package = savestr(package); /* make a copy */
4090 }
4091 else if (LOOKING_AT (cp, "sub"))
4092 {
4093 char *name, *fullname, *pos;
4094 char *sp = cp;
4095
4096 while (!notinname (*cp))
4097 cp++;
4098 if (cp == sp)
4099 continue;
4100 name = savenstr (sp, cp-sp);
4101 if ((pos = etags_strchr (name, ':')) != NULL && pos[1] == ':')
4102 fullname = name;
4103 else
4104 fullname = concat (package, "::", name);
4105 pfnote (fullname, TRUE,
4106 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4107 if (name != fullname)
4108 free (name);
4109 }
4110 else if (globals /* only if tagging global vars is enabled */
4111 && (LOOKING_AT (cp, "my") || LOOKING_AT (cp, "local")))
4112 {
4113 /* After "my" or "local", but before any following paren or space. */
4114 char *varname = NULL;
4115
4116 if (*cp == '$' || *cp == '@' || *cp == '%')
4117 {
4118 char* varstart = ++cp;
4119 while (ISALNUM (*cp) || *cp == '_')
4120 cp++;
4121 varname = savenstr (varstart, cp-varstart);
4122 }
4123 else
4124 {
4125 /* Should be examining a variable list at this point;
4126 could insist on seeing an open parenthesis. */
4127 while (*cp != '\0' && *cp != ';' && *cp != '=' && *cp != ')')
4128 cp++;
4129 }
4130
4131 /* Perhaps I should back cp up one character, so the TAGS table
4132 doesn't mention (and so depend upon) the following char. */
4133 pfnote (varname, FALSE,
4134 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4135 }
4136 }
4137 }
4138
4139
4140 /*
4141 * Python support
4142 * Look for /^[\t]*def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
4143 * Idea by Eric S. Raymond <esr@thyrsus.com> (1997)
4144 * More ideas by seb bacon <seb@jamkit.com> (2002)
4145 */
4146 static void
4147 Python_functions (inf)
4148 FILE *inf;
4149 {
4150 register char *cp;
4151
4152 LOOP_ON_INPUT_LINES (inf, lb, cp)
4153 {
4154 cp = skip_spaces (cp);
4155 if (LOOKING_AT (cp, "def") || LOOKING_AT (cp, "class"))
4156 {
4157 char *name = cp;
4158 while (!notinname (*cp) && *cp != ':')
4159 cp++;
4160 pfnote (savenstr (name, cp-name), TRUE,
4161 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4162 }
4163 }
4164 }
4165
4166 \f
4167 /*
4168 * PHP support
4169 * Look for:
4170 * - /^[ \t]*function[ \t\n]+[^ \t\n(]+/
4171 * - /^[ \t]*class[ \t\n]+[^ \t\n]+/
4172 * - /^[ \t]*define\(\"[^\"]+/
4173 * Only with --members:
4174 * - /^[ \t]*var[ \t\n]+\$[^ \t\n=;]/
4175 * Idea by Diez B. Roggisch (2001)
4176 */
4177 static void
4178 PHP_functions (inf)
4179 FILE *inf;
4180 {
4181 register char *cp, *name;
4182 bool search_identifier = FALSE;
4183
4184 LOOP_ON_INPUT_LINES (inf, lb, cp)
4185 {
4186 cp = skip_spaces (cp);
4187 name = cp;
4188 if (search_identifier
4189 && *cp != '\0')
4190 {
4191 while (!notinname (*cp))
4192 cp++;
4193 pfnote (savenstr (name, cp-name), TRUE,
4194 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4195 search_identifier = FALSE;
4196 }
4197 else if (LOOKING_AT (cp, "function"))
4198 {
4199 if(*cp == '&')
4200 cp = skip_spaces (cp+1);
4201 if(*cp != '\0')
4202 {
4203 name = cp;
4204 while (!notinname (*cp))
4205 cp++;
4206 pfnote (savenstr (name, cp-name), TRUE,
4207 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4208 }
4209 else
4210 search_identifier = TRUE;
4211 }
4212 else if (LOOKING_AT (cp, "class"))
4213 {
4214 if (*cp != '\0')
4215 {
4216 name = cp;
4217 while (*cp != '\0' && !iswhite (*cp))
4218 cp++;
4219 pfnote (savenstr (name, cp-name), FALSE,
4220 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4221 }
4222 else
4223 search_identifier = TRUE;
4224 }
4225 else if (strneq (cp, "define", 6)
4226 && (cp = skip_spaces (cp+6))
4227 && *cp++ == '('
4228 && (*cp == '"' || *cp == '\''))
4229 {
4230 char quote = *cp++;
4231 name = cp;
4232 while (*cp != quote && *cp != '\0')
4233 cp++;
4234 pfnote (savenstr (name, cp-name), FALSE,
4235 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4236 }
4237 else if (members
4238 && LOOKING_AT (cp, "var")
4239 && *cp == '$')
4240 {
4241 name = cp;
4242 while (!notinname(*cp))
4243 cp++;
4244 pfnote (savenstr (name, cp-name), FALSE,
4245 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4246 }
4247 }
4248 }
4249
4250 \f
4251 /*
4252 * Cobol tag functions
4253 * We could look for anything that could be a paragraph name.
4254 * i.e. anything that starts in column 8 is one word and ends in a full stop.
4255 * Idea by Corny de Souza (1993)
4256 */
4257 static void
4258 Cobol_paragraphs (inf)
4259 FILE *inf;
4260 {
4261 register char *bp, *ep;
4262
4263 LOOP_ON_INPUT_LINES (inf, lb, bp)
4264 {
4265 if (lb.len < 9)
4266 continue;
4267 bp += 8;
4268
4269 /* If eoln, compiler option or comment ignore whole line. */
4270 if (bp[-1] != ' ' || !ISALNUM (bp[0]))
4271 continue;
4272
4273 for (ep = bp; ISALNUM (*ep) || *ep == '-'; ep++)
4274 continue;
4275 if (*ep++ == '.')
4276 pfnote (savenstr (bp, ep-bp), TRUE,
4277 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
4278 }
4279 }
4280
4281 \f
4282 /*
4283 * Makefile support
4284 * Idea by Assar Westerlund <assar@sics.se> (2001)
4285 */
4286 static void
4287 Makefile_targets (inf)
4288 FILE *inf;
4289 {
4290 register char *bp;
4291
4292 LOOP_ON_INPUT_LINES (inf, lb, bp)
4293 {
4294 if (*bp == '\t' || *bp == '#')
4295 continue;
4296 while (*bp != '\0' && *bp != '=' && *bp != ':')
4297 bp++;
4298 if (*bp == ':')
4299 pfnote (savenstr (lb.buffer, bp - lb.buffer), TRUE,
4300 lb.buffer, bp - lb.buffer + 1, lineno, linecharno);
4301 }
4302 }
4303
4304 \f
4305 /*
4306 * Pascal parsing
4307 * Original code by Mosur K. Mohan (1989)
4308 *
4309 * Locates tags for procedures & functions. Doesn't do any type- or
4310 * var-definitions. It does look for the keyword "extern" or
4311 * "forward" immediately following the procedure statement; if found,
4312 * the tag is skipped.
4313 */
4314 static void
4315 Pascal_functions (inf)
4316 FILE *inf;
4317 {
4318 linebuffer tline; /* mostly copied from C_entries */
4319 long save_lcno;
4320 int save_lineno, save_len;
4321 char c, *cp, *namebuf;
4322
4323 bool /* each of these flags is TRUE iff: */
4324 incomment, /* point is inside a comment */
4325 inquote, /* point is inside '..' string */
4326 get_tagname, /* point is after PROCEDURE/FUNCTION
4327 keyword, so next item = potential tag */
4328 found_tag, /* point is after a potential tag */
4329 inparms, /* point is within parameter-list */
4330 verify_tag; /* point has passed the parm-list, so the
4331 next token will determine whether this
4332 is a FORWARD/EXTERN to be ignored, or
4333 whether it is a real tag */
4334
4335 save_lcno = save_lineno = save_len = 0; /* keep compiler quiet */
4336 namebuf = NULL; /* keep compiler quiet */
4337 lineno = 0;
4338 charno = 0;
4339 dbp = lb.buffer;
4340 *dbp = '\0';
4341 initbuffer (&tline);
4342
4343 incomment = inquote = FALSE;
4344 found_tag = FALSE; /* have a proc name; check if extern */
4345 get_tagname = FALSE; /* have found "procedure" keyword */
4346 inparms = FALSE; /* found '(' after "proc" */
4347 verify_tag = FALSE; /* check if "extern" is ahead */
4348
4349
4350 while (!feof (inf)) /* long main loop to get next char */
4351 {
4352 c = *dbp++;
4353 if (c == '\0') /* if end of line */
4354 {
4355 lineno++;
4356 linecharno = charno;
4357 charno += readline (&lb, inf);
4358 dbp = lb.buffer;
4359 if (*dbp == '\0')
4360 continue;
4361 if (!((found_tag && verify_tag)
4362 || get_tagname))
4363 c = *dbp++; /* only if don't need *dbp pointing
4364 to the beginning of the name of
4365 the procedure or function */
4366 }
4367 if (incomment)
4368 {
4369 if (c == '}') /* within { } comments */
4370 incomment = FALSE;
4371 else if (c == '*' && *dbp == ')') /* within (* *) comments */
4372 {
4373 dbp++;
4374 incomment = FALSE;
4375 }
4376 continue;
4377 }
4378 else if (inquote)
4379 {
4380 if (c == '\'')
4381 inquote = FALSE;
4382 continue;
4383 }
4384 else
4385 switch (c)
4386 {
4387 case '\'':
4388 inquote = TRUE; /* found first quote */
4389 continue;
4390 case '{': /* found open { comment */
4391 incomment = TRUE;
4392 continue;
4393 case '(':
4394 if (*dbp == '*') /* found open (* comment */
4395 {
4396 incomment = TRUE;
4397 dbp++;
4398 }
4399 else if (found_tag) /* found '(' after tag, i.e., parm-list */
4400 inparms = TRUE;
4401 continue;
4402 case ')': /* end of parms list */
4403 if (inparms)
4404 inparms = FALSE;
4405 continue;
4406 case ';':
4407 if (found_tag && !inparms) /* end of proc or fn stmt */
4408 {
4409 verify_tag = TRUE;
4410 break;
4411 }
4412 continue;
4413 }
4414 if (found_tag && verify_tag && (*dbp != ' '))
4415 {
4416 /* check if this is an "extern" declaration */
4417 if (*dbp == '\0')
4418 continue;
4419 if (lowcase (*dbp == 'e'))
4420 {
4421 if (nocase_tail ("extern")) /* superfluous, really! */
4422 {
4423 found_tag = FALSE;
4424 verify_tag = FALSE;
4425 }
4426 }
4427 else if (lowcase (*dbp) == 'f')
4428 {
4429 if (nocase_tail ("forward")) /* check for forward reference */
4430 {
4431 found_tag = FALSE;
4432 verify_tag = FALSE;
4433 }
4434 }
4435 if (found_tag && verify_tag) /* not external proc, so make tag */
4436 {
4437 found_tag = FALSE;
4438 verify_tag = FALSE;
4439 pfnote (namebuf, TRUE,
4440 tline.buffer, save_len, save_lineno, save_lcno);
4441 continue;
4442 }
4443 }
4444 if (get_tagname) /* grab name of proc or fn */
4445 {
4446 if (*dbp == '\0')
4447 continue;
4448
4449 /* save all values for later tagging */
4450 linebuffer_setlen (&tline, lb.len);
4451 strcpy (tline.buffer, lb.buffer);
4452 save_lineno = lineno;
4453 save_lcno = linecharno;
4454
4455 /* grab block name */
4456 for (cp = dbp + 1; *cp != '\0' && !endtoken (*cp); cp++)
4457 continue;
4458 namebuf = savenstr (dbp, cp-dbp);
4459 dbp = cp; /* set dbp to e-o-token */
4460 save_len = dbp - lb.buffer + 1;
4461 get_tagname = FALSE;
4462 found_tag = TRUE;
4463 continue;
4464
4465 /* and proceed to check for "extern" */
4466 }
4467 else if (!incomment && !inquote && !found_tag)
4468 {
4469 /* check for proc/fn keywords */
4470 switch (lowcase (c))
4471 {
4472 case 'p':
4473 if (nocase_tail ("rocedure")) /* c = 'p', dbp has advanced */
4474 get_tagname = TRUE;
4475 continue;
4476 case 'f':
4477 if (nocase_tail ("unction"))
4478 get_tagname = TRUE;
4479 continue;
4480 }
4481 }
4482 } /* while not eof */
4483
4484 free (tline.buffer);
4485 }
4486
4487 \f
4488 /*
4489 * Lisp tag functions
4490 * look for (def or (DEF, quote or QUOTE
4491 */
4492
4493 static void L_getit __P((void));
4494
4495 static void
4496 L_getit ()
4497 {
4498 if (*dbp == '\'') /* Skip prefix quote */
4499 dbp++;
4500 else if (*dbp == '(')
4501 {
4502 dbp++;
4503 /* Try to skip "(quote " */
4504 if (!LOOKING_AT (dbp, "quote") && !LOOKING_AT (dbp, "QUOTE"))
4505 /* Ok, then skip "(" before name in (defstruct (foo)) */
4506 dbp = skip_spaces (dbp);
4507 }
4508 get_tag (dbp);
4509 }
4510
4511 static void
4512 Lisp_functions (inf)
4513 FILE *inf;
4514 {
4515 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4516 {
4517 if (dbp[0] != '(')
4518 continue;
4519
4520 if (strneq (dbp+1, "def", 3) || strneq (dbp+1, "DEF", 3))
4521 {
4522 dbp = skip_non_spaces (dbp);
4523 dbp = skip_spaces (dbp);
4524 L_getit ();
4525 }
4526 else
4527 {
4528 /* Check for (foo::defmumble name-defined ... */
4529 do
4530 dbp++;
4531 while (!notinname (*dbp) && *dbp != ':');
4532 if (*dbp == ':')
4533 {
4534 do
4535 dbp++;
4536 while (*dbp == ':');
4537
4538 if (strneq (dbp, "def", 3) || strneq (dbp, "DEF", 3))
4539 {
4540 dbp = skip_non_spaces (dbp);
4541 dbp = skip_spaces (dbp);
4542 L_getit ();
4543 }
4544 }
4545 }
4546 }
4547 }
4548
4549 \f
4550 /*
4551 * Postscript tag functions
4552 * Just look for lines where the first character is '/'
4553 * Also look at "defineps" for PSWrap
4554 * Ideas by:
4555 * Richard Mlynarik <mly@adoc.xerox.com> (1997)
4556 * Masatake Yamato <masata-y@is.aist-nara.ac.jp> (1999)
4557 */
4558 static void
4559 Postscript_functions (inf)
4560 FILE *inf;
4561 {
4562 register char *bp, *ep;
4563
4564 LOOP_ON_INPUT_LINES (inf, lb, bp)
4565 {
4566 if (bp[0] == '/')
4567 {
4568 for (ep = bp+1;
4569 *ep != '\0' && *ep != ' ' && *ep != '{';
4570 ep++)
4571 continue;
4572 pfnote (savenstr (bp, ep-bp), TRUE,
4573 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
4574 }
4575 else if (LOOKING_AT (bp, "defineps"))
4576 get_tag (bp);
4577 }
4578 }
4579
4580 \f
4581 /*
4582 * Scheme tag functions
4583 * look for (def... xyzzy
4584 * (def... (xyzzy
4585 * (def ... ((...(xyzzy ....
4586 * (set! xyzzy
4587 * Original code by Ken Haase (1985?)
4588 */
4589
4590 static void
4591 Scheme_functions (inf)
4592 FILE *inf;
4593 {
4594 register char *bp;
4595
4596 LOOP_ON_INPUT_LINES (inf, lb, bp)
4597 {
4598 if (strneq (bp, "(def", 4) || strneq (bp, "(DEF", 4))
4599 {
4600 bp = skip_non_spaces (bp+4);
4601 /* Skip over open parens and white space */
4602 while (notinname (*bp))
4603 bp++;
4604 get_tag (bp);
4605 }
4606 if (LOOKING_AT (bp, "(SET!") || LOOKING_AT (bp, "(set!"))
4607 get_tag (bp);
4608 }
4609 }
4610
4611 \f
4612 /* Find tags in TeX and LaTeX input files. */
4613
4614 /* TEX_toktab is a table of TeX control sequences that define tags.
4615 Each TEX_tabent records one such control sequence.
4616 CONVERT THIS TO USE THE Stab TYPE!! */
4617 struct TEX_tabent
4618 {
4619 char *name;
4620 int len;
4621 };
4622
4623 static struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
4624
4625 /* Default set of control sequences to put into TEX_toktab.
4626 The value of environment var TEXTAGS is prepended to this. */
4627
4628 static char *TEX_defenv = "\
4629 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4630 :part:appendix:entry:index";
4631
4632 static void TEX_mode __P((FILE *));
4633 static struct TEX_tabent *TEX_decode_env __P((char *, char *));
4634 static int TEX_Token __P((char *));
4635
4636 static char TEX_esc = '\\';
4637 static char TEX_opgrp = '{';
4638 static char TEX_clgrp = '}';
4639
4640 /*
4641 * TeX/LaTeX scanning loop.
4642 */
4643 static void
4644 TeX_commands (inf)
4645 FILE *inf;
4646 {
4647 char *cp, *lasthit;
4648 register int i;
4649
4650 /* Select either \ or ! as escape character. */
4651 TEX_mode (inf);
4652
4653 /* Initialize token table once from environment. */
4654 if (!TEX_toktab)
4655 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
4656
4657 LOOP_ON_INPUT_LINES (inf, lb, cp)
4658 {
4659 lasthit = cp;
4660 /* Look at each esc in line. */
4661 while ((cp = etags_strchr (cp, TEX_esc)) != NULL)
4662 {
4663 if (*++cp == '\0')
4664 break;
4665 linecharno += cp - lasthit;
4666 lasthit = cp;
4667 i = TEX_Token (lasthit);
4668 if (i >= 0)
4669 {
4670 register char *p;
4671 for (lasthit += TEX_toktab[i].len;
4672 *lasthit == TEX_esc || *lasthit == TEX_opgrp;
4673 lasthit++)
4674 continue;
4675 for (p = lasthit;
4676 !iswhite (*p) && *p != TEX_opgrp && *p != TEX_clgrp;
4677 p++)
4678 continue;
4679 pfnote (savenstr (lasthit, p-lasthit), TRUE,
4680 lb.buffer, lb.len, lineno, linecharno);
4681 break; /* We only tag a line once */
4682 }
4683 }
4684 }
4685 }
4686
4687 #define TEX_LESC '\\'
4688 #define TEX_SESC '!'
4689 #define TEX_cmt '%'
4690
4691 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4692 chars accordingly. */
4693 static void
4694 TEX_mode (inf)
4695 FILE *inf;
4696 {
4697 int c;
4698
4699 while ((c = getc (inf)) != EOF)
4700 {
4701 /* Skip to next line if we hit the TeX comment char. */
4702 if (c == TEX_cmt)
4703 while (c != '\n')
4704 c = getc (inf);
4705 else if (c == TEX_LESC || c == TEX_SESC )
4706 break;
4707 }
4708
4709 if (c == TEX_LESC)
4710 {
4711 TEX_esc = TEX_LESC;
4712 TEX_opgrp = '{';
4713 TEX_clgrp = '}';
4714 }
4715 else
4716 {
4717 TEX_esc = TEX_SESC;
4718 TEX_opgrp = '<';
4719 TEX_clgrp = '>';
4720 }
4721 /* If the input file is compressed, inf is a pipe, and rewind may fail.
4722 No attempt is made to correct the situation. */
4723 rewind (inf);
4724 }
4725
4726 /* Read environment and prepend it to the default string.
4727 Build token table. */
4728 static struct TEX_tabent *
4729 TEX_decode_env (evarname, defenv)
4730 char *evarname;
4731 char *defenv;
4732 {
4733 register char *env, *p;
4734
4735 struct TEX_tabent *tab;
4736 int size, i;
4737
4738 /* Append default string to environment. */
4739 env = getenv (evarname);
4740 if (!env)
4741 env = defenv;
4742 else
4743 {
4744 char *oldenv = env;
4745 env = concat (oldenv, defenv, "");
4746 }
4747
4748 /* Allocate a token table */
4749 for (size = 1, p = env; p;)
4750 if ((p = etags_strchr (p, ':')) && *++p != '\0')
4751 size++;
4752 /* Add 1 to leave room for null terminator. */
4753 tab = xnew (size + 1, struct TEX_tabent);
4754
4755 /* Unpack environment string into token table. Be careful about */
4756 /* zero-length strings (leading ':', "::" and trailing ':') */
4757 for (i = 0; *env;)
4758 {
4759 p = etags_strchr (env, ':');
4760 if (!p) /* End of environment string. */
4761 p = env + strlen (env);
4762 if (p - env > 0)
4763 { /* Only non-zero strings. */
4764 tab[i].name = savenstr (env, p - env);
4765 tab[i].len = strlen (tab[i].name);
4766 i++;
4767 }
4768 if (*p)
4769 env = p + 1;
4770 else
4771 {
4772 tab[i].name = NULL; /* Mark end of table. */
4773 tab[i].len = 0;
4774 break;
4775 }
4776 }
4777 return tab;
4778 }
4779
4780 /* If the text at CP matches one of the tag-defining TeX command names,
4781 return the pointer to the first occurrence of that command in TEX_toktab.
4782 Otherwise return -1.
4783 Keep the capital `T' in `token' for dumb truncating compilers
4784 (this distinguishes it from `TEX_toktab' */
4785 static int
4786 TEX_Token (cp)
4787 char *cp;
4788 {
4789 int i;
4790
4791 for (i = 0; TEX_toktab[i].len > 0; i++)
4792 if (strneq (TEX_toktab[i].name, cp, TEX_toktab[i].len))
4793 return i;
4794 return -1;
4795 }
4796
4797 \f
4798 /* Texinfo support. Dave Love, Mar. 2000. */
4799 static void
4800 Texinfo_nodes (inf)
4801 FILE * inf;
4802 {
4803 char *cp, *start;
4804 LOOP_ON_INPUT_LINES (inf, lb, cp)
4805 if (LOOKING_AT (cp, "@node"))
4806 {
4807 start = cp;
4808 while (*cp != '\0' && *cp != ',')
4809 cp++;
4810 pfnote (savenstr (start, cp - start), TRUE,
4811 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4812 }
4813 }
4814
4815 \f
4816 /*
4817 * Prolog support
4818 *
4819 * Assumes that the predicate or rule starts at column 0.
4820 * Only the first clause of a predicate or rule is added.
4821 * Original code by Sunichirou Sugou (1989)
4822 * Rewritten by Anders Lindgren (1996)
4823 */
4824 static int prolog_pr __P((char *, char *));
4825 static void prolog_skip_comment __P((linebuffer *, FILE *));
4826 static int prolog_atom __P((char *, int));
4827
4828 static void
4829 Prolog_functions (inf)
4830 FILE *inf;
4831 {
4832 char *cp, *last;
4833 int len;
4834 int allocated;
4835
4836 allocated = 0;
4837 len = 0;
4838 last = NULL;
4839
4840 LOOP_ON_INPUT_LINES (inf, lb, cp)
4841 {
4842 if (cp[0] == '\0') /* Empty line */
4843 continue;
4844 else if (iswhite (cp[0])) /* Not a predicate */
4845 continue;
4846 else if (cp[0] == '/' && cp[1] == '*') /* comment. */
4847 prolog_skip_comment (&lb, inf);
4848 else if ((len = prolog_pr (cp, last)) > 0)
4849 {
4850 /* Predicate or rule. Store the function name so that we
4851 only generate a tag for the first clause. */
4852 if (last == NULL)
4853 last = xnew(len + 1, char);
4854 else if (len + 1 > allocated)
4855 xrnew (last, len + 1, char);
4856 allocated = len + 1;
4857 strncpy (last, cp, len);
4858 last[len] = '\0';
4859 }
4860 }
4861 }
4862
4863
4864 static void
4865 prolog_skip_comment (plb, inf)
4866 linebuffer *plb;
4867 FILE *inf;
4868 {
4869 char *cp;
4870
4871 do
4872 {
4873 for (cp = plb->buffer; *cp != '\0'; cp++)
4874 if (cp[0] == '*' && cp[1] == '/')
4875 return;
4876 lineno++;
4877 linecharno += readline (plb, inf);
4878 }
4879 while (!feof(inf));
4880 }
4881
4882 /*
4883 * A predicate or rule definition is added if it matches:
4884 * <beginning of line><Prolog Atom><whitespace>(
4885 * or <beginning of line><Prolog Atom><whitespace>:-
4886 *
4887 * It is added to the tags database if it doesn't match the
4888 * name of the previous clause header.
4889 *
4890 * Return the size of the name of the predicate or rule, or 0 if no
4891 * header was found.
4892 */
4893 static int
4894 prolog_pr (s, last)
4895 char *s;
4896 char *last; /* Name of last clause. */
4897 {
4898 int pos;
4899 int len;
4900
4901 pos = prolog_atom (s, 0);
4902 if (pos < 1)
4903 return 0;
4904
4905 len = pos;
4906 pos = skip_spaces (s + pos) - s;
4907
4908 if ((s[pos] == '.'
4909 || (s[pos] == '(' && (pos += 1))
4910 || (s[pos] == ':' && s[pos + 1] == '-' && (pos += 2)))
4911 && (last == NULL /* save only the first clause */
4912 || len != strlen (last)
4913 || !strneq (s, last, len)))
4914 {
4915 pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno);
4916 return len;
4917 }
4918 else
4919 return 0;
4920 }
4921
4922 /*
4923 * Consume a Prolog atom.
4924 * Return the number of bytes consumed, or -1 if there was an error.
4925 *
4926 * A prolog atom, in this context, could be one of:
4927 * - An alphanumeric sequence, starting with a lower case letter.
4928 * - A quoted arbitrary string. Single quotes can escape themselves.
4929 * Backslash quotes everything.
4930 */
4931 static int
4932 prolog_atom (s, pos)
4933 char *s;
4934 int pos;
4935 {
4936 int origpos;
4937
4938 origpos = pos;
4939
4940 if (ISLOWER(s[pos]) || (s[pos] == '_'))
4941 {
4942 /* The atom is unquoted. */
4943 pos++;
4944 while (ISALNUM(s[pos]) || (s[pos] == '_'))
4945 {
4946 pos++;
4947 }
4948 return pos - origpos;
4949 }
4950 else if (s[pos] == '\'')
4951 {
4952 pos++;
4953
4954 while (1)
4955 {
4956 if (s[pos] == '\'')
4957 {
4958 pos++;
4959 if (s[pos] != '\'')
4960 break;
4961 pos++; /* A double quote */
4962 }
4963 else if (s[pos] == '\0')
4964 /* Multiline quoted atoms are ignored. */
4965 return -1;
4966 else if (s[pos] == '\\')
4967 {
4968 if (s[pos+1] == '\0')
4969 return -1;
4970 pos += 2;
4971 }
4972 else
4973 pos++;
4974 }
4975 return pos - origpos;
4976 }
4977 else
4978 return -1;
4979 }
4980
4981 \f
4982 /*
4983 * Support for Erlang
4984 *
4985 * Generates tags for functions, defines, and records.
4986 * Assumes that Erlang functions start at column 0.
4987 * Original code by Anders Lindgren (1996)
4988 */
4989 static int erlang_func __P((char *, char *));
4990 static void erlang_attribute __P((char *));
4991 static int erlang_atom __P((char *, int));
4992
4993 static void
4994 Erlang_functions (inf)
4995 FILE *inf;
4996 {
4997 char *cp, *last;
4998 int len;
4999 int allocated;
5000
5001 allocated = 0;
5002 len = 0;
5003 last = NULL;
5004
5005 LOOP_ON_INPUT_LINES (inf, lb, cp)
5006 {
5007 if (cp[0] == '\0') /* Empty line */
5008 continue;
5009 else if (iswhite (cp[0])) /* Not function nor attribute */
5010 continue;
5011 else if (cp[0] == '%') /* comment */
5012 continue;
5013 else if (cp[0] == '"') /* Sometimes, strings start in column one */
5014 continue;
5015 else if (cp[0] == '-') /* attribute, e.g. "-define" */
5016 {
5017 erlang_attribute (cp);
5018 last = NULL;
5019 }
5020 else if ((len = erlang_func (cp, last)) > 0)
5021 {
5022 /*
5023 * Function. Store the function name so that we only
5024 * generates a tag for the first clause.
5025 */
5026 if (last == NULL)
5027 last = xnew (len + 1, char);
5028 else if (len + 1 > allocated)
5029 xrnew (last, len + 1, char);
5030 allocated = len + 1;
5031 strncpy (last, cp, len);
5032 last[len] = '\0';
5033 }
5034 }
5035 }
5036
5037
5038 /*
5039 * A function definition is added if it matches:
5040 * <beginning of line><Erlang Atom><whitespace>(
5041 *
5042 * It is added to the tags database if it doesn't match the
5043 * name of the previous clause header.
5044 *
5045 * Return the size of the name of the function, or 0 if no function
5046 * was found.
5047 */
5048 static int
5049 erlang_func (s, last)
5050 char *s;
5051 char *last; /* Name of last clause. */
5052 {
5053 int pos;
5054 int len;
5055
5056 pos = erlang_atom (s, 0);
5057 if (pos < 1)
5058 return 0;
5059
5060 len = pos;
5061 pos = skip_spaces (s + pos) - s;
5062
5063 /* Save only the first clause. */
5064 if (s[pos++] == '('
5065 && (last == NULL
5066 || len != (int)strlen (last)
5067 || !strneq (s, last, len)))
5068 {
5069 pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno);
5070 return len;
5071 }
5072
5073 return 0;
5074 }
5075
5076
5077 /*
5078 * Handle attributes. Currently, tags are generated for defines
5079 * and records.
5080 *
5081 * They are on the form:
5082 * -define(foo, bar).
5083 * -define(Foo(M, N), M+N).
5084 * -record(graph, {vtab = notable, cyclic = true}).
5085 */
5086 static void
5087 erlang_attribute (s)
5088 char *s;
5089 {
5090 int pos;
5091 int len;
5092
5093 if (LOOKING_AT (s, "-define") || LOOKING_AT (s, "-record"))
5094 {
5095 if (s[pos++] == '(')
5096 {
5097 pos = skip_spaces (s + pos) - s;
5098 len = erlang_atom (s, pos);
5099 if (len != 0)
5100 pfnote (savenstr (& s[pos], len), TRUE,
5101 s, pos + len, lineno, linecharno);
5102 }
5103 }
5104 return;
5105 }
5106
5107
5108 /*
5109 * Consume an Erlang atom (or variable).
5110 * Return the number of bytes consumed, or -1 if there was an error.
5111 */
5112 static int
5113 erlang_atom (s, pos)
5114 char *s;
5115 int pos;
5116 {
5117 int origpos;
5118
5119 origpos = pos;
5120
5121 if (ISALPHA (s[pos]) || s[pos] == '_')
5122 {
5123 /* The atom is unquoted. */
5124 pos++;
5125 while (ISALNUM (s[pos]) || s[pos] == '_')
5126 pos++;
5127 return pos - origpos;
5128 }
5129 else if (s[pos] == '\'')
5130 {
5131 pos++;
5132
5133 while (1)
5134 {
5135 if (s[pos] == '\'')
5136 {
5137 pos++;
5138 break;
5139 }
5140 else if (s[pos] == '\0')
5141 /* Multiline quoted atoms are ignored. */
5142 return -1;
5143 else if (s[pos] == '\\')
5144 {
5145 if (s[pos+1] == '\0')
5146 return -1;
5147 pos += 2;
5148 }
5149 else
5150 pos++;
5151 }
5152 return pos - origpos;
5153 }
5154 else
5155 return -1;
5156 }
5157
5158 \f
5159 #ifdef ETAGS_REGEXPS
5160
5161 static char *scan_separators __P((char *));
5162 static void analyse_regex __P((char *, bool));
5163 static void add_regex __P((char *, bool, language *));
5164 static char *substitute __P((char *, char *, struct re_registers *));
5165
5166 /* Take a string like "/blah/" and turn it into "blah", making sure
5167 that the first and last characters are the same, and handling
5168 quoted separator characters. Actually, stops on the occurrence of
5169 an unquoted separator. Also turns "\t" into a Tab character.
5170 Returns pointer to terminating separator. Works in place. Null
5171 terminates name string. */
5172 static char *
5173 scan_separators (name)
5174 char *name;
5175 {
5176 char sep = name[0];
5177 char *copyto = name;
5178 bool quoted = FALSE;
5179
5180 for (++name; *name != '\0'; ++name)
5181 {
5182 if (quoted)
5183 {
5184 if (*name == 't')
5185 *copyto++ = '\t';
5186 else if (*name == sep)
5187 *copyto++ = sep;
5188 else
5189 {
5190 /* Something else is quoted, so preserve the quote. */
5191 *copyto++ = '\\';
5192 *copyto++ = *name;
5193 }
5194 quoted = FALSE;
5195 }
5196 else if (*name == '\\')
5197 quoted = TRUE;
5198 else if (*name == sep)
5199 break;
5200 else
5201 *copyto++ = *name;
5202 }
5203
5204 /* Terminate copied string. */
5205 *copyto = '\0';
5206 return name;
5207 }
5208
5209 /* Look at the argument of --regex or --no-regex and do the right
5210 thing. Same for each line of a regexp file. */
5211 static void
5212 analyse_regex (regex_arg, ignore_case)
5213 char *regex_arg;
5214 bool ignore_case;
5215 {
5216 if (regex_arg == NULL)
5217 {
5218 free_patterns (); /* --no-regex: remove existing regexps */
5219 return;
5220 }
5221
5222 /* A real --regexp option or a line in a regexp file. */
5223 switch (regex_arg[0])
5224 {
5225 /* Comments in regexp file or null arg to --regex. */
5226 case '\0':
5227 case ' ':
5228 case '\t':
5229 break;
5230
5231 /* Read a regex file. This is recursive and may result in a
5232 loop, which will stop when the file descriptors are exhausted. */
5233 case '@':
5234 {
5235 FILE *regexfp;
5236 linebuffer regexbuf;
5237 char *regexfile = regex_arg + 1;
5238
5239 /* regexfile is a file containing regexps, one per line. */
5240 regexfp = fopen (regexfile, "r");
5241 if (regexfp == NULL)
5242 {
5243 pfatal (regexfile);
5244 return;
5245 }
5246 initbuffer (&regexbuf);
5247 while (readline_internal (&regexbuf, regexfp) > 0)
5248 analyse_regex (regexbuf.buffer, ignore_case);
5249 free (regexbuf.buffer);
5250 fclose (regexfp);
5251 }
5252 break;
5253
5254 /* Regexp to be used for a specific language only. */
5255 case '{':
5256 {
5257 language *lang;
5258 char *lang_name = regex_arg + 1;
5259 char *cp;
5260
5261 for (cp = lang_name; *cp != '}'; cp++)
5262 if (*cp == '\0')
5263 {
5264 error ("unterminated language name in regex: %s", regex_arg);
5265 return;
5266 }
5267 *cp = '\0';
5268 lang = get_language_from_langname (lang_name);
5269 if (lang == NULL)
5270 return;
5271 add_regex (cp + 1, ignore_case, lang);
5272 }
5273 break;
5274
5275 /* Regexp to be used for any language. */
5276 default:
5277 add_regex (regex_arg, ignore_case, NULL);
5278 break;
5279 }
5280 }
5281
5282 /* Turn a name, which is an ed-style (but Emacs syntax) regular
5283 expression, into a real regular expression by compiling it. */
5284 static void
5285 add_regex (regexp_pattern, ignore_case, lang)
5286 char *regexp_pattern;
5287 bool ignore_case;
5288 language *lang;
5289 {
5290 static struct re_pattern_buffer zeropattern;
5291 char *name;
5292 const char *err;
5293 struct re_pattern_buffer *patbuf;
5294 pattern *pp;
5295
5296
5297 if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0])
5298 {
5299 error ("%s: unterminated regexp", regexp_pattern);
5300 return;
5301 }
5302 name = scan_separators (regexp_pattern);
5303 if (regexp_pattern[0] == '\0')
5304 {
5305 error ("null regexp", (char *)NULL);
5306 return;
5307 }
5308 (void) scan_separators (name);
5309
5310 patbuf = xnew (1, struct re_pattern_buffer);
5311 *patbuf = zeropattern;
5312 if (ignore_case)
5313 patbuf->translate = lc_trans; /* translation table to fold case */
5314
5315 err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf);
5316 if (err != NULL)
5317 {
5318 error ("%s while compiling pattern", err);
5319 return;
5320 }
5321
5322 pp = p_head;
5323 p_head = xnew (1, pattern);
5324 p_head->regex = savestr (regexp_pattern);
5325 p_head->p_next = pp;
5326 p_head->lang = lang;
5327 p_head->pat = patbuf;
5328 p_head->name_pattern = savestr (name);
5329 p_head->error_signaled = FALSE;
5330 p_head->ignore_case = ignore_case;
5331 }
5332
5333 /*
5334 * Do the substitutions indicated by the regular expression and
5335 * arguments.
5336 */
5337 static char *
5338 substitute (in, out, regs)
5339 char *in, *out;
5340 struct re_registers *regs;
5341 {
5342 char *result, *t;
5343 int size, dig, diglen;
5344
5345 result = NULL;
5346 size = strlen (out);
5347
5348 /* Pass 1: figure out how much to allocate by finding all \N strings. */
5349 if (out[size - 1] == '\\')
5350 fatal ("pattern error in \"%s\"", out);
5351 for (t = etags_strchr (out, '\\');
5352 t != NULL;
5353 t = etags_strchr (t + 2, '\\'))
5354 if (ISDIGIT (t[1]))
5355 {
5356 dig = t[1] - '0';
5357 diglen = regs->end[dig] - regs->start[dig];
5358 size += diglen - 2;
5359 }
5360 else
5361 size -= 1;
5362
5363 /* Allocate space and do the substitutions. */
5364 result = xnew (size + 1, char);
5365
5366 for (t = result; *out != '\0'; out++)
5367 if (*out == '\\' && ISDIGIT (*++out))
5368 {
5369 dig = *out - '0';
5370 diglen = regs->end[dig] - regs->start[dig];
5371 strncpy (t, in + regs->start[dig], diglen);
5372 t += diglen;
5373 }
5374 else
5375 *t++ = *out;
5376 *t = '\0';
5377
5378 assert (t <= result + size && t - result == (int)strlen (result));
5379
5380 return result;
5381 }
5382
5383 /* Deallocate all patterns. */
5384 static void
5385 free_patterns ()
5386 {
5387 pattern *pp;
5388 while (p_head != NULL)
5389 {
5390 pp = p_head->p_next;
5391 free (p_head->regex);
5392 free (p_head->name_pattern);
5393 free (p_head);
5394 p_head = pp;
5395 }
5396 return;
5397 }
5398 #endif /* ETAGS_REGEXPS */
5399
5400 \f
5401 static bool
5402 nocase_tail (cp)
5403 char *cp;
5404 {
5405 register int len = 0;
5406
5407 while (*cp != '\0' && lowcase (*cp) == lowcase (dbp[len]))
5408 cp++, len++;
5409 if (*cp == '\0' && !intoken (dbp[len]))
5410 {
5411 dbp += len;
5412 return TRUE;
5413 }
5414 return FALSE;
5415 }
5416
5417 static char *
5418 get_tag (bp)
5419 register char *bp;
5420 {
5421 register char *cp, *name;
5422
5423 if (*bp == '\0')
5424 return NULL;
5425 /* Go till you get to white space or a syntactic break */
5426 for (cp = bp + 1; !notinname (*cp); cp++)
5427 continue;
5428 name = savenstr (bp, cp-bp);
5429 pfnote (name, TRUE,
5430 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
5431 return name;
5432 }
5433
5434 /* Initialize a linebuffer for use */
5435 static void
5436 initbuffer (lbp)
5437 linebuffer *lbp;
5438 {
5439 lbp->size = (DEBUG) ? 3 : 200;
5440 lbp->buffer = xnew (lbp->size, char);
5441 lbp->buffer[0] = '\0';
5442 lbp->len = 0;
5443 }
5444
5445 /*
5446 * Read a line of text from `stream' into `lbp', excluding the
5447 * newline or CR-NL, if any. Return the number of characters read from
5448 * `stream', which is the length of the line including the newline.
5449 *
5450 * On DOS or Windows we do not count the CR character, if any, before the
5451 * NL, in the returned length; this mirrors the behavior of emacs on those
5452 * platforms (for text files, it translates CR-NL to NL as it reads in the
5453 * file).
5454 */
5455 static long
5456 readline_internal (lbp, stream)
5457 linebuffer *lbp;
5458 register FILE *stream;
5459 {
5460 char *buffer = lbp->buffer;
5461 register char *p = lbp->buffer;
5462 register char *pend;
5463 int chars_deleted;
5464
5465 pend = p + lbp->size; /* Separate to avoid 386/IX compiler bug. */
5466
5467 while (1)
5468 {
5469 register int c = getc (stream);
5470 if (p == pend)
5471 {
5472 /* We're at the end of linebuffer: expand it. */
5473 lbp->size *= 2;
5474 xrnew (buffer, lbp->size, char);
5475 p += buffer - lbp->buffer;
5476 pend = buffer + lbp->size;
5477 lbp->buffer = buffer;
5478 }
5479 if (c == EOF)
5480 {
5481 *p = '\0';
5482 chars_deleted = 0;
5483 break;
5484 }
5485 if (c == '\n')
5486 {
5487 if (p > buffer && p[-1] == '\r')
5488 {
5489 p -= 1;
5490 #ifdef DOS_NT
5491 /* Assume CRLF->LF translation will be performed by Emacs
5492 when loading this file, so CRs won't appear in the buffer.
5493 It would be cleaner to compensate within Emacs;
5494 however, Emacs does not know how many CRs were deleted
5495 before any given point in the file. */
5496 chars_deleted = 1;
5497 #else
5498 chars_deleted = 2;
5499 #endif
5500 }
5501 else
5502 {
5503 chars_deleted = 1;
5504 }
5505 *p = '\0';
5506 break;
5507 }
5508 *p++ = c;
5509 }
5510 lbp->len = p - buffer;
5511
5512 return lbp->len + chars_deleted;
5513 }
5514
5515 /*
5516 * Like readline_internal, above, but in addition try to match the
5517 * input line against relevant regular expressions.
5518 */
5519 static long
5520 readline (lbp, stream)
5521 linebuffer *lbp;
5522 FILE *stream;
5523 {
5524 /* Read new line. */
5525 long result = readline_internal (lbp, stream);
5526
5527 /* Honour #line directives. */
5528 if (!no_line_directive)
5529 {
5530 static bool discard_until_line_directive;
5531
5532 /* Check whether this is a #line directive. */
5533 if (result > 12 && strneq (lbp->buffer, "#line ", 6))
5534 {
5535 int start, lno;
5536
5537 if (DEBUG) start = 0; /* shut up the compiler */
5538 if (sscanf (lbp->buffer, "#line %d \"%n", &lno, &start) == 1)
5539 {
5540 char *endp = lbp->buffer + start;
5541
5542 assert (start > 0);
5543 while ((endp = etags_strchr (endp, '"')) != NULL
5544 && endp[-1] == '\\')
5545 endp++;
5546 if (endp != NULL)
5547 /* Ok, this is a real #line directive. Let's deal with it. */
5548 {
5549 char *taggedabsname; /* absolute name of original file */
5550 char *taggedfname; /* name of original file as given */
5551 char *name; /* temp var */
5552
5553 discard_until_line_directive = FALSE; /* found it */
5554 name = lbp->buffer + start;
5555 *endp = '\0';
5556 canonicalize_filename (name); /* for DOS */
5557 taggedabsname = absolute_filename (name, curfdp->infabsdir);
5558 if (filename_is_absolute (name)
5559 || filename_is_absolute (curfdp->infname))
5560 taggedfname = savestr (taggedabsname);
5561 else
5562 taggedfname = relative_filename (taggedabsname,tagfiledir);
5563
5564 if (streq (curfdp->taggedfname, taggedfname))
5565 /* The #line directive is only a line number change. We
5566 deal with this afterwards. */
5567 free (taggedfname);
5568 else
5569 /* The tags following this #line directive should be
5570 attributed to taggedfname. In order to do this, set
5571 curfdp accordingly. */
5572 {
5573 fdesc *fdp; /* file description pointer */
5574
5575 /* Go look for a file description already set up for the
5576 file indicated in the #line directive. If there is
5577 one, use it from now until the next #line
5578 directive. */
5579 for (fdp = fdhead; fdp != NULL; fdp = fdp->next)
5580 if (streq (fdp->infname, curfdp->infname)
5581 && streq (fdp->taggedfname, taggedfname))
5582 /* If we remove the second test above (after the &&)
5583 then all entries pertaining to the same file are
5584 coalesced in the tags file. If we use it, then
5585 entries pertaining to the same file but generated
5586 from different files (via #line directives) will
5587 go into separate sections in the tags file. These
5588 alternatives look equivalent. The first one
5589 destroys some apparently useless information. */
5590 {
5591 curfdp = fdp;
5592 free (taggedfname);
5593 break;
5594 }
5595 /* Else, if we already tagged the real file, skip all
5596 input lines until the next #line directive. */
5597 if (fdp == NULL) /* not found */
5598 for (fdp = fdhead; fdp != NULL; fdp = fdp->next)
5599 if (streq (fdp->infabsname, taggedabsname))
5600 {
5601 discard_until_line_directive = TRUE;
5602 free (taggedfname);
5603 break;
5604 }
5605 /* Else create a new file description and use that from
5606 now on, until the next #line directive. */
5607 if (fdp == NULL) /* not found */
5608 {
5609 fdp = fdhead;
5610 fdhead = xnew (1, fdesc);
5611 *fdhead = *curfdp; /* copy curr. file description */
5612 fdhead->next = fdp;
5613 fdhead->infname = savestr (curfdp->infname);
5614 fdhead->infabsname = savestr (curfdp->infabsname);
5615 fdhead->infabsdir = savestr (curfdp->infabsdir);
5616 fdhead->taggedfname = taggedfname;
5617 fdhead->usecharno = FALSE;
5618 curfdp = fdhead;
5619 }
5620 }
5621 free (taggedabsname);
5622 lineno = lno;
5623 return readline (lbp, stream);
5624 } /* if a real #line directive */
5625 } /* if #line is followed by a a number */
5626 } /* if line begins with "#line " */
5627
5628 /* If we are here, no #line directive was found. */
5629 if (discard_until_line_directive)
5630 {
5631 if (result > 0)
5632 /* Do a tail recursion on ourselves, thus discarding the contents
5633 of the line buffer. */
5634 return readline (lbp, stream);
5635 /* End of file. */
5636 discard_until_line_directive = FALSE;
5637 return 0;
5638 }
5639 } /* if #line directives should be considered */
5640
5641 #ifdef ETAGS_REGEXPS
5642 {
5643 int match;
5644 pattern *pp;
5645
5646 /* Match against relevant patterns. */
5647 if (lbp->len > 0)
5648 for (pp = p_head; pp != NULL; pp = pp->p_next)
5649 {
5650 /* Only use generic regexps or those for the current language. */
5651 if (pp->lang != NULL && pp->lang != fdhead->lang)
5652 continue;
5653
5654 match = re_match (pp->pat, lbp->buffer, lbp->len, 0, &pp->regs);
5655 switch (match)
5656 {
5657 case -2:
5658 /* Some error. */
5659 if (!pp->error_signaled)
5660 {
5661 error ("error while matching \"%s\"", pp->regex);
5662 pp->error_signaled = TRUE;
5663 }
5664 break;
5665 case -1:
5666 /* No match. */
5667 break;
5668 default:
5669 /* Match occurred. Construct a tag. */
5670 if (pp->name_pattern[0] != '\0')
5671 {
5672 /* Make a named tag. */
5673 char *name = substitute (lbp->buffer,
5674 pp->name_pattern, &pp->regs);
5675 if (name != NULL)
5676 pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);
5677 }
5678 else
5679 {
5680 /* Make an unnamed tag. */
5681 pfnote ((char *)NULL, TRUE,
5682 lbp->buffer, match, lineno, linecharno);
5683 }
5684 break;
5685 }
5686 }
5687 }
5688 #endif /* ETAGS_REGEXPS */
5689
5690 return result;
5691 }
5692
5693 \f
5694 /*
5695 * Return a pointer to a space of size strlen(cp)+1 allocated
5696 * with xnew where the string CP has been copied.
5697 */
5698 static char *
5699 savestr (cp)
5700 char *cp;
5701 {
5702 return savenstr (cp, strlen (cp));
5703 }
5704
5705 /*
5706 * Return a pointer to a space of size LEN+1 allocated with xnew where
5707 * the string CP has been copied for at most the first LEN characters.
5708 */
5709 static char *
5710 savenstr (cp, len)
5711 char *cp;
5712 int len;
5713 {
5714 register char *dp;
5715
5716 dp = xnew (len + 1, char);
5717 strncpy (dp, cp, len);
5718 dp[len] = '\0';
5719 return dp;
5720 }
5721
5722 /*
5723 * Return the ptr in sp at which the character c last
5724 * appears; NULL if not found
5725 *
5726 * Identical to POSIX strrchr, included for portability.
5727 */
5728 static char *
5729 etags_strrchr (sp, c)
5730 register const char *sp;
5731 register int c;
5732 {
5733 register const char *r;
5734
5735 r = NULL;
5736 do
5737 {
5738 if (*sp == c)
5739 r = sp;
5740 } while (*sp++);
5741 return (char *)r;
5742 }
5743
5744
5745 /*
5746 * Return the ptr in sp at which the character c first
5747 * appears; NULL if not found
5748 *
5749 * Identical to POSIX strchr, included for portability.
5750 */
5751 static char *
5752 etags_strchr (sp, c)
5753 register const char *sp;
5754 register int c;
5755 {
5756 do
5757 {
5758 if (*sp == c)
5759 return (char *)sp;
5760 } while (*sp++);
5761 return NULL;
5762 }
5763
5764 /* Skip spaces, return new pointer. */
5765 static char *
5766 skip_spaces (cp)
5767 char *cp;
5768 {
5769 while (iswhite (*cp))
5770 cp++;
5771 return cp;
5772 }
5773
5774 /* Skip non spaces, return new pointer. */
5775 static char *
5776 skip_non_spaces (cp)
5777 char *cp;
5778 {
5779 while (*cp != '\0' && !iswhite (*cp))
5780 cp++;
5781 return cp;
5782 }
5783
5784 /* Print error message and exit. */
5785 void
5786 fatal (s1, s2)
5787 char *s1, *s2;
5788 {
5789 error (s1, s2);
5790 exit (BAD);
5791 }
5792
5793 static void
5794 pfatal (s1)
5795 char *s1;
5796 {
5797 perror (s1);
5798 exit (BAD);
5799 }
5800
5801 static void
5802 suggest_asking_for_help ()
5803 {
5804 fprintf (stderr, "\tTry `%s %s' for a complete list of options.\n",
5805 progname,
5806 #ifdef LONG_OPTIONS
5807 "--help"
5808 #else
5809 "-h"
5810 #endif
5811 );
5812 exit (BAD);
5813 }
5814
5815 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
5816 static void
5817 error (s1, s2)
5818 const char *s1, *s2;
5819 {
5820 fprintf (stderr, "%s: ", progname);
5821 fprintf (stderr, s1, s2);
5822 fprintf (stderr, "\n");
5823 }
5824
5825 /* Return a newly-allocated string whose contents
5826 concatenate those of s1, s2, s3. */
5827 static char *
5828 concat (s1, s2, s3)
5829 char *s1, *s2, *s3;
5830 {
5831 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
5832 char *result = xnew (len1 + len2 + len3 + 1, char);
5833
5834 strcpy (result, s1);
5835 strcpy (result + len1, s2);
5836 strcpy (result + len1 + len2, s3);
5837 result[len1 + len2 + len3] = '\0';
5838
5839 return result;
5840 }
5841
5842 \f
5843 /* Does the same work as the system V getcwd, but does not need to
5844 guess the buffer size in advance. */
5845 static char *
5846 etags_getcwd ()
5847 {
5848 #ifdef HAVE_GETCWD
5849 int bufsize = 200;
5850 char *path = xnew (bufsize, char);
5851
5852 while (getcwd (path, bufsize) == NULL)
5853 {
5854 if (errno != ERANGE)
5855 pfatal ("getcwd");
5856 bufsize *= 2;
5857 free (path);
5858 path = xnew (bufsize, char);
5859 }
5860
5861 canonicalize_filename (path);
5862 return path;
5863
5864 #else /* not HAVE_GETCWD */
5865 #if MSDOS
5866
5867 char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */
5868
5869 getwd (path);
5870
5871 for (p = path; *p != '\0'; p++)
5872 if (*p == '\\')
5873 *p = '/';
5874 else
5875 *p = lowcase (*p);
5876
5877 return strdup (path);
5878 #else /* not MSDOS */
5879 linebuffer path;
5880 FILE *pipe;
5881
5882 initbuffer (&path);
5883 pipe = (FILE *) popen ("pwd 2>/dev/null", "r");
5884 if (pipe == NULL || readline_internal (&path, pipe) == 0)
5885 pfatal ("pwd");
5886 pclose (pipe);
5887
5888 return path.buffer;
5889 #endif /* not MSDOS */
5890 #endif /* not HAVE_GETCWD */
5891 }
5892
5893 /* Return a newly allocated string containing the file name of FILE
5894 relative to the absolute directory DIR (which should end with a slash). */
5895 static char *
5896 relative_filename (file, dir)
5897 char *file, *dir;
5898 {
5899 char *fp, *dp, *afn, *res;
5900 int i;
5901
5902 /* Find the common root of file and dir (with a trailing slash). */
5903 afn = absolute_filename (file, cwd);
5904 fp = afn;
5905 dp = dir;
5906 while (*fp++ == *dp++)
5907 continue;
5908 fp--, dp--; /* back to the first differing char */
5909 #ifdef DOS_NT
5910 if (fp == afn && afn[0] != '/') /* cannot build a relative name */
5911 return afn;
5912 #endif
5913 do /* look at the equal chars until '/' */
5914 fp--, dp--;
5915 while (*fp != '/');
5916
5917 /* Build a sequence of "../" strings for the resulting relative file name. */
5918 i = 0;
5919 while ((dp = etags_strchr (dp + 1, '/')) != NULL)
5920 i += 1;
5921 res = xnew (3*i + strlen (fp + 1) + 1, char);
5922 res[0] = '\0';
5923 while (i-- > 0)
5924 strcat (res, "../");
5925
5926 /* Add the file name relative to the common root of file and dir. */
5927 strcat (res, fp + 1);
5928 free (afn);
5929
5930 return res;
5931 }
5932
5933 /* Return a newly allocated string containing the absolute file name
5934 of FILE given DIR (which should end with a slash). */
5935 static char *
5936 absolute_filename (file, dir)
5937 char *file, *dir;
5938 {
5939 char *slashp, *cp, *res;
5940
5941 if (filename_is_absolute (file))
5942 res = savestr (file);
5943 #ifdef DOS_NT
5944 /* We don't support non-absolute file names with a drive
5945 letter, like `d:NAME' (it's too much hassle). */
5946 else if (file[1] == ':')
5947 fatal ("%s: relative file names with drive letters not supported", file);
5948 #endif
5949 else
5950 res = concat (dir, file, "");
5951
5952 /* Delete the "/dirname/.." and "/." substrings. */
5953 slashp = etags_strchr (res, '/');
5954 while (slashp != NULL && slashp[0] != '\0')
5955 {
5956 if (slashp[1] == '.')
5957 {
5958 if (slashp[2] == '.'
5959 && (slashp[3] == '/' || slashp[3] == '\0'))
5960 {
5961 cp = slashp;
5962 do
5963 cp--;
5964 while (cp >= res && !filename_is_absolute (cp));
5965 if (cp < res)
5966 cp = slashp; /* the absolute name begins with "/.." */
5967 #ifdef DOS_NT
5968 /* Under MSDOS and NT we get `d:/NAME' as absolute
5969 file name, so the luser could say `d:/../NAME'.
5970 We silently treat this as `d:/NAME'. */
5971 else if (cp[0] != '/')
5972 cp = slashp;
5973 #endif
5974 strcpy (cp, slashp + 3);
5975 slashp = cp;
5976 continue;
5977 }
5978 else if (slashp[2] == '/' || slashp[2] == '\0')
5979 {
5980 strcpy (slashp, slashp + 2);
5981 continue;
5982 }
5983 }
5984
5985 slashp = etags_strchr (slashp + 1, '/');
5986 }
5987
5988 if (res[0] == '\0')
5989 return savestr ("/");
5990 else
5991 return res;
5992 }
5993
5994 /* Return a newly allocated string containing the absolute
5995 file name of dir where FILE resides given DIR (which should
5996 end with a slash). */
5997 static char *
5998 absolute_dirname (file, dir)
5999 char *file, *dir;
6000 {
6001 char *slashp, *res;
6002 char save;
6003
6004 canonicalize_filename (file);
6005 slashp = etags_strrchr (file, '/');
6006 if (slashp == NULL)
6007 return savestr (dir);
6008 save = slashp[1];
6009 slashp[1] = '\0';
6010 res = absolute_filename (file, dir);
6011 slashp[1] = save;
6012
6013 return res;
6014 }
6015
6016 /* Whether the argument string is an absolute file name. The argument
6017 string must have been canonicalized with canonicalize_filename. */
6018 static bool
6019 filename_is_absolute (fn)
6020 char *fn;
6021 {
6022 return (fn[0] == '/'
6023 #ifdef DOS_NT
6024 || (ISALPHA(fn[0]) && fn[1] == ':' && fn[2] == '/')
6025 #endif
6026 );
6027 }
6028
6029 /* Translate backslashes into slashes. Works in place. */
6030 static void
6031 canonicalize_filename (fn)
6032 register char *fn;
6033 {
6034 #ifdef DOS_NT
6035 /* Canonicalize drive letter case. */
6036 if (fn[0] != '\0' && fn[1] == ':' && ISLOWER (fn[0]))
6037 fn[0] = upcase (fn[0]);
6038 /* Convert backslashes to slashes. */
6039 for (; *fn != '\0'; fn++)
6040 if (*fn == '\\')
6041 *fn = '/';
6042 #else
6043 /* No action. */
6044 fn = NULL; /* shut up the compiler */
6045 #endif
6046 }
6047
6048 /* Set the minimum size of a string contained in a linebuffer. */
6049 static void
6050 linebuffer_setlen (lbp, toksize)
6051 linebuffer *lbp;
6052 int toksize;
6053 {
6054 while (lbp->size <= toksize)
6055 {
6056 lbp->size *= 2;
6057 xrnew (lbp->buffer, lbp->size, char);
6058 }
6059 lbp->len = toksize;
6060 }
6061
6062 /* Like malloc but get fatal error if memory is exhausted. */
6063 static PTR
6064 xmalloc (size)
6065 unsigned int size;
6066 {
6067 PTR result = (PTR) malloc (size);
6068 if (result == NULL)
6069 fatal ("virtual memory exhausted", (char *)NULL);
6070 return result;
6071 }
6072
6073 static PTR
6074 xrealloc (ptr, size)
6075 char *ptr;
6076 unsigned int size;
6077 {
6078 PTR result = (PTR) realloc (ptr, size);
6079 if (result == NULL)
6080 fatal ("virtual memory exhausted", (char *)NULL);
6081 return result;
6082 }
6083
6084 /*
6085 * Local Variables:
6086 * c-indentation-style: gnu
6087 * indent-tabs-mode: t
6088 * tab-width: 8
6089 * fill-column: 79
6090 * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc")
6091 * End:
6092 */