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