(c-maybe-labelp): Add defvar.
[emacs.git] / lib-src / etags.c
bloba9e35d34139a964cfe09bb02ccaf0ebfcc414680
1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 87, 88, 89, 93, 94, 95
3 Free Software Foundation, Inc. and Ken Arnold
5 This file is not considered part of GNU Emacs.
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.
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.
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. */
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.
31 * Francesco Potorti` (F.Potorti@cnuce.cnr.it) is the current maintainer.
34 char pot_etags_version[] = "@(#) pot revision number is 12.11";
36 #define TRUE 1
37 #define FALSE 0
39 #ifndef DEBUG
40 # define DEBUG FALSE
41 #endif
43 #ifdef MSDOS
44 # include <string.h>
45 # include <fcntl.h>
46 # include <sys/param.h>
47 #endif /* MSDOS */
49 #ifdef WINDOWSNT
50 # include <stdlib.h>
51 # include <fcntl.h>
52 # include <string.h>
53 # include <io.h>
54 # define MAXPATHLEN _MAX_PATH
55 #endif
57 #ifdef HAVE_CONFIG_H
58 # include <config.h>
59 /* On some systems, Emacs defines static as nothing for the sake
60 of unexec. We don't want that here since we don't use unexec. */
61 # undef static
62 # define ETAGS_REGEXPS
63 # define LONG_OPTIONS
64 #endif
66 #if !defined (MSDOS) && !defined (WINDOWSNT) && defined (STDC_HEADERS)
67 #include <stdlib.h>
68 #include <string.h>
69 #endif
71 #include <stdio.h>
72 #include <ctype.h>
73 #include <errno.h>
74 #ifndef errno
75 extern int errno;
76 #endif
77 #include <sys/types.h>
78 #include <sys/stat.h>
80 #if !defined (S_ISREG) && defined (S_IFREG)
81 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
82 #endif
84 #ifdef LONG_OPTIONS
85 # include <getopt.h>
86 #else
87 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
88 extern char *optarg;
89 extern int optind, opterr;
90 #endif /* LONG_OPTIONS */
92 #ifdef ETAGS_REGEXPS
93 # include <regex.h>
94 #endif /* ETAGS_REGEXPS */
96 /* Define CTAGS to make the program "ctags" compatible with the usual one.
97 Leave it undefined to make the program "etags", which makes emacs-style
98 tag tables and tags typedefs, #defines and struct/union/enum by default. */
99 #ifdef CTAGS
100 # undef CTAGS
101 # define CTAGS TRUE
102 #else
103 # define CTAGS FALSE
104 #endif
106 /* Exit codes for success and failure. */
107 #ifdef VMS
108 # define GOOD 1
109 # define BAD 0
110 #else
111 # define GOOD 0
112 # define BAD 1
113 #endif
115 /* C extensions. */
116 #define C_PLPL 0x00001 /* C++ */
117 #define C_STAR 0x00003 /* C* */
118 #define C_JAVA 0x00005 /* JAVA */
119 #define YACC 0x10000 /* yacc file */
121 #define streq(s,t) ((DEBUG && (s) == NULL && (t) == NULL \
122 && (abort (), 1)) || !strcmp (s, t))
123 #define strneq(s,t,n) ((DEBUG && (s) == NULL && (t) == NULL \
124 && (abort (), 1)) || !strncmp (s, t, n))
126 #define lowcase(c) tolower ((char)c)
128 #define CHARS 256 /* 2^sizeof(char) */
129 #define CHAR(x) ((int)x & (CHARS - 1))
130 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */
131 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
132 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
133 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
134 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
136 #ifdef DOS_NT
137 # define absolutefn(fn) (fn[0] == '/' \
138 || (fn[1] == ':' && fn[2] == '/'))
139 #else
140 # define absolutefn(fn) (fn[0] == '/')
141 #endif
145 * xnew -- allocate storage
147 * SYNOPSIS: Type *xnew (int n, Type);
149 #ifdef chkmalloc
150 # include "chkmalloc.h"
151 # define xnew(n,Type) ((Type *) trace_xmalloc (__FILE__, __LINE__, \
152 (n) * sizeof (Type)))
153 #else
154 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
155 #endif
157 typedef int bool;
159 typedef struct nd_st
160 { /* sorting structure */
161 char *name; /* function or type name */
162 char *file; /* file name */
163 bool is_func; /* use pattern or line no */
164 bool been_warned; /* set if noticed dup */
165 int lno; /* line number tag is on */
166 long cno; /* character number line starts on */
167 char *pat; /* search pattern */
168 struct nd_st *left, *right; /* left and right sons */
169 } NODE;
171 extern char *getenv ();
173 char *concat ();
174 char *savenstr (), *savestr ();
175 char *etags_strchr (), *etags_strrchr ();
176 char *etags_getcwd ();
177 char *relative_filename (), *absolute_filename (), *absolute_dirname ();
178 void grow_linebuffer ();
179 long *xmalloc (), *xrealloc ();
181 typedef void Lang_function ();
182 /* Many compilers barf on this:
183 Lang_function Asm_labels;
184 so let's write it this way */
185 void Asm_labels ();
186 void C_entries ();
187 void default_C_entries ();
188 void plain_C_entries ();
189 void Cjava_entries ();
190 void Cobol_paragraphs ();
191 void Cplusplus_entries ();
192 void Cstar_entries ();
193 void Erlang_functions ();
194 void Fortran_functions ();
195 void Yacc_entries ();
196 void Lisp_functions ();
197 void Pascal_functions ();
198 void Perl_functions ();
199 void Postscript_functions ();
200 void Prolog_functions ();
201 void Scheme_functions ();
202 void TeX_functions ();
203 void just_read_file ();
205 Lang_function *get_language_from_name ();
206 Lang_function *get_language_from_interpreter ();
207 Lang_function *get_language_from_suffix ();
208 int total_size_of_entries ();
209 long readline ();
210 long readline_internal ();
211 #ifdef ETAGS_REGEXPS
212 void analyse_regex ();
213 void add_regex ();
214 #endif /* ETAGS_REGEXPS */
215 void add_node ();
216 void error ();
217 void suggest_asking_for_help ();
218 void fatal (), pfatal ();
219 void find_entries ();
220 void free_tree ();
221 void getit ();
222 void init ();
223 void initbuffer ();
224 void pfnote (), new_pfnote ();
225 void process_file ();
226 void put_entries ();
227 void takeprec ();
230 char searchar = '/'; /* use /.../ searches */
232 int lineno; /* line number of current line */
233 long charno; /* current character number */
234 long linecharno; /* charno of start of line */
236 char *curfile; /* current input file name */
237 char *tagfile; /* output file */
238 char *progname; /* name this program was invoked with */
239 char *cwd; /* current working directory */
240 char *tagfiledir; /* directory of tagfile */
242 FILE *tagf; /* ioptr for tags file */
243 NODE *head; /* the head of the binary tree of tags */
246 * A `struct linebuffer' is a structure which holds a line of text.
247 * `readline' reads a line from a stream into a linebuffer and works
248 * regardless of the length of the line.
249 * SIZE is the size of BUFFER, LEN is the length of the string in
250 * BUFFER after readline reads it.
252 struct linebuffer
254 long size;
255 int len;
256 char *buffer;
259 struct linebuffer lb; /* the current line */
260 struct linebuffer token_name; /* used by C_entries as a temporary area */
261 struct
263 long linepos;
264 struct linebuffer lb; /* used by C_entries instead of lb */
265 } lbs[2];
267 /* boolean "functions" (see init) */
268 bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
269 char
270 /* white chars */
271 *white = " \f\t\n\013",
272 /* not in a name */
273 *nonam =" \f\t\n\013(=,[;",
274 /* token ending chars */
275 *endtk = " \t\n\013\"'#()[]{}=-+%*/&|^~!<>;,.:?",
276 /* token starting chars */
277 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
278 /* valid in-token chars */
279 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
281 bool append_to_tagfile; /* -a: append to tags */
282 /* The following four default to TRUE for etags, but to FALSE for ctags. */
283 bool typedefs; /* -t: create tags for C typedefs */
284 bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */
285 /* 0 struct/enum/union decls, and C++ */
286 /* member functions. */
287 bool constantypedefs; /* -d: create tags for C #define, enum */
288 /* constants and variables. */
289 /* -D: opposite of -d. Default under ctags. */
290 bool globals; /* create tags for C global variables */
291 bool members; /* create tags for C member variables */
292 bool update; /* -u: update tags */
293 bool vgrind_style; /* -v: create vgrind style index output */
294 bool no_warnings; /* -w: suppress warnings */
295 bool cxref_style; /* -x: create cxref style output */
296 bool cplusplus; /* .[hc] means C++, not C */
297 bool noindentypedefs; /* -I: ignore indentation in C */
299 #ifdef LONG_OPTIONS
300 struct option longopts[] =
302 { "append", no_argument, NULL, 'a' },
303 { "backward-search", no_argument, NULL, 'B' },
304 { "c++", no_argument, NULL, 'C' },
305 { "cxref", no_argument, NULL, 'x' },
306 { "defines", no_argument, NULL, 'd' },
307 { "no-defines", no_argument, NULL, 'D' },
308 { "globals", no_argument, &globals, TRUE },
309 { "no-globals", no_argument, &globals, FALSE },
310 { "help", no_argument, NULL, 'h' },
311 { "help", no_argument, NULL, 'H' },
312 { "ignore-indentation", no_argument, NULL, 'I' },
313 { "include", required_argument, NULL, 'i' },
314 { "language", required_argument, NULL, 'l' },
315 { "members", no_argument, &members, TRUE },
316 { "no-members", no_argument, &members, FALSE },
317 { "no-warn", no_argument, NULL, 'w' },
318 { "output", required_argument, NULL, 'o' },
319 #ifdef ETAGS_REGEXPS
320 { "regex", required_argument, NULL, 'r' },
321 { "no-regex", no_argument, NULL, 'R' },
322 #endif /* ETAGS_REGEXPS */
323 { "typedefs", no_argument, NULL, 't' },
324 { "typedefs-and-c++", no_argument, NULL, 'T' },
325 { "update", no_argument, NULL, 'u' },
326 { "version", no_argument, NULL, 'V' },
327 { "vgrind", no_argument, NULL, 'v' },
328 { 0 }
330 #endif /* LONG_OPTIONS */
332 #ifdef ETAGS_REGEXPS
333 /* Structure defining a regular expression. Elements are
334 the compiled pattern, and the name string. */
335 struct pattern
337 struct re_pattern_buffer *pattern;
338 struct re_registers regs;
339 char *name_pattern;
340 bool error_signaled;
343 /* Number of regexps found. */
344 int num_patterns = 0;
346 /* Array of all regexps. */
347 struct pattern *patterns = NULL;
348 #endif /* ETAGS_REGEXPS */
351 * Language stuff.
354 /* Non-NULL if language fixed. */
355 Lang_function *lang_func = NULL;
357 /* Assembly code */
358 char *Asm_suffixes [] = { "a", /* Unix assembler */
359 "asm", /* Microcontroller assembly */
360 "def", /* BSO/Tasking definition includes */
361 "inc", /* Microcontroller include files */
362 "ins", /* Microcontroller include files */
363 "s", "sa", /* Unix assembler */
364 "src", /* BSO/Tasking C compiler output */
365 NULL
368 /* Note that .c and .h can be considered C++, if the --c++ flag was
369 given. That is why default_C_entries is called here. */
370 char *default_C_suffixes [] =
371 { "c", "h", NULL };
373 char *Cplusplus_suffixes [] =
374 { "C", "H", "c++", "cc", "cpp", "cxx", "h++", "hh", "hpp", "hxx",
375 "M", /* Objective C++ */
376 "pdb", /* Postscript with C syntax */
377 NULL };
379 char *Cjava_suffixes [] =
380 { "java", NULL };
382 char *Cobol_suffixes [] =
383 { "COB", "cob", NULL };
385 char *Cstar_suffixes [] =
386 { "cs", "hs", NULL };
388 char *Erlang_suffixes [] =
389 { "erl", "hrl", NULL };
391 char *Fortran_suffixes [] =
392 { "F", "f", "f90", "for", NULL };
394 char *Lisp_suffixes [] =
395 { "cl", "clisp", "el", "l", "lisp", "lsp", "ml", NULL };
397 char *Pascal_suffixes [] =
398 { "p", "pas", NULL };
400 char *Perl_suffixes [] =
401 { "pl", "pm", NULL };
402 char *Perl_interpreters [] =
403 { "perl", "@PERL@", NULL };
405 char *plain_C_suffixes [] =
406 { "pc", /* Pro*C file */
407 "m", /* Objective C file */
408 "lm", /* Objective lex file */
409 NULL };
411 char *Postscript_suffixes [] =
412 { "ps", NULL };
414 char *Prolog_suffixes [] =
415 { "prolog", NULL };
417 /* Can't do the `SCM' or `scm' prefix with a version number. */
418 char *Scheme_suffixes [] =
419 { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "t", NULL };
421 char *TeX_suffixes [] =
422 { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL };
424 char *Yacc_suffixes [] =
425 { "y", "ym", NULL }; /* .ym is Objective yacc file */
427 /* Table of language names and corresponding functions, file suffixes
428 and interpreter names.
429 It is ok for a given function to be listed under more than one
430 name. I just didn't. */
431 struct lang_entry
433 char *name;
434 Lang_function *function;
435 char **suffixes;
436 char **interpreters;
439 struct lang_entry lang_names [] =
441 { "asm", Asm_labels, Asm_suffixes, NULL },
442 { "c", default_C_entries, default_C_suffixes, NULL },
443 { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL },
444 { "c*", Cstar_entries, Cstar_suffixes, NULL },
445 { "cobol", Cobol_paragraphs, Cobol_suffixes, NULL },
446 { "erlang", Erlang_functions, Erlang_suffixes, NULL },
447 { "fortran", Fortran_functions, Fortran_suffixes, NULL },
448 { "java", Cjava_entries, Cjava_suffixes, NULL },
449 { "lisp", Lisp_functions, Lisp_suffixes, NULL },
450 { "pascal", Pascal_functions, Pascal_suffixes, NULL },
451 { "perl", Perl_functions, Perl_suffixes, Perl_interpreters },
452 { "postscript", Postscript_functions, Postscript_suffixes, NULL },
453 { "proc", plain_C_entries, plain_C_suffixes, NULL },
454 { "prolog", Prolog_functions, Prolog_suffixes, NULL },
455 { "scheme", Scheme_functions, Scheme_suffixes, NULL },
456 { "tex", TeX_functions, TeX_suffixes, NULL },
457 { "yacc", Yacc_entries, Yacc_suffixes, NULL },
458 { "auto", NULL }, /* default guessing scheme */
459 { "none", just_read_file }, /* regexp matching only */
460 { NULL, NULL } /* end of list */
464 void
465 print_language_names ()
467 struct lang_entry *lang;
468 char **ext;
470 puts ("\nThese are the currently supported languages, along with the\n\
471 default file name suffixes:");
472 for (lang = lang_names; lang->name != NULL; lang++)
474 printf ("\t%s\t", lang->name);
475 if (lang->suffixes != NULL)
476 for (ext = lang->suffixes; *ext != NULL; ext++)
477 printf (" .%s", *ext);
478 puts ("");
480 puts ("Where `auto' means use default language for files based on file\n\
481 name suffix, and `none' means only do regexp processing on files.\n\
482 If no language is specified and no matching suffix is found,\n\
483 the first line of the file is read for a sharp-bang (#!) sequence\n\
484 followed by the name of an interpreter. If no such sequence is found,\n\
485 Fortran is tried first; if no tags are found, C is tried next.");
488 #ifndef VERSION
489 # define VERSION "19"
490 #endif
491 void
492 print_version ()
494 printf ("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION);
495 puts ("Copyright (C) 1996 Free Software Foundation, Inc. and Ken Arnold");
496 puts ("This program is distributed under the same terms as Emacs");
498 exit (GOOD);
501 void
502 print_help ()
504 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
506 These are the options accepted by %s.\n", progname, progname);
507 #ifdef LONG_OPTIONS
508 puts ("You may use unambiguous abbreviations for the long option names.");
509 #else
510 puts ("Long option names do not work with this executable, as it is not\n\
511 linked with GNU getopt.");
512 #endif /* LONG_OPTIONS */
513 puts ("A - as file name means read names from stdin.");
514 if (!CTAGS)
515 printf (" Absolute names are stored in the output file as they\n\
516 are. Relative ones are stored relative to the output file's directory.");
517 puts ("\n");
519 puts ("-a, --append\n\
520 Append tag entries to existing tags file.");
522 if (CTAGS)
523 puts ("-B, --backward-search\n\
524 Write the search commands for the tag entries using '?', the\n\
525 backward-search command instead of '/', the forward-search command.");
527 puts ("-C, --c++\n\
528 Treat files whose name suffix defaults to C language as C++ files.");
530 if (CTAGS)
531 puts ("-d, --defines\n\
532 Create tag entries for C #define constants and enum constants, too.");
533 else
534 puts ("-D, --no-defines\n\
535 Don't create tag entries for C #define constants and enum constants.\n\
536 This makes the tags file smaller.");
538 if (!CTAGS)
540 puts ("-i FILE, --include=FILE\n\
541 Include a note in tag file indicating that, when searching for\n\
542 a tag, one should also consult the tags file FILE after\n\
543 checking the current file.");
544 puts ("-l LANG, --language=LANG\n\
545 Force the following files to be considered as written in the\n\
546 named language up to the next --language=LANG option.");
549 if (CTAGS)
550 puts ("--globals\n\
551 Create tag entries for global variables in C and derived languages.");
552 else
553 puts ("--no-globals\n\
554 Do not create tag entries for global variables in C and\n\
555 derived languages. This makes the tags file smaller.");
556 puts ("--members\n\
557 Create tag entries for member variables in C and derived languages.");
559 #ifdef ETAGS_REGEXPS
560 puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
561 Make a tag for each line matching pattern REGEXP in the\n\
562 following files. regexfile is a file containing one REGEXP\n\
563 per line. REGEXP is anchored (as if preceded by ^).\n\
564 The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
565 named tags can be created with:\n\
566 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
567 puts ("-R, --no-regex\n\
568 Don't create tags from regexps for the following files.");
569 #endif /* ETAGS_REGEXPS */
570 puts ("-o FILE, --output=FILE\n\
571 Write the tags to FILE.");
572 puts ("-I, --ignore-indentation\n\
573 Don't rely on indentation quite as much as normal. Currently,\n\
574 this means not to assume that a closing brace in the first\n\
575 column is the final brace of a function or structure\n\
576 definition in C and C++.");
578 if (CTAGS)
580 puts ("-t, --typedefs\n\
581 Generate tag entries for C typedefs.");
582 puts ("-T, --typedefs-and-c++\n\
583 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
584 and C++ member functions.");
585 puts ("-u, --update\n\
586 Update the tag entries for the given files, leaving tag\n\
587 entries for other files in place. Currently, this is\n\
588 implemented by deleting the existing entries for the given\n\
589 files and then rewriting the new entries at the end of the\n\
590 tags file. It is often faster to simply rebuild the entire\n\
591 tag file than to use this.");
592 puts ("-v, --vgrind\n\
593 Generates an index of items intended for human consumption,\n\
594 similar to the output of vgrind. The index is sorted, and\n\
595 gives the page number of each item.");
596 puts ("-w, --no-warn\n\
597 Suppress warning messages about entries defined in multiple\n\
598 files.");
599 puts ("-x, --cxref\n\
600 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
601 The output uses line numbers instead of page numbers, but\n\
602 beyond that the differences are cosmetic; try both to see\n\
603 which you like.");
606 puts ("-V, --version\n\
607 Print the version of the program.\n\
608 -h, --help\n\
609 Print this help message.");
611 print_language_names ();
613 puts ("");
614 puts ("Report bugs to bug-gnu-emacs@prep.ai.mit.edu");
616 exit (GOOD);
620 enum argument_type
622 at_language,
623 at_regexp,
624 at_filename
627 /* This structure helps us allow mixing of --lang and file names. */
628 typedef struct
630 enum argument_type arg_type;
631 char *what;
632 Lang_function *function;
633 } argument;
635 #ifdef VMS /* VMS specific functions */
637 #define EOS '\0'
639 /* This is a BUG! ANY arbitrary limit is a BUG!
640 Won't someone please fix this? */
641 #define MAX_FILE_SPEC_LEN 255
642 typedef struct {
643 short curlen;
644 char body[MAX_FILE_SPEC_LEN + 1];
645 } vspec;
648 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
649 returning in each successive call the next file name matching the input
650 spec. The function expects that each in_spec passed
651 to it will be processed to completion; in particular, up to and
652 including the call following that in which the last matching name
653 is returned, the function ignores the value of in_spec, and will
654 only start processing a new spec with the following call.
655 If an error occurs, on return out_spec contains the value
656 of in_spec when the error occurred.
658 With each successive file name returned in out_spec, the
659 function's return value is one. When there are no more matching
660 names the function returns zero. If on the first call no file
661 matches in_spec, or there is any other error, -1 is returned.
664 #include <rmsdef.h>
665 #include <descrip.h>
666 #define OUTSIZE MAX_FILE_SPEC_LEN
667 short
668 fn_exp (out, in)
669 vspec *out;
670 char *in;
672 static long context = 0;
673 static struct dsc$descriptor_s o;
674 static struct dsc$descriptor_s i;
675 static bool pass1 = TRUE;
676 long status;
677 short retval;
679 if (pass1)
681 pass1 = FALSE;
682 o.dsc$a_pointer = (char *) out;
683 o.dsc$w_length = (short)OUTSIZE;
684 i.dsc$a_pointer = in;
685 i.dsc$w_length = (short)strlen(in);
686 i.dsc$b_dtype = DSC$K_DTYPE_T;
687 i.dsc$b_class = DSC$K_CLASS_S;
688 o.dsc$b_dtype = DSC$K_DTYPE_VT;
689 o.dsc$b_class = DSC$K_CLASS_VS;
691 if ((status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL)
693 out->body[out->curlen] = EOS;
694 return 1;
696 else if (status == RMS$_NMF)
697 retval = 0;
698 else
700 strcpy(out->body, in);
701 retval = -1;
703 lib$find_file_end(&context);
704 pass1 = TRUE;
705 return retval;
709 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
710 name of each file specified by the provided arg expanding wildcards.
712 char *
713 gfnames (arg, p_error)
714 char *arg;
715 bool *p_error;
717 static vspec filename = {MAX_FILE_SPEC_LEN, "\0"};
719 switch (fn_exp (&filename, arg))
721 case 1:
722 *p_error = FALSE;
723 return filename.body;
724 case 0:
725 *p_error = FALSE;
726 return NULL;
727 default:
728 *p_error = TRUE;
729 return filename.body;
733 #ifndef OLD /* Newer versions of VMS do provide `system'. */
734 system (cmd)
735 char *cmd;
737 error ("%s", "system() function not implemented under VMS");
739 #endif
741 #define VERSION_DELIM ';'
742 char *massage_name (s)
743 char *s;
745 char *start = s;
747 for ( ; *s; s++)
748 if (*s == VERSION_DELIM)
750 *s = EOS;
751 break;
753 else
754 *s = lowcase (*s);
755 return start;
757 #endif /* VMS */
761 main (argc, argv)
762 int argc;
763 char *argv[];
765 int i;
766 unsigned int nincluded_files;
767 char **included_files;
768 char *this_file;
769 argument *argbuffer;
770 int current_arg, file_count;
771 struct linebuffer filename_lb;
772 #ifdef VMS
773 bool got_err;
774 #endif
776 #ifdef DOS_NT
777 _fmode = O_BINARY; /* all of files are treated as binary files */
778 #endif /* DOS_NT */
780 progname = argv[0];
781 nincluded_files = 0;
782 included_files = xnew (argc, char *);
783 current_arg = 0;
784 file_count = 0;
786 /* Allocate enough no matter what happens. Overkill, but each one
787 is small. */
788 argbuffer = xnew (argc, argument);
790 #ifdef ETAGS_REGEXPS
791 /* Set syntax for regular expression routines. */
792 re_set_syntax (RE_SYNTAX_EMACS);
793 #endif /* ETAGS_REGEXPS */
796 * If etags, always find typedefs and structure tags. Why not?
797 * Also default is to find macro constants, enum constants and
798 * global variables.
800 if (!CTAGS)
802 typedefs = typedefs_and_cplusplus = constantypedefs = TRUE;
803 globals = TRUE;
804 members = FALSE;
807 while (1)
809 int opt;
810 char *optstring;
812 #ifdef ETAGS_REGEXPS
813 optstring = "-aCdDf:Il:o:r:RStTi:BuvxwVhH";
814 #else
815 optstring = "-aCdDf:Il:o:StTi:BuvxwVhH";
816 #endif /* ETAGS_REGEXPS */
818 #ifndef LONG_OPTIONS
819 optstring = optstring + 1;
820 #endif /* LONG_OPTIONS */
822 opt = getopt_long (argc, argv, optstring, longopts, 0);
823 if (opt == EOF)
824 break;
826 switch (opt)
828 case 0:
829 /* If getopt returns 0, then it has already processed a
830 long-named option. We should do nothing. */
831 break;
833 case 1:
834 /* This means that a file name has been seen. Record it. */
835 argbuffer[current_arg].arg_type = at_filename;
836 argbuffer[current_arg].what = optarg;
837 ++current_arg;
838 ++file_count;
839 break;
841 /* Common options. */
842 case 'a': append_to_tagfile = TRUE; break;
843 case 'C': cplusplus = TRUE; break;
844 case 'd': constantypedefs = TRUE; break;
845 case 'D': constantypedefs = FALSE; break;
846 case 'f': /* for compatibility with old makefiles */
847 case 'o':
848 if (tagfile)
850 error ("-%c option may only be given once.", opt);
851 suggest_asking_for_help ();
853 tagfile = optarg;
854 break;
855 case 'I':
856 case 'S': /* for backward compatibility */
857 noindentypedefs = TRUE;
858 break;
859 case 'l':
860 argbuffer[current_arg].function = get_language_from_name (optarg);
861 argbuffer[current_arg].arg_type = at_language;
862 ++current_arg;
863 break;
864 #ifdef ETAGS_REGEXPS
865 case 'r':
866 argbuffer[current_arg].arg_type = at_regexp;
867 argbuffer[current_arg].what = optarg;
868 ++current_arg;
869 break;
870 case 'R':
871 argbuffer[current_arg].arg_type = at_regexp;
872 argbuffer[current_arg].what = NULL;
873 ++current_arg;
874 break;
875 #endif /* ETAGS_REGEXPS */
876 case 'V':
877 print_version ();
878 break;
879 case 'h':
880 case 'H':
881 print_help ();
882 break;
883 case 't':
884 typedefs = TRUE;
885 break;
886 case 'T':
887 typedefs = typedefs_and_cplusplus = TRUE;
888 break;
889 #if (!CTAGS)
890 /* Etags options */
891 case 'i':
892 included_files[nincluded_files++] = optarg;
893 break;
894 #else /* CTAGS */
895 /* Ctags options. */
896 case 'B': searchar = '?'; break;
897 case 'u': update = TRUE; break;
898 case 'v': vgrind_style = TRUE; /*FALLTHRU*/
899 case 'x': cxref_style = TRUE; break;
900 case 'w': no_warnings = TRUE; break;
901 #endif /* CTAGS */
902 default:
903 suggest_asking_for_help ();
907 for (; optind < argc; ++optind)
909 argbuffer[current_arg].arg_type = at_filename;
910 argbuffer[current_arg].what = argv[optind];
911 ++current_arg;
912 ++file_count;
915 if (nincluded_files == 0 && file_count == 0)
917 error ("no input files specified.", 0);
918 suggest_asking_for_help ();
921 if (tagfile == NULL)
922 tagfile = CTAGS ? "tags" : "TAGS";
923 cwd = etags_getcwd (); /* the current working directory */
924 if (cwd[strlen (cwd) - 1] != '/')
926 char *oldcwd = cwd;
927 cwd = concat (oldcwd, "/", "");
928 free (oldcwd);
930 if (streq (tagfile, "-"))
931 tagfiledir = cwd;
932 else
933 tagfiledir = absolute_dirname (tagfile, cwd);
935 init (); /* set up boolean "functions" */
937 initbuffer (&lb);
938 initbuffer (&token_name);
939 initbuffer (&lbs[0].lb);
940 initbuffer (&lbs[1].lb);
941 initbuffer (&filename_lb);
943 if (!CTAGS)
945 if (streq (tagfile, "-"))
947 tagf = stdout;
948 #ifdef DOS_NT
949 /* Switch redirected `stdout' to binary mode (setting `_fmode'
950 doesn't take effect until after `stdout' is already open). */
951 if (!isatty (fileno (stdout)))
952 setmode (fileno (stdout), O_BINARY);
953 #endif /* DOS_NT */
955 else
956 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
957 if (tagf == NULL)
958 pfatal (tagfile);
962 * Loop through files finding functions.
964 for (i = 0; i < current_arg; ++i)
966 switch (argbuffer[i].arg_type)
968 case at_language:
969 lang_func = argbuffer[i].function;
970 break;
971 #ifdef ETAGS_REGEXPS
972 case at_regexp:
973 analyse_regex (argbuffer[i].what);
974 break;
975 #endif
976 case at_filename:
977 #ifdef VMS
978 while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL)
980 if (got_err)
982 error ("can't find file %s\n", this_file);
983 argc--, argv++;
985 else
987 this_file = massage_name (this_file);
989 #else
990 this_file = argbuffer[i].what;
991 #endif
992 /* Input file named "-" means read file names from stdin
993 and use them. */
994 if (streq (this_file, "-"))
995 while (readline_internal (&filename_lb, stdin) > 0)
996 process_file (filename_lb.buffer);
997 else
998 process_file (this_file);
999 #ifdef VMS
1001 #endif
1002 break;
1006 if (!CTAGS)
1008 while (nincluded_files-- > 0)
1009 fprintf (tagf, "\f\n%s,include\n", *included_files++);
1011 fclose (tagf);
1012 exit (GOOD);
1015 /* If CTAGS, we are here. process_file did not write the tags yet,
1016 because we want them ordered. Let's do it now. */
1017 if (cxref_style)
1019 put_entries (head);
1020 exit (GOOD);
1023 if (update)
1025 char cmd[BUFSIZ];
1026 for (i = 0; i < current_arg; ++i)
1028 if (argbuffer[i].arg_type != at_filename)
1029 continue;
1030 sprintf (cmd,
1031 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1032 tagfile, argbuffer[i].what, tagfile);
1033 if (system (cmd) != GOOD)
1034 fatal ("failed to execute shell command", (char *)NULL);
1036 append_to_tagfile = TRUE;
1039 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1040 if (tagf == NULL)
1041 pfatal (tagfile);
1042 put_entries (head);
1043 fclose (tagf);
1045 if (update)
1047 char cmd[BUFSIZ];
1048 sprintf (cmd, "sort %s -o %s", tagfile, tagfile);
1049 exit (system (cmd));
1051 return GOOD;
1056 * Return a Lang_function given the name.
1058 Lang_function *
1059 get_language_from_name (name)
1060 char *name;
1062 struct lang_entry *lang;
1064 if (name != NULL)
1065 for (lang = lang_names; lang->name != NULL; lang++)
1067 if (streq (name, lang->name))
1068 return lang->function;
1071 error ("language \"%s\" not recognized.", optarg);
1072 suggest_asking_for_help ();
1074 /* This point should never be reached. The function should either
1075 return a function pointer or never return. Note that a NULL
1076 pointer cannot be considered as an error, as it means that the
1077 language has not been explicitely imposed by the user ("auto"). */
1078 return NULL; /* avoid warnings from compiler */
1083 * Return a Lang_function given the interpreter name.
1085 Lang_function *
1086 get_language_from_interpreter (interpreter)
1087 char *interpreter;
1089 struct lang_entry *lang;
1090 char **iname;
1092 if (interpreter == NULL)
1093 return NULL;
1094 for (lang = lang_names; lang->name != NULL; lang++)
1095 if (lang->interpreters != NULL)
1096 for (iname = lang->interpreters; *iname != NULL; iname++)
1097 if (streq (*iname, interpreter))
1098 return lang->function;
1100 return NULL;
1106 * Return a Lang_function given the file suffix.
1108 Lang_function *
1109 get_language_from_suffix (suffix)
1110 char *suffix;
1112 struct lang_entry *lang;
1113 char **ext;
1115 if (suffix == NULL)
1116 return NULL;
1117 for (lang = lang_names; lang->name != NULL; lang++)
1118 if (lang->suffixes != NULL)
1119 for (ext = lang->suffixes; *ext != NULL; ext++)
1120 if (streq (*ext, suffix))
1121 return lang->function;
1123 return NULL;
1128 * This routine is called on each file argument.
1130 void
1131 process_file (file)
1132 char *file;
1134 struct stat stat_buf;
1135 FILE *inf;
1136 #ifdef DOS_NT
1137 char *p;
1139 for (p = file; *p != '\0'; p++)
1140 if (*p == '\\')
1141 *p = '/';
1142 #endif
1144 if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode))
1146 error ("skipping %s: it is not a regular file.", file);
1147 return;
1149 if (streq (file, tagfile) && !streq (tagfile, "-"))
1151 error ("skipping inclusion of %s in self.", file);
1152 return;
1154 inf = fopen (file, "r");
1155 if (inf == NULL)
1157 perror (file);
1158 return;
1161 find_entries (file, inf);
1163 if (!CTAGS)
1165 char *filename;
1167 if (absolutefn (file))
1169 /* file is an absolute file name. Canonicalise it. */
1170 filename = absolute_filename (file, cwd);
1172 else
1174 /* file is a file name relative to cwd. Make it relative
1175 to the directory of the tags file. */
1176 filename = relative_filename (file, tagfiledir);
1178 fprintf (tagf, "\f\n%s,%d\n", filename, total_size_of_entries (head));
1179 free (filename);
1180 put_entries (head);
1181 free_tree (head);
1182 head = NULL;
1187 * This routine sets up the boolean pseudo-functions which work
1188 * by setting boolean flags dependent upon the corresponding character
1189 * Every char which is NOT in that string is not a white char. Therefore,
1190 * all of the array "_wht" is set to FALSE, and then the elements
1191 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1192 * of a char is TRUE if it is the string "white", else FALSE.
1194 void
1195 init ()
1197 register char *sp;
1198 register int i;
1200 for (i = 0; i < CHARS; i++)
1201 _wht[i] = _nin[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
1202 for (sp = white; *sp; sp++) _wht[*sp] = TRUE; _wht[0] = _wht['\n'];
1203 for (sp = nonam; *sp; sp++) _nin[*sp] = TRUE; _nin[0] = _nin['\n'];
1204 for (sp = endtk; *sp; sp++) _etk[*sp] = TRUE; _etk[0] = _etk['\n'];
1205 for (sp = midtk; *sp; sp++) _itk[*sp] = TRUE; _btk[0] = _btk['\n'];
1206 for (sp = begtk; *sp; sp++) _btk[*sp] = TRUE; _itk[0] = _itk['\n'];
1210 * This routine opens the specified file and calls the function
1211 * which finds the function and type definitions.
1213 void
1214 find_entries (file, inf)
1215 char *file;
1216 FILE *inf;
1218 char *cp;
1219 Lang_function *function;
1220 NODE *old_last_node;
1221 extern NODE *last_node;
1224 /* Memory leakage here: the memory block pointed by curfile is never
1225 released. The amount of memory leaked here is the sum of the
1226 lengths of the input file names. */
1227 curfile = savestr (file);
1229 /* If user specified a language, use it. */
1230 function = lang_func;
1231 if (function != NULL)
1233 function (inf);
1234 fclose (inf);
1235 return;
1238 cp = etags_strrchr (file, '.');
1239 if (cp != NULL)
1241 cp += 1;
1242 function = get_language_from_suffix (cp);
1243 if (function != NULL)
1245 function (inf);
1246 fclose (inf);
1247 return;
1251 /* Look for sharp-bang as the first two characters. */
1252 if (readline_internal (&lb, inf)
1253 && lb.len >= 2
1254 && lb.buffer[0] == '#'
1255 && lb.buffer[1] == '!')
1257 char *lp;
1259 /* Set lp to point at the first char after the last slash in the
1260 line or, if no slashes, at the first nonblank. Then set cp to
1261 the first successive blank and terminate the string. */
1262 lp = etags_strrchr (lb.buffer+2, '/');
1263 if (lp != NULL)
1264 lp += 1;
1265 else
1266 for (lp = lb.buffer+2; *lp != '\0' && isspace (*lp); lp++)
1267 continue;
1268 for (cp = lp; *cp != '\0' && !isspace (*cp); cp++)
1269 continue;
1270 *cp = '\0';
1272 if (strlen (lp) > 0)
1274 function = get_language_from_interpreter (lp);
1275 if (function != NULL)
1277 function (inf);
1278 fclose (inf);
1279 return;
1283 rewind (inf);
1285 /* Try Fortran. */
1286 old_last_node = last_node;
1287 Fortran_functions (inf);
1289 /* No Fortran entries found. Try C. */
1290 if (old_last_node == last_node)
1292 rewind (inf);
1293 default_C_entries (inf);
1295 fclose (inf);
1296 return;
1299 /* Record a tag. */
1300 void
1301 pfnote (name, is_func, linestart, linelen, lno, cno)
1302 char *name; /* tag name, or NULL if unnamed */
1303 bool is_func; /* tag is a function */
1304 char *linestart; /* start of the line where tag is */
1305 int linelen; /* length of the line where tag is */
1306 int lno; /* line number */
1307 long cno; /* character number */
1309 register NODE *np;
1311 if (CTAGS && name == NULL)
1312 return;
1314 np = xnew (1, NODE);
1316 /* If ctags mode, change name "main" to M<thisfilename>. */
1317 if (CTAGS && !cxref_style && streq (name, "main"))
1319 register char *fp = etags_strrchr (curfile, '/');
1320 np->name = concat ("M", fp == 0 ? curfile : fp + 1, "");
1321 fp = etags_strrchr (np->name, '.');
1322 if (fp && fp[1] != '\0' && fp[2] == '\0')
1323 fp[0] = 0;
1325 else
1326 np->name = name;
1327 np->been_warned = FALSE;
1328 np->file = curfile;
1329 np->is_func = is_func;
1330 np->lno = lno;
1331 /* Our char numbers are 0-base, because of C language tradition?
1332 ctags compatibility? old versions compatibility? I don't know.
1333 Anyway, since emacs's are 1-base we expect etags.el to take care
1334 of the difference. If we wanted to have 1-based numbers, we would
1335 uncomment the +1 below. */
1336 np->cno = cno /* + 1 */ ;
1337 np->left = np->right = NULL;
1338 if (CTAGS && !cxref_style)
1340 if (strlen (linestart) < 50)
1341 np->pat = concat (linestart, "$", "");
1342 else
1343 np->pat = savenstr (linestart, 50);
1345 else
1346 np->pat = savenstr (linestart, linelen);
1348 add_node (np, &head);
1351 /* Date: Wed, 22 Jan 1997 02:56:31 -0500
1352 * From: Sam Kendall <kendall@cybercom.net>
1353 * Subject: Proposal for firming up the TAGS format specification
1354 * To: F.Potorti@cnuce.cnr.it
1356 * pfnote should emit the optimized form [unnamed tag] only if:
1357 * 1. name does not contain any of the characters " \t\r\n()";
1358 * 2. linestart contains name as either a rightmost, or rightmost but
1359 * one character, substring;
1360 * 3. the character, if any, immediately before name in linestart must
1361 * be one of the characters " \t()";
1362 * 4. the character, if any, immediately after name in linestart must
1363 * also be one of the characters " \t()".
1365 #define traditional_tag_style TRUE
1366 void
1367 new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno)
1368 char *name; /* tag name, or NULL if unnamed */
1369 int namelen; /* tag length */
1370 bool is_func; /* tag is a function */
1371 char *linestart; /* start of the line where tag is */
1372 int linelen; /* length of the line where tag is */
1373 int lno; /* line number */
1374 long cno; /* character number */
1376 register char *cp;
1377 bool named;
1379 named = TRUE;
1380 if (!CTAGS)
1382 for (cp = name; !notinname (*cp); cp++)
1383 continue;
1384 if (*cp == '\0') /* rule #1 */
1386 cp = linestart + linelen - namelen;
1387 if (notinname (linestart[linelen-1]))
1388 cp -= 1; /* rule #4 */
1389 if (cp >= linestart /* rule #2 */
1390 && (cp == linestart
1391 || notinname (cp[-1])) /* rule #3 */
1392 && strneq (name, cp, namelen)) /* rule #2 */
1393 named = FALSE; /* use unnamed tag */
1397 if (named)
1398 name = savenstr (name, namelen);
1399 else
1400 name = NULL;
1401 pfnote (name, is_func, linestart, linelen, lno, cno);
1405 * free_tree ()
1406 * recurse on left children, iterate on right children.
1408 void
1409 free_tree (node)
1410 register NODE *node;
1412 while (node)
1414 register NODE *node_right = node->right;
1415 free_tree (node->left);
1416 if (node->name != NULL)
1417 free (node->name);
1418 free (node->pat);
1419 free ((char *) node);
1420 node = node_right;
1425 * add_node ()
1426 * Adds a node to the tree of nodes. In etags mode, we don't keep
1427 * it sorted; we just keep a linear list. In ctags mode, maintain
1428 * an ordered tree, with no attempt at balancing.
1430 * add_node is the only function allowed to add nodes, so it can
1431 * maintain state.
1433 NODE *last_node = NULL;
1434 void
1435 add_node (node, cur_node_p)
1436 NODE *node, **cur_node_p;
1438 register int dif;
1439 register NODE *cur_node = *cur_node_p;
1441 if (cur_node == NULL)
1443 *cur_node_p = node;
1444 last_node = node;
1445 return;
1448 if (!CTAGS)
1450 /* Etags Mode */
1451 if (last_node == NULL)
1452 fatal ("internal error in add_node", (char *)NULL);
1453 last_node->right = node;
1454 last_node = node;
1456 else
1458 /* Ctags Mode */
1459 dif = strcmp (node->name, cur_node->name);
1462 * If this tag name matches an existing one, then
1463 * do not add the node, but maybe print a warning.
1465 if (!dif)
1467 if (streq (node->file, cur_node->file))
1469 if (!no_warnings)
1471 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1472 node->file, lineno, node->name);
1473 fprintf (stderr, "Second entry ignored\n");
1476 else if (!cur_node->been_warned && !no_warnings)
1478 fprintf
1479 (stderr,
1480 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1481 node->file, cur_node->file, node->name);
1482 cur_node->been_warned = TRUE;
1484 return;
1487 /* Actually add the node */
1488 add_node (node, dif < 0 ? &cur_node->left : &cur_node->right);
1492 void
1493 put_entries (node)
1494 register NODE *node;
1496 register char *sp;
1498 if (node == NULL)
1499 return;
1501 /* Output subentries that precede this one */
1502 put_entries (node->left);
1504 /* Output this entry */
1506 if (!CTAGS)
1508 if (node->name != NULL)
1509 fprintf (tagf, "%s\177%s\001%d,%d\n",
1510 node->pat, node->name, node->lno, node->cno);
1511 else
1512 fprintf (tagf, "%s\177%d,%d\n",
1513 node->pat, node->lno, node->cno);
1515 else
1517 if (node->name == NULL)
1518 error ("internal error: NULL name in ctags mode.", (char *)NULL);
1520 if (cxref_style)
1522 if (vgrind_style)
1523 fprintf (stdout, "%s %s %d\n",
1524 node->name, node->file, (node->lno + 63) / 64);
1525 else
1526 fprintf (stdout, "%-16s %3d %-16s %s\n",
1527 node->name, node->lno, node->file, node->pat);
1529 else
1531 fprintf (tagf, "%s\t%s\t", node->name, node->file);
1533 if (node->is_func)
1534 { /* a function */
1535 putc (searchar, tagf);
1536 putc ('^', tagf);
1538 for (sp = node->pat; *sp; sp++)
1540 if (*sp == '\\' || *sp == searchar)
1541 putc ('\\', tagf);
1542 putc (*sp, tagf);
1544 putc (searchar, tagf);
1546 else
1547 { /* a typedef; text pattern inadequate */
1548 fprintf (tagf, "%d", node->lno);
1550 putc ('\n', tagf);
1554 /* Output subentries that follow this one */
1555 put_entries (node->right);
1558 /* Length of a number's decimal representation. */
1560 number_len (num)
1561 long num;
1563 int len = 0;
1564 if (!num)
1565 return 1;
1566 for (; num; num /= 10)
1567 ++len;
1568 return len;
1572 * Return total number of characters that put_entries will output for
1573 * the nodes in the subtree of the specified node. Works only if
1574 * we are not ctags, but called only in that case. This count
1575 * is irrelevant with the new tags.el, but is still supplied for
1576 * backward compatibility.
1579 total_size_of_entries (node)
1580 register NODE *node;
1582 register int total;
1584 if (node == NULL)
1585 return 0;
1587 total = 0;
1588 for (; node; node = node->right)
1590 /* Count left subentries. */
1591 total += total_size_of_entries (node->left);
1593 /* Count this entry */
1594 total += strlen (node->pat) + 1;
1595 total += number_len ((long) node->lno) + 1 + number_len (node->cno) + 1;
1596 if (node->name != NULL)
1597 total += 1 + strlen (node->name); /* \001name */
1600 return total;
1604 * The C symbol tables.
1606 enum sym_type
1608 st_none,
1609 st_C_objprot, st_C_objimpl, st_C_objend,
1610 st_C_gnumacro,
1611 st_C_ignore,
1612 st_C_javastruct,
1613 st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
1616 /* Feed stuff between (but not including) %[ and %] lines to:
1617 gperf -c -k 1,3 -o -p -r -t
1619 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1621 @interface, 0, st_C_objprot
1622 @protocol, 0, st_C_objprot
1623 @implementation,0, st_C_objimpl
1624 @end, 0, st_C_objend
1625 import, C_JAVA, st_C_ignore
1626 package, C_JAVA, st_C_ignore
1627 friend, C_PLPL, st_C_ignore
1628 extends, C_JAVA, st_C_javastruct
1629 implements, C_JAVA, st_C_javastruct
1630 class, C_PLPL, st_C_struct
1631 namespace, C_PLPL, st_C_struct
1632 domain, C_STAR, st_C_struct
1633 union, 0, st_C_struct
1634 struct, 0, st_C_struct
1635 enum, 0, st_C_enum
1636 typedef, 0, st_C_typedef
1637 define, 0, st_C_define
1638 bool, C_PLPL, st_C_typespec
1639 long, 0, st_C_typespec
1640 short, 0, st_C_typespec
1641 int, 0, st_C_typespec
1642 char, 0, st_C_typespec
1643 float, 0, st_C_typespec
1644 double, 0, st_C_typespec
1645 signed, 0, st_C_typespec
1646 unsigned, 0, st_C_typespec
1647 auto, 0, st_C_typespec
1648 void, 0, st_C_typespec
1649 extern, 0, st_C_typespec
1650 static, 0, st_C_typespec
1651 const, 0, st_C_typespec
1652 volatile, 0, st_C_typespec
1653 explicit, C_PLPL, st_C_typespec
1654 mutable, C_PLPL, st_C_typespec
1655 typename, C_PLPL, st_C_typespec
1656 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
1657 DEFUN, 0, st_C_gnumacro
1658 SYSCALL, 0, st_C_gnumacro
1659 ENTRY, 0, st_C_gnumacro
1660 PSEUDO, 0, st_C_gnumacro
1661 # These are defined inside C functions, so currently they are not met.
1662 # EXFUN used in glibc, DEFVAR_* in emacs.
1663 #EXFUN, 0, st_C_gnumacro
1664 #DEFVAR_, 0, st_C_gnumacro
1666 and replace lines between %< and %> with its output. */
1667 /*%<*/
1668 /* starting time is 10:31:16 */
1669 /* C code produced by gperf version 2.1 (K&R C version) */
1670 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
1673 struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
1675 #define MIN_WORD_LENGTH 3
1676 #define MAX_WORD_LENGTH 15
1677 #define MIN_HASH_VALUE 15
1678 #define MAX_HASH_VALUE 128
1680 39 keywords
1681 114 is the maximum key range
1684 static int
1685 hash (str, len)
1686 register char *str;
1687 register unsigned int len;
1689 static unsigned char hash_table[] =
1691 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1692 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1693 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1694 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1695 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1696 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1697 128, 128, 128, 128, 39, 128, 128, 128, 54, 48,
1698 46, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1699 28, 128, 128, 40, 32, 128, 128, 128, 128, 128,
1700 128, 128, 128, 128, 128, 128, 128, 24, 30, 47,
1701 62, 7, 60, 27, 128, 60, 128, 128, 59, 16,
1702 31, 23, 45, 128, 4, 14, 2, 55, 5, 128,
1703 128, 128, 128, 128, 128, 128, 128, 128,
1705 return len + hash_table[str[2]] + hash_table[str[0]];
1708 struct C_stab_entry *
1709 in_word_set (str, len)
1710 register char *str;
1711 register unsigned int len;
1714 static struct C_stab_entry wordlist[] =
1716 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1717 {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1718 {"extern", 0, st_C_typespec},
1719 {"extends", C_JAVA, st_C_javastruct},
1720 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1721 {"struct", 0, st_C_struct},
1722 {"mutable", C_PLPL, st_C_typespec},
1723 {"",}, {"",}, {"",}, {"",},
1724 {"auto", 0, st_C_typespec},
1725 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1726 {"",}, {"",},
1727 {"short", 0, st_C_typespec},
1728 {"",},
1729 {"static", 0, st_C_typespec},
1730 {"",}, {"",},
1731 {"signed", 0, st_C_typespec},
1732 {"",}, {"",}, {"",}, {"",},
1733 {"@protocol", 0, st_C_objprot},
1734 {"",},
1735 {"typedef", 0, st_C_typedef},
1736 {"typename", C_PLPL, st_C_typespec},
1737 {"namespace", C_PLPL, st_C_struct},
1738 {"bool", C_PLPL, st_C_typespec},
1739 {"",}, {"",},
1740 {"explicit", C_PLPL, st_C_typespec},
1741 {"",}, {"",}, {"",}, {"",},
1742 {"int", 0, st_C_typespec},
1743 {"enum", 0, st_C_enum},
1744 {"",}, {"",},
1745 {"void", 0, st_C_typespec},
1746 {"@implementation", 0, st_C_objimpl},
1747 {"",},
1748 {"volatile", 0, st_C_typespec},
1749 {"",},
1750 {"@end", 0, st_C_objend},
1751 {"char", 0, st_C_typespec},
1752 {"class", C_PLPL, st_C_struct},
1753 {"unsigned", 0, st_C_typespec},
1754 {"",}, {"",},
1755 {"@interface", 0, st_C_objprot},
1756 {"",},
1757 {"PSEUDO", 0, st_C_gnumacro},
1758 {"const", 0, st_C_typespec},
1759 {"domain", C_STAR, st_C_struct},
1760 {"ENTRY", 0, st_C_gnumacro},
1761 {"",},
1762 {"SYSCALL", 0, st_C_gnumacro},
1763 {"float", 0, st_C_typespec},
1764 {"",}, {"",}, {"",}, {"",}, {"",},
1765 {"long", 0, st_C_typespec},
1766 {"",}, {"",}, {"",}, {"",},
1767 {"package", C_JAVA, st_C_ignore},
1768 {"",}, {"",}, {"",}, {"",}, {"",},
1769 {"DEFUN", 0, st_C_gnumacro},
1770 {"",}, {"",}, {"",}, {"",}, {"",},
1771 {"import", C_JAVA, st_C_ignore},
1772 {"",}, {"",}, {"",},
1773 {"implements", C_JAVA, st_C_javastruct},
1774 {"",}, {"",}, {"",}, {"",},
1775 {"union", 0, st_C_struct},
1776 {"",}, {"",},
1777 {"double", 0, st_C_typespec},
1778 {"",}, {"",},
1779 {"friend", C_PLPL, st_C_ignore},
1780 {"",},
1781 {"define", 0, st_C_define},
1784 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
1786 register int key = hash (str, len);
1788 if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)
1790 register char *s = wordlist[key].name;
1792 if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
1793 return &wordlist[key];
1796 return 0;
1798 /* ending time is 10:31:16 */
1799 /*%>*/
1801 enum sym_type
1802 C_symtype (str, len, c_ext)
1803 char *str;
1804 int len;
1805 int c_ext;
1807 register struct C_stab_entry *se = in_word_set (str, len);
1809 if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
1810 return st_none;
1811 return se->type;
1815 * C functions and variables are recognized using a simple
1816 * finite automaton. fvdef is its state variable.
1818 enum
1820 fvnone, /* nothing seen */
1821 fvnameseen, /* function or variable name seen */
1822 fstartlist, /* func: just after open parenthesis */
1823 finlist, /* func: in parameter list */
1824 flistseen, /* func: after parameter list */
1825 fignore, /* func: before open brace */
1826 vignore /* var-like: ignore until ';' */
1827 } fvdef;
1831 * typedefs are recognized using a simple finite automaton.
1832 * typdef is its state variable.
1834 enum
1836 tnone, /* nothing seen */
1837 ttypedseen, /* typedef keyword seen */
1838 tinbody, /* inside typedef body */
1839 tend, /* just before typedef tag */
1840 tignore /* junk after typedef tag */
1841 } typdef;
1845 * struct-like structures (enum, struct and union) are recognized
1846 * using another simple finite automaton. `structdef' is its state
1847 * variable.
1849 enum
1851 snone, /* nothing seen yet */
1852 skeyseen, /* struct-like keyword seen */
1853 stagseen, /* struct-like tag seen */
1854 scolonseen, /* colon seen after struct-like tag */
1855 sinbody /* in struct body: recognize member func defs*/
1856 } structdef;
1859 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1860 * struct tag, and structtype is the type of the preceding struct-like
1861 * keyword.
1863 char *structtag = "<uninited>";
1864 enum sym_type structtype;
1867 * When objdef is different from onone, objtag is the name of the class.
1869 char *objtag = "<uninited>";
1872 * Yet another little state machine to deal with preprocessor lines.
1874 enum
1876 dnone, /* nothing seen */
1877 dsharpseen, /* '#' seen as first char on line */
1878 ddefineseen, /* '#' and 'define' seen */
1879 dignorerest /* ignore rest of line */
1880 } definedef;
1883 * State machine for Objective C protocols and implementations.
1884 * Tom R.Hageman <tom@basil.icce.rug.nl>
1886 enum
1888 onone, /* nothing seen */
1889 oprotocol, /* @interface or @protocol seen */
1890 oimplementation, /* @implementations seen */
1891 otagseen, /* class name seen */
1892 oparenseen, /* parenthesis before category seen */
1893 ocatseen, /* category name seen */
1894 oinbody, /* in @implementation body */
1895 omethodsign, /* in @implementation body, after +/- */
1896 omethodtag, /* after method name */
1897 omethodcolon, /* after method colon */
1898 omethodparm, /* after method parameter */
1899 oignore /* wait for @end */
1900 } objdef;
1904 * Use this structure to keep info about the token read, and how it
1905 * should be tagged. Used by the make_C_tag function to build a tag.
1907 typedef struct
1909 bool valid;
1910 char *str;
1911 bool named;
1912 int linelen;
1913 int lineno;
1914 long linepos;
1915 char *buffer;
1916 } TOKEN;
1917 TOKEN tok; /* latest token read */
1921 * Set this to TRUE, and the next token considered is called a function.
1922 * Used only for GNU emacs's function-defining macros.
1924 bool next_token_is_func;
1927 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1929 bool yacc_rules;
1932 * methodlen is the length of the method name stored in token_name.
1934 int methodlen;
1937 * consider_token ()
1938 * checks to see if the current token is at the start of a
1939 * function or variable, or corresponds to a typedef, or
1940 * is a struct/union/enum tag, or #define, or an enum constant.
1942 * *IS_FUNC gets TRUE iff the token is a function or #define macro
1943 * with args. C_EXT is which language we are looking at.
1945 * In the future we will need some way to adjust where the end of
1946 * the token is; for instance, implementing the C++ keyword
1947 * `operator' properly will adjust the end of the token to be after
1948 * whatever follows `operator'.
1950 * Globals
1951 * fvdef IN OUT
1952 * structdef IN OUT
1953 * definedef IN OUT
1954 * typdef IN OUT
1955 * objdef IN OUT
1956 * next_token_is_func IN OUT
1959 bool
1960 consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var)
1961 register char *str; /* IN: token pointer */
1962 register int len; /* IN: token length */
1963 register char c; /* IN: first char after the token */
1964 int c_ext; /* IN: C extensions mask */
1965 int cblev; /* IN: curly brace level */
1966 int parlev; /* IN: parenthesis level */
1967 bool *is_func_or_var; /* OUT: function or variable found */
1969 enum sym_type toktype = C_symtype (str, len, c_ext);
1972 * Advance the definedef state machine.
1974 switch (definedef)
1976 case dnone:
1977 /* We're not on a preprocessor line. */
1978 break;
1979 case dsharpseen:
1980 if (toktype == st_C_define)
1982 definedef = ddefineseen;
1984 else
1986 definedef = dignorerest;
1988 return FALSE;
1989 case ddefineseen:
1991 * Make a tag for any macro, unless it is a constant
1992 * and constantypedefs is FALSE.
1994 definedef = dignorerest;
1995 *is_func_or_var = (c == '(');
1996 if (!*is_func_or_var && !constantypedefs)
1997 return FALSE;
1998 else
1999 return TRUE;
2000 case dignorerest:
2001 return FALSE;
2002 default:
2003 error ("internal error: definedef value.", (char *)NULL);
2007 * Now typedefs
2009 switch (typdef)
2011 case tnone:
2012 if (toktype == st_C_typedef)
2014 if (typedefs)
2015 typdef = ttypedseen;
2016 fvdef = fvnone;
2017 return FALSE;
2019 break;
2020 case ttypedseen:
2021 switch (toktype)
2023 case st_none:
2024 case st_C_typespec:
2025 typdef = tend;
2026 break;
2027 case st_C_struct:
2028 case st_C_enum:
2029 break;
2031 /* Do not return here, so the structdef stuff has a chance. */
2032 break;
2033 case tend:
2034 switch (toktype)
2036 case st_C_typespec:
2037 case st_C_struct:
2038 case st_C_enum:
2039 return FALSE;
2041 return TRUE;
2045 * This structdef business is currently only invoked when cblev==0.
2046 * It should be recursively invoked whatever the curly brace level,
2047 * and a stack of states kept, to allow for definitions of structs
2048 * within structs.
2050 * This structdef business is NOT invoked when we are ctags and the
2051 * file is plain C. This is because a struct tag may have the same
2052 * name as another tag, and this loses with ctags.
2054 switch (toktype)
2056 case st_C_javastruct:
2057 if (structdef == stagseen)
2058 structdef = scolonseen;
2059 return FALSE;
2060 break;
2061 case st_C_struct:
2062 case st_C_enum:
2063 if (typdef == ttypedseen
2064 || (typedefs_and_cplusplus && cblev == 0 && structdef == snone))
2066 structdef = skeyseen;
2067 structtype = toktype;
2069 return FALSE;
2072 if (structdef == skeyseen)
2074 /* Save the tag for struct/union/class, for functions and variables
2075 that may be defined inside. */
2076 if (structtype == st_C_struct)
2077 structtag = savenstr (str, len);
2078 else
2079 structtag = "<enum>";
2080 structdef = stagseen;
2081 return TRUE;
2084 /* Avoid entering fvdef stuff if typdef is going on. */
2085 if (typdef != tnone)
2087 definedef = dnone;
2088 return FALSE;
2091 /* Detect GNU macros.
2093 DEFUN note for writers of emacs C code:
2094 The DEFUN macro, used in emacs C source code, has a first arg
2095 that is a string (the lisp function name), and a second arg that
2096 is a C function name. Since etags skips strings, the second arg
2097 is tagged. This is unfortunate, as it would be better to tag the
2098 first arg. The simplest way to deal with this problem would be
2099 to name the tag with a name built from the function name, by
2100 removing the initial 'F' character and substituting '-' for '_'.
2101 Anyway, this assumes that the conventions of naming lisp
2102 functions will never change. Currently, this method is not
2103 implemented, so writers of emacs code are recommended to put the
2104 first two args of a DEFUN on the same line. */
2105 if (definedef == dnone && toktype == st_C_gnumacro)
2107 next_token_is_func = TRUE;
2108 return FALSE;
2110 if (next_token_is_func)
2112 next_token_is_func = FALSE;
2113 fvdef = fignore;
2114 *is_func_or_var = TRUE;
2115 return TRUE;
2118 /* Detect Objective C constructs. */
2119 switch (objdef)
2121 case onone:
2122 switch (toktype)
2124 case st_C_objprot:
2125 objdef = oprotocol;
2126 return FALSE;
2127 case st_C_objimpl:
2128 objdef = oimplementation;
2129 return FALSE;
2131 break;
2132 case oimplementation:
2133 /* Save the class tag for functions or variables defined inside. */
2134 objtag = savenstr (str, len);
2135 objdef = oinbody;
2136 return FALSE;
2137 case oprotocol:
2138 /* Save the class tag for categories. */
2139 objtag = savenstr (str, len);
2140 objdef = otagseen;
2141 *is_func_or_var = TRUE;
2142 return TRUE;
2143 case oparenseen:
2144 objdef = ocatseen;
2145 *is_func_or_var = TRUE;
2146 return TRUE;
2147 case oinbody:
2148 break;
2149 case omethodsign:
2150 if (parlev == 0)
2152 objdef = omethodtag;
2153 methodlen = len;
2154 grow_linebuffer (&token_name, methodlen + 1);
2155 strncpy (token_name.buffer, str, len);
2156 token_name.buffer[methodlen] = '\0';
2157 token_name.len = methodlen;
2158 return TRUE;
2160 return FALSE;
2161 case omethodcolon:
2162 if (parlev == 0)
2163 objdef = omethodparm;
2164 return FALSE;
2165 case omethodparm:
2166 if (parlev == 0)
2168 objdef = omethodtag;
2169 methodlen += len;
2170 grow_linebuffer (&token_name, methodlen + 1);
2171 strncat (token_name.buffer, str, len);
2172 token_name.len = methodlen;
2173 return TRUE;
2175 return FALSE;
2176 case oignore:
2177 if (toktype == st_C_objend)
2179 /* Memory leakage here: the string pointed by objtag is
2180 never released, because many tests would be needed to
2181 avoid breaking on incorrect input code. The amount of
2182 memory leaked here is the sum of the lengths of the
2183 class tags.
2184 free (objtag); */
2185 objdef = onone;
2187 return FALSE;
2190 /* A function, variable or enum constant? */
2191 switch (toktype)
2193 case st_C_typespec:
2194 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2195 fvdef = fvnone; /* should be useless */
2196 return FALSE;
2197 case st_C_ignore:
2198 fvdef = vignore;
2199 return FALSE;
2200 case st_none:
2201 if (constantypedefs && structdef == sinbody && structtype == st_C_enum)
2202 return TRUE;
2203 if (fvdef == fvnone)
2205 fvdef = fvnameseen; /* function or variable */
2206 *is_func_or_var = TRUE;
2207 return TRUE;
2211 return FALSE;
2215 * C_entries ()
2216 * This routine finds functions, variables, typedefs,
2217 * #define's, enum constants and struct/union/enum definitions in
2218 * #C syntax and adds them to the list.
2220 #define current_lb_is_new (newndx == curndx)
2221 #define switch_line_buffers() (curndx = 1 - curndx)
2223 #define curlb (lbs[curndx].lb)
2224 #define othlb (lbs[1-curndx].lb)
2225 #define newlb (lbs[newndx].lb)
2226 #define curlinepos (lbs[curndx].linepos)
2227 #define othlinepos (lbs[1-curndx].linepos)
2228 #define newlinepos (lbs[newndx].linepos)
2230 #define CNL_SAVE_DEFINEDEF \
2231 do { \
2232 curlinepos = charno; \
2233 lineno++; \
2234 linecharno = charno; \
2235 charno += readline (&curlb, inf); \
2236 lp = curlb.buffer; \
2237 quotednl = FALSE; \
2238 newndx = curndx; \
2239 } while (0)
2241 #define CNL \
2242 do { \
2243 CNL_SAVE_DEFINEDEF; \
2244 if (savetok.valid) \
2246 tok = savetok; \
2247 savetok.valid = FALSE; \
2249 definedef = dnone; \
2250 } while (0)
2253 void
2254 make_C_tag (isfun)
2255 bool isfun;
2257 /* This function should never be called when tok.valid is FALSE, but
2258 we must protect against invalid input or internal errors. */
2259 if (tok.valid)
2261 if (traditional_tag_style)
2263 /* This was the original code. Now we call new_pfnote instead,
2264 which uses the new method for naming tags (see new_pfnote). */
2265 char *name = NULL;
2267 if (CTAGS || tok.named)
2268 name = savestr (token_name.buffer);
2269 pfnote (name, isfun,
2270 tok.buffer, tok.linelen, tok.lineno, tok.linepos);
2272 else
2273 new_pfnote (token_name.buffer, token_name.len, isfun,
2274 tok.buffer, tok.linelen, tok.lineno, tok.linepos);
2275 tok.valid = FALSE;
2277 else if (DEBUG)
2278 abort ();
2282 void
2283 C_entries (c_ext, inf)
2284 int c_ext; /* extension of C */
2285 FILE *inf; /* input file */
2287 register char c; /* latest char read; '\0' for end of line */
2288 register char *lp; /* pointer one beyond the character `c' */
2289 int curndx, newndx; /* indices for current and new lb */
2290 register int tokoff; /* offset in line of start of current token */
2291 register int toklen; /* length of current token */
2292 char *qualifier; /* string used to qualify names */
2293 int qlen; /* length of qualifier */
2294 int cblev; /* current curly brace level */
2295 int parlev; /* current parenthesis level */
2296 bool incomm, inquote, inchar, quotednl, midtoken;
2297 bool cplpl, cjava;
2298 TOKEN savetok; /* token saved during preprocessor handling */
2301 curndx = newndx = 0;
2302 lineno = 0;
2303 charno = 0;
2304 lp = curlb.buffer;
2305 *lp = 0;
2307 fvdef = fvnone; typdef = tnone; structdef = snone;
2308 definedef = dnone; objdef = onone;
2309 next_token_is_func = yacc_rules = FALSE;
2310 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2311 tok.valid = savetok.valid = FALSE;
2312 cblev = 0;
2313 parlev = 0;
2314 cplpl = (c_ext & C_PLPL) == C_PLPL;
2315 cjava = (c_ext & C_JAVA) == C_JAVA;
2316 if (cjava)
2317 { qualifier = "."; qlen = 1; }
2318 else
2319 { qualifier = "::"; qlen = 2; }
2321 while (!feof (inf))
2323 c = *lp++;
2324 if (c == '\\')
2326 /* If we're at the end of the line, the next character is a
2327 '\0'; don't skip it, because it's the thing that tells us
2328 to read the next line. */
2329 if (*lp == '\0')
2331 quotednl = TRUE;
2332 continue;
2334 lp++;
2335 c = ' ';
2337 else if (incomm)
2339 switch (c)
2341 case '*':
2342 if (*lp == '/')
2344 c = *lp++;
2345 incomm = FALSE;
2347 break;
2348 case '\0':
2349 /* Newlines inside comments do not end macro definitions in
2350 traditional cpp. */
2351 CNL_SAVE_DEFINEDEF;
2352 break;
2354 continue;
2356 else if (inquote)
2358 switch (c)
2360 case '"':
2361 inquote = FALSE;
2362 break;
2363 case '\0':
2364 /* Newlines inside strings do not end macro definitions
2365 in traditional cpp, even though compilers don't
2366 usually accept them. */
2367 CNL_SAVE_DEFINEDEF;
2368 break;
2370 continue;
2372 else if (inchar)
2374 switch (c)
2376 case '\0':
2377 /* Hmmm, something went wrong. */
2378 CNL;
2379 /* FALLTHRU */
2380 case '\'':
2381 inchar = FALSE;
2382 break;
2384 continue;
2386 else
2387 switch (c)
2389 case '"':
2390 inquote = TRUE;
2391 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2392 fvdef = fvnone;
2393 continue;
2394 case '\'':
2395 inchar = TRUE;
2396 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2397 fvdef = fvnone;
2398 continue;
2399 case '/':
2400 if (*lp == '*')
2402 lp++;
2403 incomm = TRUE;
2404 continue;
2406 else if (/* cplpl && */ *lp == '/')
2408 c = '\0';
2409 break;
2411 else
2412 break;
2413 case '%':
2414 if ((c_ext & YACC) && *lp == '%')
2416 /* entering or exiting rules section in yacc file */
2417 lp++;
2418 definedef = dnone; fvdef = fvnone;
2419 typdef = tnone; structdef = snone;
2420 next_token_is_func = FALSE;
2421 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2422 cblev = 0;
2423 yacc_rules = !yacc_rules;
2424 continue;
2426 else
2427 break;
2428 case '#':
2429 if (definedef == dnone)
2431 char *cp;
2432 bool cpptoken = TRUE;
2434 /* Look back on this line. If all blanks, or nonblanks
2435 followed by an end of comment, this is a preprocessor
2436 token. */
2437 for (cp = newlb.buffer; cp < lp-1; cp++)
2438 if (!iswhite (*cp))
2440 if (*cp == '*' && *(cp+1) == '/')
2442 cp++;
2443 cpptoken = TRUE;
2445 else
2446 cpptoken = FALSE;
2448 if (cpptoken)
2449 definedef = dsharpseen;
2450 } /* if (definedef == dnone) */
2452 continue;
2453 } /* switch (c) */
2456 /* Consider token only if some complicated conditions are satisfied. */
2457 if ((definedef != dnone
2458 || (cblev == 0 && structdef != scolonseen)
2459 || (cblev == 1 && cplpl && structdef == sinbody)
2460 || (structdef == sinbody && structtype == st_C_enum))
2461 && typdef != tignore
2462 && definedef != dignorerest
2463 && fvdef != finlist)
2465 if (midtoken)
2467 if (endtoken (c))
2469 if (c == ':' && cplpl && *lp == ':' && begtoken(*(lp + 1)))
2472 * This handles :: in the middle, but not at the
2473 * beginning of an identifier.
2475 lp += 2;
2476 toklen += 3;
2478 else
2480 bool funorvar = FALSE;
2482 if (yacc_rules
2483 || consider_token (newlb.buffer + tokoff, toklen, c,
2484 c_ext, cblev, parlev, &funorvar))
2486 tok.named = FALSE;
2487 if (structdef == sinbody
2488 && definedef == dnone
2489 && funorvar)
2490 /* function or var defined in C++ class body */
2492 int len = strlen (structtag) + qlen + toklen;
2493 grow_linebuffer (&token_name, len + 1);
2494 strcpy (token_name.buffer, structtag);
2495 strcat (token_name.buffer, qualifier);
2496 strncat (token_name.buffer,
2497 newlb.buffer + tokoff, toklen);
2498 token_name.len = len;
2499 tok.named = TRUE;
2501 else if (objdef == ocatseen)
2502 /* Objective C category */
2504 int len = strlen (objtag) + 2 + toklen;
2505 grow_linebuffer (&token_name, len + 1);
2506 strcpy (token_name.buffer, objtag);
2507 strcat (token_name.buffer, "(");
2508 strncat (token_name.buffer,
2509 newlb.buffer + tokoff, toklen);
2510 strcat (token_name.buffer, ")");
2511 token_name.len = len;
2512 tok.named = TRUE;
2514 else if (objdef == omethodtag
2515 || objdef == omethodparm)
2516 /* Objective C method */
2518 tok.named = TRUE;
2520 else
2522 grow_linebuffer (&token_name, toklen + 1);
2523 strncpy (token_name.buffer,
2524 newlb.buffer + tokoff, toklen);
2525 token_name.buffer[toklen] = '\0';
2526 token_name.len = toklen;
2527 /* Name macros. */
2528 tok.named = (structdef == stagseen
2529 || typdef == tend
2530 || (funorvar
2531 && definedef == dignorerest));
2533 tok.lineno = lineno;
2534 tok.linelen = tokoff + toklen + 1;
2535 tok.buffer = newlb.buffer;
2536 tok.linepos = newlinepos;
2537 tok.valid = TRUE;
2539 if (definedef == dnone
2540 && (fvdef == fvnameseen
2541 || structdef == stagseen
2542 || typdef == tend
2543 || objdef != onone))
2545 if (current_lb_is_new)
2546 switch_line_buffers ();
2548 else
2549 make_C_tag (funorvar);
2551 midtoken = FALSE;
2553 } /* if (endtoken (c)) */
2554 else if (intoken (c))
2556 toklen++;
2557 continue;
2559 } /* if (midtoken) */
2560 else if (begtoken (c))
2562 switch (definedef)
2564 case dnone:
2565 switch (fvdef)
2567 case fstartlist:
2568 fvdef = finlist;
2569 continue;
2570 case flistseen:
2571 make_C_tag (TRUE); /* a function */
2572 fvdef = fignore;
2573 break;
2574 case fvnameseen:
2575 fvdef = fvnone;
2576 break;
2578 if (structdef == stagseen && !cjava)
2579 structdef = snone;
2580 break;
2581 case dsharpseen:
2582 savetok = tok;
2584 if (!yacc_rules || lp == newlb.buffer + 1)
2586 tokoff = lp - 1 - newlb.buffer;
2587 toklen = 1;
2588 midtoken = TRUE;
2590 continue;
2591 } /* if (begtoken) */
2592 } /* if must look at token */
2595 /* Detect end of line, colon, comma, semicolon and various braces
2596 after having handled a token.*/
2597 switch (c)
2599 case ':':
2600 if (definedef != dnone)
2601 break;
2602 switch (objdef)
2604 case otagseen:
2605 objdef = oignore;
2606 make_C_tag (TRUE); /* an Objective C class */
2607 break;
2608 case omethodtag:
2609 case omethodparm:
2610 objdef = omethodcolon;
2611 methodlen += 1;
2612 grow_linebuffer (&token_name, methodlen + 1);
2613 strcat (token_name.buffer, ":");
2614 token_name.len = methodlen;
2615 break;
2617 if (structdef == stagseen)
2618 structdef = scolonseen;
2619 else
2620 switch (fvdef)
2622 case fvnameseen:
2623 if (yacc_rules)
2625 make_C_tag (FALSE); /* a yacc function */
2626 fvdef = fignore;
2628 break;
2629 case fstartlist:
2630 fvdef = fvnone;
2631 break;
2633 break;
2634 case ';':
2635 if (definedef != dnone)
2636 break;
2637 if (cblev == 0)
2638 switch (typdef)
2640 case tend:
2641 make_C_tag (FALSE); /* a typedef */
2642 /* FALLTHRU */
2643 default:
2644 typdef = tnone;
2646 switch (fvdef)
2648 case fignore:
2649 break;
2650 case fvnameseen:
2651 if ((globals && cblev == 0) || (members && cblev == 1))
2652 make_C_tag (FALSE); /* a variable */
2653 /* FALLTHRU */
2654 default:
2655 fvdef = fvnone;
2656 /* The following instruction invalidates the token.
2657 Probably the token should be invalidated in all
2658 other cases where some state machine is reset. */
2659 tok.valid = FALSE;
2661 if (structdef == stagseen)
2662 structdef = snone;
2663 break;
2664 case ',':
2665 if (definedef != dnone)
2666 break;
2667 switch (objdef)
2669 case omethodtag:
2670 case omethodparm:
2671 make_C_tag (TRUE); /* an Objective C method */
2672 objdef = oinbody;
2673 break;
2675 switch (fvdef)
2677 case finlist:
2678 case fignore:
2679 case vignore:
2680 break;
2681 case fvnameseen:
2682 if ((globals && cblev == 0) || (members && cblev == 1))
2683 make_C_tag (FALSE); /* a variable */
2684 break;
2685 default:
2686 fvdef = fvnone;
2688 if (structdef == stagseen)
2689 structdef = snone;
2690 break;
2691 case '[':
2692 if (definedef != dnone)
2693 break;
2694 if (cblev == 0 && typdef == tend)
2696 typdef = tignore;
2697 make_C_tag (FALSE); /* a typedef */
2698 break;
2700 switch (fvdef)
2702 case finlist:
2703 case fignore:
2704 case vignore:
2705 break;
2706 case fvnameseen:
2707 if ((globals && cblev == 0) || (members && cblev == 1))
2708 make_C_tag (FALSE); /* a variable */
2709 /* FALLTHRU */
2710 default:
2711 fvdef = fvnone;
2713 if (structdef == stagseen)
2714 structdef = snone;
2715 break;
2716 case '(':
2717 if (definedef != dnone)
2718 break;
2719 if (objdef == otagseen && parlev == 0)
2720 objdef = oparenseen;
2721 switch (fvdef)
2723 case fvnone:
2724 switch (typdef)
2726 case ttypedseen:
2727 case tend:
2728 if (tok.valid && *lp != '*')
2730 /* This handles constructs like:
2731 typedef void OperatorFun (int fun); */
2732 make_C_tag (FALSE);
2733 typdef = tignore;
2735 break;
2736 } /* switch (typdef) */
2737 break;
2738 case fvnameseen:
2739 fvdef = fstartlist;
2740 break;
2741 case flistseen:
2742 fvdef = finlist;
2743 break;
2745 parlev++;
2746 break;
2747 case ')':
2748 if (definedef != dnone)
2749 break;
2750 if (objdef == ocatseen && parlev == 1)
2752 make_C_tag (TRUE); /* an Objective C category */
2753 objdef = oignore;
2755 if (--parlev == 0)
2757 switch (fvdef)
2759 case fstartlist:
2760 case finlist:
2761 fvdef = flistseen;
2762 break;
2764 if (cblev == 0 && typdef == tend)
2766 typdef = tignore;
2767 make_C_tag (FALSE); /* a typedef */
2770 else if (parlev < 0) /* can happen due to ill-conceived #if's. */
2771 parlev = 0;
2772 break;
2773 case '{':
2774 if (definedef != dnone)
2775 break;
2776 if (typdef == ttypedseen)
2777 typdef = tinbody;
2778 switch (structdef)
2780 case skeyseen: /* unnamed struct */
2781 structdef = sinbody;
2782 structtag = "_anonymous_";
2783 break;
2784 case stagseen:
2785 case scolonseen: /* named struct */
2786 structdef = sinbody;
2787 make_C_tag (FALSE); /* a struct */
2788 break;
2790 switch (fvdef)
2792 case flistseen:
2793 make_C_tag (TRUE); /* a function */
2794 /* FALLTHRU */
2795 case fignore:
2796 fvdef = fvnone;
2797 break;
2798 case fvnone:
2799 switch (objdef)
2801 case otagseen:
2802 make_C_tag (TRUE); /* an Objective C class */
2803 objdef = oignore;
2804 break;
2805 case omethodtag:
2806 case omethodparm:
2807 make_C_tag (TRUE); /* an Objective C method */
2808 objdef = oinbody;
2809 break;
2810 default:
2811 /* Neutralize `extern "C" {' grot. */
2812 if (cblev == 0 && structdef == snone && typdef == tnone)
2813 cblev = -1;
2816 cblev++;
2817 break;
2818 case '*':
2819 if (definedef != dnone)
2820 break;
2821 if (fvdef == fstartlist)
2822 fvdef = fvnone; /* avoid tagging `foo' in `foo (*bar()) ()' */
2823 break;
2824 case '}':
2825 if (definedef != dnone)
2826 break;
2827 if (!noindentypedefs && lp == newlb.buffer + 1)
2829 cblev = 0; /* reset curly brace level if first column */
2830 parlev = 0; /* also reset paren level, just in case... */
2832 else if (cblev > 0)
2833 cblev--;
2834 if (cblev == 0)
2836 if (typdef == tinbody)
2837 typdef = tend;
2838 /* Memory leakage here: the string pointed by structtag is
2839 never released, because I fear to miss something and
2840 break things while freeing the area. The amount of
2841 memory leaked here is the sum of the lengths of the
2842 struct tags.
2843 if (structdef == sinbody)
2844 free (structtag); */
2846 structdef = snone;
2847 structtag = "<error>";
2849 break;
2850 case '=':
2851 if (definedef != dnone)
2852 break;
2853 switch (fvdef)
2855 case finlist:
2856 case fignore:
2857 case vignore:
2858 break;
2859 case fvnameseen:
2860 if ((globals && cblev == 0) || (members && cblev == 1))
2861 make_C_tag (FALSE); /* a variable */
2862 /* FALLTHRU */
2863 default:
2864 fvdef = vignore;
2866 break;
2867 case '+':
2868 case '-':
2869 if (objdef == oinbody && cblev == 0)
2871 objdef = omethodsign;
2872 break;
2874 /* FALLTHRU */
2875 case '#': case '~': case '&': case '%': case '/': case '|':
2876 case '^': case '!': case '<': case '>': case '.': case '?': case ']':
2877 if (definedef != dnone)
2878 break;
2879 /* These surely cannot follow a function tag. */
2880 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2881 fvdef = fvnone;
2882 break;
2883 case '\0':
2884 if (objdef == otagseen)
2886 make_C_tag (TRUE); /* an Objective C class */
2887 objdef = oignore;
2889 /* If a macro spans multiple lines don't reset its state. */
2890 if (quotednl)
2891 CNL_SAVE_DEFINEDEF;
2892 else
2893 CNL;
2894 break;
2895 } /* switch (c) */
2897 } /* while not eof */
2901 * Process either a C++ file or a C file depending on the setting
2902 * of a global flag.
2904 void
2905 default_C_entries (inf)
2906 FILE *inf;
2908 C_entries (cplusplus ? C_PLPL : 0, inf);
2911 /* Always do plain ANSI C. */
2912 void
2913 plain_C_entries (inf)
2914 FILE *inf;
2916 C_entries (0, inf);
2919 /* Always do C++. */
2920 void
2921 Cplusplus_entries (inf)
2922 FILE *inf;
2924 C_entries (C_PLPL, inf);
2927 /* Always do Java. */
2928 void
2929 Cjava_entries (inf)
2930 FILE *inf;
2932 C_entries (C_JAVA, inf);
2935 /* Always do C*. */
2936 void
2937 Cstar_entries (inf)
2938 FILE *inf;
2940 C_entries (C_STAR, inf);
2943 /* Always do Yacc. */
2944 void
2945 Yacc_entries (inf)
2946 FILE *inf;
2948 C_entries (YACC, inf);
2951 /* Fortran parsing */
2953 char *dbp;
2955 bool
2956 tail (cp)
2957 char *cp;
2959 register int len = 0;
2961 while (*cp && lowcase(*cp) == lowcase(dbp[len]))
2962 cp++, len++;
2963 if (*cp == '\0' && !intoken(dbp[len]))
2965 dbp += len;
2966 return TRUE;
2968 return FALSE;
2971 void
2972 takeprec ()
2974 while (isspace (*dbp))
2975 dbp++;
2976 if (*dbp != '*')
2977 return;
2978 dbp++;
2979 while (isspace (*dbp))
2980 dbp++;
2981 if (strneq (dbp, "(*)", 3))
2983 dbp += 3;
2984 return;
2986 if (!isdigit (*dbp))
2988 --dbp; /* force failure */
2989 return;
2992 dbp++;
2993 while (isdigit (*dbp));
2996 void
2997 getit (inf)
2998 FILE *inf;
3000 register char *cp;
3002 while (isspace (*dbp))
3003 dbp++;
3004 if (*dbp == '\0')
3006 lineno++;
3007 linecharno = charno;
3008 charno += readline (&lb, inf);
3009 dbp = lb.buffer;
3010 if (dbp[5] != '&')
3011 return;
3012 dbp += 6;
3013 while (isspace (*dbp))
3014 dbp++;
3016 if (!isalpha (*dbp)
3017 && *dbp != '_'
3018 && *dbp != '$')
3019 return;
3020 for (cp = dbp + 1;
3021 (*cp
3022 && (isalpha (*cp) || isdigit (*cp) || (*cp == '_') || (*cp == '$')));
3023 cp++)
3024 continue;
3025 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
3026 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3029 void
3030 Fortran_functions (inf)
3031 FILE *inf;
3033 lineno = 0;
3034 charno = 0;
3036 while (!feof (inf))
3038 lineno++;
3039 linecharno = charno;
3040 charno += readline (&lb, inf);
3041 dbp = lb.buffer;
3042 if (*dbp == '%')
3043 dbp++; /* Ratfor escape to fortran */
3044 while (isspace (*dbp))
3045 dbp++;
3046 if (*dbp == '\0')
3047 continue;
3048 switch (lowcase (*dbp))
3050 case 'i':
3051 if (tail ("integer"))
3052 takeprec ();
3053 break;
3054 case 'r':
3055 if (tail ("real"))
3056 takeprec ();
3057 break;
3058 case 'l':
3059 if (tail ("logical"))
3060 takeprec ();
3061 break;
3062 case 'c':
3063 if (tail ("complex") || tail ("character"))
3064 takeprec ();
3065 break;
3066 case 'd':
3067 if (tail ("double"))
3069 while (isspace (*dbp))
3070 dbp++;
3071 if (*dbp == '\0')
3072 continue;
3073 if (tail ("precision"))
3074 break;
3075 continue;
3077 break;
3079 while (isspace (*dbp))
3080 dbp++;
3081 if (*dbp == '\0')
3082 continue;
3083 switch (lowcase (*dbp))
3085 case 'f':
3086 if (tail ("function"))
3087 getit (inf);
3088 continue;
3089 case 's':
3090 if (tail ("subroutine"))
3091 getit (inf);
3092 continue;
3093 case 'e':
3094 if (tail ("entry"))
3095 getit (inf);
3096 continue;
3097 case 'p':
3098 if (tail ("program"))
3100 getit (inf);
3101 continue;
3103 if (tail ("procedure"))
3104 getit (inf);
3105 continue;
3111 * Bob Weiner, Motorola Inc., 4/3/94
3112 * Unix and microcontroller assembly tag handling
3113 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
3115 void
3116 Asm_labels (inf)
3117 FILE *inf;
3119 register char *cp;
3121 lineno = 0;
3122 charno = 0;
3124 while (!feof (inf))
3126 lineno++;
3127 linecharno = charno;
3128 charno += readline (&lb, inf);
3129 cp = lb.buffer;
3131 /* If first char is alphabetic or one of [_.$], test for colon
3132 following identifier. */
3133 if (isalpha (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3135 /* Read past label. */
3136 cp++;
3137 while (isalnum (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3138 cp++;
3139 if (*cp == ':' || isspace (*cp))
3141 /* Found end of label, so copy it and add it to the table. */
3142 pfnote ((CTAGS) ? savenstr(lb.buffer, cp-lb.buffer) : NULL, TRUE,
3143 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3150 * Perl support by Bart Robinson <lomew@cs.utah.edu>
3151 * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/
3153 void
3154 Perl_functions (inf)
3155 FILE *inf;
3157 register char *cp;
3159 lineno = 0;
3160 charno = 0;
3162 while (!feof (inf))
3164 lineno++;
3165 linecharno = charno;
3166 charno += readline (&lb, inf);
3167 cp = lb.buffer;
3169 if (*cp++ == 's' && *cp++ == 'u' && *cp++ == 'b' && isspace (*cp++))
3171 while (*cp && isspace (*cp))
3172 cp++;
3173 while (*cp && ! isspace (*cp) && *cp != '{')
3174 cp++;
3175 pfnote ((CTAGS) ? savenstr (lb.buffer, cp-lb.buffer) : NULL, TRUE,
3176 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3181 /* Idea by Corny de Souza
3182 * Cobol tag functions
3183 * We could look for anything that could be a paragraph name.
3184 * i.e. anything that starts in column 8 is one word and ends in a full stop.
3186 void
3187 Cobol_paragraphs (inf)
3188 FILE *inf;
3190 register char *cp;
3192 lineno = 0;
3193 charno = 0;
3195 while (!feof (inf))
3197 lineno++;
3198 linecharno = charno;
3199 charno += readline (&lb, inf);
3201 if (lb.len < 9)
3202 continue;
3203 dbp = lb.buffer + 8;
3205 /* If eoln, compiler option or comment ignore whole line. */
3206 if (dbp[-1] != ' ' || !isalnum (dbp[0]))
3207 continue;
3209 for (cp = dbp; isalnum (*cp) || *cp == '-'; cp++)
3210 continue;
3211 if (*cp++ == '.')
3212 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
3213 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3217 /* Added by Mosur Mohan, 4/22/88 */
3218 /* Pascal parsing */
3221 * Locates tags for procedures & functions. Doesn't do any type- or
3222 * var-definitions. It does look for the keyword "extern" or
3223 * "forward" immediately following the procedure statement; if found,
3224 * the tag is skipped.
3226 void
3227 Pascal_functions (inf)
3228 FILE *inf;
3230 struct linebuffer tline; /* mostly copied from C_entries */
3231 long save_lcno;
3232 int save_lineno, save_len;
3233 char c, *cp, *namebuf;
3235 bool /* each of these flags is TRUE iff: */
3236 incomment, /* point is inside a comment */
3237 inquote, /* point is inside '..' string */
3238 get_tagname, /* point is after PROCEDURE/FUNCTION
3239 keyword, so next item = potential tag */
3240 found_tag, /* point is after a potential tag */
3241 inparms, /* point is within parameter-list */
3242 verify_tag; /* point has passed the parm-list, so the
3243 next token will determine whether this
3244 is a FORWARD/EXTERN to be ignored, or
3245 whether it is a real tag */
3247 lineno = 0;
3248 charno = 0;
3249 dbp = lb.buffer;
3250 *dbp = '\0';
3251 save_len = 0;
3252 initbuffer (&tline);
3254 incomment = inquote = FALSE;
3255 found_tag = FALSE; /* have a proc name; check if extern */
3256 get_tagname = FALSE; /* have found "procedure" keyword */
3257 inparms = FALSE; /* found '(' after "proc" */
3258 verify_tag = FALSE; /* check if "extern" is ahead */
3260 /* long main loop to get next char */
3261 while (!feof (inf))
3263 c = *dbp++;
3264 if (c == '\0') /* if end of line */
3266 lineno++;
3267 linecharno = charno;
3268 charno += readline (&lb, inf);
3269 dbp = lb.buffer;
3270 if (*dbp == '\0')
3271 continue;
3272 if (!((found_tag && verify_tag) ||
3273 get_tagname))
3274 c = *dbp++; /* only if don't need *dbp pointing
3275 to the beginning of the name of
3276 the procedure or function */
3278 if (incomment)
3280 if (c == '}') /* within { } comments */
3281 incomment = FALSE;
3282 else if (c == '*' && *dbp == ')') /* within (* *) comments */
3284 dbp++;
3285 incomment = FALSE;
3287 continue;
3289 else if (inquote)
3291 if (c == '\'')
3292 inquote = FALSE;
3293 continue;
3295 else
3296 switch (c)
3298 case '\'':
3299 inquote = TRUE; /* found first quote */
3300 continue;
3301 case '{': /* found open { comment */
3302 incomment = TRUE;
3303 continue;
3304 case '(':
3305 if (*dbp == '*') /* found open (* comment */
3307 incomment = TRUE;
3308 dbp++;
3310 else if (found_tag) /* found '(' after tag, i.e., parm-list */
3311 inparms = TRUE;
3312 continue;
3313 case ')': /* end of parms list */
3314 if (inparms)
3315 inparms = FALSE;
3316 continue;
3317 case ';':
3318 if (found_tag && !inparms) /* end of proc or fn stmt */
3320 verify_tag = TRUE;
3321 break;
3323 continue;
3325 if (found_tag && verify_tag && (*dbp != ' '))
3327 /* check if this is an "extern" declaration */
3328 if (*dbp == '\0')
3329 continue;
3330 if (lowcase (*dbp == 'e'))
3332 if (tail ("extern")) /* superfluous, really! */
3334 found_tag = FALSE;
3335 verify_tag = FALSE;
3338 else if (lowcase (*dbp) == 'f')
3340 if (tail ("forward")) /* check for forward reference */
3342 found_tag = FALSE;
3343 verify_tag = FALSE;
3346 if (found_tag && verify_tag) /* not external proc, so make tag */
3348 found_tag = FALSE;
3349 verify_tag = FALSE;
3350 pfnote (namebuf, TRUE,
3351 tline.buffer, save_len, save_lineno, save_lcno);
3352 continue;
3355 if (get_tagname) /* grab name of proc or fn */
3357 if (*dbp == '\0')
3358 continue;
3360 /* save all values for later tagging */
3361 grow_linebuffer (&tline, lb.len + 1);
3362 strcpy (tline.buffer, lb.buffer);
3363 save_lineno = lineno;
3364 save_lcno = linecharno;
3366 /* grab block name */
3367 for (cp = dbp + 1; *cp != '\0' && !endtoken (*cp); cp++)
3368 continue;
3369 namebuf = (CTAGS) ? savenstr (dbp, cp-dbp) : NULL;
3370 dbp = cp; /* set dbp to e-o-token */
3371 save_len = dbp - lb.buffer + 1;
3372 get_tagname = FALSE;
3373 found_tag = TRUE;
3374 continue;
3376 /* and proceed to check for "extern" */
3378 else if (!incomment && !inquote && !found_tag)
3380 /* check for proc/fn keywords */
3381 switch (lowcase (c))
3383 case 'p':
3384 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
3385 get_tagname = TRUE;
3386 continue;
3387 case 'f':
3388 if (tail ("unction"))
3389 get_tagname = TRUE;
3390 continue;
3393 } /* while not eof */
3395 free (tline.buffer);
3399 * lisp tag functions
3400 * look for (def or (DEF, quote or QUOTE
3403 L_isdef (strp)
3404 register char *strp;
3406 return ((strp[1] == 'd' || strp[1] == 'D')
3407 && (strp[2] == 'e' || strp[2] == 'E')
3408 && (strp[3] == 'f' || strp[3] == 'F'));
3412 L_isquote (strp)
3413 register char *strp;
3415 return ((*(++strp) == 'q' || *strp == 'Q')
3416 && (*(++strp) == 'u' || *strp == 'U')
3417 && (*(++strp) == 'o' || *strp == 'O')
3418 && (*(++strp) == 't' || *strp == 'T')
3419 && (*(++strp) == 'e' || *strp == 'E')
3420 && isspace (*(++strp)));
3423 void
3424 L_getit ()
3426 register char *cp;
3428 if (*dbp == '\'') /* Skip prefix quote */
3429 dbp++;
3430 else if (*dbp == '(' && L_isquote (dbp)) /* Skip "(quote " */
3432 dbp += 7;
3433 while (isspace (*dbp))
3434 dbp++;
3436 for (cp = dbp /*+1*/;
3437 *cp != '\0' && *cp != '(' && *cp != ' ' && *cp != ')';
3438 cp++)
3439 continue;
3440 if (cp == dbp)
3441 return;
3443 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
3444 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3447 void
3448 Lisp_functions (inf)
3449 FILE *inf;
3451 lineno = 0;
3452 charno = 0;
3454 while (!feof (inf))
3456 lineno++;
3457 linecharno = charno;
3458 charno += readline (&lb, inf);
3459 dbp = lb.buffer;
3460 if (dbp[0] == '(')
3462 if (L_isdef (dbp))
3464 while (!isspace (*dbp))
3465 dbp++;
3466 while (isspace (*dbp))
3467 dbp++;
3468 L_getit ();
3470 else
3472 /* Check for (foo::defmumble name-defined ... */
3474 dbp++;
3475 while (*dbp && !isspace (*dbp)
3476 && *dbp != ':' && *dbp != '(' && *dbp != ')');
3477 if (*dbp == ':')
3480 dbp++;
3481 while (*dbp == ':');
3483 if (L_isdef (dbp - 1))
3485 while (!isspace (*dbp))
3486 dbp++;
3487 while (isspace (*dbp))
3488 dbp++;
3489 L_getit ();
3498 * Postscript tag functions
3499 * Just look for lines where the first character is '/'
3500 * Richard Mlynarik <mly@adoc.xerox.com>
3502 void
3503 Postscript_functions (inf)
3504 FILE *inf;
3506 lineno = 0;
3507 charno = 0;
3509 while (!feof (inf))
3511 lineno++;
3512 linecharno = charno;
3513 charno += readline (&lb, inf);
3514 dbp = lb.buffer;
3515 if (dbp[0] == '/')
3517 register char *cp;
3518 for (cp = dbp+1;
3519 *cp != '\0' && *cp != ' ' && *cp != '{';
3520 cp++)
3521 continue;
3522 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
3523 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3530 * Scheme tag functions
3531 * look for (def... xyzzy
3532 * look for (def... (xyzzy
3533 * look for (def ... ((...(xyzzy ....
3534 * look for (set! xyzzy
3537 void get_scheme ();
3539 void
3540 Scheme_functions (inf)
3541 FILE *inf;
3543 lineno = 0;
3544 charno = 0;
3546 while (!feof (inf))
3548 lineno++;
3549 linecharno = charno;
3550 charno += readline (&lb, inf);
3551 dbp = lb.buffer;
3552 if (dbp[0] == '(' &&
3553 (dbp[1] == 'D' || dbp[1] == 'd') &&
3554 (dbp[2] == 'E' || dbp[2] == 'e') &&
3555 (dbp[3] == 'F' || dbp[3] == 'f'))
3557 while (!isspace (*dbp))
3558 dbp++;
3559 /* Skip over open parens and white space */
3560 while (*dbp && (isspace (*dbp) || *dbp == '('))
3561 dbp++;
3562 get_scheme ();
3564 if (dbp[0] == '(' &&
3565 (dbp[1] == 'S' || dbp[1] == 's') &&
3566 (dbp[2] == 'E' || dbp[2] == 'e') &&
3567 (dbp[3] == 'T' || dbp[3] == 't') &&
3568 (dbp[4] == '!' || dbp[4] == '!') &&
3569 (isspace (dbp[5])))
3571 while (!isspace (*dbp))
3572 dbp++;
3573 /* Skip over white space */
3574 while (isspace (*dbp))
3575 dbp++;
3576 get_scheme ();
3581 void
3582 get_scheme ()
3584 register char *cp;
3586 if (*dbp == '\0')
3587 return;
3588 /* Go till you get to white space or a syntactic break */
3589 for (cp = dbp + 1;
3590 *cp && *cp != '(' && *cp != ')' && !isspace (*cp);
3591 cp++)
3592 continue;
3593 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
3594 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3597 /* Find tags in TeX and LaTeX input files. */
3599 /* TEX_toktab is a table of TeX control sequences that define tags.
3600 Each TEX_tabent records one such control sequence.
3601 CONVERT THIS TO USE THE Stab TYPE!! */
3602 struct TEX_tabent
3604 char *name;
3605 int len;
3608 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
3610 /* Default set of control sequences to put into TEX_toktab.
3611 The value of environment var TEXTAGS is prepended to this. */
3613 char *TEX_defenv = "\
3614 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
3615 :part:appendix:entry:index";
3617 void TEX_mode ();
3618 struct TEX_tabent *TEX_decode_env ();
3619 int TEX_Token ();
3621 char TEX_esc = '\\';
3622 char TEX_opgrp = '{';
3623 char TEX_clgrp = '}';
3626 * TeX/LaTeX scanning loop.
3628 void
3629 TeX_functions (inf)
3630 FILE *inf;
3632 char *lasthit;
3633 register int i;
3635 lineno = 0;
3636 charno = 0;
3638 /* Select either \ or ! as escape character. */
3639 TEX_mode (inf);
3641 /* Initialize token table once from environment. */
3642 if (!TEX_toktab)
3643 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
3645 while (!feof (inf))
3646 { /* Scan each line in file */
3647 lineno++;
3648 linecharno = charno;
3649 charno += readline (&lb, inf);
3650 dbp = lb.buffer;
3651 lasthit = dbp;
3652 while (dbp = etags_strchr (dbp, TEX_esc)) /* Look at each esc in line */
3654 if (!*(++dbp))
3655 break;
3656 linecharno += dbp - lasthit;
3657 lasthit = dbp;
3658 i = TEX_Token (lasthit);
3659 if (i >= 0)
3661 /* We seem to include the TeX command in the tag name.
3662 register char *p;
3663 for (p = lasthit + TEX_toktab[i].len;
3664 *p != '\0' && *p != TEX_clgrp;
3665 p++)
3666 continue; */
3667 pfnote (/*savenstr (lasthit, p-lasthit)*/ (char *)NULL, TRUE,
3668 lb.buffer, lb.len, lineno, linecharno);
3669 break; /* We only tag a line once */
3675 #define TEX_LESC '\\'
3676 #define TEX_SESC '!'
3677 #define TEX_cmt '%'
3679 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
3680 chars accordingly. */
3681 void
3682 TEX_mode (inf)
3683 FILE *inf;
3685 int c;
3687 while ((c = getc (inf)) != EOF)
3689 /* Skip to next line if we hit the TeX comment char. */
3690 if (c == TEX_cmt)
3691 while (c != '\n')
3692 c = getc (inf);
3693 else if (c == TEX_LESC || c == TEX_SESC )
3694 break;
3697 if (c == TEX_LESC)
3699 TEX_esc = TEX_LESC;
3700 TEX_opgrp = '{';
3701 TEX_clgrp = '}';
3703 else
3705 TEX_esc = TEX_SESC;
3706 TEX_opgrp = '<';
3707 TEX_clgrp = '>';
3709 rewind (inf);
3712 /* Read environment and prepend it to the default string.
3713 Build token table. */
3714 struct TEX_tabent *
3715 TEX_decode_env (evarname, defenv)
3716 char *evarname;
3717 char *defenv;
3719 register char *env, *p;
3721 struct TEX_tabent *tab;
3722 int size, i;
3724 /* Append default string to environment. */
3725 env = getenv (evarname);
3726 if (!env)
3727 env = defenv;
3728 else
3730 char *oldenv = env;
3731 env = concat (oldenv, defenv, "");
3732 free (oldenv);
3735 /* Allocate a token table */
3736 for (size = 1, p = env; p;)
3737 if ((p = etags_strchr (p, ':')) && *(++p))
3738 size++;
3739 /* Add 1 to leave room for null terminator. */
3740 tab = xnew (size + 1, struct TEX_tabent);
3742 /* Unpack environment string into token table. Be careful about */
3743 /* zero-length strings (leading ':', "::" and trailing ':') */
3744 for (i = 0; *env;)
3746 p = etags_strchr (env, ':');
3747 if (!p) /* End of environment string. */
3748 p = env + strlen (env);
3749 if (p - env > 0)
3750 { /* Only non-zero strings. */
3751 tab[i].name = savenstr (env, p - env);
3752 tab[i].len = strlen (tab[i].name);
3753 i++;
3755 if (*p)
3756 env = p + 1;
3757 else
3759 tab[i].name = NULL; /* Mark end of table. */
3760 tab[i].len = 0;
3761 break;
3764 return tab;
3767 /* If the text at CP matches one of the tag-defining TeX command names,
3768 return the pointer to the first occurrence of that command in TEX_toktab.
3769 Otherwise return -1.
3770 Keep the capital `T' in `Token' for dumb truncating compilers
3771 (this distinguishes it from `TEX_toktab' */
3773 TEX_Token (cp)
3774 char *cp;
3776 int i;
3778 for (i = 0; TEX_toktab[i].len > 0; i++)
3779 if (strneq (TEX_toktab[i].name, cp, TEX_toktab[i].len))
3780 return i;
3781 return -1;
3785 * Prolog support (rewritten) by Anders Lindgren, Mar. 96
3787 * Assumes that the predicate starts at column 0.
3788 * Only the first clause of a predicate is added.
3790 int prolog_pred ();
3791 void prolog_skip_comment ();
3792 int prolog_atom ();
3793 int eat_white ();
3795 void
3796 Prolog_functions (inf)
3797 FILE *inf;
3799 char * last;
3800 int len;
3801 int allocated;
3803 allocated = 0;
3804 len = 0;
3805 last = NULL;
3807 lineno = 0;
3808 linecharno = 0;
3809 charno = 0;
3811 while (!feof (inf))
3813 lineno++;
3814 linecharno += charno;
3815 charno = readline (&lb, inf);
3816 dbp = lb.buffer;
3817 if (dbp[0] == '\0') /* Empty line */
3818 continue;
3819 else if (isspace (dbp[0])) /* Not a predicate */
3820 continue;
3821 else if (dbp[0] == '/' && dbp[1] == '*') /* comment. */
3822 prolog_skip_comment (&lb, inf);
3823 else if (len = prolog_pred (dbp, last))
3825 /* Predicate. Store the function name so that we only
3826 generate a tag for the first clause. */
3827 if (last == NULL)
3828 last = xnew(len + 1, char);
3829 else if (len + 1 > allocated)
3830 last = (char *) xrealloc(last, len + 1);
3831 allocated = len + 1;
3832 strncpy (last, dbp, len);
3833 last[len] = '\0';
3839 void
3840 prolog_skip_comment (plb, inf)
3841 struct linebuffer *plb;
3842 FILE *inf;
3844 char *cp;
3848 for (cp = plb->buffer; *cp != '\0'; cp++)
3849 if (cp[0] == '*' && cp[1] == '/')
3850 return;
3851 lineno++;
3852 linecharno += readline (plb, inf);
3854 while (!feof(inf));
3858 * A predicate definition is added if it matches:
3859 * <beginning of line><Prolog Atom><whitespace>(
3861 * It is added to the tags database if it doesn't match the
3862 * name of the previous clause header.
3864 * Return the size of the name of the predicate, or 0 if no header
3865 * was found.
3868 prolog_pred (s, last)
3869 char *s;
3870 char *last; /* Name of last clause. */
3872 int pos;
3873 int len;
3875 pos = prolog_atom (s, 0);
3876 if (pos < 1)
3877 return 0;
3879 len = pos;
3880 pos += eat_white (s, pos);
3882 if ((s[pos] == '(') || (s[pos] == '.'))
3884 if (s[pos] == '(')
3885 pos++;
3887 /* Save only the first clause. */
3888 if (last == NULL
3889 || len != strlen (last)
3890 || !strneq (s, last, len))
3892 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
3893 s, pos, lineno, linecharno);
3894 return len;
3897 return 0;
3901 * Consume a Prolog atom.
3902 * Return the number of bytes consumed, or -1 if there was an error.
3904 * A prolog atom, in this context, could be one of:
3905 * - An alphanumeric sequence, starting with a lower case letter.
3906 * - A quoted arbitrary string. Single quotes can escape themselves.
3907 * Backslash quotes everything.
3910 prolog_atom (s, pos)
3911 char *s;
3912 int pos;
3914 int origpos;
3916 origpos = pos;
3918 if (islower(s[pos]) || (s[pos] == '_'))
3920 /* The atom is unquoted. */
3921 pos++;
3922 while (isalnum(s[pos]) || (s[pos] == '_'))
3924 pos++;
3926 return pos - origpos;
3928 else if (s[pos] == '\'')
3930 pos++;
3932 while (1)
3934 if (s[pos] == '\'')
3936 pos++;
3937 if (s[pos] != '\'')
3938 break;
3939 pos++; /* A double quote */
3941 else if (s[pos] == '\0')
3942 /* Multiline quoted atoms are ignored. */
3943 return -1;
3944 else if (s[pos] == '\\')
3946 if (s[pos+1] == '\0')
3947 return -1;
3948 pos += 2;
3950 else
3951 pos++;
3953 return pos - origpos;
3955 else
3956 return -1;
3959 /* Consume whitespace. Return the number of bytes eaten. */
3961 eat_white (s, pos)
3962 char *s;
3963 int pos;
3965 int origpos = pos;
3967 origpos = pos;
3969 while (isspace (s[pos]))
3970 pos++;
3972 return pos - origpos;
3976 * Support for Erlang -- Anders Lindgren, Feb 1996.
3978 * Generates tags for functions, defines, and records.
3980 * Assumes that Erlang functions start at column 0.
3982 int erlang_func ();
3983 void erlang_attribute ();
3984 int erlang_atom ();
3986 void
3987 Erlang_functions (inf)
3988 FILE *inf;
3990 char * last;
3991 int len;
3992 int allocated;
3994 allocated = 0;
3995 len = 0;
3996 last = NULL;
3998 lineno = 0;
3999 linecharno = 0;
4000 charno = 0;
4002 while (!feof (inf))
4004 lineno++;
4005 linecharno += charno;
4006 charno = readline (&lb, inf);
4007 dbp = lb.buffer;
4008 if (dbp[0] == '\0') /* Empty line */
4009 continue;
4010 else if (isspace (dbp[0])) /* Not function nor attribute */
4011 continue;
4012 else if (dbp[0] == '%') /* comment */
4013 continue;
4014 else if (dbp[0] == '"') /* Sometimes, strings start in column one */
4015 continue;
4016 else if (dbp[0] == '-') /* attribute, e.g. "-define" */
4018 erlang_attribute (dbp);
4019 last = NULL;
4021 else if (len = erlang_func (dbp, last))
4024 * Function. Store the function name so that we only
4025 * generates a tag for the first clause.
4027 if (last == NULL)
4028 last = xnew (len + 1, char);
4029 else if (len + 1 > allocated)
4030 last = (char *) xrealloc (last, len + 1);
4031 allocated = len + 1;
4032 strncpy (last, dbp, len);
4033 last[len] = '\0';
4040 * A function definition is added if it matches:
4041 * <beginning of line><Erlang Atom><whitespace>(
4043 * It is added to the tags database if it doesn't match the
4044 * name of the previous clause header.
4046 * Return the size of the name of the function, or 0 if no function
4047 * was found.
4050 erlang_func (s, last)
4051 char *s;
4052 char *last; /* Name of last clause. */
4054 int pos;
4055 int len;
4057 pos = erlang_atom (s, 0);
4058 if (pos < 1)
4059 return 0;
4061 len = pos;
4062 pos += eat_white (s, pos);
4064 /* Save only the first clause. */
4065 if (s[pos++] == '('
4066 && (last == NULL
4067 || len != strlen (last)
4068 || !strneq (s, last, len)))
4070 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
4071 s, pos, lineno, linecharno);
4072 return len;
4075 return 0;
4080 * Handle attributes. Currently, tags are generated for defines
4081 * and records.
4083 * They are on the form:
4084 * -define(foo, bar).
4085 * -define(Foo(M, N), M+N).
4086 * -record(graph, {vtab = notable, cyclic = true}).
4088 void
4089 erlang_attribute (s)
4090 char *s;
4092 int pos;
4093 int len;
4095 if (strneq (s, "-define", 7) || strneq (s, "-record", 7))
4097 pos = 7 + eat_white (s, pos);
4098 if (s[pos++] == '(')
4100 pos += eat_white (s, pos);
4101 if (len = erlang_atom (s, pos))
4102 pfnote ((CTAGS) ? savenstr (& s[pos], len) : NULL, TRUE,
4103 s, pos + len, lineno, linecharno);
4106 return;
4111 * Consume an Erlang atom (or variable).
4112 * Return the number of bytes consumed, or -1 if there was an error.
4115 erlang_atom (s, pos)
4116 char *s;
4117 int pos;
4119 int origpos;
4121 origpos = pos;
4123 if (isalpha (s[pos]) || s[pos] == '_')
4125 /* The atom is unquoted. */
4126 pos++;
4127 while (isalnum (s[pos]) || s[pos] == '_')
4128 pos++;
4129 return pos - origpos;
4131 else if (s[pos] == '\'')
4133 pos++;
4135 while (1)
4137 if (s[pos] == '\'')
4139 pos++;
4140 break;
4142 else if (s[pos] == '\0')
4143 /* Multiline quoted atoms are ignored. */
4144 return -1;
4145 else if (s[pos] == '\\')
4147 if (s[pos+1] == '\0')
4148 return -1;
4149 pos += 2;
4151 else
4152 pos++;
4154 return pos - origpos;
4156 else
4157 return -1;
4160 #ifdef ETAGS_REGEXPS
4161 /* Take a string like "/blah/" and turn it into "blah", making sure
4162 that the first and last characters are the same, and handling
4163 quoted separator characters. Actually, stops on the occurrence of
4164 an unquoted separator. Also turns "\t" into a Tab character.
4165 Returns pointer to terminating separator. Works in place. Null
4166 terminates name string. */
4167 char *
4168 scan_separators (name)
4169 char *name;
4171 char sep = name[0];
4172 char *copyto = name;
4173 bool quoted = FALSE;
4175 for (++name; *name != '\0'; ++name)
4177 if (quoted)
4179 if (*name == 't')
4180 *copyto++ = '\t';
4181 else if (*name == sep)
4182 *copyto++ = sep;
4183 else
4185 /* Something else is quoted, so preserve the quote. */
4186 *copyto++ = '\\';
4187 *copyto++ = *name;
4189 quoted = FALSE;
4191 else if (*name == '\\')
4192 quoted = TRUE;
4193 else if (*name == sep)
4194 break;
4195 else
4196 *copyto++ = *name;
4199 /* Terminate copied string. */
4200 *copyto = '\0';
4201 return name;
4204 /* Look at the argument of --regex or --no-regex and do the right
4205 thing. */
4206 void
4207 analyse_regex (regex_arg)
4208 char *regex_arg;
4210 struct stat stat_buf;
4212 if (regex_arg == NULL)
4214 /* Remove existing regexps. */
4215 num_patterns = 0;
4216 patterns = NULL;
4217 return;
4219 if (regex_arg[0] == '\0')
4221 error ("missing regexp", (char *)NULL);
4222 return;
4224 if (regex_arg[0] == '@'
4225 && stat (regex_arg + 1, &stat_buf) == 0)
4227 FILE *regexfp;
4228 struct linebuffer regexbuf;
4229 char *regexfile = regex_arg + 1;
4231 /* regexfile is a file containing regexps, one per line. */
4232 regexfp = fopen (regexfile, "r");
4233 if (regexfp == NULL)
4235 perror (regexfile);
4236 return;
4238 initbuffer (&regexbuf);
4239 while (readline_internal (&regexbuf, regexfp))
4240 add_regex (regexbuf.buffer);
4241 free (regexbuf.buffer);
4242 fclose (regexfp);
4244 else
4246 add_regex (regex_arg);
4250 /* Turn a name, which is an ed-style (but Emacs syntax) regular
4251 expression, into a real regular expression by compiling it. */
4252 void
4253 add_regex (regexp_pattern)
4254 char *regexp_pattern;
4256 char *name;
4257 const char *err;
4258 struct re_pattern_buffer *patbuf;
4261 if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0])
4263 error ("%s: unterminated regexp", regexp_pattern);
4264 return;
4266 name = scan_separators (regexp_pattern);
4267 if (regexp_pattern[0] == '\0')
4269 error ("null regexp", (char *)NULL);
4270 return;
4272 (void) scan_separators (name);
4274 patbuf = xnew (1, struct re_pattern_buffer);
4275 patbuf->translate = NULL;
4276 patbuf->fastmap = NULL;
4277 patbuf->buffer = NULL;
4278 patbuf->allocated = 0;
4280 re_syntax_options = RE_INTERVALS;
4281 err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf);
4282 if (err != NULL)
4284 error ("%s while compiling pattern", err);
4285 return;
4288 num_patterns += 1;
4289 if (num_patterns == 1)
4290 patterns = xnew (1, struct pattern);
4291 else
4292 patterns = ((struct pattern *)
4293 xrealloc (patterns,
4294 (num_patterns * sizeof (struct pattern))));
4295 patterns[num_patterns - 1].pattern = patbuf;
4296 patterns[num_patterns - 1].name_pattern = savestr (name);
4297 patterns[num_patterns - 1].error_signaled = FALSE;
4301 * Do the substitutions indicated by the regular expression and
4302 * arguments.
4304 char *
4305 substitute (in, out, regs)
4306 char *in, *out;
4307 struct re_registers *regs;
4309 char *result, *t;
4310 int size, dig, diglen;
4312 result = NULL;
4313 size = strlen (out);
4315 /* Pass 1: figure out how much to allocate by finding all \N strings. */
4316 if (out[size - 1] == '\\')
4317 fatal ("pattern error in \"%s\"", out);
4318 for (t = etags_strchr (out, '\\');
4319 t != NULL;
4320 t = etags_strchr (t + 2, '\\'))
4321 if (isdigit (t[1]))
4323 dig = t[1] - '0';
4324 diglen = regs->end[dig] - regs->start[dig];
4325 size += diglen - 2;
4327 else
4328 size -= 1;
4330 /* Allocate space and do the substitutions. */
4331 result = xnew (size + 1, char);
4333 for (t = result; *out != '\0'; out++)
4334 if (*out == '\\' && isdigit (*++out))
4336 /* Using "dig2" satisfies my debugger. Bleah. */
4337 dig = *out - '0';
4338 diglen = regs->end[dig] - regs->start[dig];
4339 strncpy (t, in + regs->start[dig], diglen);
4340 t += diglen;
4342 else
4343 *t++ = *out;
4344 *t = '\0';
4346 if (DEBUG && (t > result + size || t - result != strlen (result)))
4347 abort ();
4349 return result;
4352 #endif /* ETAGS_REGEXPS */
4353 /* Initialize a linebuffer for use */
4354 void
4355 initbuffer (linebuffer)
4356 struct linebuffer *linebuffer;
4358 linebuffer->size = 200;
4359 linebuffer->buffer = xnew (200, char);
4363 * Read a line of text from `stream' into `linebuffer'.
4364 * Return the number of characters read from `stream',
4365 * which is the length of the line including the newline, if any.
4367 long
4368 readline_internal (linebuffer, stream)
4369 struct linebuffer *linebuffer;
4370 register FILE *stream;
4372 char *buffer = linebuffer->buffer;
4373 register char *p = linebuffer->buffer;
4374 register char *pend;
4375 int chars_deleted;
4377 pend = p + linebuffer->size; /* Separate to avoid 386/IX compiler bug. */
4379 while (1)
4381 register int c = getc (stream);
4382 if (p == pend)
4384 linebuffer->size *= 2;
4385 buffer = (char *) xrealloc (buffer, linebuffer->size);
4386 p += buffer - linebuffer->buffer;
4387 pend = buffer + linebuffer->size;
4388 linebuffer->buffer = buffer;
4390 if (c == EOF)
4392 *p = '\0';
4393 chars_deleted = 0;
4394 break;
4396 if (c == '\n')
4398 if (p > buffer && p[-1] == '\r')
4400 p -= 1;
4401 #ifdef DOS_NT
4402 /* Assume CRLF->LF translation will be performed by Emacs
4403 when loading this file, so CRs won't appear in the buffer.
4404 It would be cleaner to compensate within Emacs;
4405 however, Emacs does not know how many CRs were deleted
4406 before any given point in the file. */
4407 chars_deleted = 1;
4408 #else
4409 chars_deleted = 2;
4410 #endif
4412 else
4414 chars_deleted = 1;
4416 *p = '\0';
4417 break;
4419 *p++ = c;
4421 linebuffer->len = p - buffer;
4423 return linebuffer->len + chars_deleted;
4427 * Like readline_internal, above, but in addition try to match the
4428 * input line against any existing regular expressions.
4430 long
4431 readline (linebuffer, stream)
4432 struct linebuffer *linebuffer;
4433 FILE *stream;
4435 /* Read new line. */
4436 long result = readline_internal (linebuffer, stream);
4437 #ifdef ETAGS_REGEXPS
4438 int i;
4440 /* Match against all listed patterns. */
4441 if (linebuffer->len > 0)
4442 for (i = 0; i < num_patterns; ++i)
4444 int match = re_match (patterns[i].pattern, linebuffer->buffer,
4445 linebuffer->len, 0, &patterns[i].regs);
4446 switch (match)
4448 case -2:
4449 /* Some error. */
4450 if (!patterns[i].error_signaled)
4452 error ("error while matching pattern %d", i);
4453 patterns[i].error_signaled = TRUE;
4455 break;
4456 case -1:
4457 /* No match. */
4458 break;
4459 default:
4460 /* Match occurred. Construct a tag. */
4461 if (patterns[i].name_pattern[0] != '\0')
4463 /* Make a named tag. */
4464 char *name = substitute (linebuffer->buffer,
4465 patterns[i].name_pattern,
4466 &patterns[i].regs);
4467 if (name != NULL)
4468 pfnote (name, TRUE,
4469 linebuffer->buffer, match, lineno, linecharno);
4471 else
4473 /* Make an unnamed tag. */
4474 pfnote ((char *)NULL, TRUE,
4475 linebuffer->buffer, match, lineno, linecharno);
4477 break;
4480 #endif /* ETAGS_REGEXPS */
4482 return result;
4486 * Read a file, but do no processing. This is used to do regexp
4487 * matching on files that have no language defined.
4489 void
4490 just_read_file (inf)
4491 FILE *inf;
4493 lineno = 0;
4494 charno = 0;
4496 while (!feof (inf))
4498 ++lineno;
4499 linecharno = charno;
4500 charno += readline (&lb, inf);
4506 * Return a pointer to a space of size strlen(cp)+1 allocated
4507 * with xnew where the string CP has been copied.
4509 char *
4510 savestr (cp)
4511 char *cp;
4513 return savenstr (cp, strlen (cp));
4517 * Return a pointer to a space of size LEN+1 allocated with xnew where
4518 * the string CP has been copied for at most the first LEN characters.
4520 char *
4521 savenstr (cp, len)
4522 char *cp;
4523 int len;
4525 register char *dp;
4527 dp = xnew (len + 1, char);
4528 strncpy (dp, cp, len);
4529 dp[len] = '\0';
4530 return dp;
4534 * Return the ptr in sp at which the character c last
4535 * appears; NULL if not found
4537 * Identical to System V strrchr, included for portability.
4539 char *
4540 etags_strrchr (sp, c)
4541 register char *sp, c;
4543 register char *r;
4545 r = NULL;
4548 if (*sp == c)
4549 r = sp;
4550 } while (*sp++);
4551 return r;
4556 * Return the ptr in sp at which the character c first
4557 * appears; NULL if not found
4559 * Identical to System V strchr, included for portability.
4561 char *
4562 etags_strchr (sp, c)
4563 register char *sp, c;
4567 if (*sp == c)
4568 return sp;
4569 } while (*sp++);
4570 return NULL;
4573 /* Print error message and exit. */
4574 void
4575 fatal (s1, s2)
4576 char *s1, *s2;
4578 error (s1, s2);
4579 exit (BAD);
4582 void
4583 pfatal (s1)
4584 char *s1;
4586 perror (s1);
4587 exit (BAD);
4590 void
4591 suggest_asking_for_help ()
4593 fprintf (stderr, "\tTry `%s --help' for a complete list of options.\n",
4594 progname);
4595 exit (BAD);
4598 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
4599 void
4600 error (s1, s2)
4601 char *s1, *s2;
4603 fprintf (stderr, "%s: ", progname);
4604 fprintf (stderr, s1, s2);
4605 fprintf (stderr, "\n");
4608 /* Return a newly-allocated string whose contents
4609 concatenate those of s1, s2, s3. */
4610 char *
4611 concat (s1, s2, s3)
4612 char *s1, *s2, *s3;
4614 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
4615 char *result = xnew (len1 + len2 + len3 + 1, char);
4617 strcpy (result, s1);
4618 strcpy (result + len1, s2);
4619 strcpy (result + len1 + len2, s3);
4620 result[len1 + len2 + len3] = '\0';
4622 return result;
4625 /* Does the same work as the system V getcwd, but does not need to
4626 guess the buffer size in advance. */
4627 char *
4628 etags_getcwd ()
4630 #ifdef HAVE_GETCWD
4631 int bufsize = 200;
4632 char *path = xnew (bufsize, char);
4634 while (getcwd (path, bufsize) == NULL)
4636 if (errno != ERANGE)
4637 pfatal ("getcwd");
4638 bufsize *= 2;
4639 free (path);
4640 path = xnew (bufsize, char);
4643 #if WINDOWSNT
4645 /* Convert backslashes to slashes. */
4646 char *p;
4647 for (p = path; *p != '\0'; p++)
4648 if (*p == '\\')
4649 *p = '/';
4651 #endif
4653 return path;
4655 #else /* not HAVE_GETCWD */
4656 #ifdef MSDOS
4657 char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */
4659 getwd (path);
4661 for (p = path; *p != '\0'; p++)
4662 if (*p == '\\')
4663 *p = '/';
4664 else
4665 *p = lowcase (*p);
4667 return strdup (path);
4668 #else /* not MSDOS */
4669 struct linebuffer path;
4670 FILE *pipe;
4672 initbuffer (&path);
4673 pipe = (FILE *) popen ("pwd 2>/dev/null", "r");
4674 if (pipe == NULL || readline_internal (&path, pipe) == 0)
4675 pfatal ("pwd");
4676 pclose (pipe);
4678 return path.buffer;
4679 #endif /* not MSDOS */
4680 #endif /* not HAVE_GETCWD */
4683 /* Return a newly allocated string containing the file name
4684 of FILE relative to the absolute directory DIR (which
4685 should end with a slash). */
4686 char *
4687 relative_filename (file, dir)
4688 char *file, *dir;
4690 char *fp, *dp, *abs, *res;
4691 int i;
4693 /* Find the common root of file and dir (with a trailing slash). */
4694 abs = absolute_filename (file, cwd);
4695 fp = abs;
4696 dp = dir;
4697 while (*fp++ == *dp++)
4698 continue;
4699 fp--, dp--; /* back to the first differing char */
4700 do /* look at the equal chars until '/' */
4701 fp--, dp--;
4702 while (*fp != '/');
4704 /* Build a sequence of "../" strings for the resulting relative file name. */
4705 i = 0;
4706 while ((dp = etags_strchr (dp + 1, '/')) != NULL)
4707 i += 1;
4708 res = xnew (3*i + strlen (fp + 1) + 1, char);
4709 res[0] = '\0';
4710 while (i-- > 0)
4711 strcat (res, "../");
4713 /* Add the file name relative to the common root of file and dir. */
4714 strcat (res, fp + 1);
4715 free (abs);
4717 return res;
4720 /* Return a newly allocated string containing the
4721 absolute file name of FILE given CWD (which should
4722 end with a slash). */
4723 char *
4724 absolute_filename (file, cwd)
4725 char *file, *cwd;
4727 char *slashp, *cp, *res;
4729 if (absolutefn (file))
4730 res = savestr (file);
4731 #ifdef DOS_NT
4732 /* We don't support non-absolute file names with a drive
4733 letter, like `d:NAME' (it's too much hassle). */
4734 else if (file[1] == ':')
4735 fatal ("%s: relative file names with drive letters not supported", file);
4736 #endif
4737 else
4738 res = concat (cwd, file, "");
4740 /* Delete the "/dirname/.." and "/." substrings. */
4741 slashp = etags_strchr (res, '/');
4742 while (slashp != NULL && slashp[0] != '\0')
4744 if (slashp[1] == '.')
4746 if (slashp[2] == '.'
4747 && (slashp[3] == '/' || slashp[3] == '\0'))
4749 cp = slashp;
4751 cp--;
4752 while (cp >= res && !absolutefn (cp));
4753 if (cp < res)
4754 cp = slashp; /* the absolute name begins with "/.." */
4755 #ifdef DOS_NT
4756 /* Under MSDOS and NT we get `d:/NAME' as absolute
4757 file name, so the luser could say `d:/../NAME'.
4758 We silently treat this as `d:/NAME'. */
4759 else if (cp[0] != '/')
4760 cp = slashp;
4761 #endif
4762 strcpy (cp, slashp + 3);
4763 slashp = cp;
4764 continue;
4766 else if (slashp[2] == '/' || slashp[2] == '\0')
4768 strcpy (slashp, slashp + 2);
4769 continue;
4773 slashp = etags_strchr (slashp + 1, '/');
4776 if (res[0] == '\0')
4777 return savestr ("/");
4778 else
4779 return res;
4782 /* Return a newly allocated string containing the absolute
4783 file name of dir where FILE resides given CWD (which should
4784 end with a slash). */
4785 char *
4786 absolute_dirname (file, cwd)
4787 char *file, *cwd;
4789 char *slashp, *res;
4790 char save;
4791 #ifdef DOS_NT
4792 char *p;
4794 for (p = file; *p != '\0'; p++)
4795 if (*p == '\\')
4796 *p = '/';
4797 #endif
4799 slashp = etags_strrchr (file, '/');
4800 if (slashp == NULL)
4801 return savestr (cwd);
4802 save = slashp[1];
4803 slashp[1] = '\0';
4804 res = absolute_filename (file, cwd);
4805 slashp[1] = save;
4807 return res;
4810 /* Increase the size of a linebuffer. */
4811 void
4812 grow_linebuffer (bufp, toksize)
4813 struct linebuffer *bufp;
4814 int toksize;
4816 while (bufp->size < toksize)
4817 bufp->size *= 2;
4818 bufp->buffer = (char *) xrealloc (bufp->buffer, bufp->size);
4821 /* Like malloc but get fatal error if memory is exhausted. */
4822 long *
4823 xmalloc (size)
4824 unsigned int size;
4826 long *result = (long *) malloc (size);
4827 if (result == NULL)
4828 fatal ("virtual memory exhausted", (char *)NULL);
4829 return result;
4832 long *
4833 xrealloc (ptr, size)
4834 char *ptr;
4835 unsigned int size;
4837 long *result = (long *) realloc (ptr, size);
4838 if (result == NULL)
4839 fatal ("virtual memory exhausted", (char *)NULL);
4840 return result;