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