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