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