Add detailed instructions to unpack and install intlfonts on MS-DOS.
[emacs.git] / lib-src / etags.c
bloba1059e334d156f650bb7461f2893c61bd24adf72
1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 87, 88, 89, 93, 94, 95, 98
3 Free Software Foundation, Inc. and Ken Arnold
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 /* This is to declare getcwd. */
81 #ifdef HAVE_UNISTD_H
82 #include <unistd.h>
83 #endif
85 #if !defined (S_ISREG) && defined (S_IFREG)
86 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
87 #endif
89 #ifdef LONG_OPTIONS
90 # include <getopt.h>
91 #else
92 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
93 extern char *optarg;
94 extern int optind, opterr;
95 #endif /* LONG_OPTIONS */
97 #ifdef ETAGS_REGEXPS
98 # include <regex.h>
99 #endif /* ETAGS_REGEXPS */
101 /* Define CTAGS to make the program "ctags" compatible with the usual one.
102 Leave it undefined to make the program "etags", which makes emacs-style
103 tag tables and tags typedefs, #defines and struct/union/enum by default. */
104 #ifdef CTAGS
105 # undef CTAGS
106 # define CTAGS TRUE
107 #else
108 # define CTAGS FALSE
109 #endif
111 /* Exit codes for success and failure. */
112 #ifdef VMS
113 # define GOOD 1
114 # define BAD 0
115 #else
116 # define GOOD 0
117 # define BAD 1
118 #endif
120 /* C extensions. */
121 #define C_PLPL 0x00001 /* C++ */
122 #define C_STAR 0x00003 /* C* */
123 #define C_JAVA 0x00005 /* JAVA */
124 #define YACC 0x10000 /* yacc file */
126 #define streq(s,t) ((DEBUG && (s) == NULL && (t) == NULL \
127 && (abort (), 1)) || !strcmp (s, t))
128 #define strneq(s,t,n) ((DEBUG && (s) == NULL && (t) == NULL \
129 && (abort (), 1)) || !strncmp (s, t, n))
131 #define lowcase(c) tolower ((char)c)
133 #define CHARS 256 /* 2^sizeof(char) */
134 #define CHAR(x) ((int)x & (CHARS - 1))
135 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */
136 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
137 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
138 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
139 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
141 #ifdef DOS_NT
142 # define absolutefn(fn) (fn[0] == '/' \
143 || (fn[1] == ':' && fn[2] == '/'))
144 #else
145 # define absolutefn(fn) (fn[0] == '/')
146 #endif
150 * xnew -- allocate storage
152 * SYNOPSIS: Type *xnew (int n, Type);
154 #ifdef chkmalloc
155 # include "chkmalloc.h"
156 # define xnew(n,Type) ((Type *) trace_xmalloc (__FILE__, __LINE__, \
157 (n) * sizeof (Type)))
158 #else
159 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
160 #endif
162 typedef int bool;
164 typedef struct nd_st
165 { /* sorting structure */
166 char *name; /* function or type name */
167 char *file; /* file name */
168 bool is_func; /* use pattern or line no */
169 bool been_warned; /* set if noticed dup */
170 int lno; /* line number tag is on */
171 long cno; /* character number line starts on */
172 char *pat; /* search pattern */
173 struct nd_st *left, *right; /* left and right sons */
174 } NODE;
176 extern char *getenv ();
178 char *concat ();
179 char *savenstr (), *savestr ();
180 char *etags_strchr (), *etags_strrchr ();
181 char *etags_getcwd ();
182 char *relative_filename (), *absolute_filename (), *absolute_dirname ();
183 void grow_linebuffer ();
184 long *xmalloc (), *xrealloc ();
186 typedef void Lang_function ();
187 /* Many compilers barf on this:
188 Lang_function Asm_labels;
189 so let's write it this way */
190 void Asm_labels ();
191 void C_entries ();
192 void default_C_entries ();
193 void plain_C_entries ();
194 void Cjava_entries ();
195 void Cobol_paragraphs ();
196 void Cplusplus_entries ();
197 void Cstar_entries ();
198 void Erlang_functions ();
199 void Fortran_functions ();
200 void Yacc_entries ();
201 void Lisp_functions ();
202 void Pascal_functions ();
203 void Perl_functions ();
204 void Postscript_functions ();
205 void Prolog_functions ();
206 void Scheme_functions ();
207 void TeX_functions ();
208 void just_read_file ();
210 Lang_function *get_language_from_name ();
211 Lang_function *get_language_from_interpreter ();
212 Lang_function *get_language_from_suffix ();
213 int total_size_of_entries ();
214 long readline ();
215 long readline_internal ();
216 #ifdef ETAGS_REGEXPS
217 void analyse_regex ();
218 void add_regex ();
219 #endif /* ETAGS_REGEXPS */
220 void add_node ();
221 void error ();
222 void suggest_asking_for_help ();
223 void fatal (), pfatal ();
224 void find_entries ();
225 void free_tree ();
226 void getit ();
227 void init ();
228 void initbuffer ();
229 void pfnote (), new_pfnote ();
230 void process_file ();
231 void put_entries ();
232 void takeprec ();
235 char searchar = '/'; /* use /.../ searches */
237 int lineno; /* line number of current line */
238 long charno; /* current character number */
239 long linecharno; /* charno of start of line */
241 char *curfile; /* current input file name */
242 char *tagfile; /* output file */
243 char *progname; /* name this program was invoked with */
244 char *cwd; /* current working directory */
245 char *tagfiledir; /* directory of tagfile */
247 FILE *tagf; /* ioptr for tags file */
248 NODE *head; /* the head of the binary tree of tags */
251 * A `struct linebuffer' is a structure which holds a line of text.
252 * `readline' reads a line from a stream into a linebuffer and works
253 * regardless of the length of the line.
254 * SIZE is the size of BUFFER, LEN is the length of the string in
255 * BUFFER after readline reads it.
257 struct linebuffer
259 long size;
260 int len;
261 char *buffer;
264 struct linebuffer lb; /* the current line */
265 struct linebuffer token_name; /* used by C_entries as a temporary area */
266 struct
268 long linepos;
269 struct linebuffer lb; /* used by C_entries instead of lb */
270 } lbs[2];
272 /* boolean "functions" (see init) */
273 bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
274 char
275 /* white chars */
276 *white = " \f\t\n\013",
277 /* not in a name */
278 *nonam =" \f\t\n\013(=,[;",
279 /* token ending chars */
280 *endtk = " \t\n\013\"'#()[]{}=-+%*/&|^~!<>;,.:?",
281 /* token starting chars */
282 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
283 /* valid in-token chars */
284 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
286 bool append_to_tagfile; /* -a: append to tags */
287 /* The following four default to TRUE for etags, but to FALSE for ctags. */
288 bool typedefs; /* -t: create tags for C typedefs */
289 bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */
290 /* 0 struct/enum/union decls, and C++ */
291 /* member functions. */
292 bool constantypedefs; /* -d: create tags for C #define, enum */
293 /* constants and variables. */
294 /* -D: opposite of -d. Default under ctags. */
295 bool globals; /* create tags for C global variables */
296 bool members; /* create tags for C member variables */
297 bool update; /* -u: update tags */
298 bool vgrind_style; /* -v: create vgrind style index output */
299 bool no_warnings; /* -w: suppress warnings */
300 bool cxref_style; /* -x: create cxref style output */
301 bool cplusplus; /* .[hc] means C++, not C */
302 bool noindentypedefs; /* -I: ignore indentation in C */
304 #ifdef LONG_OPTIONS
305 struct option longopts[] =
307 { "append", no_argument, NULL, 'a' },
308 { "backward-search", no_argument, NULL, 'B' },
309 { "c++", no_argument, NULL, 'C' },
310 { "cxref", no_argument, NULL, 'x' },
311 { "defines", no_argument, NULL, 'd' },
312 { "no-defines", no_argument, NULL, 'D' },
313 { "globals", no_argument, &globals, TRUE },
314 { "no-globals", no_argument, &globals, FALSE },
315 { "help", no_argument, NULL, 'h' },
316 { "help", no_argument, NULL, 'H' },
317 { "ignore-indentation", no_argument, NULL, 'I' },
318 { "include", required_argument, NULL, 'i' },
319 { "language", required_argument, NULL, 'l' },
320 { "members", no_argument, &members, TRUE },
321 { "no-members", no_argument, &members, FALSE },
322 { "no-warn", no_argument, NULL, 'w' },
323 { "output", required_argument, NULL, 'o' },
324 #ifdef ETAGS_REGEXPS
325 { "regex", required_argument, NULL, 'r' },
326 { "no-regex", no_argument, NULL, 'R' },
327 #endif /* ETAGS_REGEXPS */
328 { "typedefs", no_argument, NULL, 't' },
329 { "typedefs-and-c++", no_argument, NULL, 'T' },
330 { "update", no_argument, NULL, 'u' },
331 { "version", no_argument, NULL, 'V' },
332 { "vgrind", no_argument, NULL, 'v' },
333 { 0 }
335 #endif /* LONG_OPTIONS */
337 #ifdef ETAGS_REGEXPS
338 /* Structure defining a regular expression. Elements are
339 the compiled pattern, and the name string. */
340 struct pattern
342 struct re_pattern_buffer *pattern;
343 struct re_registers regs;
344 char *name_pattern;
345 bool error_signaled;
348 /* Number of regexps found. */
349 int num_patterns = 0;
351 /* Array of all regexps. */
352 struct pattern *patterns = NULL;
353 #endif /* ETAGS_REGEXPS */
356 * Language stuff.
359 /* Non-NULL if language fixed. */
360 Lang_function *lang_func = NULL;
362 /* Assembly code */
363 char *Asm_suffixes [] = { "a", /* Unix assembler */
364 "asm", /* Microcontroller assembly */
365 "def", /* BSO/Tasking definition includes */
366 "inc", /* Microcontroller include files */
367 "ins", /* Microcontroller include files */
368 "s", "sa", /* Unix assembler */
369 "S", /* cpp-processed Unix assembler */
370 "src", /* BSO/Tasking C compiler output */
371 NULL
374 /* Note that .c and .h can be considered C++, if the --c++ flag was
375 given. That is why default_C_entries is called here. */
376 char *default_C_suffixes [] =
377 { "c", "h", NULL };
379 char *Cplusplus_suffixes [] =
380 { "C", "H", "c++", "cc", "cpp", "cxx", "h++", "hh", "hpp", "hxx",
381 "M", /* Objective C++ */
382 "pdb", /* Postscript with C syntax */
383 NULL };
385 char *Cjava_suffixes [] =
386 { "java", NULL };
388 char *Cobol_suffixes [] =
389 { "COB", "cob", NULL };
391 char *Cstar_suffixes [] =
392 { "cs", "hs", NULL };
394 char *Erlang_suffixes [] =
395 { "erl", "hrl", NULL };
397 char *Fortran_suffixes [] =
398 { "F", "f", "f90", "for", NULL };
400 char *Lisp_suffixes [] =
401 { "cl", "clisp", "el", "l", "lisp", "lsp", "ml", NULL };
403 char *Pascal_suffixes [] =
404 { "p", "pas", NULL };
406 char *Perl_suffixes [] =
407 { "pl", "pm", NULL };
408 char *Perl_interpreters [] =
409 { "perl", "@PERL@", NULL };
411 char *plain_C_suffixes [] =
412 { "pc", /* Pro*C file */
413 "m", /* Objective C file */
414 "lm", /* Objective lex file */
415 NULL };
417 char *Postscript_suffixes [] =
418 { "ps", NULL };
420 char *Prolog_suffixes [] =
421 { "prolog", NULL };
423 /* Can't do the `SCM' or `scm' prefix with a version number. */
424 char *Scheme_suffixes [] =
425 { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "t", NULL };
427 char *TeX_suffixes [] =
428 { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL };
430 char *Yacc_suffixes [] =
431 { "y", "ym", "yy", "yxx", "y++", NULL }; /* .ym is Objective yacc file */
433 /* Table of language names and corresponding functions, file suffixes
434 and interpreter names.
435 It is ok for a given function to be listed under more than one
436 name. I just didn't. */
437 struct lang_entry
439 char *name;
440 Lang_function *function;
441 char **suffixes;
442 char **interpreters;
445 struct lang_entry lang_names [] =
447 { "asm", Asm_labels, Asm_suffixes, NULL },
448 { "c", default_C_entries, default_C_suffixes, NULL },
449 { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL },
450 { "c*", Cstar_entries, Cstar_suffixes, NULL },
451 { "cobol", Cobol_paragraphs, Cobol_suffixes, NULL },
452 { "erlang", Erlang_functions, Erlang_suffixes, NULL },
453 { "fortran", Fortran_functions, Fortran_suffixes, NULL },
454 { "java", Cjava_entries, Cjava_suffixes, NULL },
455 { "lisp", Lisp_functions, Lisp_suffixes, NULL },
456 { "pascal", Pascal_functions, Pascal_suffixes, NULL },
457 { "perl", Perl_functions, Perl_suffixes, Perl_interpreters },
458 { "postscript", Postscript_functions, Postscript_suffixes, NULL },
459 { "proc", plain_C_entries, plain_C_suffixes, NULL },
460 { "prolog", Prolog_functions, Prolog_suffixes, NULL },
461 { "scheme", Scheme_functions, Scheme_suffixes, NULL },
462 { "tex", TeX_functions, TeX_suffixes, NULL },
463 { "yacc", Yacc_entries, Yacc_suffixes, NULL },
464 { "auto", NULL }, /* default guessing scheme */
465 { "none", just_read_file }, /* regexp matching only */
466 { NULL, NULL } /* end of list */
470 void
471 print_language_names ()
473 struct lang_entry *lang;
474 char **ext;
476 puts ("\nThese are the currently supported languages, along with the\n\
477 default file name suffixes:");
478 for (lang = lang_names; lang->name != NULL; lang++)
480 printf ("\t%s\t", lang->name);
481 if (lang->suffixes != NULL)
482 for (ext = lang->suffixes; *ext != NULL; ext++)
483 printf (" .%s", *ext);
484 puts ("");
486 puts ("Where `auto' means use default language for files based on file\n\
487 name suffix, and `none' means only do regexp processing on files.\n\
488 If no language is specified and no matching suffix is found,\n\
489 the first line of the file is read for a sharp-bang (#!) sequence\n\
490 followed by the name of an interpreter. If no such sequence is found,\n\
491 Fortran is tried first; if no tags are found, C is tried next.");
494 #ifndef VERSION
495 # define VERSION "19"
496 #endif
497 void
498 print_version ()
500 printf ("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION);
501 puts ("Copyright (C) 1996 Free Software Foundation, Inc. and Ken Arnold");
502 puts ("This program is distributed under the same terms as Emacs");
504 exit (GOOD);
507 void
508 print_help ()
510 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
512 These are the options accepted by %s.\n", progname, progname);
513 #ifdef LONG_OPTIONS
514 puts ("You may use unambiguous abbreviations for the long option names.");
515 #else
516 puts ("Long option names do not work with this executable, as it is not\n\
517 linked with GNU getopt.");
518 #endif /* LONG_OPTIONS */
519 puts ("A - as file name means read names from stdin.");
520 if (!CTAGS)
521 printf (" Absolute names are stored in the output file as they\n\
522 are. Relative ones are stored relative to the output file's directory.");
523 puts ("\n");
525 puts ("-a, --append\n\
526 Append tag entries to existing tags file.");
528 if (CTAGS)
529 puts ("-B, --backward-search\n\
530 Write the search commands for the tag entries using '?', the\n\
531 backward-search command instead of '/', the forward-search command.");
533 puts ("-C, --c++\n\
534 Treat files whose name suffix defaults to C language as C++ files.");
536 if (CTAGS)
537 puts ("-d, --defines\n\
538 Create tag entries for C #define constants and enum constants, too.");
539 else
540 puts ("-D, --no-defines\n\
541 Don't create tag entries for C #define constants and enum constants.\n\
542 This makes the tags file smaller.");
544 if (!CTAGS)
546 puts ("-i FILE, --include=FILE\n\
547 Include a note in tag file indicating that, when searching for\n\
548 a tag, one should also consult the tags file FILE after\n\
549 checking the current file.");
550 puts ("-l LANG, --language=LANG\n\
551 Force the following files to be considered as written in the\n\
552 named language up to the next --language=LANG option.");
555 if (CTAGS)
556 puts ("--globals\n\
557 Create tag entries for global variables in C and derived languages.");
558 else
559 puts ("--no-globals\n\
560 Do not create tag entries for global variables in C and\n\
561 derived languages. This makes the tags file smaller.");
562 puts ("--members\n\
563 Create tag entries for member variables in C and derived languages.");
565 #ifdef ETAGS_REGEXPS
566 puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
567 Make a tag for each line matching pattern REGEXP in the\n\
568 following files. regexfile is a file containing one REGEXP\n\
569 per line. REGEXP is anchored (as if preceded by ^).\n\
570 The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
571 named tags can be created with:\n\
572 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
573 puts ("-R, --no-regex\n\
574 Don't create tags from regexps for the following files.");
575 #endif /* ETAGS_REGEXPS */
576 puts ("-o FILE, --output=FILE\n\
577 Write the tags to FILE.");
578 puts ("-I, --ignore-indentation\n\
579 Don't rely on indentation quite as much as normal. Currently,\n\
580 this means not to assume that a closing brace in the first\n\
581 column is the final brace of a function or structure\n\
582 definition in C and C++.");
584 if (CTAGS)
586 puts ("-t, --typedefs\n\
587 Generate tag entries for C typedefs.");
588 puts ("-T, --typedefs-and-c++\n\
589 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
590 and C++ member functions.");
591 puts ("-u, --update\n\
592 Update the tag entries for the given files, leaving tag\n\
593 entries for other files in place. Currently, this is\n\
594 implemented by deleting the existing entries for the given\n\
595 files and then rewriting the new entries at the end of the\n\
596 tags file. It is often faster to simply rebuild the entire\n\
597 tag file than to use this.");
598 puts ("-v, --vgrind\n\
599 Generates an index of items intended for human consumption,\n\
600 similar to the output of vgrind. The index is sorted, and\n\
601 gives the page number of each item.");
602 puts ("-w, --no-warn\n\
603 Suppress warning messages about entries defined in multiple\n\
604 files.");
605 puts ("-x, --cxref\n\
606 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
607 The output uses line numbers instead of page numbers, but\n\
608 beyond that the differences are cosmetic; try both to see\n\
609 which you like.");
612 puts ("-V, --version\n\
613 Print the version of the program.\n\
614 -h, --help\n\
615 Print this help message.");
617 print_language_names ();
619 puts ("");
620 puts ("Report bugs to bug-gnu-emacs@prep.ai.mit.edu");
622 exit (GOOD);
626 enum argument_type
628 at_language,
629 at_regexp,
630 at_filename
633 /* This structure helps us allow mixing of --lang and file names. */
634 typedef struct
636 enum argument_type arg_type;
637 char *what;
638 Lang_function *function;
639 } argument;
641 #ifdef VMS /* VMS specific functions */
643 #define EOS '\0'
645 /* This is a BUG! ANY arbitrary limit is a BUG!
646 Won't someone please fix this? */
647 #define MAX_FILE_SPEC_LEN 255
648 typedef struct {
649 short curlen;
650 char body[MAX_FILE_SPEC_LEN + 1];
651 } vspec;
654 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
655 returning in each successive call the next file name matching the input
656 spec. The function expects that each in_spec passed
657 to it will be processed to completion; in particular, up to and
658 including the call following that in which the last matching name
659 is returned, the function ignores the value of in_spec, and will
660 only start processing a new spec with the following call.
661 If an error occurs, on return out_spec contains the value
662 of in_spec when the error occurred.
664 With each successive file name returned in out_spec, the
665 function's return value is one. When there are no more matching
666 names the function returns zero. If on the first call no file
667 matches in_spec, or there is any other error, -1 is returned.
670 #include <rmsdef.h>
671 #include <descrip.h>
672 #define OUTSIZE MAX_FILE_SPEC_LEN
673 short
674 fn_exp (out, in)
675 vspec *out;
676 char *in;
678 static long context = 0;
679 static struct dsc$descriptor_s o;
680 static struct dsc$descriptor_s i;
681 static bool pass1 = TRUE;
682 long status;
683 short retval;
685 if (pass1)
687 pass1 = FALSE;
688 o.dsc$a_pointer = (char *) out;
689 o.dsc$w_length = (short)OUTSIZE;
690 i.dsc$a_pointer = in;
691 i.dsc$w_length = (short)strlen(in);
692 i.dsc$b_dtype = DSC$K_DTYPE_T;
693 i.dsc$b_class = DSC$K_CLASS_S;
694 o.dsc$b_dtype = DSC$K_DTYPE_VT;
695 o.dsc$b_class = DSC$K_CLASS_VS;
697 if ((status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL)
699 out->body[out->curlen] = EOS;
700 return 1;
702 else if (status == RMS$_NMF)
703 retval = 0;
704 else
706 strcpy(out->body, in);
707 retval = -1;
709 lib$find_file_end(&context);
710 pass1 = TRUE;
711 return retval;
715 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
716 name of each file specified by the provided arg expanding wildcards.
718 char *
719 gfnames (arg, p_error)
720 char *arg;
721 bool *p_error;
723 static vspec filename = {MAX_FILE_SPEC_LEN, "\0"};
725 switch (fn_exp (&filename, arg))
727 case 1:
728 *p_error = FALSE;
729 return filename.body;
730 case 0:
731 *p_error = FALSE;
732 return NULL;
733 default:
734 *p_error = TRUE;
735 return filename.body;
739 #ifndef OLD /* Newer versions of VMS do provide `system'. */
740 system (cmd)
741 char *cmd;
743 error ("%s", "system() function not implemented under VMS");
745 #endif
747 #define VERSION_DELIM ';'
748 char *massage_name (s)
749 char *s;
751 char *start = s;
753 for ( ; *s; s++)
754 if (*s == VERSION_DELIM)
756 *s = EOS;
757 break;
759 else
760 *s = lowcase (*s);
761 return start;
763 #endif /* VMS */
767 main (argc, argv)
768 int argc;
769 char *argv[];
771 int i;
772 unsigned int nincluded_files;
773 char **included_files;
774 char *this_file;
775 argument *argbuffer;
776 int current_arg, file_count;
777 struct linebuffer filename_lb;
778 #ifdef VMS
779 bool got_err;
780 #endif
782 #ifdef DOS_NT
783 _fmode = O_BINARY; /* all of files are treated as binary files */
784 #endif /* DOS_NT */
786 progname = argv[0];
787 nincluded_files = 0;
788 included_files = xnew (argc, char *);
789 current_arg = 0;
790 file_count = 0;
792 /* Allocate enough no matter what happens. Overkill, but each one
793 is small. */
794 argbuffer = xnew (argc, argument);
796 #ifdef ETAGS_REGEXPS
797 /* Set syntax for regular expression routines. */
798 re_set_syntax (RE_SYNTAX_EMACS);
799 #endif /* ETAGS_REGEXPS */
802 * If etags, always find typedefs and structure tags. Why not?
803 * Also default is to find macro constants, enum constants and
804 * global variables.
806 if (!CTAGS)
808 typedefs = typedefs_and_cplusplus = constantypedefs = TRUE;
809 globals = TRUE;
810 members = FALSE;
813 while (1)
815 int opt;
816 char *optstring;
818 #ifdef ETAGS_REGEXPS
819 optstring = "-aCdDf:Il:o:r:RStTi:BuvxwVhH";
820 #else
821 optstring = "-aCdDf:Il:o:StTi:BuvxwVhH";
822 #endif /* ETAGS_REGEXPS */
824 #ifndef LONG_OPTIONS
825 optstring = optstring + 1;
826 #endif /* LONG_OPTIONS */
828 opt = getopt_long (argc, argv, optstring, longopts, 0);
829 if (opt == EOF)
830 break;
832 switch (opt)
834 case 0:
835 /* If getopt returns 0, then it has already processed a
836 long-named option. We should do nothing. */
837 break;
839 case 1:
840 /* This means that a file name has been seen. Record it. */
841 argbuffer[current_arg].arg_type = at_filename;
842 argbuffer[current_arg].what = optarg;
843 ++current_arg;
844 ++file_count;
845 break;
847 /* Common options. */
848 case 'a': append_to_tagfile = TRUE; break;
849 case 'C': cplusplus = TRUE; break;
850 case 'd': constantypedefs = TRUE; break;
851 case 'D': constantypedefs = FALSE; break;
852 case 'f': /* for compatibility with old makefiles */
853 case 'o':
854 if (tagfile)
856 error ("-%c option may only be given once.", opt);
857 suggest_asking_for_help ();
859 tagfile = optarg;
860 break;
861 case 'I':
862 case 'S': /* for backward compatibility */
863 noindentypedefs = TRUE;
864 break;
865 case 'l':
866 argbuffer[current_arg].function = get_language_from_name (optarg);
867 argbuffer[current_arg].arg_type = at_language;
868 ++current_arg;
869 break;
870 #ifdef ETAGS_REGEXPS
871 case 'r':
872 argbuffer[current_arg].arg_type = at_regexp;
873 argbuffer[current_arg].what = optarg;
874 ++current_arg;
875 break;
876 case 'R':
877 argbuffer[current_arg].arg_type = at_regexp;
878 argbuffer[current_arg].what = NULL;
879 ++current_arg;
880 break;
881 #endif /* ETAGS_REGEXPS */
882 case 'V':
883 print_version ();
884 break;
885 case 'h':
886 case 'H':
887 print_help ();
888 break;
889 case 't':
890 typedefs = TRUE;
891 break;
892 case 'T':
893 typedefs = typedefs_and_cplusplus = TRUE;
894 break;
895 #if (!CTAGS)
896 /* Etags options */
897 case 'i':
898 included_files[nincluded_files++] = optarg;
899 break;
900 #else /* CTAGS */
901 /* Ctags options. */
902 case 'B': searchar = '?'; break;
903 case 'u': update = TRUE; break;
904 case 'v': vgrind_style = TRUE; /*FALLTHRU*/
905 case 'x': cxref_style = TRUE; break;
906 case 'w': no_warnings = TRUE; break;
907 #endif /* CTAGS */
908 default:
909 suggest_asking_for_help ();
913 for (; optind < argc; ++optind)
915 argbuffer[current_arg].arg_type = at_filename;
916 argbuffer[current_arg].what = argv[optind];
917 ++current_arg;
918 ++file_count;
921 if (nincluded_files == 0 && file_count == 0)
923 error ("no input files specified.", 0);
924 suggest_asking_for_help ();
927 if (tagfile == NULL)
928 tagfile = CTAGS ? "tags" : "TAGS";
929 cwd = etags_getcwd (); /* the current working directory */
930 if (cwd[strlen (cwd) - 1] != '/')
932 char *oldcwd = cwd;
933 cwd = concat (oldcwd, "/", "");
934 free (oldcwd);
936 if (streq (tagfile, "-"))
937 tagfiledir = cwd;
938 else
939 tagfiledir = absolute_dirname (tagfile, cwd);
941 init (); /* set up boolean "functions" */
943 initbuffer (&lb);
944 initbuffer (&token_name);
945 initbuffer (&lbs[0].lb);
946 initbuffer (&lbs[1].lb);
947 initbuffer (&filename_lb);
949 if (!CTAGS)
951 if (streq (tagfile, "-"))
953 tagf = stdout;
954 #ifdef DOS_NT
955 /* Switch redirected `stdout' to binary mode (setting `_fmode'
956 doesn't take effect until after `stdout' is already open). */
957 if (!isatty (fileno (stdout)))
958 setmode (fileno (stdout), O_BINARY);
959 #endif /* DOS_NT */
961 else
962 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
963 if (tagf == NULL)
964 pfatal (tagfile);
968 * Loop through files finding functions.
970 for (i = 0; i < current_arg; ++i)
972 switch (argbuffer[i].arg_type)
974 case at_language:
975 lang_func = argbuffer[i].function;
976 break;
977 #ifdef ETAGS_REGEXPS
978 case at_regexp:
979 analyse_regex (argbuffer[i].what);
980 break;
981 #endif
982 case at_filename:
983 #ifdef VMS
984 while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL)
986 if (got_err)
988 error ("can't find file %s\n", this_file);
989 argc--, argv++;
991 else
993 this_file = massage_name (this_file);
995 #else
996 this_file = argbuffer[i].what;
997 #endif
998 /* Input file named "-" means read file names from stdin
999 and use them. */
1000 if (streq (this_file, "-"))
1001 while (readline_internal (&filename_lb, stdin) > 0)
1002 process_file (filename_lb.buffer);
1003 else
1004 process_file (this_file);
1005 #ifdef VMS
1007 #endif
1008 break;
1012 if (!CTAGS)
1014 while (nincluded_files-- > 0)
1015 fprintf (tagf, "\f\n%s,include\n", *included_files++);
1017 fclose (tagf);
1018 exit (GOOD);
1021 /* If CTAGS, we are here. process_file did not write the tags yet,
1022 because we want them ordered. Let's do it now. */
1023 if (cxref_style)
1025 put_entries (head);
1026 exit (GOOD);
1029 if (update)
1031 char cmd[BUFSIZ];
1032 for (i = 0; i < current_arg; ++i)
1034 if (argbuffer[i].arg_type != at_filename)
1035 continue;
1036 sprintf (cmd,
1037 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1038 tagfile, argbuffer[i].what, tagfile);
1039 if (system (cmd) != GOOD)
1040 fatal ("failed to execute shell command", (char *)NULL);
1042 append_to_tagfile = TRUE;
1045 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1046 if (tagf == NULL)
1047 pfatal (tagfile);
1048 put_entries (head);
1049 fclose (tagf);
1051 if (update)
1053 char cmd[BUFSIZ];
1054 sprintf (cmd, "sort %s -o %s", tagfile, tagfile);
1055 exit (system (cmd));
1057 return GOOD;
1062 * Return a Lang_function given the name.
1064 Lang_function *
1065 get_language_from_name (name)
1066 char *name;
1068 struct lang_entry *lang;
1070 if (name != NULL)
1071 for (lang = lang_names; lang->name != NULL; lang++)
1073 if (streq (name, lang->name))
1074 return lang->function;
1077 error ("language \"%s\" not recognized.", optarg);
1078 suggest_asking_for_help ();
1080 /* This point should never be reached. The function should either
1081 return a function pointer or never return. Note that a NULL
1082 pointer cannot be considered as an error, as it means that the
1083 language has not been explicitely imposed by the user ("auto"). */
1084 return NULL; /* avoid warnings from compiler */
1089 * Return a Lang_function given the interpreter name.
1091 Lang_function *
1092 get_language_from_interpreter (interpreter)
1093 char *interpreter;
1095 struct lang_entry *lang;
1096 char **iname;
1098 if (interpreter == NULL)
1099 return NULL;
1100 for (lang = lang_names; lang->name != NULL; lang++)
1101 if (lang->interpreters != NULL)
1102 for (iname = lang->interpreters; *iname != NULL; iname++)
1103 if (streq (*iname, interpreter))
1104 return lang->function;
1106 return NULL;
1112 * Return a Lang_function given the file suffix.
1114 Lang_function *
1115 get_language_from_suffix (suffix)
1116 char *suffix;
1118 struct lang_entry *lang;
1119 char **ext;
1121 if (suffix == NULL)
1122 return NULL;
1123 for (lang = lang_names; lang->name != NULL; lang++)
1124 if (lang->suffixes != NULL)
1125 for (ext = lang->suffixes; *ext != NULL; ext++)
1126 if (streq (*ext, suffix))
1127 return lang->function;
1129 return NULL;
1134 * This routine is called on each file argument.
1136 void
1137 process_file (file)
1138 char *file;
1140 struct stat stat_buf;
1141 FILE *inf;
1142 #ifdef DOS_NT
1143 char *p;
1145 for (p = file; *p != '\0'; p++)
1146 if (*p == '\\')
1147 *p = '/';
1148 #endif
1150 if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode))
1152 error ("skipping %s: it is not a regular file.", file);
1153 return;
1155 if (streq (file, tagfile) && !streq (tagfile, "-"))
1157 error ("skipping inclusion of %s in self.", file);
1158 return;
1160 inf = fopen (file, "r");
1161 if (inf == NULL)
1163 perror (file);
1164 return;
1167 find_entries (file, inf);
1169 if (!CTAGS)
1171 char *filename;
1173 if (absolutefn (file))
1175 /* file is an absolute file name. Canonicalise it. */
1176 filename = absolute_filename (file, cwd);
1178 else
1180 /* file is a file name relative to cwd. Make it relative
1181 to the directory of the tags file. */
1182 filename = relative_filename (file, tagfiledir);
1184 fprintf (tagf, "\f\n%s,%d\n", filename, total_size_of_entries (head));
1185 free (filename);
1186 put_entries (head);
1187 free_tree (head);
1188 head = NULL;
1193 * This routine sets up the boolean pseudo-functions which work
1194 * by setting boolean flags dependent upon the corresponding character
1195 * Every char which is NOT in that string is not a white char. Therefore,
1196 * all of the array "_wht" is set to FALSE, and then the elements
1197 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1198 * of a char is TRUE if it is the string "white", else FALSE.
1200 void
1201 init ()
1203 register char *sp;
1204 register int i;
1206 for (i = 0; i < CHARS; i++)
1207 _wht[i] = _nin[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
1208 for (sp = white; *sp; sp++) _wht[*sp] = TRUE; _wht[0] = _wht['\n'];
1209 for (sp = nonam; *sp; sp++) _nin[*sp] = TRUE; _nin[0] = _nin['\n'];
1210 for (sp = endtk; *sp; sp++) _etk[*sp] = TRUE; _etk[0] = _etk['\n'];
1211 for (sp = midtk; *sp; sp++) _itk[*sp] = TRUE; _btk[0] = _btk['\n'];
1212 for (sp = begtk; *sp; sp++) _btk[*sp] = TRUE; _itk[0] = _itk['\n'];
1216 * This routine opens the specified file and calls the function
1217 * which finds the function and type definitions.
1219 void
1220 find_entries (file, inf)
1221 char *file;
1222 FILE *inf;
1224 char *cp;
1225 Lang_function *function;
1226 NODE *old_last_node;
1227 extern NODE *last_node;
1230 /* Memory leakage here: the memory block pointed by curfile is never
1231 released. The amount of memory leaked here is the sum of the
1232 lengths of the input file names. */
1233 curfile = savestr (file);
1235 /* If user specified a language, use it. */
1236 function = lang_func;
1237 if (function != NULL)
1239 function (inf);
1240 fclose (inf);
1241 return;
1244 cp = etags_strrchr (file, '.');
1245 if (cp != NULL)
1247 cp += 1;
1248 function = get_language_from_suffix (cp);
1249 if (function != NULL)
1251 function (inf);
1252 fclose (inf);
1253 return;
1257 /* Look for sharp-bang as the first two characters. */
1258 if (readline_internal (&lb, inf)
1259 && lb.len >= 2
1260 && lb.buffer[0] == '#'
1261 && lb.buffer[1] == '!')
1263 char *lp;
1265 /* Set lp to point at the first char after the last slash in the
1266 line or, if no slashes, at the first nonblank. Then set cp to
1267 the first successive blank and terminate the string. */
1268 lp = etags_strrchr (lb.buffer+2, '/');
1269 if (lp != NULL)
1270 lp += 1;
1271 else
1272 for (lp = lb.buffer+2; *lp != '\0' && isspace (*lp); lp++)
1273 continue;
1274 for (cp = lp; *cp != '\0' && !isspace (*cp); cp++)
1275 continue;
1276 *cp = '\0';
1278 if (strlen (lp) > 0)
1280 function = get_language_from_interpreter (lp);
1281 if (function != NULL)
1283 function (inf);
1284 fclose (inf);
1285 return;
1289 rewind (inf);
1291 /* Try Fortran. */
1292 old_last_node = last_node;
1293 Fortran_functions (inf);
1295 /* No Fortran entries found. Try C. */
1296 if (old_last_node == last_node)
1298 rewind (inf);
1299 default_C_entries (inf);
1301 fclose (inf);
1302 return;
1305 /* Record a tag. */
1306 void
1307 pfnote (name, is_func, linestart, linelen, lno, cno)
1308 char *name; /* tag name, or NULL if unnamed */
1309 bool is_func; /* tag is a function */
1310 char *linestart; /* start of the line where tag is */
1311 int linelen; /* length of the line where tag is */
1312 int lno; /* line number */
1313 long cno; /* character number */
1315 register NODE *np;
1317 if (CTAGS && name == NULL)
1318 return;
1320 np = xnew (1, NODE);
1322 /* If ctags mode, change name "main" to M<thisfilename>. */
1323 if (CTAGS && !cxref_style && streq (name, "main"))
1325 register char *fp = etags_strrchr (curfile, '/');
1326 np->name = concat ("M", fp == 0 ? curfile : fp + 1, "");
1327 fp = etags_strrchr (np->name, '.');
1328 if (fp && fp[1] != '\0' && fp[2] == '\0')
1329 fp[0] = 0;
1331 else
1332 np->name = name;
1333 np->been_warned = FALSE;
1334 np->file = curfile;
1335 np->is_func = is_func;
1336 np->lno = lno;
1337 /* Our char numbers are 0-base, because of C language tradition?
1338 ctags compatibility? old versions compatibility? I don't know.
1339 Anyway, since emacs's are 1-base we expect etags.el to take care
1340 of the difference. If we wanted to have 1-based numbers, we would
1341 uncomment the +1 below. */
1342 np->cno = cno /* + 1 */ ;
1343 np->left = np->right = NULL;
1344 if (CTAGS && !cxref_style)
1346 if (strlen (linestart) < 50)
1347 np->pat = concat (linestart, "$", "");
1348 else
1349 np->pat = savenstr (linestart, 50);
1351 else
1352 np->pat = savenstr (linestart, linelen);
1354 add_node (np, &head);
1357 /* Date: Wed, 22 Jan 1997 02:56:31 -0500
1358 * From: Sam Kendall <kendall@cybercom.net>
1359 * Subject: Proposal for firming up the TAGS format specification
1360 * To: F.Potorti@cnuce.cnr.it
1362 * pfnote should emit the optimized form [unnamed tag] only if:
1363 * 1. name does not contain any of the characters " \t\r\n()";
1364 * 2. linestart contains name as either a rightmost, or rightmost but
1365 * one character, substring;
1366 * 3. the character, if any, immediately before name in linestart must
1367 * be one of the characters " \t()";
1368 * 4. the character, if any, immediately after name in linestart must
1369 * also be one of the characters " \t()".
1371 #define traditional_tag_style TRUE
1372 void
1373 new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno)
1374 char *name; /* tag name, or NULL if unnamed */
1375 int namelen; /* tag length */
1376 bool is_func; /* tag is a function */
1377 char *linestart; /* start of the line where tag is */
1378 int linelen; /* length of the line where tag is */
1379 int lno; /* line number */
1380 long cno; /* character number */
1382 register char *cp;
1383 bool named;
1385 named = TRUE;
1386 if (!CTAGS)
1388 for (cp = name; !notinname (*cp); cp++)
1389 continue;
1390 if (*cp == '\0') /* rule #1 */
1392 cp = linestart + linelen - namelen;
1393 if (notinname (linestart[linelen-1]))
1394 cp -= 1; /* rule #4 */
1395 if (cp >= linestart /* rule #2 */
1396 && (cp == linestart
1397 || notinname (cp[-1])) /* rule #3 */
1398 && strneq (name, cp, namelen)) /* rule #2 */
1399 named = FALSE; /* use unnamed tag */
1403 if (named)
1404 name = savenstr (name, namelen);
1405 else
1406 name = NULL;
1407 pfnote (name, is_func, linestart, linelen, lno, cno);
1411 * free_tree ()
1412 * recurse on left children, iterate on right children.
1414 void
1415 free_tree (node)
1416 register NODE *node;
1418 while (node)
1420 register NODE *node_right = node->right;
1421 free_tree (node->left);
1422 if (node->name != NULL)
1423 free (node->name);
1424 free (node->pat);
1425 free ((char *) node);
1426 node = node_right;
1431 * add_node ()
1432 * Adds a node to the tree of nodes. In etags mode, we don't keep
1433 * it sorted; we just keep a linear list. In ctags mode, maintain
1434 * an ordered tree, with no attempt at balancing.
1436 * add_node is the only function allowed to add nodes, so it can
1437 * maintain state.
1439 NODE *last_node = NULL;
1440 void
1441 add_node (node, cur_node_p)
1442 NODE *node, **cur_node_p;
1444 register int dif;
1445 register NODE *cur_node = *cur_node_p;
1447 if (cur_node == NULL)
1449 *cur_node_p = node;
1450 last_node = node;
1451 return;
1454 if (!CTAGS)
1456 /* Etags Mode */
1457 if (last_node == NULL)
1458 fatal ("internal error in add_node", (char *)NULL);
1459 last_node->right = node;
1460 last_node = node;
1462 else
1464 /* Ctags Mode */
1465 dif = strcmp (node->name, cur_node->name);
1468 * If this tag name matches an existing one, then
1469 * do not add the node, but maybe print a warning.
1471 if (!dif)
1473 if (streq (node->file, cur_node->file))
1475 if (!no_warnings)
1477 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1478 node->file, lineno, node->name);
1479 fprintf (stderr, "Second entry ignored\n");
1482 else if (!cur_node->been_warned && !no_warnings)
1484 fprintf
1485 (stderr,
1486 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1487 node->file, cur_node->file, node->name);
1488 cur_node->been_warned = TRUE;
1490 return;
1493 /* Actually add the node */
1494 add_node (node, dif < 0 ? &cur_node->left : &cur_node->right);
1498 void
1499 put_entries (node)
1500 register NODE *node;
1502 register char *sp;
1504 if (node == NULL)
1505 return;
1507 /* Output subentries that precede this one */
1508 put_entries (node->left);
1510 /* Output this entry */
1512 if (!CTAGS)
1514 if (node->name != NULL)
1515 fprintf (tagf, "%s\177%s\001%d,%ld\n",
1516 node->pat, node->name, node->lno, node->cno);
1517 else
1518 fprintf (tagf, "%s\177%d,%ld\n",
1519 node->pat, node->lno, node->cno);
1521 else
1523 if (node->name == NULL)
1524 error ("internal error: NULL name in ctags mode.", (char *)NULL);
1526 if (cxref_style)
1528 if (vgrind_style)
1529 fprintf (stdout, "%s %s %d\n",
1530 node->name, node->file, (node->lno + 63) / 64);
1531 else
1532 fprintf (stdout, "%-16s %3d %-16s %s\n",
1533 node->name, node->lno, node->file, node->pat);
1535 else
1537 fprintf (tagf, "%s\t%s\t", node->name, node->file);
1539 if (node->is_func)
1540 { /* a function */
1541 putc (searchar, tagf);
1542 putc ('^', tagf);
1544 for (sp = node->pat; *sp; sp++)
1546 if (*sp == '\\' || *sp == searchar)
1547 putc ('\\', tagf);
1548 putc (*sp, tagf);
1550 putc (searchar, tagf);
1552 else
1553 { /* a typedef; text pattern inadequate */
1554 fprintf (tagf, "%d", node->lno);
1556 putc ('\n', tagf);
1560 /* Output subentries that follow this one */
1561 put_entries (node->right);
1564 /* Length of a number's decimal representation. */
1566 number_len (num)
1567 long num;
1569 int len = 0;
1570 if (!num)
1571 return 1;
1572 for (; num; num /= 10)
1573 ++len;
1574 return len;
1578 * Return total number of characters that put_entries will output for
1579 * the nodes in the subtree of the specified node. Works only if
1580 * we are not ctags, but called only in that case. This count
1581 * is irrelevant with the new tags.el, but is still supplied for
1582 * backward compatibility.
1585 total_size_of_entries (node)
1586 register NODE *node;
1588 register int total;
1590 if (node == NULL)
1591 return 0;
1593 total = 0;
1594 for (; node; node = node->right)
1596 /* Count left subentries. */
1597 total += total_size_of_entries (node->left);
1599 /* Count this entry */
1600 total += strlen (node->pat) + 1;
1601 total += number_len ((long) node->lno) + 1 + number_len (node->cno) + 1;
1602 if (node->name != NULL)
1603 total += 1 + strlen (node->name); /* \001name */
1606 return total;
1610 * The C symbol tables.
1612 enum sym_type
1614 st_none,
1615 st_C_objprot, st_C_objimpl, st_C_objend,
1616 st_C_gnumacro,
1617 st_C_ignore,
1618 st_C_javastruct,
1619 st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
1622 /* Feed stuff between (but not including) %[ and %] lines to:
1623 gperf -c -k 1,3 -o -p -r -t
1625 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1627 @interface, 0, st_C_objprot
1628 @protocol, 0, st_C_objprot
1629 @implementation,0, st_C_objimpl
1630 @end, 0, st_C_objend
1631 import, C_JAVA, st_C_ignore
1632 package, C_JAVA, st_C_ignore
1633 friend, C_PLPL, st_C_ignore
1634 extends, C_JAVA, st_C_javastruct
1635 implements, C_JAVA, st_C_javastruct
1636 class, C_PLPL, st_C_struct
1637 namespace, C_PLPL, st_C_struct
1638 domain, C_STAR, st_C_struct
1639 union, 0, st_C_struct
1640 struct, 0, st_C_struct
1641 enum, 0, st_C_enum
1642 typedef, 0, st_C_typedef
1643 define, 0, st_C_define
1644 bool, C_PLPL, st_C_typespec
1645 long, 0, st_C_typespec
1646 short, 0, st_C_typespec
1647 int, 0, st_C_typespec
1648 char, 0, st_C_typespec
1649 float, 0, st_C_typespec
1650 double, 0, st_C_typespec
1651 signed, 0, st_C_typespec
1652 unsigned, 0, st_C_typespec
1653 auto, 0, st_C_typespec
1654 void, 0, st_C_typespec
1655 extern, 0, st_C_typespec
1656 static, 0, st_C_typespec
1657 const, 0, st_C_typespec
1658 volatile, 0, st_C_typespec
1659 explicit, C_PLPL, st_C_typespec
1660 mutable, C_PLPL, st_C_typespec
1661 typename, C_PLPL, st_C_typespec
1662 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
1663 DEFUN, 0, st_C_gnumacro
1664 SYSCALL, 0, st_C_gnumacro
1665 ENTRY, 0, st_C_gnumacro
1666 PSEUDO, 0, st_C_gnumacro
1667 # These are defined inside C functions, so currently they are not met.
1668 # EXFUN used in glibc, DEFVAR_* in emacs.
1669 #EXFUN, 0, st_C_gnumacro
1670 #DEFVAR_, 0, st_C_gnumacro
1672 and replace lines between %< and %> with its output. */
1673 /*%<*/
1674 /* starting time is 10:31:16 */
1675 /* C code produced by gperf version 2.1 (K&R C version) */
1676 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
1679 struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
1681 #define MIN_WORD_LENGTH 3
1682 #define MAX_WORD_LENGTH 15
1683 #define MIN_HASH_VALUE 15
1684 #define MAX_HASH_VALUE 128
1686 39 keywords
1687 114 is the maximum key range
1690 static int
1691 hash (str, len)
1692 register char *str;
1693 register unsigned int len;
1695 static unsigned char hash_table[] =
1697 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1698 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1699 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1700 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1701 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1702 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1703 128, 128, 128, 128, 39, 128, 128, 128, 54, 48,
1704 46, 128, 128, 128, 128, 128, 128, 128, 128, 128,
1705 28, 128, 128, 40, 32, 128, 128, 128, 128, 128,
1706 128, 128, 128, 128, 128, 128, 128, 24, 30, 47,
1707 62, 7, 60, 27, 128, 60, 128, 128, 59, 16,
1708 31, 23, 45, 128, 4, 14, 2, 55, 5, 128,
1709 128, 128, 128, 128, 128, 128, 128, 128,
1711 return len + hash_table[str[2]] + hash_table[str[0]];
1714 struct C_stab_entry *
1715 in_word_set (str, len)
1716 register char *str;
1717 register unsigned int len;
1720 static struct C_stab_entry wordlist[] =
1722 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1723 {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1724 {"extern", 0, st_C_typespec},
1725 {"extends", C_JAVA, st_C_javastruct},
1726 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1727 {"struct", 0, st_C_struct},
1728 {"mutable", C_PLPL, st_C_typespec},
1729 {"",}, {"",}, {"",}, {"",},
1730 {"auto", 0, st_C_typespec},
1731 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1732 {"",}, {"",},
1733 {"short", 0, st_C_typespec},
1734 {"",},
1735 {"static", 0, st_C_typespec},
1736 {"",}, {"",},
1737 {"signed", 0, st_C_typespec},
1738 {"",}, {"",}, {"",}, {"",},
1739 {"@protocol", 0, st_C_objprot},
1740 {"",},
1741 {"typedef", 0, st_C_typedef},
1742 {"typename", C_PLPL, st_C_typespec},
1743 {"namespace", C_PLPL, st_C_struct},
1744 {"bool", C_PLPL, st_C_typespec},
1745 {"",}, {"",},
1746 {"explicit", C_PLPL, st_C_typespec},
1747 {"",}, {"",}, {"",}, {"",},
1748 {"int", 0, st_C_typespec},
1749 {"enum", 0, st_C_enum},
1750 {"",}, {"",},
1751 {"void", 0, st_C_typespec},
1752 {"@implementation", 0, st_C_objimpl},
1753 {"",},
1754 {"volatile", 0, st_C_typespec},
1755 {"",},
1756 {"@end", 0, st_C_objend},
1757 {"char", 0, st_C_typespec},
1758 {"class", C_PLPL, st_C_struct},
1759 {"unsigned", 0, st_C_typespec},
1760 {"",}, {"",},
1761 {"@interface", 0, st_C_objprot},
1762 {"",},
1763 {"PSEUDO", 0, st_C_gnumacro},
1764 {"const", 0, st_C_typespec},
1765 {"domain", C_STAR, st_C_struct},
1766 {"ENTRY", 0, st_C_gnumacro},
1767 {"",},
1768 {"SYSCALL", 0, st_C_gnumacro},
1769 {"float", 0, st_C_typespec},
1770 {"",}, {"",}, {"",}, {"",}, {"",},
1771 {"long", 0, st_C_typespec},
1772 {"",}, {"",}, {"",}, {"",},
1773 {"package", C_JAVA, st_C_ignore},
1774 {"",}, {"",}, {"",}, {"",}, {"",},
1775 {"DEFUN", 0, st_C_gnumacro},
1776 {"",}, {"",}, {"",}, {"",}, {"",},
1777 {"import", C_JAVA, st_C_ignore},
1778 {"",}, {"",}, {"",},
1779 {"implements", C_JAVA, st_C_javastruct},
1780 {"",}, {"",}, {"",}, {"",},
1781 {"union", 0, st_C_struct},
1782 {"",}, {"",},
1783 {"double", 0, st_C_typespec},
1784 {"",}, {"",},
1785 {"friend", C_PLPL, st_C_ignore},
1786 {"",},
1787 {"define", 0, st_C_define},
1790 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
1792 register int key = hash (str, len);
1794 if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)
1796 register char *s = wordlist[key].name;
1798 if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
1799 return &wordlist[key];
1802 return 0;
1804 /* ending time is 10:31:16 */
1805 /*%>*/
1807 enum sym_type
1808 C_symtype (str, len, c_ext)
1809 char *str;
1810 int len;
1811 int c_ext;
1813 register struct C_stab_entry *se = in_word_set (str, len);
1815 if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
1816 return st_none;
1817 return se->type;
1821 * C functions and variables are recognized using a simple
1822 * finite automaton. fvdef is its state variable.
1824 enum
1826 fvnone, /* nothing seen */
1827 fvnameseen, /* function or variable name seen */
1828 fstartlist, /* func: just after open parenthesis */
1829 finlist, /* func: in parameter list */
1830 flistseen, /* func: after parameter list */
1831 fignore, /* func: before open brace */
1832 vignore /* var-like: ignore until ';' */
1833 } fvdef;
1837 * typedefs are recognized using a simple finite automaton.
1838 * typdef is its state variable.
1840 enum
1842 tnone, /* nothing seen */
1843 ttypedseen, /* typedef keyword seen */
1844 tinbody, /* inside typedef body */
1845 tend, /* just before typedef tag */
1846 tignore /* junk after typedef tag */
1847 } typdef;
1851 * struct-like structures (enum, struct and union) are recognized
1852 * using another simple finite automaton. `structdef' is its state
1853 * variable.
1855 enum
1857 snone, /* nothing seen yet */
1858 skeyseen, /* struct-like keyword seen */
1859 stagseen, /* struct-like tag seen */
1860 scolonseen, /* colon seen after struct-like tag */
1861 sinbody /* in struct body: recognize member func defs*/
1862 } structdef;
1865 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1866 * struct tag, and structtype is the type of the preceding struct-like
1867 * keyword.
1869 char *structtag = "<uninited>";
1870 enum sym_type structtype;
1873 * When objdef is different from onone, objtag is the name of the class.
1875 char *objtag = "<uninited>";
1878 * Yet another little state machine to deal with preprocessor lines.
1880 enum
1882 dnone, /* nothing seen */
1883 dsharpseen, /* '#' seen as first char on line */
1884 ddefineseen, /* '#' and 'define' seen */
1885 dignorerest /* ignore rest of line */
1886 } definedef;
1889 * State machine for Objective C protocols and implementations.
1890 * Tom R.Hageman <tom@basil.icce.rug.nl>
1892 enum
1894 onone, /* nothing seen */
1895 oprotocol, /* @interface or @protocol seen */
1896 oimplementation, /* @implementations seen */
1897 otagseen, /* class name seen */
1898 oparenseen, /* parenthesis before category seen */
1899 ocatseen, /* category name seen */
1900 oinbody, /* in @implementation body */
1901 omethodsign, /* in @implementation body, after +/- */
1902 omethodtag, /* after method name */
1903 omethodcolon, /* after method colon */
1904 omethodparm, /* after method parameter */
1905 oignore /* wait for @end */
1906 } objdef;
1910 * Use this structure to keep info about the token read, and how it
1911 * should be tagged. Used by the make_C_tag function to build a tag.
1913 typedef struct
1915 bool valid;
1916 char *str;
1917 bool named;
1918 int linelen;
1919 int lineno;
1920 long linepos;
1921 char *buffer;
1922 } TOKEN;
1923 TOKEN tok; /* latest token read */
1927 * Set this to TRUE, and the next token considered is called a function.
1928 * Used only for GNU emacs's function-defining macros.
1930 bool next_token_is_func;
1933 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1935 bool yacc_rules;
1938 * methodlen is the length of the method name stored in token_name.
1940 int methodlen;
1943 * consider_token ()
1944 * checks to see if the current token is at the start of a
1945 * function or variable, or corresponds to a typedef, or
1946 * is a struct/union/enum tag, or #define, or an enum constant.
1948 * *IS_FUNC gets TRUE iff the token is a function or #define macro
1949 * with args. C_EXT is which language we are looking at.
1951 * In the future we will need some way to adjust where the end of
1952 * the token is; for instance, implementing the C++ keyword
1953 * `operator' properly will adjust the end of the token to be after
1954 * whatever follows `operator'.
1956 * Globals
1957 * fvdef IN OUT
1958 * structdef IN OUT
1959 * definedef IN OUT
1960 * typdef IN OUT
1961 * objdef IN OUT
1962 * next_token_is_func IN OUT
1965 bool
1966 consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var)
1967 register char *str; /* IN: token pointer */
1968 register int len; /* IN: token length */
1969 register char c; /* IN: first char after the token */
1970 int c_ext; /* IN: C extensions mask */
1971 int cblev; /* IN: curly brace level */
1972 int parlev; /* IN: parenthesis level */
1973 bool *is_func_or_var; /* OUT: function or variable found */
1975 enum sym_type toktype = C_symtype (str, len, c_ext);
1978 * Advance the definedef state machine.
1980 switch (definedef)
1982 case dnone:
1983 /* We're not on a preprocessor line. */
1984 break;
1985 case dsharpseen:
1986 if (toktype == st_C_define)
1988 definedef = ddefineseen;
1990 else
1992 definedef = dignorerest;
1994 return FALSE;
1995 case ddefineseen:
1997 * Make a tag for any macro, unless it is a constant
1998 * and constantypedefs is FALSE.
2000 definedef = dignorerest;
2001 *is_func_or_var = (c == '(');
2002 if (!*is_func_or_var && !constantypedefs)
2003 return FALSE;
2004 else
2005 return TRUE;
2006 case dignorerest:
2007 return FALSE;
2008 default:
2009 error ("internal error: definedef value.", (char *)NULL);
2013 * Now typedefs
2015 switch (typdef)
2017 case tnone:
2018 if (toktype == st_C_typedef)
2020 if (typedefs)
2021 typdef = ttypedseen;
2022 fvdef = fvnone;
2023 return FALSE;
2025 break;
2026 case ttypedseen:
2027 switch (toktype)
2029 case st_none:
2030 case st_C_typespec:
2031 typdef = tend;
2032 break;
2033 case st_C_struct:
2034 case st_C_enum:
2035 break;
2037 /* Do not return here, so the structdef stuff has a chance. */
2038 break;
2039 case tend:
2040 switch (toktype)
2042 case st_C_typespec:
2043 case st_C_struct:
2044 case st_C_enum:
2045 return FALSE;
2047 return TRUE;
2051 * This structdef business is currently only invoked when cblev==0.
2052 * It should be recursively invoked whatever the curly brace level,
2053 * and a stack of states kept, to allow for definitions of structs
2054 * within structs.
2056 * This structdef business is NOT invoked when we are ctags and the
2057 * file is plain C. This is because a struct tag may have the same
2058 * name as another tag, and this loses with ctags.
2060 switch (toktype)
2062 case st_C_javastruct:
2063 if (structdef == stagseen)
2064 structdef = scolonseen;
2065 return FALSE;
2066 break;
2067 case st_C_struct:
2068 case st_C_enum:
2069 if (typdef == ttypedseen
2070 || (typedefs_and_cplusplus && cblev == 0 && structdef == snone))
2072 structdef = skeyseen;
2073 structtype = toktype;
2075 return FALSE;
2078 if (structdef == skeyseen)
2080 /* Save the tag for struct/union/class, for functions and variables
2081 that may be defined inside. */
2082 if (structtype == st_C_struct)
2083 structtag = savenstr (str, len);
2084 else
2085 structtag = "<enum>";
2086 structdef = stagseen;
2087 return TRUE;
2090 /* Avoid entering fvdef stuff if typdef is going on. */
2091 if (typdef != tnone)
2093 definedef = dnone;
2094 return FALSE;
2097 /* Detect GNU macros.
2099 DEFUN note for writers of emacs C code:
2100 The DEFUN macro, used in emacs C source code, has a first arg
2101 that is a string (the lisp function name), and a second arg that
2102 is a C function name. Since etags skips strings, the second arg
2103 is tagged. This is unfortunate, as it would be better to tag the
2104 first arg. The simplest way to deal with this problem would be
2105 to name the tag with a name built from the function name, by
2106 removing the initial 'F' character and substituting '-' for '_'.
2107 Anyway, this assumes that the conventions of naming lisp
2108 functions will never change. Currently, this method is not
2109 implemented, so writers of emacs code are recommended to put the
2110 first two args of a DEFUN on the same line. */
2111 if (definedef == dnone && toktype == st_C_gnumacro)
2113 next_token_is_func = TRUE;
2114 return FALSE;
2116 if (next_token_is_func)
2118 next_token_is_func = FALSE;
2119 fvdef = fignore;
2120 *is_func_or_var = TRUE;
2121 return TRUE;
2124 /* Detect Objective C constructs. */
2125 switch (objdef)
2127 case onone:
2128 switch (toktype)
2130 case st_C_objprot:
2131 objdef = oprotocol;
2132 return FALSE;
2133 case st_C_objimpl:
2134 objdef = oimplementation;
2135 return FALSE;
2137 break;
2138 case oimplementation:
2139 /* Save the class tag for functions or variables defined inside. */
2140 objtag = savenstr (str, len);
2141 objdef = oinbody;
2142 return FALSE;
2143 case oprotocol:
2144 /* Save the class tag for categories. */
2145 objtag = savenstr (str, len);
2146 objdef = otagseen;
2147 *is_func_or_var = TRUE;
2148 return TRUE;
2149 case oparenseen:
2150 objdef = ocatseen;
2151 *is_func_or_var = TRUE;
2152 return TRUE;
2153 case oinbody:
2154 break;
2155 case omethodsign:
2156 if (parlev == 0)
2158 objdef = omethodtag;
2159 methodlen = len;
2160 grow_linebuffer (&token_name, methodlen + 1);
2161 strncpy (token_name.buffer, str, len);
2162 token_name.buffer[methodlen] = '\0';
2163 token_name.len = methodlen;
2164 return TRUE;
2166 return FALSE;
2167 case omethodcolon:
2168 if (parlev == 0)
2169 objdef = omethodparm;
2170 return FALSE;
2171 case omethodparm:
2172 if (parlev == 0)
2174 objdef = omethodtag;
2175 methodlen += len;
2176 grow_linebuffer (&token_name, methodlen + 1);
2177 strncat (token_name.buffer, str, len);
2178 token_name.len = methodlen;
2179 return TRUE;
2181 return FALSE;
2182 case oignore:
2183 if (toktype == st_C_objend)
2185 /* Memory leakage here: the string pointed by objtag is
2186 never released, because many tests would be needed to
2187 avoid breaking on incorrect input code. The amount of
2188 memory leaked here is the sum of the lengths of the
2189 class tags.
2190 free (objtag); */
2191 objdef = onone;
2193 return FALSE;
2196 /* A function, variable or enum constant? */
2197 switch (toktype)
2199 case st_C_typespec:
2200 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2201 fvdef = fvnone; /* should be useless */
2202 return FALSE;
2203 case st_C_ignore:
2204 fvdef = vignore;
2205 return FALSE;
2206 case st_none:
2207 if (constantypedefs && structdef == sinbody && structtype == st_C_enum)
2208 return TRUE;
2209 if (fvdef == fvnone)
2211 fvdef = fvnameseen; /* function or variable */
2212 *is_func_or_var = TRUE;
2213 return TRUE;
2217 return FALSE;
2221 * C_entries ()
2222 * This routine finds functions, variables, typedefs,
2223 * #define's, enum constants and struct/union/enum definitions in
2224 * #C syntax and adds them to the list.
2226 #define current_lb_is_new (newndx == curndx)
2227 #define switch_line_buffers() (curndx = 1 - curndx)
2229 #define curlb (lbs[curndx].lb)
2230 #define othlb (lbs[1-curndx].lb)
2231 #define newlb (lbs[newndx].lb)
2232 #define curlinepos (lbs[curndx].linepos)
2233 #define othlinepos (lbs[1-curndx].linepos)
2234 #define newlinepos (lbs[newndx].linepos)
2236 #define CNL_SAVE_DEFINEDEF \
2237 do { \
2238 curlinepos = charno; \
2239 lineno++; \
2240 linecharno = charno; \
2241 charno += readline (&curlb, inf); \
2242 lp = curlb.buffer; \
2243 quotednl = FALSE; \
2244 newndx = curndx; \
2245 } while (0)
2247 #define CNL \
2248 do { \
2249 CNL_SAVE_DEFINEDEF; \
2250 if (savetok.valid) \
2252 tok = savetok; \
2253 savetok.valid = FALSE; \
2255 definedef = dnone; \
2256 } while (0)
2259 void
2260 make_C_tag (isfun)
2261 bool isfun;
2263 /* This function should never be called when tok.valid is FALSE, but
2264 we must protect against invalid input or internal errors. */
2265 if (tok.valid)
2267 if (traditional_tag_style)
2269 /* This was the original code. Now we call new_pfnote instead,
2270 which uses the new method for naming tags (see new_pfnote). */
2271 char *name = NULL;
2273 if (CTAGS || tok.named)
2274 name = savestr (token_name.buffer);
2275 pfnote (name, isfun,
2276 tok.buffer, tok.linelen, tok.lineno, tok.linepos);
2278 else
2279 new_pfnote (token_name.buffer, token_name.len, isfun,
2280 tok.buffer, tok.linelen, tok.lineno, tok.linepos);
2281 tok.valid = FALSE;
2283 else if (DEBUG)
2284 abort ();
2288 void
2289 C_entries (c_ext, inf)
2290 int c_ext; /* extension of C */
2291 FILE *inf; /* input file */
2293 register char c; /* latest char read; '\0' for end of line */
2294 register char *lp; /* pointer one beyond the character `c' */
2295 int curndx, newndx; /* indices for current and new lb */
2296 register int tokoff; /* offset in line of start of current token */
2297 register int toklen; /* length of current token */
2298 char *qualifier; /* string used to qualify names */
2299 int qlen; /* length of qualifier */
2300 int cblev; /* current curly brace level */
2301 int parlev; /* current parenthesis level */
2302 bool incomm, inquote, inchar, quotednl, midtoken;
2303 bool cplpl, cjava;
2304 TOKEN savetok; /* token saved during preprocessor handling */
2307 curndx = newndx = 0;
2308 lineno = 0;
2309 charno = 0;
2310 lp = curlb.buffer;
2311 *lp = 0;
2313 fvdef = fvnone; typdef = tnone; structdef = snone;
2314 definedef = dnone; objdef = onone;
2315 next_token_is_func = yacc_rules = FALSE;
2316 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2317 tok.valid = savetok.valid = FALSE;
2318 cblev = 0;
2319 parlev = 0;
2320 cplpl = (c_ext & C_PLPL) == C_PLPL;
2321 cjava = (c_ext & C_JAVA) == C_JAVA;
2322 if (cjava)
2323 { qualifier = "."; qlen = 1; }
2324 else
2325 { qualifier = "::"; qlen = 2; }
2327 while (!feof (inf))
2329 c = *lp++;
2330 if (c == '\\')
2332 /* If we're at the end of the line, the next character is a
2333 '\0'; don't skip it, because it's the thing that tells us
2334 to read the next line. */
2335 if (*lp == '\0')
2337 quotednl = TRUE;
2338 continue;
2340 lp++;
2341 c = ' ';
2343 else if (incomm)
2345 switch (c)
2347 case '*':
2348 if (*lp == '/')
2350 c = *lp++;
2351 incomm = FALSE;
2353 break;
2354 case '\0':
2355 /* Newlines inside comments do not end macro definitions in
2356 traditional cpp. */
2357 CNL_SAVE_DEFINEDEF;
2358 break;
2360 continue;
2362 else if (inquote)
2364 switch (c)
2366 case '"':
2367 inquote = FALSE;
2368 break;
2369 case '\0':
2370 /* Newlines inside strings do not end macro definitions
2371 in traditional cpp, even though compilers don't
2372 usually accept them. */
2373 CNL_SAVE_DEFINEDEF;
2374 break;
2376 continue;
2378 else if (inchar)
2380 switch (c)
2382 case '\0':
2383 /* Hmmm, something went wrong. */
2384 CNL;
2385 /* FALLTHRU */
2386 case '\'':
2387 inchar = FALSE;
2388 break;
2390 continue;
2392 else
2393 switch (c)
2395 case '"':
2396 inquote = TRUE;
2397 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2398 fvdef = fvnone;
2399 continue;
2400 case '\'':
2401 inchar = TRUE;
2402 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2403 fvdef = fvnone;
2404 continue;
2405 case '/':
2406 if (*lp == '*')
2408 lp++;
2409 incomm = TRUE;
2410 continue;
2412 else if (/* cplpl && */ *lp == '/')
2414 c = '\0';
2415 break;
2417 else
2418 break;
2419 case '%':
2420 if ((c_ext & YACC) && *lp == '%')
2422 /* entering or exiting rules section in yacc file */
2423 lp++;
2424 definedef = dnone; fvdef = fvnone;
2425 typdef = tnone; structdef = snone;
2426 next_token_is_func = FALSE;
2427 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2428 cblev = 0;
2429 yacc_rules = !yacc_rules;
2430 continue;
2432 else
2433 break;
2434 case '#':
2435 if (definedef == dnone)
2437 char *cp;
2438 bool cpptoken = TRUE;
2440 /* Look back on this line. If all blanks, or nonblanks
2441 followed by an end of comment, this is a preprocessor
2442 token. */
2443 for (cp = newlb.buffer; cp < lp-1; cp++)
2444 if (!iswhite (*cp))
2446 if (*cp == '*' && *(cp+1) == '/')
2448 cp++;
2449 cpptoken = TRUE;
2451 else
2452 cpptoken = FALSE;
2454 if (cpptoken)
2455 definedef = dsharpseen;
2456 } /* if (definedef == dnone) */
2458 continue;
2459 } /* switch (c) */
2462 /* Consider token only if some complicated conditions are satisfied. */
2463 if ((definedef != dnone
2464 || (cblev == 0 && structdef != scolonseen)
2465 || (cblev == 1 && cplpl && structdef == sinbody)
2466 || (structdef == sinbody && structtype == st_C_enum))
2467 && typdef != tignore
2468 && definedef != dignorerest
2469 && fvdef != finlist)
2471 if (midtoken)
2473 if (endtoken (c))
2475 if (c == ':' && cplpl && *lp == ':' && begtoken(*(lp + 1)))
2478 * This handles :: in the middle, but not at the
2479 * beginning of an identifier.
2481 lp += 2;
2482 toklen += 3;
2484 else
2486 bool funorvar = FALSE;
2488 if (yacc_rules
2489 || consider_token (newlb.buffer + tokoff, toklen, c,
2490 c_ext, cblev, parlev, &funorvar))
2492 tok.named = FALSE;
2493 if (structdef == sinbody
2494 && definedef == dnone
2495 && funorvar)
2496 /* function or var defined in C++ class body */
2498 int len = strlen (structtag) + qlen + toklen;
2499 grow_linebuffer (&token_name, len + 1);
2500 strcpy (token_name.buffer, structtag);
2501 strcat (token_name.buffer, qualifier);
2502 strncat (token_name.buffer,
2503 newlb.buffer + tokoff, toklen);
2504 token_name.len = len;
2505 tok.named = TRUE;
2507 else if (objdef == ocatseen)
2508 /* Objective C category */
2510 int len = strlen (objtag) + 2 + toklen;
2511 grow_linebuffer (&token_name, len + 1);
2512 strcpy (token_name.buffer, objtag);
2513 strcat (token_name.buffer, "(");
2514 strncat (token_name.buffer,
2515 newlb.buffer + tokoff, toklen);
2516 strcat (token_name.buffer, ")");
2517 token_name.len = len;
2518 tok.named = TRUE;
2520 else if (objdef == omethodtag
2521 || objdef == omethodparm)
2522 /* Objective C method */
2524 tok.named = TRUE;
2526 else
2528 grow_linebuffer (&token_name, toklen + 1);
2529 strncpy (token_name.buffer,
2530 newlb.buffer + tokoff, toklen);
2531 token_name.buffer[toklen] = '\0';
2532 token_name.len = toklen;
2533 /* Name macros. */
2534 tok.named = (structdef == stagseen
2535 || typdef == tend
2536 || (funorvar
2537 && definedef == dignorerest));
2539 tok.lineno = lineno;
2540 tok.linelen = tokoff + toklen + 1;
2541 tok.buffer = newlb.buffer;
2542 tok.linepos = newlinepos;
2543 tok.valid = TRUE;
2545 if (definedef == dnone
2546 && (fvdef == fvnameseen
2547 || structdef == stagseen
2548 || typdef == tend
2549 || objdef != onone))
2551 if (current_lb_is_new)
2552 switch_line_buffers ();
2554 else
2555 make_C_tag (funorvar);
2557 midtoken = FALSE;
2559 } /* if (endtoken (c)) */
2560 else if (intoken (c))
2562 toklen++;
2563 continue;
2565 } /* if (midtoken) */
2566 else if (begtoken (c))
2568 switch (definedef)
2570 case dnone:
2571 switch (fvdef)
2573 case fstartlist:
2574 fvdef = finlist;
2575 continue;
2576 case flistseen:
2577 make_C_tag (TRUE); /* a function */
2578 fvdef = fignore;
2579 break;
2580 case fvnameseen:
2581 fvdef = fvnone;
2582 break;
2584 if (structdef == stagseen && !cjava)
2585 structdef = snone;
2586 break;
2587 case dsharpseen:
2588 savetok = tok;
2590 if (!yacc_rules || lp == newlb.buffer + 1)
2592 tokoff = lp - 1 - newlb.buffer;
2593 toklen = 1;
2594 midtoken = TRUE;
2596 continue;
2597 } /* if (begtoken) */
2598 } /* if must look at token */
2601 /* Detect end of line, colon, comma, semicolon and various braces
2602 after having handled a token.*/
2603 switch (c)
2605 case ':':
2606 if (definedef != dnone)
2607 break;
2608 switch (objdef)
2610 case otagseen:
2611 objdef = oignore;
2612 make_C_tag (TRUE); /* an Objective C class */
2613 break;
2614 case omethodtag:
2615 case omethodparm:
2616 objdef = omethodcolon;
2617 methodlen += 1;
2618 grow_linebuffer (&token_name, methodlen + 1);
2619 strcat (token_name.buffer, ":");
2620 token_name.len = methodlen;
2621 break;
2623 if (structdef == stagseen)
2624 structdef = scolonseen;
2625 else
2626 switch (fvdef)
2628 case fvnameseen:
2629 if (yacc_rules)
2631 make_C_tag (FALSE); /* a yacc function */
2632 fvdef = fignore;
2634 break;
2635 case fstartlist:
2636 fvdef = fvnone;
2637 break;
2639 break;
2640 case ';':
2641 if (definedef != dnone)
2642 break;
2643 if (cblev == 0)
2644 switch (typdef)
2646 case tend:
2647 make_C_tag (FALSE); /* a typedef */
2648 /* FALLTHRU */
2649 default:
2650 typdef = tnone;
2652 switch (fvdef)
2654 case fignore:
2655 break;
2656 case fvnameseen:
2657 if ((globals && cblev == 0) || (members && cblev == 1))
2658 make_C_tag (FALSE); /* a variable */
2659 /* FALLTHRU */
2660 default:
2661 fvdef = fvnone;
2662 /* The following instruction invalidates the token.
2663 Probably the token should be invalidated in all
2664 other cases where some state machine is reset. */
2665 tok.valid = FALSE;
2667 if (structdef == stagseen)
2668 structdef = snone;
2669 break;
2670 case ',':
2671 if (definedef != dnone)
2672 break;
2673 switch (objdef)
2675 case omethodtag:
2676 case omethodparm:
2677 make_C_tag (TRUE); /* an Objective C method */
2678 objdef = oinbody;
2679 break;
2681 switch (fvdef)
2683 case finlist:
2684 case fignore:
2685 case vignore:
2686 break;
2687 case fvnameseen:
2688 if ((globals && cblev == 0) || (members && cblev == 1))
2689 make_C_tag (FALSE); /* a variable */
2690 break;
2691 default:
2692 fvdef = fvnone;
2694 if (structdef == stagseen)
2695 structdef = snone;
2696 break;
2697 case '[':
2698 if (definedef != dnone)
2699 break;
2700 if (cblev == 0 && typdef == tend)
2702 typdef = tignore;
2703 make_C_tag (FALSE); /* a typedef */
2704 break;
2706 switch (fvdef)
2708 case finlist:
2709 case fignore:
2710 case vignore:
2711 break;
2712 case fvnameseen:
2713 if ((globals && cblev == 0) || (members && cblev == 1))
2714 make_C_tag (FALSE); /* a variable */
2715 /* FALLTHRU */
2716 default:
2717 fvdef = fvnone;
2719 if (structdef == stagseen)
2720 structdef = snone;
2721 break;
2722 case '(':
2723 if (definedef != dnone)
2724 break;
2725 if (objdef == otagseen && parlev == 0)
2726 objdef = oparenseen;
2727 switch (fvdef)
2729 case fvnone:
2730 switch (typdef)
2732 case ttypedseen:
2733 case tend:
2734 if (tok.valid && *lp != '*')
2736 /* This handles constructs like:
2737 typedef void OperatorFun (int fun); */
2738 make_C_tag (FALSE);
2739 typdef = tignore;
2741 break;
2742 } /* switch (typdef) */
2743 break;
2744 case fvnameseen:
2745 fvdef = fstartlist;
2746 break;
2747 case flistseen:
2748 fvdef = finlist;
2749 break;
2751 parlev++;
2752 break;
2753 case ')':
2754 if (definedef != dnone)
2755 break;
2756 if (objdef == ocatseen && parlev == 1)
2758 make_C_tag (TRUE); /* an Objective C category */
2759 objdef = oignore;
2761 if (--parlev == 0)
2763 switch (fvdef)
2765 case fstartlist:
2766 case finlist:
2767 fvdef = flistseen;
2768 break;
2770 if (cblev == 0 && typdef == tend)
2772 typdef = tignore;
2773 make_C_tag (FALSE); /* a typedef */
2776 else if (parlev < 0) /* can happen due to ill-conceived #if's. */
2777 parlev = 0;
2778 break;
2779 case '{':
2780 if (definedef != dnone)
2781 break;
2782 if (typdef == ttypedseen)
2783 typdef = tinbody;
2784 switch (structdef)
2786 case skeyseen: /* unnamed struct */
2787 structdef = sinbody;
2788 structtag = "_anonymous_";
2789 break;
2790 case stagseen:
2791 case scolonseen: /* named struct */
2792 structdef = sinbody;
2793 make_C_tag (FALSE); /* a struct */
2794 break;
2796 switch (fvdef)
2798 case flistseen:
2799 make_C_tag (TRUE); /* a function */
2800 /* FALLTHRU */
2801 case fignore:
2802 fvdef = fvnone;
2803 break;
2804 case fvnone:
2805 switch (objdef)
2807 case otagseen:
2808 make_C_tag (TRUE); /* an Objective C class */
2809 objdef = oignore;
2810 break;
2811 case omethodtag:
2812 case omethodparm:
2813 make_C_tag (TRUE); /* an Objective C method */
2814 objdef = oinbody;
2815 break;
2816 default:
2817 /* Neutralize `extern "C" {' grot. */
2818 if (cblev == 0 && structdef == snone && typdef == tnone)
2819 cblev = -1;
2822 cblev++;
2823 break;
2824 case '*':
2825 if (definedef != dnone)
2826 break;
2827 if (fvdef == fstartlist)
2828 fvdef = fvnone; /* avoid tagging `foo' in `foo (*bar()) ()' */
2829 break;
2830 case '}':
2831 if (definedef != dnone)
2832 break;
2833 if (!noindentypedefs && lp == newlb.buffer + 1)
2835 cblev = 0; /* reset curly brace level if first column */
2836 parlev = 0; /* also reset paren level, just in case... */
2838 else if (cblev > 0)
2839 cblev--;
2840 if (cblev == 0)
2842 if (typdef == tinbody)
2843 typdef = tend;
2844 /* Memory leakage here: the string pointed by structtag is
2845 never released, because I fear to miss something and
2846 break things while freeing the area. The amount of
2847 memory leaked here is the sum of the lengths of the
2848 struct tags.
2849 if (structdef == sinbody)
2850 free (structtag); */
2852 structdef = snone;
2853 structtag = "<error>";
2855 break;
2856 case '=':
2857 if (definedef != dnone)
2858 break;
2859 switch (fvdef)
2861 case finlist:
2862 case fignore:
2863 case vignore:
2864 break;
2865 case fvnameseen:
2866 if ((globals && cblev == 0) || (members && cblev == 1))
2867 make_C_tag (FALSE); /* a variable */
2868 /* FALLTHRU */
2869 default:
2870 fvdef = vignore;
2872 break;
2873 case '+':
2874 case '-':
2875 if (objdef == oinbody && cblev == 0)
2877 objdef = omethodsign;
2878 break;
2880 /* FALLTHRU */
2881 case '#': case '~': case '&': case '%': case '/': case '|':
2882 case '^': case '!': case '<': case '>': case '.': case '?': case ']':
2883 if (definedef != dnone)
2884 break;
2885 /* These surely cannot follow a function tag. */
2886 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2887 fvdef = fvnone;
2888 break;
2889 case '\0':
2890 if (objdef == otagseen)
2892 make_C_tag (TRUE); /* an Objective C class */
2893 objdef = oignore;
2895 /* If a macro spans multiple lines don't reset its state. */
2896 if (quotednl)
2897 CNL_SAVE_DEFINEDEF;
2898 else
2899 CNL;
2900 break;
2901 } /* switch (c) */
2903 } /* while not eof */
2907 * Process either a C++ file or a C file depending on the setting
2908 * of a global flag.
2910 void
2911 default_C_entries (inf)
2912 FILE *inf;
2914 C_entries (cplusplus ? C_PLPL : 0, inf);
2917 /* Always do plain ANSI C. */
2918 void
2919 plain_C_entries (inf)
2920 FILE *inf;
2922 C_entries (0, inf);
2925 /* Always do C++. */
2926 void
2927 Cplusplus_entries (inf)
2928 FILE *inf;
2930 C_entries (C_PLPL, inf);
2933 /* Always do Java. */
2934 void
2935 Cjava_entries (inf)
2936 FILE *inf;
2938 C_entries (C_JAVA, inf);
2941 /* Always do C*. */
2942 void
2943 Cstar_entries (inf)
2944 FILE *inf;
2946 C_entries (C_STAR, inf);
2949 /* Always do Yacc. */
2950 void
2951 Yacc_entries (inf)
2952 FILE *inf;
2954 C_entries (YACC, inf);
2957 /* Fortran parsing */
2959 char *dbp;
2961 bool
2962 tail (cp)
2963 char *cp;
2965 register int len = 0;
2967 while (*cp && lowcase(*cp) == lowcase(dbp[len]))
2968 cp++, len++;
2969 if (*cp == '\0' && !intoken(dbp[len]))
2971 dbp += len;
2972 return TRUE;
2974 return FALSE;
2977 void
2978 takeprec ()
2980 while (isspace (*dbp))
2981 dbp++;
2982 if (*dbp != '*')
2983 return;
2984 dbp++;
2985 while (isspace (*dbp))
2986 dbp++;
2987 if (strneq (dbp, "(*)", 3))
2989 dbp += 3;
2990 return;
2992 if (!isdigit (*dbp))
2994 --dbp; /* force failure */
2995 return;
2998 dbp++;
2999 while (isdigit (*dbp));
3002 void
3003 getit (inf)
3004 FILE *inf;
3006 register char *cp;
3008 while (isspace (*dbp))
3009 dbp++;
3010 if (*dbp == '\0')
3012 lineno++;
3013 linecharno = charno;
3014 charno += readline (&lb, inf);
3015 dbp = lb.buffer;
3016 if (dbp[5] != '&')
3017 return;
3018 dbp += 6;
3019 while (isspace (*dbp))
3020 dbp++;
3022 if (!isalpha (*dbp)
3023 && *dbp != '_'
3024 && *dbp != '$')
3025 return;
3026 for (cp = dbp + 1;
3027 (*cp
3028 && (isalpha (*cp) || isdigit (*cp) || (*cp == '_') || (*cp == '$')));
3029 cp++)
3030 continue;
3031 pfnote (savenstr (dbp, cp-dbp), TRUE,
3032 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3035 void
3036 Fortran_functions (inf)
3037 FILE *inf;
3039 lineno = 0;
3040 charno = 0;
3042 while (!feof (inf))
3044 lineno++;
3045 linecharno = charno;
3046 charno += readline (&lb, inf);
3047 dbp = lb.buffer;
3048 if (*dbp == '%')
3049 dbp++; /* Ratfor escape to fortran */
3050 while (isspace (*dbp))
3051 dbp++;
3052 if (*dbp == '\0')
3053 continue;
3054 switch (lowcase (*dbp))
3056 case 'i':
3057 if (tail ("integer"))
3058 takeprec ();
3059 break;
3060 case 'r':
3061 if (tail ("real"))
3062 takeprec ();
3063 break;
3064 case 'l':
3065 if (tail ("logical"))
3066 takeprec ();
3067 break;
3068 case 'c':
3069 if (tail ("complex") || tail ("character"))
3070 takeprec ();
3071 break;
3072 case 'd':
3073 if (tail ("double"))
3075 while (isspace (*dbp))
3076 dbp++;
3077 if (*dbp == '\0')
3078 continue;
3079 if (tail ("precision"))
3080 break;
3081 continue;
3083 break;
3085 while (isspace (*dbp))
3086 dbp++;
3087 if (*dbp == '\0')
3088 continue;
3089 switch (lowcase (*dbp))
3091 case 'f':
3092 if (tail ("function"))
3093 getit (inf);
3094 continue;
3095 case 's':
3096 if (tail ("subroutine"))
3097 getit (inf);
3098 continue;
3099 case 'e':
3100 if (tail ("entry"))
3101 getit (inf);
3102 continue;
3103 case 'p':
3104 if (tail ("program"))
3106 getit (inf);
3107 continue;
3109 if (tail ("procedure"))
3110 getit (inf);
3111 continue;
3112 case 'b':
3113 if (tail ("blockdata") || tail ("block data"))
3115 while (isspace (*dbp))
3116 dbp++;
3117 if (*dbp == '\0') /* assume un-named */
3118 pfnote (savestr ("blockdata"), TRUE, lb.buffer,
3119 dbp - lb.buffer, lineno, linecharno);
3120 else
3121 getit (inf); /* look for name */
3123 continue;
3129 * Bob Weiner, Motorola Inc., 4/3/94
3130 * Unix and microcontroller assembly tag handling
3131 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
3133 void
3134 Asm_labels (inf)
3135 FILE *inf;
3137 register char *cp;
3139 lineno = 0;
3140 charno = 0;
3142 while (!feof (inf))
3144 lineno++;
3145 linecharno = charno;
3146 charno += readline (&lb, inf);
3147 cp = lb.buffer;
3149 /* If first char is alphabetic or one of [_.$], test for colon
3150 following identifier. */
3151 if (isalpha (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3153 /* Read past label. */
3154 cp++;
3155 while (isalnum (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3156 cp++;
3157 if (*cp == ':' || isspace (*cp))
3159 /* Found end of label, so copy it and add it to the table. */
3160 pfnote (savenstr(lb.buffer, cp-lb.buffer), TRUE,
3161 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3168 * Perl support by Bart Robinson <lomew@cs.utah.edu>
3169 * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/
3171 void
3172 Perl_functions (inf)
3173 FILE *inf;
3175 register char *cp;
3177 lineno = 0;
3178 charno = 0;
3180 while (!feof (inf))
3182 lineno++;
3183 linecharno = charno;
3184 charno += readline (&lb, inf);
3185 cp = lb.buffer;
3187 if (*cp++ == 's' && *cp++ == 'u' && *cp++ == 'b' && isspace (*cp++))
3189 while (*cp && isspace (*cp))
3190 cp++;
3191 while (*cp && ! isspace (*cp) && *cp != '{')
3192 cp++;
3193 pfnote (savenstr (lb.buffer, cp-lb.buffer), TRUE,
3194 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3199 /* Idea by Corny de Souza
3200 * Cobol tag functions
3201 * We could look for anything that could be a paragraph name.
3202 * i.e. anything that starts in column 8 is one word and ends in a full stop.
3204 void
3205 Cobol_paragraphs (inf)
3206 FILE *inf;
3208 register char *cp;
3210 lineno = 0;
3211 charno = 0;
3213 while (!feof (inf))
3215 lineno++;
3216 linecharno = charno;
3217 charno += readline (&lb, inf);
3219 if (lb.len < 9)
3220 continue;
3221 dbp = lb.buffer + 8;
3223 /* If eoln, compiler option or comment ignore whole line. */
3224 if (dbp[-1] != ' ' || !isalnum (dbp[0]))
3225 continue;
3227 for (cp = dbp; isalnum (*cp) || *cp == '-'; cp++)
3228 continue;
3229 if (*cp++ == '.')
3230 pfnote (savenstr (dbp, cp-dbp), TRUE,
3231 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3235 /* Added by Mosur Mohan, 4/22/88 */
3236 /* Pascal parsing */
3239 * Locates tags for procedures & functions. Doesn't do any type- or
3240 * var-definitions. It does look for the keyword "extern" or
3241 * "forward" immediately following the procedure statement; if found,
3242 * the tag is skipped.
3244 void
3245 Pascal_functions (inf)
3246 FILE *inf;
3248 struct linebuffer tline; /* mostly copied from C_entries */
3249 long save_lcno;
3250 int save_lineno, save_len;
3251 char c, *cp, *namebuf;
3253 bool /* each of these flags is TRUE iff: */
3254 incomment, /* point is inside a comment */
3255 inquote, /* point is inside '..' string */
3256 get_tagname, /* point is after PROCEDURE/FUNCTION
3257 keyword, so next item = potential tag */
3258 found_tag, /* point is after a potential tag */
3259 inparms, /* point is within parameter-list */
3260 verify_tag; /* point has passed the parm-list, so the
3261 next token will determine whether this
3262 is a FORWARD/EXTERN to be ignored, or
3263 whether it is a real tag */
3265 lineno = 0;
3266 charno = 0;
3267 dbp = lb.buffer;
3268 *dbp = '\0';
3269 save_len = 0;
3270 initbuffer (&tline);
3272 incomment = inquote = FALSE;
3273 found_tag = FALSE; /* have a proc name; check if extern */
3274 get_tagname = FALSE; /* have found "procedure" keyword */
3275 inparms = FALSE; /* found '(' after "proc" */
3276 verify_tag = FALSE; /* check if "extern" is ahead */
3278 /* long main loop to get next char */
3279 while (!feof (inf))
3281 c = *dbp++;
3282 if (c == '\0') /* if end of line */
3284 lineno++;
3285 linecharno = charno;
3286 charno += readline (&lb, inf);
3287 dbp = lb.buffer;
3288 if (*dbp == '\0')
3289 continue;
3290 if (!((found_tag && verify_tag) ||
3291 get_tagname))
3292 c = *dbp++; /* only if don't need *dbp pointing
3293 to the beginning of the name of
3294 the procedure or function */
3296 if (incomment)
3298 if (c == '}') /* within { } comments */
3299 incomment = FALSE;
3300 else if (c == '*' && *dbp == ')') /* within (* *) comments */
3302 dbp++;
3303 incomment = FALSE;
3305 continue;
3307 else if (inquote)
3309 if (c == '\'')
3310 inquote = FALSE;
3311 continue;
3313 else
3314 switch (c)
3316 case '\'':
3317 inquote = TRUE; /* found first quote */
3318 continue;
3319 case '{': /* found open { comment */
3320 incomment = TRUE;
3321 continue;
3322 case '(':
3323 if (*dbp == '*') /* found open (* comment */
3325 incomment = TRUE;
3326 dbp++;
3328 else if (found_tag) /* found '(' after tag, i.e., parm-list */
3329 inparms = TRUE;
3330 continue;
3331 case ')': /* end of parms list */
3332 if (inparms)
3333 inparms = FALSE;
3334 continue;
3335 case ';':
3336 if (found_tag && !inparms) /* end of proc or fn stmt */
3338 verify_tag = TRUE;
3339 break;
3341 continue;
3343 if (found_tag && verify_tag && (*dbp != ' '))
3345 /* check if this is an "extern" declaration */
3346 if (*dbp == '\0')
3347 continue;
3348 if (lowcase (*dbp == 'e'))
3350 if (tail ("extern")) /* superfluous, really! */
3352 found_tag = FALSE;
3353 verify_tag = FALSE;
3356 else if (lowcase (*dbp) == 'f')
3358 if (tail ("forward")) /* check for forward reference */
3360 found_tag = FALSE;
3361 verify_tag = FALSE;
3364 if (found_tag && verify_tag) /* not external proc, so make tag */
3366 found_tag = FALSE;
3367 verify_tag = FALSE;
3368 pfnote (namebuf, TRUE,
3369 tline.buffer, save_len, save_lineno, save_lcno);
3370 continue;
3373 if (get_tagname) /* grab name of proc or fn */
3375 if (*dbp == '\0')
3376 continue;
3378 /* save all values for later tagging */
3379 grow_linebuffer (&tline, lb.len + 1);
3380 strcpy (tline.buffer, lb.buffer);
3381 save_lineno = lineno;
3382 save_lcno = linecharno;
3384 /* grab block name */
3385 for (cp = dbp + 1; *cp != '\0' && !endtoken (*cp); cp++)
3386 continue;
3387 namebuf = savenstr (dbp, cp-dbp);
3388 dbp = cp; /* set dbp to e-o-token */
3389 save_len = dbp - lb.buffer + 1;
3390 get_tagname = FALSE;
3391 found_tag = TRUE;
3392 continue;
3394 /* and proceed to check for "extern" */
3396 else if (!incomment && !inquote && !found_tag)
3398 /* check for proc/fn keywords */
3399 switch (lowcase (c))
3401 case 'p':
3402 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
3403 get_tagname = TRUE;
3404 continue;
3405 case 'f':
3406 if (tail ("unction"))
3407 get_tagname = TRUE;
3408 continue;
3411 } /* while not eof */
3413 free (tline.buffer);
3417 * lisp tag functions
3418 * look for (def or (DEF, quote or QUOTE
3421 L_isdef (strp)
3422 register char *strp;
3424 return ((strp[1] == 'd' || strp[1] == 'D')
3425 && (strp[2] == 'e' || strp[2] == 'E')
3426 && (strp[3] == 'f' || strp[3] == 'F'));
3430 L_isquote (strp)
3431 register char *strp;
3433 return ((*(++strp) == 'q' || *strp == 'Q')
3434 && (*(++strp) == 'u' || *strp == 'U')
3435 && (*(++strp) == 'o' || *strp == 'O')
3436 && (*(++strp) == 't' || *strp == 'T')
3437 && (*(++strp) == 'e' || *strp == 'E')
3438 && isspace (*(++strp)));
3441 void
3442 L_getit ()
3444 register char *cp;
3446 if (*dbp == '\'') /* Skip prefix quote */
3447 dbp++;
3448 else if (*dbp == '(' && L_isquote (dbp)) /* Skip "(quote " */
3450 dbp += 7;
3451 while (isspace (*dbp))
3452 dbp++;
3454 for (cp = dbp /*+1*/;
3455 *cp != '\0' && *cp != '(' && *cp != ' ' && *cp != ')';
3456 cp++)
3457 continue;
3458 if (cp == dbp)
3459 return;
3461 pfnote (savenstr (dbp, cp-dbp), TRUE,
3462 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3465 void
3466 Lisp_functions (inf)
3467 FILE *inf;
3469 lineno = 0;
3470 charno = 0;
3472 while (!feof (inf))
3474 lineno++;
3475 linecharno = charno;
3476 charno += readline (&lb, inf);
3477 dbp = lb.buffer;
3478 if (dbp[0] == '(')
3480 if (L_isdef (dbp))
3482 while (!isspace (*dbp))
3483 dbp++;
3484 while (isspace (*dbp))
3485 dbp++;
3486 L_getit ();
3488 else
3490 /* Check for (foo::defmumble name-defined ... */
3492 dbp++;
3493 while (*dbp && !isspace (*dbp)
3494 && *dbp != ':' && *dbp != '(' && *dbp != ')');
3495 if (*dbp == ':')
3498 dbp++;
3499 while (*dbp == ':');
3501 if (L_isdef (dbp - 1))
3503 while (!isspace (*dbp))
3504 dbp++;
3505 while (isspace (*dbp))
3506 dbp++;
3507 L_getit ();
3516 * Postscript tag functions
3517 * Just look for lines where the first character is '/'
3518 * Richard Mlynarik <mly@adoc.xerox.com>
3520 void
3521 Postscript_functions (inf)
3522 FILE *inf;
3524 lineno = 0;
3525 charno = 0;
3527 while (!feof (inf))
3529 lineno++;
3530 linecharno = charno;
3531 charno += readline (&lb, inf);
3532 dbp = lb.buffer;
3533 if (dbp[0] == '/')
3535 register char *cp;
3536 for (cp = dbp+1;
3537 *cp != '\0' && *cp != ' ' && *cp != '{';
3538 cp++)
3539 continue;
3540 pfnote (savenstr (dbp, cp-dbp), TRUE,
3541 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3548 * Scheme tag functions
3549 * look for (def... xyzzy
3550 * look for (def... (xyzzy
3551 * look for (def ... ((...(xyzzy ....
3552 * look for (set! xyzzy
3555 void get_scheme ();
3557 void
3558 Scheme_functions (inf)
3559 FILE *inf;
3561 lineno = 0;
3562 charno = 0;
3564 while (!feof (inf))
3566 lineno++;
3567 linecharno = charno;
3568 charno += readline (&lb, inf);
3569 dbp = lb.buffer;
3570 if (dbp[0] == '(' &&
3571 (dbp[1] == 'D' || dbp[1] == 'd') &&
3572 (dbp[2] == 'E' || dbp[2] == 'e') &&
3573 (dbp[3] == 'F' || dbp[3] == 'f'))
3575 while (!isspace (*dbp))
3576 dbp++;
3577 /* Skip over open parens and white space */
3578 while (*dbp && (isspace (*dbp) || *dbp == '('))
3579 dbp++;
3580 get_scheme ();
3582 if (dbp[0] == '(' &&
3583 (dbp[1] == 'S' || dbp[1] == 's') &&
3584 (dbp[2] == 'E' || dbp[2] == 'e') &&
3585 (dbp[3] == 'T' || dbp[3] == 't') &&
3586 (dbp[4] == '!' || dbp[4] == '!') &&
3587 (isspace (dbp[5])))
3589 while (!isspace (*dbp))
3590 dbp++;
3591 /* Skip over white space */
3592 while (isspace (*dbp))
3593 dbp++;
3594 get_scheme ();
3599 void
3600 get_scheme ()
3602 register char *cp;
3604 if (*dbp == '\0')
3605 return;
3606 /* Go till you get to white space or a syntactic break */
3607 for (cp = dbp + 1;
3608 *cp && *cp != '(' && *cp != ')' && !isspace (*cp);
3609 cp++)
3610 continue;
3611 pfnote (savenstr (dbp, cp-dbp), TRUE,
3612 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3615 /* Find tags in TeX and LaTeX input files. */
3617 /* TEX_toktab is a table of TeX control sequences that define tags.
3618 Each TEX_tabent records one such control sequence.
3619 CONVERT THIS TO USE THE Stab TYPE!! */
3620 struct TEX_tabent
3622 char *name;
3623 int len;
3626 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
3628 /* Default set of control sequences to put into TEX_toktab.
3629 The value of environment var TEXTAGS is prepended to this. */
3631 char *TEX_defenv = "\
3632 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
3633 :part:appendix:entry:index";
3635 void TEX_mode ();
3636 struct TEX_tabent *TEX_decode_env ();
3637 int TEX_Token ();
3639 char TEX_esc = '\\';
3640 char TEX_opgrp = '{';
3641 char TEX_clgrp = '}';
3644 * TeX/LaTeX scanning loop.
3646 void
3647 TeX_functions (inf)
3648 FILE *inf;
3650 char *lasthit;
3651 register int i;
3653 lineno = 0;
3654 charno = 0;
3656 /* Select either \ or ! as escape character. */
3657 TEX_mode (inf);
3659 /* Initialize token table once from environment. */
3660 if (!TEX_toktab)
3661 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
3663 while (!feof (inf))
3664 { /* Scan each line in file */
3665 lineno++;
3666 linecharno = charno;
3667 charno += readline (&lb, inf);
3668 dbp = lb.buffer;
3669 lasthit = dbp;
3670 while (dbp = etags_strchr (dbp, TEX_esc)) /* Look at each esc in line */
3672 if (!*(++dbp))
3673 break;
3674 linecharno += dbp - lasthit;
3675 lasthit = dbp;
3676 i = TEX_Token (lasthit);
3677 if (i >= 0)
3679 /* We seem to include the TeX command in the tag name.
3680 register char *p;
3681 for (p = lasthit + TEX_toktab[i].len;
3682 *p != '\0' && *p != TEX_clgrp;
3683 p++)
3684 continue; */
3685 pfnote (/*savenstr (lasthit, p-lasthit)*/ (char *)NULL, TRUE,
3686 lb.buffer, lb.len, lineno, linecharno);
3687 break; /* We only tag a line once */
3693 #define TEX_LESC '\\'
3694 #define TEX_SESC '!'
3695 #define TEX_cmt '%'
3697 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
3698 chars accordingly. */
3699 void
3700 TEX_mode (inf)
3701 FILE *inf;
3703 int c;
3705 while ((c = getc (inf)) != EOF)
3707 /* Skip to next line if we hit the TeX comment char. */
3708 if (c == TEX_cmt)
3709 while (c != '\n')
3710 c = getc (inf);
3711 else if (c == TEX_LESC || c == TEX_SESC )
3712 break;
3715 if (c == TEX_LESC)
3717 TEX_esc = TEX_LESC;
3718 TEX_opgrp = '{';
3719 TEX_clgrp = '}';
3721 else
3723 TEX_esc = TEX_SESC;
3724 TEX_opgrp = '<';
3725 TEX_clgrp = '>';
3727 rewind (inf);
3730 /* Read environment and prepend it to the default string.
3731 Build token table. */
3732 struct TEX_tabent *
3733 TEX_decode_env (evarname, defenv)
3734 char *evarname;
3735 char *defenv;
3737 register char *env, *p;
3739 struct TEX_tabent *tab;
3740 int size, i;
3742 /* Append default string to environment. */
3743 env = getenv (evarname);
3744 if (!env)
3745 env = defenv;
3746 else
3748 char *oldenv = env;
3749 env = concat (oldenv, defenv, "");
3752 /* Allocate a token table */
3753 for (size = 1, p = env; p;)
3754 if ((p = etags_strchr (p, ':')) && *(++p))
3755 size++;
3756 /* Add 1 to leave room for null terminator. */
3757 tab = xnew (size + 1, struct TEX_tabent);
3759 /* Unpack environment string into token table. Be careful about */
3760 /* zero-length strings (leading ':', "::" and trailing ':') */
3761 for (i = 0; *env;)
3763 p = etags_strchr (env, ':');
3764 if (!p) /* End of environment string. */
3765 p = env + strlen (env);
3766 if (p - env > 0)
3767 { /* Only non-zero strings. */
3768 tab[i].name = savenstr (env, p - env);
3769 tab[i].len = strlen (tab[i].name);
3770 i++;
3772 if (*p)
3773 env = p + 1;
3774 else
3776 tab[i].name = NULL; /* Mark end of table. */
3777 tab[i].len = 0;
3778 break;
3781 return tab;
3784 /* If the text at CP matches one of the tag-defining TeX command names,
3785 return the pointer to the first occurrence of that command in TEX_toktab.
3786 Otherwise return -1.
3787 Keep the capital `T' in `Token' for dumb truncating compilers
3788 (this distinguishes it from `TEX_toktab' */
3790 TEX_Token (cp)
3791 char *cp;
3793 int i;
3795 for (i = 0; TEX_toktab[i].len > 0; i++)
3796 if (strneq (TEX_toktab[i].name, cp, TEX_toktab[i].len))
3797 return i;
3798 return -1;
3802 * Prolog support (rewritten) by Anders Lindgren, Mar. 96
3804 * Assumes that the predicate starts at column 0.
3805 * Only the first clause of a predicate is added.
3807 int prolog_pred ();
3808 void prolog_skip_comment ();
3809 int prolog_atom ();
3810 int eat_white ();
3812 void
3813 Prolog_functions (inf)
3814 FILE *inf;
3816 char * last;
3817 int len;
3818 int allocated;
3820 allocated = 0;
3821 len = 0;
3822 last = NULL;
3824 lineno = 0;
3825 linecharno = 0;
3826 charno = 0;
3828 while (!feof (inf))
3830 lineno++;
3831 linecharno += charno;
3832 charno = readline (&lb, inf);
3833 dbp = lb.buffer;
3834 if (dbp[0] == '\0') /* Empty line */
3835 continue;
3836 else if (isspace (dbp[0])) /* Not a predicate */
3837 continue;
3838 else if (dbp[0] == '/' && dbp[1] == '*') /* comment. */
3839 prolog_skip_comment (&lb, inf);
3840 else if (len = prolog_pred (dbp, last))
3842 /* Predicate. Store the function name so that we only
3843 generate a tag for the first clause. */
3844 if (last == NULL)
3845 last = xnew(len + 1, char);
3846 else if (len + 1 > allocated)
3847 last = (char *) xrealloc(last, len + 1);
3848 allocated = len + 1;
3849 strncpy (last, dbp, len);
3850 last[len] = '\0';
3856 void
3857 prolog_skip_comment (plb, inf)
3858 struct linebuffer *plb;
3859 FILE *inf;
3861 char *cp;
3865 for (cp = plb->buffer; *cp != '\0'; cp++)
3866 if (cp[0] == '*' && cp[1] == '/')
3867 return;
3868 lineno++;
3869 linecharno += readline (plb, inf);
3871 while (!feof(inf));
3875 * A predicate definition is added if it matches:
3876 * <beginning of line><Prolog Atom><whitespace>(
3878 * It is added to the tags database if it doesn't match the
3879 * name of the previous clause header.
3881 * Return the size of the name of the predicate, or 0 if no header
3882 * was found.
3885 prolog_pred (s, last)
3886 char *s;
3887 char *last; /* Name of last clause. */
3889 int pos;
3890 int len;
3892 pos = prolog_atom (s, 0);
3893 if (pos < 1)
3894 return 0;
3896 len = pos;
3897 pos += eat_white (s, pos);
3899 if ((s[pos] == '(') || (s[pos] == '.'))
3901 if (s[pos] == '(')
3902 pos++;
3904 /* Save only the first clause. */
3905 if (last == NULL
3906 || len != strlen (last)
3907 || !strneq (s, last, len))
3909 pfnote (savenstr (s, len), TRUE,
3910 s, pos, lineno, linecharno);
3911 return len;
3914 return 0;
3918 * Consume a Prolog atom.
3919 * Return the number of bytes consumed, or -1 if there was an error.
3921 * A prolog atom, in this context, could be one of:
3922 * - An alphanumeric sequence, starting with a lower case letter.
3923 * - A quoted arbitrary string. Single quotes can escape themselves.
3924 * Backslash quotes everything.
3927 prolog_atom (s, pos)
3928 char *s;
3929 int pos;
3931 int origpos;
3933 origpos = pos;
3935 if (islower(s[pos]) || (s[pos] == '_'))
3937 /* The atom is unquoted. */
3938 pos++;
3939 while (isalnum(s[pos]) || (s[pos] == '_'))
3941 pos++;
3943 return pos - origpos;
3945 else if (s[pos] == '\'')
3947 pos++;
3949 while (1)
3951 if (s[pos] == '\'')
3953 pos++;
3954 if (s[pos] != '\'')
3955 break;
3956 pos++; /* A double quote */
3958 else if (s[pos] == '\0')
3959 /* Multiline quoted atoms are ignored. */
3960 return -1;
3961 else if (s[pos] == '\\')
3963 if (s[pos+1] == '\0')
3964 return -1;
3965 pos += 2;
3967 else
3968 pos++;
3970 return pos - origpos;
3972 else
3973 return -1;
3976 /* Consume whitespace. Return the number of bytes eaten. */
3978 eat_white (s, pos)
3979 char *s;
3980 int pos;
3982 int origpos = pos;
3984 origpos = pos;
3986 while (isspace (s[pos]))
3987 pos++;
3989 return pos - origpos;
3993 * Support for Erlang -- Anders Lindgren, Feb 1996.
3995 * Generates tags for functions, defines, and records.
3997 * Assumes that Erlang functions start at column 0.
3999 int erlang_func ();
4000 void erlang_attribute ();
4001 int erlang_atom ();
4003 void
4004 Erlang_functions (inf)
4005 FILE *inf;
4007 char * last;
4008 int len;
4009 int allocated;
4011 allocated = 0;
4012 len = 0;
4013 last = NULL;
4015 lineno = 0;
4016 linecharno = 0;
4017 charno = 0;
4019 while (!feof (inf))
4021 lineno++;
4022 linecharno += charno;
4023 charno = readline (&lb, inf);
4024 dbp = lb.buffer;
4025 if (dbp[0] == '\0') /* Empty line */
4026 continue;
4027 else if (isspace (dbp[0])) /* Not function nor attribute */
4028 continue;
4029 else if (dbp[0] == '%') /* comment */
4030 continue;
4031 else if (dbp[0] == '"') /* Sometimes, strings start in column one */
4032 continue;
4033 else if (dbp[0] == '-') /* attribute, e.g. "-define" */
4035 erlang_attribute (dbp);
4036 last = NULL;
4038 else if (len = erlang_func (dbp, last))
4041 * Function. Store the function name so that we only
4042 * generates a tag for the first clause.
4044 if (last == NULL)
4045 last = xnew (len + 1, char);
4046 else if (len + 1 > allocated)
4047 last = (char *) xrealloc (last, len + 1);
4048 allocated = len + 1;
4049 strncpy (last, dbp, len);
4050 last[len] = '\0';
4057 * A function definition is added if it matches:
4058 * <beginning of line><Erlang Atom><whitespace>(
4060 * It is added to the tags database if it doesn't match the
4061 * name of the previous clause header.
4063 * Return the size of the name of the function, or 0 if no function
4064 * was found.
4067 erlang_func (s, last)
4068 char *s;
4069 char *last; /* Name of last clause. */
4071 int pos;
4072 int len;
4074 pos = erlang_atom (s, 0);
4075 if (pos < 1)
4076 return 0;
4078 len = pos;
4079 pos += eat_white (s, pos);
4081 /* Save only the first clause. */
4082 if (s[pos++] == '('
4083 && (last == NULL
4084 || len != strlen (last)
4085 || !strneq (s, last, len)))
4087 pfnote (savenstr (s, len), TRUE,
4088 s, pos, lineno, linecharno);
4089 return len;
4092 return 0;
4097 * Handle attributes. Currently, tags are generated for defines
4098 * and records.
4100 * They are on the form:
4101 * -define(foo, bar).
4102 * -define(Foo(M, N), M+N).
4103 * -record(graph, {vtab = notable, cyclic = true}).
4105 void
4106 erlang_attribute (s)
4107 char *s;
4109 int pos;
4110 int len;
4112 if (strneq (s, "-define", 7) || strneq (s, "-record", 7))
4114 pos = 7 + eat_white (s, pos);
4115 if (s[pos++] == '(')
4117 pos += eat_white (s, pos);
4118 if (len = erlang_atom (s, pos))
4119 pfnote (savenstr (& s[pos], len), TRUE,
4120 s, pos + len, lineno, linecharno);
4123 return;
4128 * Consume an Erlang atom (or variable).
4129 * Return the number of bytes consumed, or -1 if there was an error.
4132 erlang_atom (s, pos)
4133 char *s;
4134 int pos;
4136 int origpos;
4138 origpos = pos;
4140 if (isalpha (s[pos]) || s[pos] == '_')
4142 /* The atom is unquoted. */
4143 pos++;
4144 while (isalnum (s[pos]) || s[pos] == '_')
4145 pos++;
4146 return pos - origpos;
4148 else if (s[pos] == '\'')
4150 pos++;
4152 while (1)
4154 if (s[pos] == '\'')
4156 pos++;
4157 break;
4159 else if (s[pos] == '\0')
4160 /* Multiline quoted atoms are ignored. */
4161 return -1;
4162 else if (s[pos] == '\\')
4164 if (s[pos+1] == '\0')
4165 return -1;
4166 pos += 2;
4168 else
4169 pos++;
4171 return pos - origpos;
4173 else
4174 return -1;
4177 #ifdef ETAGS_REGEXPS
4178 /* Take a string like "/blah/" and turn it into "blah", making sure
4179 that the first and last characters are the same, and handling
4180 quoted separator characters. Actually, stops on the occurrence of
4181 an unquoted separator. Also turns "\t" into a Tab character.
4182 Returns pointer to terminating separator. Works in place. Null
4183 terminates name string. */
4184 char *
4185 scan_separators (name)
4186 char *name;
4188 char sep = name[0];
4189 char *copyto = name;
4190 bool quoted = FALSE;
4192 for (++name; *name != '\0'; ++name)
4194 if (quoted)
4196 if (*name == 't')
4197 *copyto++ = '\t';
4198 else if (*name == sep)
4199 *copyto++ = sep;
4200 else
4202 /* Something else is quoted, so preserve the quote. */
4203 *copyto++ = '\\';
4204 *copyto++ = *name;
4206 quoted = FALSE;
4208 else if (*name == '\\')
4209 quoted = TRUE;
4210 else if (*name == sep)
4211 break;
4212 else
4213 *copyto++ = *name;
4216 /* Terminate copied string. */
4217 *copyto = '\0';
4218 return name;
4221 /* Look at the argument of --regex or --no-regex and do the right
4222 thing. */
4223 void
4224 analyse_regex (regex_arg)
4225 char *regex_arg;
4227 struct stat stat_buf;
4229 if (regex_arg == NULL)
4231 /* Remove existing regexps. */
4232 num_patterns = 0;
4233 patterns = NULL;
4234 return;
4236 if (regex_arg[0] == '\0')
4238 error ("missing regexp", (char *)NULL);
4239 return;
4241 if (regex_arg[0] == '@'
4242 && stat (regex_arg + 1, &stat_buf) == 0)
4244 FILE *regexfp;
4245 struct linebuffer regexbuf;
4246 char *regexfile = regex_arg + 1;
4248 /* regexfile is a file containing regexps, one per line. */
4249 regexfp = fopen (regexfile, "r");
4250 if (regexfp == NULL)
4252 perror (regexfile);
4253 return;
4255 initbuffer (&regexbuf);
4256 while (readline_internal (&regexbuf, regexfp))
4257 add_regex (regexbuf.buffer);
4258 free (regexbuf.buffer);
4259 fclose (regexfp);
4261 else
4263 add_regex (regex_arg);
4267 /* Turn a name, which is an ed-style (but Emacs syntax) regular
4268 expression, into a real regular expression by compiling it. */
4269 void
4270 add_regex (regexp_pattern)
4271 char *regexp_pattern;
4273 char *name;
4274 const char *err;
4275 struct re_pattern_buffer *patbuf;
4278 if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0])
4280 error ("%s: unterminated regexp", regexp_pattern);
4281 return;
4283 name = scan_separators (regexp_pattern);
4284 if (regexp_pattern[0] == '\0')
4286 error ("null regexp", (char *)NULL);
4287 return;
4289 (void) scan_separators (name);
4291 patbuf = xnew (1, struct re_pattern_buffer);
4292 patbuf->translate = NULL;
4293 patbuf->fastmap = NULL;
4294 patbuf->buffer = NULL;
4295 patbuf->allocated = 0;
4297 re_syntax_options = RE_INTERVALS;
4298 err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf);
4299 if (err != NULL)
4301 error ("%s while compiling pattern", err);
4302 return;
4305 num_patterns += 1;
4306 if (num_patterns == 1)
4307 patterns = xnew (1, struct pattern);
4308 else
4309 patterns = ((struct pattern *)
4310 xrealloc (patterns,
4311 (num_patterns * sizeof (struct pattern))));
4312 patterns[num_patterns - 1].pattern = patbuf;
4313 patterns[num_patterns - 1].name_pattern = savestr (name);
4314 patterns[num_patterns - 1].error_signaled = FALSE;
4318 * Do the substitutions indicated by the regular expression and
4319 * arguments.
4321 char *
4322 substitute (in, out, regs)
4323 char *in, *out;
4324 struct re_registers *regs;
4326 char *result, *t;
4327 int size, dig, diglen;
4329 result = NULL;
4330 size = strlen (out);
4332 /* Pass 1: figure out how much to allocate by finding all \N strings. */
4333 if (out[size - 1] == '\\')
4334 fatal ("pattern error in \"%s\"", out);
4335 for (t = etags_strchr (out, '\\');
4336 t != NULL;
4337 t = etags_strchr (t + 2, '\\'))
4338 if (isdigit (t[1]))
4340 dig = t[1] - '0';
4341 diglen = regs->end[dig] - regs->start[dig];
4342 size += diglen - 2;
4344 else
4345 size -= 1;
4347 /* Allocate space and do the substitutions. */
4348 result = xnew (size + 1, char);
4350 for (t = result; *out != '\0'; out++)
4351 if (*out == '\\' && isdigit (*++out))
4353 /* Using "dig2" satisfies my debugger. Bleah. */
4354 dig = *out - '0';
4355 diglen = regs->end[dig] - regs->start[dig];
4356 strncpy (t, in + regs->start[dig], diglen);
4357 t += diglen;
4359 else
4360 *t++ = *out;
4361 *t = '\0';
4363 if (DEBUG && (t > result + size || t - result != strlen (result)))
4364 abort ();
4366 return result;
4369 #endif /* ETAGS_REGEXPS */
4370 /* Initialize a linebuffer for use */
4371 void
4372 initbuffer (linebuffer)
4373 struct linebuffer *linebuffer;
4375 linebuffer->size = 200;
4376 linebuffer->buffer = xnew (200, char);
4380 * Read a line of text from `stream' into `linebuffer'.
4381 * Return the number of characters read from `stream',
4382 * which is the length of the line including the newline, if any.
4384 long
4385 readline_internal (linebuffer, stream)
4386 struct linebuffer *linebuffer;
4387 register FILE *stream;
4389 char *buffer = linebuffer->buffer;
4390 register char *p = linebuffer->buffer;
4391 register char *pend;
4392 int chars_deleted;
4394 pend = p + linebuffer->size; /* Separate to avoid 386/IX compiler bug. */
4396 while (1)
4398 register int c = getc (stream);
4399 if (p == pend)
4401 linebuffer->size *= 2;
4402 buffer = (char *) xrealloc (buffer, linebuffer->size);
4403 p += buffer - linebuffer->buffer;
4404 pend = buffer + linebuffer->size;
4405 linebuffer->buffer = buffer;
4407 if (c == EOF)
4409 *p = '\0';
4410 chars_deleted = 0;
4411 break;
4413 if (c == '\n')
4415 if (p > buffer && p[-1] == '\r')
4417 p -= 1;
4418 #ifdef DOS_NT
4419 /* Assume CRLF->LF translation will be performed by Emacs
4420 when loading this file, so CRs won't appear in the buffer.
4421 It would be cleaner to compensate within Emacs;
4422 however, Emacs does not know how many CRs were deleted
4423 before any given point in the file. */
4424 chars_deleted = 1;
4425 #else
4426 chars_deleted = 2;
4427 #endif
4429 else
4431 chars_deleted = 1;
4433 *p = '\0';
4434 break;
4436 *p++ = c;
4438 linebuffer->len = p - buffer;
4440 return linebuffer->len + chars_deleted;
4444 * Like readline_internal, above, but in addition try to match the
4445 * input line against any existing regular expressions.
4447 long
4448 readline (linebuffer, stream)
4449 struct linebuffer *linebuffer;
4450 FILE *stream;
4452 /* Read new line. */
4453 long result = readline_internal (linebuffer, stream);
4454 #ifdef ETAGS_REGEXPS
4455 int i;
4457 /* Match against all listed patterns. */
4458 if (linebuffer->len > 0)
4459 for (i = 0; i < num_patterns; ++i)
4461 int match = re_match (patterns[i].pattern, linebuffer->buffer,
4462 linebuffer->len, 0, &patterns[i].regs);
4463 switch (match)
4465 case -2:
4466 /* Some error. */
4467 if (!patterns[i].error_signaled)
4469 error ("error while matching pattern %d", i);
4470 patterns[i].error_signaled = TRUE;
4472 break;
4473 case -1:
4474 /* No match. */
4475 break;
4476 default:
4477 /* Match occurred. Construct a tag. */
4478 if (patterns[i].name_pattern[0] != '\0')
4480 /* Make a named tag. */
4481 char *name = substitute (linebuffer->buffer,
4482 patterns[i].name_pattern,
4483 &patterns[i].regs);
4484 if (name != NULL)
4485 pfnote (name, TRUE,
4486 linebuffer->buffer, match, lineno, linecharno);
4488 else
4490 /* Make an unnamed tag. */
4491 pfnote ((char *)NULL, TRUE,
4492 linebuffer->buffer, match, lineno, linecharno);
4494 break;
4497 #endif /* ETAGS_REGEXPS */
4499 return result;
4503 * Read a file, but do no processing. This is used to do regexp
4504 * matching on files that have no language defined.
4506 void
4507 just_read_file (inf)
4508 FILE *inf;
4510 lineno = 0;
4511 charno = 0;
4513 while (!feof (inf))
4515 ++lineno;
4516 linecharno = charno;
4517 charno += readline (&lb, inf);
4523 * Return a pointer to a space of size strlen(cp)+1 allocated
4524 * with xnew where the string CP has been copied.
4526 char *
4527 savestr (cp)
4528 char *cp;
4530 return savenstr (cp, strlen (cp));
4534 * Return a pointer to a space of size LEN+1 allocated with xnew where
4535 * the string CP has been copied for at most the first LEN characters.
4537 char *
4538 savenstr (cp, len)
4539 char *cp;
4540 int len;
4542 register char *dp;
4544 dp = xnew (len + 1, char);
4545 strncpy (dp, cp, len);
4546 dp[len] = '\0';
4547 return dp;
4551 * Return the ptr in sp at which the character c last
4552 * appears; NULL if not found
4554 * Identical to System V strrchr, included for portability.
4556 char *
4557 etags_strrchr (sp, c)
4558 register char *sp, c;
4560 register char *r;
4562 r = NULL;
4565 if (*sp == c)
4566 r = sp;
4567 } while (*sp++);
4568 return r;
4573 * Return the ptr in sp at which the character c first
4574 * appears; NULL if not found
4576 * Identical to System V strchr, included for portability.
4578 char *
4579 etags_strchr (sp, c)
4580 register char *sp, c;
4584 if (*sp == c)
4585 return sp;
4586 } while (*sp++);
4587 return NULL;
4590 /* Print error message and exit. */
4591 void
4592 fatal (s1, s2)
4593 char *s1, *s2;
4595 error (s1, s2);
4596 exit (BAD);
4599 void
4600 pfatal (s1)
4601 char *s1;
4603 perror (s1);
4604 exit (BAD);
4607 void
4608 suggest_asking_for_help ()
4610 fprintf (stderr, "\tTry `%s --help' for a complete list of options.\n",
4611 progname);
4612 exit (BAD);
4615 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
4616 void
4617 error (s1, s2)
4618 char *s1, *s2;
4620 fprintf (stderr, "%s: ", progname);
4621 fprintf (stderr, s1, s2);
4622 fprintf (stderr, "\n");
4625 /* Return a newly-allocated string whose contents
4626 concatenate those of s1, s2, s3. */
4627 char *
4628 concat (s1, s2, s3)
4629 char *s1, *s2, *s3;
4631 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
4632 char *result = xnew (len1 + len2 + len3 + 1, char);
4634 strcpy (result, s1);
4635 strcpy (result + len1, s2);
4636 strcpy (result + len1 + len2, s3);
4637 result[len1 + len2 + len3] = '\0';
4639 return result;
4642 /* Does the same work as the system V getcwd, but does not need to
4643 guess the buffer size in advance. */
4644 char *
4645 etags_getcwd ()
4647 #if defined (HAVE_GETCWD) || defined (WINDOWSNT)
4648 int bufsize = 200;
4649 char *path = xnew (bufsize, char);
4651 while (getcwd (path, bufsize) == NULL)
4653 if (errno != ERANGE)
4654 pfatal ("getcwd");
4655 bufsize *= 2;
4656 free (path);
4657 path = xnew (bufsize, char);
4660 #if WINDOWSNT
4662 /* Convert backslashes to slashes. */
4663 char *p;
4664 for (p = path; *p != '\0'; p++)
4665 if (*p == '\\')
4666 *p = '/';
4667 /* Canonicalize drive letter case. */
4668 if (islower (path[0]))
4669 path[0] = toupper (path[0]);
4671 #endif
4673 return path;
4675 #else /* not HAVE_GETCWD */
4676 #ifdef MSDOS
4677 char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */
4679 getwd (path);
4681 for (p = path; *p != '\0'; p++)
4682 if (*p == '\\')
4683 *p = '/';
4684 else
4685 *p = lowcase (*p);
4687 return strdup (path);
4688 #else /* not MSDOS */
4689 struct linebuffer path;
4690 FILE *pipe;
4692 initbuffer (&path);
4693 pipe = (FILE *) popen ("pwd 2>/dev/null", "r");
4694 if (pipe == NULL || readline_internal (&path, pipe) == 0)
4695 pfatal ("pwd");
4696 pclose (pipe);
4698 return path.buffer;
4699 #endif /* not MSDOS */
4700 #endif /* not HAVE_GETCWD */
4703 /* Return a newly allocated string containing the file name
4704 of FILE relative to the absolute directory DIR (which
4705 should end with a slash). */
4706 char *
4707 relative_filename (file, dir)
4708 char *file, *dir;
4710 char *fp, *dp, *abs, *res;
4711 int i;
4713 /* Find the common root of file and dir (with a trailing slash). */
4714 abs = absolute_filename (file, cwd);
4715 fp = abs;
4716 dp = dir;
4717 while (*fp++ == *dp++)
4718 continue;
4719 fp--, dp--; /* back to the first differing char */
4720 do { /* look at the equal chars until '/' */
4721 if (fp == abs) return abs; /* first char differs, give up */
4722 fp--, dp--;
4723 } while (*fp != '/');
4725 /* Build a sequence of "../" strings for the resulting relative file name. */
4726 i = 0;
4727 while ((dp = etags_strchr (dp + 1, '/')) != NULL)
4728 i += 1;
4729 res = xnew (3*i + strlen (fp + 1) + 1, char);
4730 res[0] = '\0';
4731 while (i-- > 0)
4732 strcat (res, "../");
4734 /* Add the file name relative to the common root of file and dir. */
4735 strcat (res, fp + 1);
4736 free (abs);
4738 return res;
4741 /* Return a newly allocated string containing the
4742 absolute file name of FILE given CWD (which should
4743 end with a slash). */
4744 char *
4745 absolute_filename (file, cwd)
4746 char *file, *cwd;
4748 char *slashp, *cp, *res;
4750 if (absolutefn (file))
4751 res = savestr (file);
4752 #ifdef DOS_NT
4753 /* We don't support non-absolute file names with a drive
4754 letter, like `d:NAME' (it's too much hassle). */
4755 else if (file[1] == ':')
4756 fatal ("%s: relative file names with drive letters not supported", file);
4757 #endif
4758 else
4759 res = concat (cwd, file, "");
4761 /* Delete the "/dirname/.." and "/." substrings. */
4762 slashp = etags_strchr (res, '/');
4763 while (slashp != NULL && slashp[0] != '\0')
4765 if (slashp[1] == '.')
4767 if (slashp[2] == '.'
4768 && (slashp[3] == '/' || slashp[3] == '\0'))
4770 cp = slashp;
4772 cp--;
4773 while (cp >= res && !absolutefn (cp));
4774 if (cp < res)
4775 cp = slashp; /* the absolute name begins with "/.." */
4776 #ifdef DOS_NT
4777 /* Under MSDOS and NT we get `d:/NAME' as absolute
4778 file name, so the luser could say `d:/../NAME'.
4779 We silently treat this as `d:/NAME'. */
4780 else if (cp[0] != '/')
4781 cp = slashp;
4782 #endif
4783 strcpy (cp, slashp + 3);
4784 slashp = cp;
4785 continue;
4787 else if (slashp[2] == '/' || slashp[2] == '\0')
4789 strcpy (slashp, slashp + 2);
4790 continue;
4794 slashp = etags_strchr (slashp + 1, '/');
4797 #ifdef DOS_NT
4798 /* Canonicalize drive letter case. */
4799 if (res[0] && islower (res[0]))
4800 res[0] = toupper (res[0]);
4801 #endif
4803 if (res[0] == '\0')
4804 return savestr ("/");
4805 else
4806 return res;
4809 /* Return a newly allocated string containing the absolute
4810 file name of dir where FILE resides given CWD (which should
4811 end with a slash). */
4812 char *
4813 absolute_dirname (file, cwd)
4814 char *file, *cwd;
4816 char *slashp, *res;
4817 char save;
4818 #ifdef DOS_NT
4819 char *p;
4821 for (p = file; *p != '\0'; p++)
4822 if (*p == '\\')
4823 *p = '/';
4824 #endif
4826 slashp = etags_strrchr (file, '/');
4827 if (slashp == NULL)
4828 return savestr (cwd);
4829 save = slashp[1];
4830 slashp[1] = '\0';
4831 res = absolute_filename (file, cwd);
4832 slashp[1] = save;
4834 return res;
4837 /* Increase the size of a linebuffer. */
4838 void
4839 grow_linebuffer (bufp, toksize)
4840 struct linebuffer *bufp;
4841 int toksize;
4843 while (bufp->size < toksize)
4844 bufp->size *= 2;
4845 bufp->buffer = (char *) xrealloc (bufp->buffer, bufp->size);
4848 /* Like malloc but get fatal error if memory is exhausted. */
4849 long *
4850 xmalloc (size)
4851 unsigned int size;
4853 long *result = (long *) malloc (size);
4854 if (result == NULL)
4855 fatal ("virtual memory exhausted", (char *)NULL);
4856 return result;
4859 long *
4860 xrealloc (ptr, size)
4861 char *ptr;
4862 unsigned int size;
4864 long *result = (long *) realloc (ptr, size);
4865 if (result == NULL)
4866 fatal ("virtual memory exhausted", (char *)NULL);
4867 return result;