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