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