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