* etags.c: #include "config.h" and the alloca CPP tangle before
[bpt/emacs.git] / lib-src / etags.c
1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 1987, 1988, 1989, 1993 Free Software Foundation, Inc. and Ken Arnold
3
4 This file is not considered part of GNU Emacs.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /*
21 * Authors:
22 * Ctags originally by Ken Arnold.
23 * FORTRAN added by Jim Kleckner.
24 * Ed Pelegri-Llopart added C typedefs.
25 * Gnu Emacs TAGS format and modifications by RMS?
26 * Sam Kendall added C++.
27 */
28
29 #include "../src/config.h"
30 #undef static
31
32 /* AIX requires this to be the first thing in the file. */
33 #ifdef __GNUC__
34 #ifndef alloca
35 #define alloca __builtin_alloca
36 #endif
37 #else /* not __GNUC__ */
38 #if HAVE_ALLOCA_H
39 #include <alloca.h>
40 #else /* not HAVE_ALLOCA_H */
41 #ifdef _AIX
42 #pragma alloca
43 #else /* not _AIX */
44 char *alloca ();
45 #endif /* not _AIX */
46 #endif /* not HAVE_ALLOCA_H */
47 #endif /* not __GNUC__ */
48
49 #include <stdio.h>
50 #include <ctype.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
53
54 #include "getopt.h"
55
56 extern char *malloc (), *realloc ();
57 extern char *getenv ();
58 extern char *strcpy (), *strncpy ();
59 extern int strcmp ();
60
61 char *etags_index (), *etags_rindex ();
62 char *savenstr ();
63
64 /* Define the symbol ETAGS to make the program "etags",
65 which makes emacs-style tag tables by default.
66 Define CTAGS to make the program "ctags" compatible with the usual one.
67 Define neither one to get behavior that depends
68 on the name with which the program is invoked
69 (but we don't normally compile it that way). */
70
71 #if !defined(ETAGS) && !defined(CTAGS)
72 /* If neither is defined, program can be run as either. */
73 #define ETAGS
74 #define CTAGS
75 #endif
76
77 /* On VMS, CTAGS is not useful, so always do ETAGS. */
78 #ifdef VMS
79 #ifndef ETAGS
80 #define ETAGS
81 #endif
82 #endif
83
84 /* Exit codes for success and failure. */
85 #ifdef VMS
86 #define GOOD (1)
87 #define BAD (0)
88 #else
89 #define GOOD (0)
90 #define BAD (1)
91 #endif
92
93 /*
94 * The FILEPOS abstract type, which represents a position in a file,
95 * plus the following accessor functions:
96 *
97 * long GET_CHARNO (pos)
98 * returns absolute char number.
99 * void SET_FILEPOS (pos, fp, charno)
100 * FILE *fp; long charno;
101 * sets `pos' from the current file
102 * position of `fp' and from `charno',
103 * which must be the absolute character
104 * number corresponding to the current
105 * position of `fp'.
106 *
107 * The `pos' parameter is an lvalue expression of type FILEPOS.
108 * Parameters to the accessor functions are evaluated 0 or more times,
109 * and so must have no side effects.
110 *
111 * FILEPOS objects can also be assigned and passed to and from
112 * functions in the normal C manner.
113 *
114 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
115 */
116
117 #ifndef DEBUG
118 /* real implementation */
119 typedef long FILEPOS;
120 #define GET_CHARNO(pos) ((pos) + 0)
121 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
122 #else
123 /* debugging implementation */
124 typedef struct
125 {
126 long charno;
127 } FILEPOS;
128
129 #define GET_CHARNO(pos) ((pos).charno + 0)
130 #define SET_FILEPOS(pos, fp, cno) \
131 ((void) ((pos).charno = (cno), \
132 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
133 : 0))
134 #endif
135
136 #define streq(s, t) (strcmp (s, t) == 0)
137 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
138 #define logical int
139
140 #define TRUE 1
141 #define FALSE 0
142
143 #define iswhite(arg) (_wht[arg]) /* T if char is white */
144 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
145 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
146 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
147
148 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
149
150 struct nd_st
151 { /* sorting structure */
152 char *name; /* function or type name */
153 char *file; /* file name */
154 logical is_func; /* use pattern or line no */
155 logical rewritten; /* list name separately */
156 logical been_warned; /* set if noticed dup */
157 int lno; /* line number tag is on */
158 long cno; /* character number line starts on */
159 char *pat; /* search pattern */
160 struct nd_st *left, *right; /* left and right sons */
161 };
162
163 long ftell ();
164 typedef struct nd_st NODE;
165
166 logical header_file; /* TRUE if .h file, FALSE o.w. */
167 /* boolean "functions" (see init) */
168 logical _wht[0177], _etk[0177], _itk[0177], _btk[0177];
169
170
171 char *concat ();
172 char *savenstr ();
173 char *savestr ();
174 char *xmalloc ();
175 char *xrealloc ();
176 int L_isdef ();
177 int PF_funcs ();
178 int total_size_of_entries ();
179 logical consider_token ();
180 logical tail ();
181 long readline ();
182 void Asm_funcs ();
183 void C_entries ();
184 void L_funcs ();
185 void L_getit ();
186 void PAS_funcs ();
187 void Scheme_funcs ();
188 void TEX_funcs ();
189 void add_node ();
190 void error ();
191 void fatal ();
192 void find_entries ();
193 void free_tree ();
194 void getit ();
195 void getline ();
196 void init ();
197 void initbuffer ();
198 void initbuffer ();
199 void pfnote ();
200 void process_file ();
201 void put_entries ();
202 void takeprec ();
203
204 /*
205 * MACRO
206 * xnew -- allocate storage
207 *
208 * SYNOPSIS
209 * Type *xnew (int n, Type);
210 */
211 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
212 \f
213
214
215 /*
216 * Symbol table stuff.
217 *
218 * Should probably be implemented with hash table; linked list for now.
219 */
220
221 enum sym_type
222 {
223 st_none, st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
224 };
225
226 struct stab_entry
227 {
228 char *sym;
229 int symlen;
230 enum sym_type type;
231 struct stab_entry *next;
232 };
233
234 typedef struct stab_entry Stab_entry;
235 typedef Stab_entry *Stab;
236
237 /*
238 * NAME
239 * Stab, Stab_entry, stab_create, stab_search, stab_find -- symbol table
240 *
241 * SYNOPSIS
242 * Types: Stab, Stab_entry, enum sym_type
243 *
244 * Stab * stab_create ()
245 *
246 * Stab_entry * stab_find (stab, sym)
247 * Stab *stab;
248 * char *sym;
249 *
250 * Stab_entry * stab_search (stab, sym)
251 * Stab *stab;
252 * char *sym;
253 *
254 * DESCRIPTION
255 * stab_create creates a Stab, a symbol table object, and returns a
256 * pointer to it. stab_find finds a symbol in a Stab; it returns a
257 * pointer to the Stab_entry if found, otherwise NULL. stab_search
258 * is like stab_find, except that it creates a new Stab_entry,
259 * initialized with type = st_none, if one did not exist already
260 * (it never returns NULL).
261 *
262 * A Stab_entry is a structure that contains at least the following
263 * members:
264 *
265 * char *name; // must not be modified
266 * enum sym_type type; // should be set
267 *
268 * The type field is initially set to st_none; it should be set to
269 * something else by the caller of stab_search. Other possible values
270 * of an enum sym_type can be added.
271 */
272
273 Stab *
274 stab_create ()
275 {
276 Stab *sp;
277 sp = xnew (1, Stab);
278 *sp = NULL; /* a Stab starts out as a null Stab_entry* */
279 return sp;
280 }
281
282 Stab_entry *
283 stab_find (stab, sym, symlen)
284 Stab *stab;
285 register char *sym;
286 register int symlen;
287 {
288 register Stab_entry *se;
289 for (se = *stab; se != NULL; se = se->next)
290 {
291 if (se->symlen == symlen && strneq (se->sym, sym, symlen))
292 return se;
293 }
294
295 return NULL;
296 }
297
298 Stab_entry *
299 stab_search (stab, sym, symlen)
300 register Stab *stab;
301 char *sym;
302 int symlen;
303 {
304 register Stab_entry *se;
305 se = stab_find (stab, sym, symlen);
306
307 if (se == NULL)
308 {
309 /* make a new one */
310 se = xnew (1, Stab_entry);
311 se->sym = savenstr (sym, symlen);
312 se->symlen = symlen;
313 se->type = st_none;
314 se->next = *stab;
315 *stab = se;
316 }
317
318 return se;
319 }
320
321 /*
322 * NAME
323 * stab_type -- type of a symbol table entry
324 *
325 * SYNOPSIS
326 * enum sym_type stab_type (Stab_entry *se);
327 *
328 * WARNING
329 * May evaluate its argument more than once.
330 */
331
332 #define stab_type(se) ((se)==NULL ? st_none : (se)->type)
333 \f
334
335
336 typedef int LINENO;
337
338 typedef struct
339 {
340 char *p;
341 int len;
342 LINENO lineno;
343 logical rewritten;
344 } TOKEN;
345
346 /* C extensions.
347 */
348 #define C_PLPL 0x00001 /* C++ */
349 #define C_STAR 0x00003 /* C* */
350 #define YACC 0x10000 /* yacc file */
351
352 char searchar = '/'; /* use /.../ searches */
353
354 LINENO lineno; /* line number of current line */
355 long charno; /* current character number */
356
357 long linecharno; /* charno of start of line; not used by C, but
358 * by every other language.
359 */
360
361 char *curfile, /* current input file name */
362 *outfile, /* output file */
363 *white = " \f\t\n", /* white chars */
364 *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
365 /* token starting chars */
366 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$",
367 /* valid in-token chars */
368 *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
369
370 int append_to_tagfile; /* -a: append to tags */
371 int emacs_tags_format; /* emacs style output (no -e option any more) */
372 /* The following three default to 1 for etags, but to 0 for ctags. */
373 int typedefs; /* -t: create tags for typedefs */
374 int typedefs_and_cplusplus; /* -T: create tags for typedefs, level */
375 /* 0 struct/enum/union decls, and C++ */
376 /* member functions */
377 int constantypedefs; /* -d: create tags for C #define and enum */
378 /* constants. Default under etags. Enum */
379 /* constants not implemented. */
380 /* -D: opposite of -d. Default under ctags. */
381 int update; /* -u: update tags */
382 int vgrind_style; /* -v: create vgrind style index output */
383 int no_warnings; /* -w: suppress warnings */
384 int cxref_style; /* -x: create cxref style output */
385 int cplusplus; /* .[hc] means C++, not C */
386 int noindentypedefs; /* -S: ignore indentation in C */
387
388 /* Name this program was invoked with. */
389 char *progname;
390
391 struct option longopts[] = {
392 { "append", no_argument, NULL, 'a' },
393 { "backward-search", no_argument, NULL, 'B' },
394 { "c++", no_argument, NULL, 'C' },
395 { "cxref", no_argument, NULL, 'x' },
396 { "defines", no_argument, NULL, 'd' },
397 { "forward-search", no_argument, NULL, 'F' },
398 { "help", no_argument, NULL, 'H' },
399 { "ignore-indentation", no_argument, NULL, 'S' },
400 { "include", required_argument, NULL, 'i' },
401 { "no-defines", no_argument, NULL, 'D' },
402 { "no-warn", no_argument, NULL, 'w' },
403 { "output", required_argument, NULL, 'o' },
404 { "typedefs", no_argument, NULL, 't' },
405 { "typedefs-and-c++", no_argument, NULL, 'T' },
406 { "update", no_argument, NULL, 'u' },
407 { "version", no_argument, NULL, 'V' },
408 { "vgrind", no_argument, NULL, 'v' },
409 { 0 }
410 };
411
412 FILE *inf, /* ioptr for current input file */
413 *outf; /* ioptr for tags file */
414
415 NODE *head; /* the head of the binary tree of tags */
416
417 int permit_duplicates = 1; /* Nonzero means allow duplicate tags. */
418
419 /* A `struct linebuffer' is a structure which holds a line of text.
420 `readline' reads a line from a stream into a linebuffer
421 and works regardless of the length of the line. */
422
423 struct linebuffer
424 {
425 long size;
426 char *buffer;
427 };
428
429 struct linebuffer lb; /* the current line */
430 struct linebuffer filename_lb; /* used to read in filenames */
431 struct
432 {
433 FILEPOS linepos;
434 struct linebuffer lb; /* used by C_entries instead of lb */
435 } lbs[2];
436 \f
437 void
438 print_version ()
439 {
440 #ifdef CTAGS
441 printf ("CTAGS ");
442 #ifdef ETAGS
443 printf ("and ");
444 #endif
445 #endif
446 #ifdef ETAGS
447 printf ("ETAGS ");
448 #endif
449 printf ("for Emacs version 19.0.\n");
450
451 exit (0);
452 }
453
454 void
455 print_help ()
456 {
457 printf ("These are the options accepted by %s. You may use unambiguous\n\
458 abbreviations for the long option names.\n\n", progname);
459
460 fputs ("\
461 -a, --append\n\
462 Append tag entries to existing tags file.\n\
463 -C, --c++\n\
464 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
465 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
466 extensions are always assumed to be C++ code.\n\
467 -d, --defines\n\
468 Create tag entries for #defines, too.", stdout);
469
470 #ifdef ETAGS
471 fputs (" This is the default\n\
472 behavior.", stdout);
473 #endif
474
475 fputs ("\n\
476 -D, --no-defines\n\
477 Don't create tag entries for #defines.", stdout);
478
479 #ifdef CTAGS
480 fputs (" This is the default\n\
481 behavior.", stdout);
482 #endif
483
484 puts ("\n\
485 -o FILE, --output=FILE\n\
486 Write the tags to FILE.\n\
487 -S, --ignore-indentation\n\
488 Don't rely on indentation quite as much as normal. Currently,\n\
489 this means not to assume that a closing brace in the first\n\
490 column is the final brace of a function or structure\n\
491 definition.\n\
492 -t, --typedefs\n\
493 Generate tag entries for typedefs. This is the default\n\
494 behavior.\n\
495 -T, --typedefs-and-c++\n\
496 Generate tag entries for typedefs, struct/enum/union tags, and\n\
497 C++ member functions.");
498
499 #ifdef ETAGS
500 puts ("-i FILE, --include=FILE\n\
501 Include a note in tag file indicating that, when searching for\n\
502 a tag, one should also consult the tags file FILE after\n\
503 checking the current file.");
504 #endif
505
506 #ifdef CTAGS
507 puts ("-B, --backward-search\n\
508 Write the search commands for the tag entries using '?', the\n\
509 backward-search command.\n\
510 -F, --forward-search\n\
511 Write the search commands for the tag entries using '/', the\n\
512 forward-search command.\n\
513 -u, --update\n\
514 Update the tag entries for the given files, leaving tag\n\
515 entries for other files in place. Currently, this is\n\
516 implemented by deleting the existing entries for the given\n\
517 files and then rewriting the new entries at the end of the\n\
518 tags file. It is often faster to simply rebuild the entire\n\
519 tag file than to use this.\n\
520 -v, --vgrind\n\
521 Generates an index of items intended for human consumption,\n\
522 similar to the output of vgrind. The index is sorted, and\n\
523 gives the page number of each item.\n\
524 -x, --cxref\n\
525 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
526 The output uses line numbers instead of page numbers, but\n\
527 beyond that the differences are cosmetic; try both to see\n\
528 which you like.\n\
529 -w, --no-warn\n\
530 Suppress warning messages about entries defined in multiple\n\
531 files.");
532 #endif
533
534 puts ("-V, --version\n\
535 Print the version of the program.\n\
536 -H, --help\n\
537 Print this help message.");
538
539 exit (0);
540 }
541
542 \f
543 void
544 main (argc, argv)
545 int argc;
546 char *argv[];
547 {
548 char cmd[100];
549 int i;
550 unsigned int nincluded_files = 0;
551 char **included_files = (char **) alloca (argc * sizeof (char *));
552 char *this_file;
553 #ifdef VMS
554 char got_err;
555
556 extern char *gfnames ();
557 extern char *massage_name ();
558 #endif
559
560 progname = argv[0];
561
562 #ifndef CTAGS
563 emacs_tags_format = 1;
564 #else
565 emacs_tags_format = 0;
566 #endif
567
568 /*
569 * If etags, always find typedefs and structure tags. Why not?
570 * Also default is to find macro constants.
571 */
572 if (emacs_tags_format)
573 typedefs = typedefs_and_cplusplus = constantypedefs = 1;
574
575 for (;;)
576 {
577 int opt;
578 opt = getopt_long (argc, argv, "aCdDo:f:StTi:BFuvxwVH", longopts, 0);
579
580 if (opt == EOF)
581 break;
582
583 switch (opt)
584 {
585 case '\0':
586 /* If getopt returns '\0', then it has already processed a
587 long-named option. We should do nothing. */
588 break;
589
590 /* Common options. */
591 case 'a':
592 append_to_tagfile++;
593 break;
594 case 'C':
595 cplusplus = 1;
596 break;
597 case 'd':
598 constantypedefs = 1;
599 break;
600 case 'D':
601 constantypedefs = 0;
602 break;
603 case 'f':
604 case 'o':
605 if (outfile)
606 {
607 fprintf (stderr,
608 "%s: -%c flag may only be given once\n", progname, opt);
609 goto usage;
610 }
611 outfile = optarg;
612 break;
613 case 'S':
614 noindentypedefs++;
615 break;
616 case 't':
617 typedefs++;
618 break;
619 case 'T':
620 typedefs++;
621 typedefs_and_cplusplus++;
622 break;
623 case 'V':
624 print_version ();
625 break;
626 case 'H':
627 print_help ();
628 break;
629
630 /* Etags options */
631 case 'i':
632 if (!emacs_tags_format)
633 goto usage;
634 included_files[nincluded_files++] = optarg;
635 break;
636
637 /* Ctags options. */
638 case 'B':
639 searchar = '?';
640 if (emacs_tags_format)
641 goto usage;
642 break;
643 case 'F':
644 searchar = '/';
645 if (emacs_tags_format)
646 goto usage;
647 break;
648 case 'u':
649 update++;
650 if (emacs_tags_format)
651 goto usage;
652 break;
653 case 'v':
654 vgrind_style++;
655 /*FALLTHRU*/
656 case 'x':
657 cxref_style++;
658 if (emacs_tags_format)
659 goto usage;
660 break;
661 case 'w':
662 no_warnings++;
663 if (emacs_tags_format)
664 goto usage;
665 break;
666
667 default:
668 goto usage;
669 }
670 }
671
672 if (optind == argc && nincluded_files == 0)
673 {
674 fprintf (stderr, "%s: No input files specified.\n", progname);
675
676 usage:
677 fprintf (stderr, "%s: Try `%s --help' for a complete list of options.\n",
678 progname, progname);
679 exit (BAD);
680 }
681
682 if (outfile == 0)
683 {
684 outfile = emacs_tags_format ? "TAGS" : "tags";
685 }
686
687 init (); /* set up boolean "functions" */
688
689 initbuffer (&lb);
690 initbuffer (&lbs[0].lb);
691 initbuffer (&lbs[1].lb);
692 initbuffer (&filename_lb);
693 /*
694 * loop through files finding functions
695 */
696 if (emacs_tags_format)
697 {
698 if (streq (outfile, "-"))
699 outf = stdout;
700 else
701 outf = fopen (outfile, append_to_tagfile ? "a" : "w");
702 if (!outf)
703 {
704 perror (outfile);
705 exit (1);
706 }
707 }
708
709 #ifdef VMS
710 argc -= optind;
711 argv += optind;
712 while (gfnames (&argc, &argv, &got_err) != NULL)
713 {
714 if (got_err)
715 {
716 error ("Can't find file %s\n", this_file);
717 argc--, argv++;
718 }
719 else
720 {
721 this_file = massage_name (this_file);
722 #if 0
723 }
724 } /* solely to balance out the ifdef'd parens above */
725 #endif
726 #else
727 for (; optind < argc; optind++)
728 {
729 this_file = argv[optind];
730 if (1)
731 {
732 #endif
733 /* Input file named "-" means read file names from stdin
734 and use them. */
735 if (streq (this_file, "-"))
736 {
737 while (!feof (stdin))
738 {
739 (void) readline (&filename_lb, stdin);
740 if (strlen (filename_lb.buffer) > 0)
741 process_file (filename_lb.buffer);
742 }
743 }
744 else
745 process_file (this_file);
746 }
747 }
748
749 if (emacs_tags_format)
750 {
751 while (nincluded_files-- > 0)
752 fprintf (outf, "\f\n%s,include\n", *included_files++);
753
754 (void) fclose (outf);
755 exit (0);
756 }
757
758 if (cxref_style)
759 {
760 put_entries (head);
761 exit (GOOD);
762 }
763 if (update)
764 {
765 /* update cannot be set under VMS, so we may assume that argc
766 and argv have not been munged. */
767 for (i = optind; i < argc; i++)
768 {
769 sprintf (cmd,
770 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
771 outfile, argv[i], outfile);
772 (void) system (cmd);
773 }
774 append_to_tagfile++;
775 }
776 outf = fopen (outfile, append_to_tagfile ? "a" : "w");
777 if (outf == NULL)
778 {
779 perror (outfile);
780 exit (GOOD);
781 }
782 put_entries (head);
783 (void) fclose (outf);
784 if (update)
785 {
786 sprintf (cmd, "sort %s -o %s", outfile, outfile);
787 (void) system (cmd);
788 }
789 exit (GOOD);
790 }
791
792
793 /*
794 * This routine is called on each file argument.
795 */
796 void
797 process_file (file)
798 char *file;
799 {
800 struct stat stat_buf;
801
802 stat (file, &stat_buf);
803 if (!(stat_buf.st_mode & S_IFREG)
804 #ifdef S_IFLNK
805 || !(stat_buf.st_mode & S_IFLNK)
806 #endif
807 )
808 {
809 fprintf (stderr, "Skipping %s: it is not a regular file.\n", file);
810 return;
811 }
812
813 if (streq (file, outfile) && !streq (outfile, "-"))
814 {
815 fprintf (stderr, "Skipping inclusion of %s in self.\n", file);
816 return;
817 }
818 if (emacs_tags_format)
819 {
820 char *cp = etags_rindex (file, '/');
821 if (cp)
822 ++cp;
823 else
824 cp = file;
825 }
826 find_entries (file);
827 if (emacs_tags_format)
828 {
829 fprintf (outf, "\f\n%s,%d\n",
830 file, total_size_of_entries (head));
831 put_entries (head);
832 free_tree (head);
833 head = NULL;
834 }
835 }
836
837 /*
838 * This routine sets up the boolean pseudo-functions which work
839 * by setting boolean flags dependent upon the corresponding character
840 * Every char which is NOT in that string is not a white char. Therefore,
841 * all of the array "_wht" is set to FALSE, and then the elements
842 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
843 * of a char is TRUE if it is the string "white", else FALSE.
844 */
845 void
846 init ()
847 {
848 register char *sp;
849 register int i;
850
851 for (i = 0; i < 0177; i++)
852 _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
853 for (sp = white; *sp; sp++)
854 _wht[*sp] = TRUE;
855 for (sp = endtk; *sp; sp++)
856 _etk[*sp] = TRUE;
857 for (sp = intk; *sp; sp++)
858 _itk[*sp] = TRUE;
859 for (sp = begtk; *sp; sp++)
860 _btk[*sp] = TRUE;
861 _wht[0] = _wht['\n'];
862 _etk[0] = _etk['\n'];
863 _btk[0] = _btk['\n'];
864 _itk[0] = _itk['\n'];
865 }
866
867 /*
868 * This routine opens the specified file and calls the function
869 * which finds the function and type definitions.
870 */
871 void
872 find_entries (file)
873 char *file;
874 {
875 char *cp;
876 void prolog_funcs ();
877
878 inf = fopen (file, "r");
879 if (inf == NULL)
880 {
881 perror (file);
882 return;
883 }
884 curfile = savestr (file);
885 cp = etags_rindex (file, '.');
886
887 header_file = (cp && (streq (cp + 1, "h")));
888
889 /* .tex, .aux or .bbl implies LaTeX source code */
890 if (cp && (streq (cp + 1, "tex") || streq (cp + 1, "aux")
891 || streq (cp + 1, "bbl")))
892 {
893 TEX_funcs (inf);
894 goto close_and_return;
895 }
896 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
897 if (cp && (streq (cp + 1, "l")
898 || streq (cp + 1, "el")
899 || streq (cp + 1, "lsp")
900 || streq (cp + 1, "lisp")
901 || streq (cp + 1, "cl")
902 || streq (cp + 1, "clisp")))
903 {
904 L_funcs (inf);
905 goto close_and_return;
906 }
907 /* .scm or .sm or .scheme or ... implies scheme source code */
908 if (cp && (streq (cp + 1, "sm")
909 || streq (cp + 1, "scm")
910 || streq (cp + 1, "scheme")
911 || streq (cp + 1, "t")
912 || streq (cp + 1, "sch")
913 || streq (cp + 1, "SM")
914 || streq (cp + 1, "SCM")
915 /* The `SCM' or `scm' prefix with a version number */
916 || (cp[-1] == 'm' && cp[-2] == 'c' && cp[-3] == 's'
917 && string_numeric_p (cp + 1))
918 || (cp[-1] == 'M' && cp[-2] == 'C' && cp[-3] == 'S'
919 && string_numeric_p (cp + 1))))
920 {
921 Scheme_funcs (inf);
922 fclose (inf);
923 return;
924 }
925 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
926 Or even ".sa". */
927 if (cp && (streq (cp + 1, "s")
928 || streq (cp + 1, "a")
929 || streq (cp + 1, "sa")))
930 {
931 Asm_funcs (inf);
932 fclose (inf);
933 return;
934 }
935 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
936 if (cp && (streq (cp + 1, "C")
937 || streq (cp + 1, "H")
938 || streq (cp + 1, "cxx")
939 || streq (cp + 1, "hxx")
940 || streq (cp + 1, "cc")))
941 {
942 C_entries (C_PLPL); /* C++ */
943 goto close_and_return;
944 }
945 /* .cs or .hs: a C* file */
946 if (cp && (streq (cp + 1, "cs")
947 || streq (cp + 1, "hs")))
948 {
949 C_entries (C_STAR);
950 goto close_and_return;
951 }
952 /* .y: a yacc file */
953 if (cp && (streq (cp + 1, "y")))
954 {
955 C_entries (YACC);
956 goto close_and_return;
957 }
958 /* .pl implies prolog source code */
959 if (cp && streq (cp + 1, "pl"))
960 {
961 prolog_funcs (inf);
962 goto close_and_return;
963 }
964 /* .p or .pas: a Pascal file */
965 if (cp && (streq (cp + 1, "p")
966 || streq (cp + 1, "pas")))
967 {
968 PAS_funcs (inf);
969 goto close_and_return;
970 }
971 /* If .f or .for, assume it is fortran or nothing. */
972 if (cp && (streq (cp + 1, "f")
973 || streq (cp + 1, "for")))
974 {
975 PF_funcs (inf);
976 goto close_and_return;
977 }
978 /* if not a .c or .h or .y file, try fortran */
979 if (cp && ((cp[1] != 'c'
980 && cp[1] != 'h'
981 && cp[1] != 'y')
982 || (cp[1] != 0 && cp[2] != 0)))
983 {
984 if (PF_funcs (inf) != 0)
985 goto close_and_return;
986 rewind (inf); /* no fortran tags found, try C */
987 }
988 C_entries (cplusplus ? C_PLPL : 0);
989
990 close_and_return:
991 (void) fclose (inf);
992 }
993
994 /* Nonzero if string STR is composed of digits. */
995
996 int
997 string_numeric_p (str)
998 char *str;
999 {
1000 while (*str)
1001 {
1002 if (*str < '0' || *str > '9')
1003 return 0;
1004 }
1005 return 1;
1006 }
1007 \f
1008 /* Record a tag. */
1009 /* Should take a TOKEN* instead!! */
1010 void
1011 pfnote (name, is_func, rewritten, linestart, linelen, lno, cno)
1012 char *name; /* tag name */
1013 logical is_func; /* function or type name? */
1014 logical rewritten; /* tag different from text of definition? */
1015 char *linestart;
1016 int linelen;
1017 int lno;
1018 long cno;
1019 {
1020 register char *fp;
1021 register NODE *np;
1022 char tem[51];
1023 char c;
1024
1025 np = (NODE *) malloc (sizeof (NODE));
1026 if (np == NULL)
1027 {
1028 if (!emacs_tags_format)
1029 {
1030 /* It's okay to output early in etags -- it only disrupts the
1031 * character count of the tag entries, which is no longer used
1032 * by tags.el anyway.
1033 */
1034 error ("too many entries to sort");
1035 }
1036 put_entries (head);
1037 free_tree (head);
1038 head = NULL;
1039 np = xnew (1, NODE);
1040 }
1041 /* If ctags mode, change name "main" to M<thisfilename>. */
1042 if (!emacs_tags_format && !cxref_style && streq (name, "main"))
1043 {
1044 fp = etags_rindex (curfile, '/');
1045 name = concat ("M", fp == 0 ? curfile : fp + 1, "");
1046 fp = etags_rindex (name, '.');
1047 if (fp && fp[1] != '\0' && fp[2] == '\0')
1048 *fp = 0;
1049 rewritten = TRUE;
1050 }
1051 np->name = savestr (name);
1052 np->file = curfile;
1053 np->is_func = is_func;
1054 np->rewritten = rewritten;
1055 np->lno = lno;
1056 /* UNCOMMENT THE +1 HERE: */
1057 np->cno = cno /* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
1058 np->left = np->right = 0;
1059 if (emacs_tags_format)
1060 {
1061 c = linestart[linelen];
1062 linestart[linelen] = 0;
1063 }
1064 else if (cxref_style == 0)
1065 {
1066 sprintf (tem, strlen (linestart) < 50 ? "%s$" : "%.50s", linestart);
1067 linestart = tem;
1068 }
1069 np->pat = savestr (linestart);
1070 if (emacs_tags_format)
1071 {
1072 linestart[linelen] = c;
1073 }
1074
1075 add_node (np, &head);
1076 }
1077
1078 /*
1079 * free_tree ()
1080 * recurse on left children, iterate on right children.
1081 */
1082 void
1083 free_tree (node)
1084 register NODE *node;
1085 {
1086 while (node)
1087 {
1088 register NODE *node_right = node->right;
1089 free_tree (node->left);
1090 free (node->name);
1091 free (node->pat);
1092 free ((char *) node);
1093 node = node_right;
1094 }
1095 }
1096
1097 /*
1098 * add_node ()
1099 * Adds a node to the tree of nodes. In etags mode, we don't keep
1100 * it sorted; we just keep a linear list. In ctags mode, maintain
1101 * an ordered tree, with no attempt at balancing.
1102 *
1103 * add_node is the only function allowed to add nodes, so it can
1104 * maintain state.
1105 */
1106 /* Must avoid static vars within functions since some systems
1107 #define static as nothing. */
1108 static NODE *last_node = NULL;
1109
1110 void
1111 add_node (node, cur_node_p)
1112 NODE *node, **cur_node_p;
1113 {
1114 register int dif;
1115 register NODE *cur_node = *cur_node_p;
1116
1117 if (cur_node == NULL)
1118 {
1119 *cur_node_p = node;
1120 last_node = node;
1121 return;
1122 }
1123
1124 if (emacs_tags_format)
1125 {
1126 /* Etags Mode */
1127 if (!last_node)
1128 fatal ("internal error in add_node");
1129 last_node->right = node;
1130 last_node = node;
1131 }
1132 else
1133 {
1134 /* Ctags Mode */
1135 dif = strcmp (node->name, cur_node->name);
1136
1137 /*
1138 * If this tag name matches an existing one, then
1139 * do not add the node, but maybe print a warning.
1140 */
1141 if (!dif)
1142 {
1143 if (node->file == cur_node->file)
1144 {
1145 if (!no_warnings)
1146 {
1147 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1148 node->file, lineno, node->name);
1149 fprintf (stderr, "Second entry ignored\n");
1150 }
1151 return;
1152 }
1153 if (!cur_node->been_warned && !no_warnings)
1154 {
1155 fprintf (stderr,
1156 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1157 node->file, cur_node->file, node->name);
1158 }
1159 cur_node->been_warned = TRUE;
1160 return;
1161 }
1162
1163 /* Maybe refuse to add duplicate nodes. */
1164 if (!permit_duplicates)
1165 {
1166 if (!strcmp (node->name, cur_node->name)
1167 && !strcmp (node->file, cur_node->file))
1168 return;
1169 }
1170
1171 /* Actually add the node */
1172 add_node (node, dif < 0 ? &cur_node->left : &cur_node->right);
1173 }
1174 }
1175 \f
1176 void
1177 put_entries (node)
1178 register NODE *node;
1179 {
1180 register char *sp;
1181
1182 if (node == NULL)
1183 return;
1184
1185 /* Output subentries that precede this one */
1186 put_entries (node->left);
1187
1188 /* Output this entry */
1189
1190 if (emacs_tags_format)
1191 {
1192 if (node->rewritten)
1193 {
1194 fprintf (outf, "%s\177%s\001%d,%d\n",
1195 node->name, node->pat, node->lno, node->cno);
1196 }
1197 else
1198 {
1199 fprintf (outf, "%s\177%d,%d\n",
1200 node->pat, node->lno, node->cno);
1201 }
1202 }
1203 else if (!cxref_style)
1204 {
1205 fprintf (outf, "%s\t%s\t",
1206 node->name, node->file);
1207
1208 if (node->is_func)
1209 { /* a function */
1210 putc (searchar, outf);
1211 putc ('^', outf);
1212
1213 for (sp = node->pat; *sp; sp++)
1214 {
1215 if (*sp == '\\' || *sp == searchar)
1216 putc ('\\', outf);
1217 putc (*sp, outf);
1218 }
1219 putc (searchar, outf);
1220 }
1221 else
1222 { /* a typedef; text pattern inadequate */
1223 fprintf (outf, "%d", node->lno);
1224 }
1225 putc ('\n', outf);
1226 }
1227 else if (vgrind_style)
1228 fprintf (stdout, "%s %s %d\n",
1229 node->name, node->file, (node->lno + 63) / 64);
1230 else
1231 fprintf (stdout, "%-16s %3d %-16s %s\n",
1232 node->name, node->lno, node->file, node->pat);
1233
1234 /* Output subentries that follow this one */
1235 put_entries (node->right);
1236 }
1237
1238 /* Length of a number's decimal representation. */
1239 int
1240 number_len (num)
1241 long num;
1242 {
1243 int len = 0;
1244 if (!num)
1245 return 1;
1246 for (; num; num /= 10)
1247 ++len;
1248 return len;
1249 }
1250
1251 /*
1252 * Return total number of characters that put_entries will output for
1253 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1254 * is set, but called only in that case. This count is irrelevant with
1255 * the new tags.el, but is still supplied for backward compatibility.
1256 */
1257 int
1258 total_size_of_entries (node)
1259 register NODE *node;
1260 {
1261 register int total;
1262
1263 if (node == NULL)
1264 return 0;
1265
1266 total = 0;
1267 for (; node; node = node->right)
1268 {
1269 /* Count left subentries. */
1270 total += total_size_of_entries (node->left);
1271
1272 /* Count this entry */
1273 total += strlen (node->pat) + 1;
1274 total += number_len ((long) node->lno) + 1 + number_len (node->cno) + 1;
1275 if (node->rewritten)
1276 total += 1 + strlen (node->name); /* \001name */
1277 }
1278
1279 return total;
1280 }
1281 \f
1282 /*
1283 * The C symbol tables.
1284 */
1285
1286 Stab *C_stab, *C_PLPL_stab, *C_STAR_stab;
1287
1288 /*
1289 * SYNOPSIS
1290 * Stab *get_C_stab (int c_ext);
1291 */
1292 #define get_C_stab(c_ext) ((c_ext & C_STAR) ? C_STAR_stab : \
1293 (c_ext & C_PLPL) ? C_PLPL_stab : \
1294 C_stab)
1295
1296 void
1297 add_keyword (stab, sym, type)
1298 Stab *stab;
1299 char *sym;
1300 enum sym_type type;
1301 {
1302 stab_search (stab, sym, strlen (sym))->type = type;
1303 }
1304
1305 Stab *
1306 C_create_stab (c_ext)
1307 int c_ext;
1308 {
1309 Stab *stab;
1310
1311 stab = stab_create ();
1312
1313 /* C, C++ and C* */
1314 if (c_ext & C_PLPL)
1315 add_keyword (stab, "class", st_C_struct);
1316 if (c_ext & C_STAR)
1317 add_keyword (stab, "domain", st_C_struct);
1318 add_keyword (stab, "union", st_C_struct);
1319 add_keyword (stab, "struct", st_C_struct);
1320 add_keyword (stab, "enum", st_C_enum);
1321 add_keyword (stab, "typedef", st_C_typedef);
1322 add_keyword (stab, "define", st_C_define);
1323 add_keyword (stab, "long", st_C_typespec);
1324 add_keyword (stab, "short", st_C_typespec);
1325 add_keyword (stab, "int", st_C_typespec);
1326 add_keyword (stab, "char", st_C_typespec);
1327 add_keyword (stab, "float", st_C_typespec);
1328 add_keyword (stab, "double", st_C_typespec);
1329 add_keyword (stab, "signed", st_C_typespec);
1330 add_keyword (stab, "unsigned", st_C_typespec);
1331 add_keyword (stab, "auto", st_C_typespec);
1332 add_keyword (stab, "void", st_C_typespec);
1333 add_keyword (stab, "extern", st_C_typespec);
1334 add_keyword (stab, "static", st_C_typespec);
1335 add_keyword (stab, "const", st_C_typespec);
1336 add_keyword (stab, "volatile", st_C_typespec);
1337
1338 return stab;
1339 }
1340
1341 void
1342 C_create_stabs ()
1343 {
1344 C_stab = C_create_stab (0);
1345 C_PLPL_stab = C_create_stab (C_PLPL);
1346 C_STAR_stab = C_create_stab (C_STAR | C_PLPL);
1347 }
1348 \f
1349 /*
1350 * etags.c 4.2 1993/03/22 12:13:40 pot Exp
1351 * C functions are recognized using a simple finite automaton.
1352 * funcdef is its state variable.
1353 */
1354 typedef enum
1355 {
1356 fnone, ftagseen, finlist, flistseen
1357 } FUNCST;
1358 FUNCST funcdef;
1359
1360
1361 /* typedefs are recognized using a simple finite automaton.
1362 * typeddef is its state variable.
1363 */
1364 typedef enum
1365 {
1366 tnone, ttypedseen, tinbody, tend
1367 } TYPEDST;
1368 TYPEDST typdef;
1369
1370
1371 /* struct tags for C++ are recognized using another simple
1372 * finite automaton. `structdef' is its state variable.
1373 * This machinery is only invoked for C++; otherwise structdef
1374 * should remain snone. However, this machinery can easily be
1375 * adapted to find structure tags in normal C code.
1376 */
1377 typedef enum
1378 {
1379 snone, /* nothing seen yet */
1380 skeyseen, /* struct-like keyword seen */
1381 stagseen, /* struct-like tag seen */
1382 scolonseen, /* colon seen after struct-like tag */
1383 sinbody /* in class body: recognize member func defs */
1384 } STRUCTST;
1385 STRUCTST structdef;
1386 /*
1387 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1388 * struct tag, and structkey is the preceding struct-like keyword.
1389 */
1390 char structtag[BUFSIZ];
1391 Stab_entry *structkey;
1392
1393 /*
1394 * Yet another little state machine to deal with preprocessor lines.
1395 */
1396 typedef enum
1397 {
1398 dnone, /* nothing seen */
1399 dsharpseen, /* '#' seen as first char on line */
1400 ddefineseen, /* '#' and 'define' seen */
1401 dignorerest /* ignore rest of line */
1402 } DEFINEST;
1403 DEFINEST definedef;
1404
1405 /*
1406 * Set this to TRUE, and the next token considered is called a function.
1407 * Used only for GNUmacs's function-defining macros.
1408 */
1409 logical next_token_is_func;
1410
1411 /*
1412 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1413 */
1414 logical yacc_rules;
1415
1416 /*
1417 * C_entries ()
1418 * This routine finds functions, typedefs, #define's and
1419 * struct/union/enum definitions in C syntax and adds them
1420 * to the list.
1421 */
1422
1423 /*
1424 * LEVEL_OK_FOR_FUNCDEF allows C++ function definition within class body.
1425 * Currently typdef and structdef stuff (typedefs and struct
1426 * definitions) are only noticed when level==0, but that may change.
1427 */
1428 #define LEVEL_OK_FOR_FUNCDEF() \
1429 (level==0 || (cplpl && level==1 && structdef==sinbody))
1430
1431 #define curlb (lbs[curndx].lb)
1432 #define othlb (lbs[1-curndx].lb)
1433 #define newlb (lbs[newndx].lb)
1434 #define curlinepos (lbs[curndx].linepos)
1435 #define othlinepos (lbs[1-curndx].linepos)
1436 #define newlinepos (lbs[newndx].linepos)
1437
1438 #define CNL_SAVE_DEFINEDEF \
1439 do { \
1440 SET_FILEPOS (curlinepos, inf, charno); \
1441 lineno++; \
1442 charno += readline (&curlb, inf); \
1443 lp = curlb.buffer; \
1444 quotednl = FALSE; \
1445 newndx = curndx; \
1446 } while (FALSE)
1447
1448 #define CNL \
1449 do { \
1450 CNL_SAVE_DEFINEDEF; \
1451 definedef = dnone; \
1452 } while (FALSE)
1453
1454 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1455 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1456 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1457 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1458
1459 void
1460 C_entries (c_ext)
1461 int c_ext; /* extension of C? */
1462 {
1463 register char c; /* latest char read; '\0' for end of line */
1464 register char *lp; /* pointer one beyond the character `c' */
1465 int curndx, newndx; /* indices for current and new lb */
1466 TOKEN tok; /* latest token read for funcdef & structdef */
1467 char tokb[BUFSIZ]; /* latest token name for funcdef & structdef */
1468 register int tokoff; /* offset in line of start of latest token */
1469 register int toklen; /* length of latest token */
1470 int level; /* current curly brace level */
1471 logical incomm, inquote, inchar, quotednl, midtoken;
1472 logical cplpl;
1473
1474 curndx = newndx = 0;
1475 lineno = 0;
1476 charno = 0;
1477 lp = curlb.buffer;
1478 *lp = 0;
1479
1480 definedef = dnone; funcdef = fnone; typdef= tnone; structdef= snone;
1481 next_token_is_func = yacc_rules = FALSE;
1482 midtoken = inquote = inchar = incomm = quotednl = FALSE;
1483 level = 0;
1484 cplpl = c_ext & C_PLPL;
1485
1486 C_create_stabs ();
1487
1488 while (!feof (inf))
1489 {
1490 c = *lp++;
1491 if (c == '\\')
1492 {
1493 /* If we're at the end of the line, the next character is a
1494 '\0'; don't skip it, because it's the thing that tells us
1495 to read the next line. */
1496 if (*lp == '\0')
1497 {
1498 quotednl = TRUE;
1499 continue;
1500 }
1501 lp++;
1502 c = ' ';
1503 }
1504 else if (incomm)
1505 {
1506 switch (c)
1507 {
1508 case '*':
1509 if (*lp == '/')
1510 {
1511 c = *lp++;
1512 incomm = FALSE;
1513 }
1514 break;
1515 case '\0':
1516 /* Newlines inside comments do not end macro definitions in
1517 traditional cpp. */
1518 CNL_SAVE_DEFINEDEF;
1519 break;
1520 }
1521 continue;
1522 }
1523 else if (inquote)
1524 {
1525 switch (c)
1526 {
1527 case '"':
1528 inquote = FALSE;
1529 break;
1530 case '\0':
1531 /* Newlines inside strings, do not end macro definitions
1532 in traditional cpp, even though compilers don't
1533 usually accept them. */
1534 CNL_SAVE_DEFINEDEF;
1535 break;
1536 }
1537 continue;
1538 }
1539 else if (inchar)
1540 {
1541 if (c == '\'')
1542 inchar = FALSE;
1543 continue;
1544 }
1545 else
1546 switch (c)
1547 {
1548 case '"':
1549 inquote = TRUE;
1550 continue;
1551 case '\'':
1552 inchar = TRUE;
1553 continue;
1554 case '/':
1555 if (*lp == '*')
1556 {
1557 lp++;
1558 incomm = TRUE;
1559 continue;
1560 }
1561 else if (cplpl && *lp == '/')
1562 {
1563 c = 0;
1564 break;
1565 }
1566 continue;
1567 case '%':
1568 if ((c_ext & YACC) && *lp == '%')
1569 {
1570 /* entering or exiting rules section in yacc file */
1571 lp++;
1572 definedef = dnone; funcdef = fnone;
1573 typdef= tnone; structdef= snone;
1574 next_token_is_func = FALSE;
1575 midtoken = inquote = inchar = incomm = quotednl = FALSE;
1576 level = 0;
1577 yacc_rules = !yacc_rules;
1578 continue;
1579 }
1580 case '#':
1581 if (lp == newlb.buffer + 1 && definedef == dnone)
1582 definedef = dsharpseen;
1583 continue;
1584 } /* switch (c) */
1585
1586
1587 if (LEVEL_OK_FOR_FUNCDEF ()
1588 && definedef != dignorerest
1589 && structdef != scolonseen
1590 && funcdef != finlist)
1591 {
1592 if (midtoken)
1593 {
1594 if (endtoken (c))
1595 {
1596 if (cplpl && c == ':' && *lp == ':' && intoken (*(lp + 1)))
1597 {
1598 /*
1599 * This handles :: in the middle, but not at beginning
1600 * of an identifier.
1601 */
1602 lp += 2;
1603 toklen += 3;
1604 }
1605 else
1606 {
1607 logical is_func;
1608
1609 tok.lineno = lineno;
1610 tok.p = newlb.buffer + tokoff;
1611 tok.len = toklen;
1612 tok.rewritten = FALSE;
1613 if (yacc_rules
1614 || consider_token (c, lp, &tok,
1615 c_ext, level, &is_func))
1616 {
1617 if (structdef == sinbody
1618 && definedef == dnone && is_func)
1619 { /* function defined in C++ class body */
1620 sprintf (tokb, "%s::%.*s",
1621 ((structtag[0] == '\0')
1622 ? "_anonymous_" : structtag),
1623 tok.len, tok.p);
1624 tok.rewritten = TRUE;
1625 }
1626 else
1627 {
1628 sprintf (tokb, "%.*s", tok.len, tok.p);
1629 }
1630
1631 if (funcdef == ftagseen || structdef == stagseen)
1632 {
1633 if (newndx == curndx)
1634 curndx = 1 - curndx; /* switch line buffers */
1635 }
1636 else
1637 MAKE_TAG_FROM_NEW_LB (is_func);
1638 }
1639 midtoken = FALSE;
1640 }
1641 } /* if (endtoken (c)) */
1642 else if (intoken (c))
1643 {
1644 toklen++;
1645 continue;
1646 }
1647 } /* if (midtoken) */
1648 else if (begtoken (c))
1649 {
1650 switch (funcdef)
1651 {
1652 case flistseen:
1653 MAKE_TAG_FROM_OTH_LB (TRUE);
1654 /* FALLTHRU */
1655 case ftagseen:
1656 funcdef = fnone;
1657 break;
1658 }
1659 if (structdef == stagseen)
1660 structdef = snone;
1661 if (!yacc_rules || lp == newlb.buffer + 1)
1662 {
1663 tokoff = lp - 1 - newlb.buffer;
1664 toklen = 1;
1665 midtoken = TRUE;
1666 }
1667 continue;
1668 }
1669 } /* if must look at token */
1670
1671
1672 /* Detect end of line, colon, comma, semicolon and various braces
1673 after having handled the last token on the line.*/
1674 switch (c)
1675 {
1676 case ':':
1677 if (structdef == stagseen)
1678 structdef = scolonseen;
1679 else if (yacc_rules && funcdef == ftagseen)
1680 {
1681 MAKE_TAG_FROM_OTH_LB (FALSE);
1682 funcdef == fnone;
1683 }
1684 break;
1685 case ';':
1686 funcdef = fnone;
1687 /* FALLTHRU */
1688 case ',':
1689 if (funcdef != finlist)
1690 funcdef = fnone;
1691 if (level == 0 && typdef == tend)
1692 typdef = tnone;
1693 /* FALLTHRU */
1694 case '[':
1695 if (funcdef != finlist)
1696 funcdef = fnone;
1697 if (structdef == stagseen)
1698 structdef = snone;
1699 break;
1700 case '(':
1701 switch (funcdef)
1702 {
1703 case ftagseen:
1704 funcdef = finlist;
1705 break;
1706 case finlist:
1707 case flistseen:
1708 funcdef = fnone;
1709 break;
1710 }
1711 break;
1712 case ')':
1713 if (funcdef == finlist)
1714 funcdef = flistseen;
1715 break;
1716 case '{':
1717 if (typdef == ttypedseen)
1718 typdef = tinbody;
1719 switch (structdef)
1720 {
1721 case skeyseen: /* unnamed struct */
1722 structtag[0] = '\0';
1723 structdef = sinbody;
1724 break;
1725 case stagseen:
1726 case scolonseen: /* named struct */
1727 structdef = sinbody;
1728 MAKE_TAG_FROM_OTH_LB (FALSE);
1729 break;
1730 }
1731 level++;
1732 /* FALLTHRU */
1733 case '*':
1734 if (funcdef == flistseen)
1735 {
1736 MAKE_TAG_FROM_OTH_LB (TRUE);
1737 funcdef = fnone;
1738 }
1739 break;
1740 case '}':
1741 if (!noindentypedefs && lp == newlb.buffer + 1)
1742 level = 0; /* reset level if first column */
1743 else if (level > 0)
1744 level--;
1745 if (level == 0)
1746 {
1747 if (typdef == tinbody)
1748 typdef = tend;
1749 structdef = snone;
1750 (void) strcpy (structtag, "<error 2>");
1751 }
1752 break;
1753 case '\0':
1754 /* If a macro spans multiple lines don't reset its state. */
1755 if (quotednl)
1756 CNL_SAVE_DEFINEDEF;
1757 else
1758 CNL;
1759 break;
1760 } /* switch (c) */
1761
1762 } /* while not eof */
1763 }
1764
1765 /*
1766 * consider_token ()
1767 * checks to see if the current token is at the start of a
1768 * function, or corresponds to a typedef, or is a struct/union/enum
1769 * tag.
1770 *
1771 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1772 * C_EXT is which language we are looking at.
1773 *
1774 * In the future we will need some way to adjust where the end of
1775 * the token is; for instance, implementing the C++ keyword
1776 * `operator' properly will adjust the end of the token to be after
1777 * whatever follows `operator'.
1778 *
1779 * Globals
1780 * funcdef IN OUT
1781 * structdef IN OUT
1782 * definedef IN OUT
1783 * typdef IN OUT
1784 * next_token_is_func IN OUT
1785 */
1786
1787 logical
1788 consider_token (c, lp, tokp, c_ext, level, is_func)
1789 register char c; /* IN: first char after the token */
1790 register char *lp; /* IN: lp points to 2nd char after the token */
1791 register TOKEN *tokp; /* IN */
1792 int c_ext; /* IN */
1793 int level; /* IN */
1794 logical *is_func; /* OUT */
1795 {
1796 logical firsttok; /* TRUE if have seen first token in ()'s */
1797 Stab_entry *tokse = stab_find (get_C_stab (c_ext), tokp->p, tokp->len);
1798 enum sym_type toktype = stab_type (tokse);
1799
1800 *is_func = FALSE; /* not a function */
1801
1802 /*
1803 * Advance the definedef state machine.
1804 */
1805 switch (definedef)
1806 {
1807 case dnone:
1808 /* We're not on a preprocessor line. */
1809 break;
1810 case dsharpseen:
1811 if (toktype == st_C_define)
1812 {
1813 definedef = ddefineseen;
1814 }
1815 else
1816 {
1817 definedef = dignorerest;
1818 }
1819 return (FALSE);
1820 case ddefineseen:
1821 /*
1822 * Make a tag for any macro.
1823 */
1824 definedef = dignorerest;
1825 *is_func = (c == '(');
1826 if (!*is_func && !constantypedefs)
1827 return (FALSE);
1828 else
1829 return (TRUE);
1830 case dignorerest:
1831 return (FALSE);
1832 default:
1833 error ("internal error: definedef value");
1834 }
1835
1836 /*
1837 * Now typedefs
1838 */
1839 switch (typdef)
1840 {
1841 case tnone:
1842 if (toktype == st_C_typedef)
1843 {
1844 if (typedefs)
1845 typdef = ttypedseen;
1846 return (FALSE);
1847 }
1848 break;
1849 case ttypedseen:
1850 switch (toktype)
1851 {
1852 case st_none:
1853 case st_C_typespec:
1854 typdef = tend;
1855 break;
1856 case st_C_struct:
1857 case st_C_enum:
1858 break;
1859 }
1860 /* Do not return here, so the structdef stuff has a chance. */
1861 break;
1862 case tend:
1863 switch (toktype)
1864 {
1865 case st_C_typespec:
1866 case st_C_struct:
1867 case st_C_enum:
1868 return (FALSE);
1869 }
1870 return (TRUE);
1871 }
1872
1873 /*
1874 * This structdef business is currently only invoked when level==0.
1875 * It should be recursively invoked whatever the level, and a stack of
1876 * states kept, to allow for definitions of structs within structs.
1877 *
1878 * This structdef business is NOT invoked when we are ctags and the
1879 * file is plain C. This is because a struct tag may have the same
1880 * name as another tag, and this loses with ctags.
1881 *
1882 * This if statement deals with the typdef state machine as
1883 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1884 * return (FALSE). All the other code here is for the structdef
1885 * state machine.
1886 */
1887 switch (toktype)
1888 {
1889 case st_C_struct:
1890 case st_C_enum:
1891 if (typdef == ttypedseen
1892 || (typedefs_and_cplusplus && level == 0 && structdef == snone))
1893 {
1894 structdef = skeyseen;
1895 structkey = tokse;
1896 }
1897 return (FALSE);
1898 }
1899 if (structdef == skeyseen)
1900 {
1901 if (stab_type (structkey) == st_C_struct)
1902 {
1903 (void) strncpy (structtag, tokp->p, tokp->len);
1904 structtag[tokp->len] = '\0'; /* for struct/union/class */
1905 }
1906 else
1907 {
1908 structtag[0] = '\0'; /* for enum (why is it treated differently?) */
1909 }
1910 structdef = stagseen;
1911 return (TRUE);
1912 }
1913
1914 /* Avoid entering funcdef stuff if typdef is going on. */
1915 if (typdef != tnone)
1916 {
1917 definedef = dnone;
1918 return (FALSE);
1919 }
1920
1921 /* Detect GNUmacs's function-defining macros. */
1922 if (definedef == dnone)
1923 {
1924 if (strneq (tokp->p, "DEF", 3)
1925 || strneq (tokp->p, "ENTRY", 5)
1926 || strneq (tokp->p, "SYSCALL", 7)
1927 || strneq (tokp->p, "PSEUDO", 6))
1928 {
1929 next_token_is_func = TRUE;
1930 return (FALSE);
1931 }
1932 if (strneq (tokp->p, "EXFUN", 5))
1933 {
1934 next_token_is_func = FALSE;
1935 return (FALSE);
1936 }
1937 }
1938 if (next_token_is_func)
1939 {
1940 next_token_is_func = FALSE;
1941 return (TRUE);
1942 }
1943
1944 /* A function? */
1945 switch (toktype)
1946 {
1947 case st_C_typespec:
1948 funcdef == fnone; /* should be useless */
1949 return (FALSE);
1950 default:
1951 funcdef = ftagseen;
1952 *is_func = TRUE;
1953 return (TRUE);
1954 }
1955 }
1956 \f
1957 /* Fortran parsing */
1958
1959 char *dbp;
1960 int pfcnt;
1961
1962 int
1963 PF_funcs (fi)
1964 FILE *fi;
1965 {
1966 lineno = 0;
1967 charno = 0;
1968 pfcnt = 0;
1969
1970 while (!feof (fi))
1971 {
1972 lineno++;
1973 linecharno = charno;
1974 charno += readline (&lb, fi);
1975 dbp = lb.buffer;
1976 if (*dbp == '%')
1977 dbp++; /* Ratfor escape to fortran */
1978 while (isspace (*dbp))
1979 dbp++;
1980 if (*dbp == 0)
1981 continue;
1982 switch (*dbp | ' ')
1983 {
1984 case 'i':
1985 if (tail ("integer"))
1986 takeprec ();
1987 break;
1988 case 'r':
1989 if (tail ("real"))
1990 takeprec ();
1991 break;
1992 case 'l':
1993 if (tail ("logical"))
1994 takeprec ();
1995 break;
1996 case 'c':
1997 if (tail ("complex") || tail ("character"))
1998 takeprec ();
1999 break;
2000 case 'd':
2001 if (tail ("double"))
2002 {
2003 while (isspace (*dbp))
2004 dbp++;
2005 if (*dbp == 0)
2006 continue;
2007 if (tail ("precision"))
2008 break;
2009 continue;
2010 }
2011 break;
2012 }
2013 while (isspace (*dbp))
2014 dbp++;
2015 if (*dbp == 0)
2016 continue;
2017 switch (*dbp | ' ')
2018 {
2019 case 'f':
2020 if (tail ("function"))
2021 getit ();
2022 continue;
2023 case 's':
2024 if (tail ("subroutine"))
2025 getit ();
2026 continue;
2027 case 'e':
2028 if (tail ("entry"))
2029 getit ();
2030 continue;
2031 case 'p':
2032 if (tail ("program"))
2033 {
2034 getit ();
2035 continue;
2036 }
2037 if (tail ("procedure"))
2038 getit ();
2039 continue;
2040 }
2041 }
2042 return (pfcnt);
2043 }
2044
2045 logical
2046 tail (cp)
2047 char *cp;
2048 {
2049 register int len = 0;
2050
2051 while (*cp && (*cp & ~' ') == ((*(dbp + len)) & ~' '))
2052 cp++, len++;
2053 if (*cp == 0)
2054 {
2055 dbp += len;
2056 return (1);
2057 }
2058 return (0);
2059 }
2060
2061 void
2062 takeprec ()
2063 {
2064 while (isspace (*dbp))
2065 dbp++;
2066 if (*dbp != '*')
2067 return;
2068 dbp++;
2069 while (isspace (*dbp))
2070 dbp++;
2071 if (!isdigit (*dbp))
2072 {
2073 --dbp; /* force failure */
2074 return;
2075 }
2076 do
2077 dbp++;
2078 while (isdigit (*dbp));
2079 }
2080
2081 void
2082 getit ()
2083 {
2084 register char *cp;
2085 char c;
2086 char nambuf[BUFSIZ];
2087
2088 while (isspace (*dbp))
2089 dbp++;
2090 if (*dbp == 0
2091 || (!isalpha (*dbp)
2092 && *dbp != '_'
2093 && *dbp != '$'))
2094 return;
2095 for (cp = dbp + 1; *cp && (isalpha (*cp) || isdigit (*cp)
2096 || (*cp == '_') || (*cp == '$')); cp++)
2097 continue;
2098 c = cp[0];
2099 cp[0] = 0;
2100 (void) strcpy (nambuf, dbp);
2101 cp[0] = c;
2102 pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
2103 pfcnt++;
2104 }
2105
2106 /* Handle a file of assembler code. */
2107
2108 void
2109 Asm_funcs (fi)
2110 FILE *fi;
2111 {
2112 int i;
2113 register char c;
2114
2115 lineno = 0;
2116 charno = 0;
2117 pfcnt = 0;
2118
2119 while (!feof (fi))
2120 {
2121 lineno++;
2122 linecharno = charno;
2123 charno += readline (&lb, fi);
2124 dbp = lb.buffer;
2125
2126 for (i = 0; ((c = dbp[i]) && !isspace (c)) && (c != ':'); i++)
2127 ;
2128
2129 if ((i > 0) && (c == ':'))
2130 getit ();
2131 }
2132 }
2133 \f
2134 /* Added by Mosur Mohan, 4/22/88 */
2135 /* Pascal parsing */
2136
2137 #define GET_NEW_LINE \
2138 { \
2139 linecharno = charno; lineno++; \
2140 charno += 1 + readline (&lb, inf); \
2141 dbp = lb.buffer; \
2142 }
2143
2144 /* Locates tags for procedures & functions.
2145 * Doesn't do any type- or var-definitions.
2146 * It does look for the keyword "extern" or "forward"
2147 * immediately following the procedure statement;
2148 * if found, the tag is skipped.
2149 */
2150
2151 void
2152 PAS_funcs (fi)
2153 FILE *fi;
2154 {
2155 struct linebuffer tline; /* mostly copied from C_entries */
2156 long save_lcno;
2157 int save_lineno;
2158 char c, *cp;
2159 char nambuf[BUFSIZ];
2160
2161 logical /* each of these flags is TRUE iff: */
2162 incomm1, /* point is inside {..} comment */
2163 incomm2, /* point is inside (*..*) comment */
2164 inquote, /* point is inside '..' string */
2165 get_tagname, /* point is after PROCEDURE/FUNCTION */
2166 /* keyword, so next item = potential tag */
2167 found_tag, /* point is after a potential tag */
2168 inparms, /* point is within parameter-list */
2169 verify_tag; /* point has passed the parm-list, so the */
2170 /* next token will determine whether */
2171 /* this is a FORWARD/EXTERN to be */
2172 /* ignored, or whether it is a real tag */
2173
2174 lineno = 0;
2175 charno = 0;
2176 dbp = lb.buffer;
2177 *dbp = 0;
2178 initbuffer (&tline);
2179
2180 incomm1 = incomm2 = inquote = FALSE;
2181 found_tag = FALSE; /* have a proc name; check if extern */
2182 get_tagname = FALSE; /* have found "procedure" keyword */
2183 inparms = FALSE; /* found '(' after "proc" */
2184 verify_tag = FALSE; /* check if "extern" is ahead */
2185
2186 /* long main loop to get next char */
2187 while (!feof (fi))
2188 {
2189 c = *dbp++;
2190 if (c == 0) /* if end of line */
2191 {
2192 GET_NEW_LINE;
2193 if (*dbp == 0)
2194 continue;
2195 if (!((found_tag && verify_tag) ||
2196 get_tagname))
2197 c = *dbp++; /* only if don't need *dbp pointing */
2198 /* to the beginning of the name of */
2199 /* the procedure or function */
2200 }
2201 if (incomm1) /* within { - } comments */
2202 {
2203 if (c == '}')
2204 incomm1 = FALSE;
2205 continue;
2206 }
2207 else if (incomm2) /* within (* - *) comments */
2208 {
2209 if (c == '*')
2210 {
2211 while ((c = *dbp++) == '*')
2212 continue;
2213 if (c == 0)
2214 GET_NEW_LINE;
2215 if (c == ')')
2216 incomm2 = FALSE;
2217 }
2218 continue;
2219 }
2220 else if (inquote)
2221 {
2222 if (c == '\'')
2223 inquote = FALSE;
2224 continue;
2225 }
2226 else
2227 switch (c)
2228 {
2229 case '\'':
2230 inquote = TRUE; /* found first quote */
2231 continue;
2232 case '{': /* found open-{-comment */
2233 incomm1 = TRUE;
2234 continue;
2235 case '(':
2236 if (*dbp == '*') /* found open-(*-comment */
2237 {
2238 incomm2 = TRUE;
2239 dbp++;
2240 }
2241 else if (found_tag) /* found '(' after tag, i.e., parm-list */
2242 inparms = TRUE;
2243 continue;
2244 case ')': /* end of parms list */
2245 if (inparms)
2246 inparms = FALSE;
2247 continue;
2248 case ';':
2249 if ((found_tag) && (!inparms)) /* end of proc or fn stmt */
2250 {
2251 verify_tag = TRUE;
2252 break;
2253 }
2254 continue;
2255 }
2256 if ((found_tag) && (verify_tag) && (*dbp != ' '))
2257 {
2258 /* check if this is an "extern" declaration */
2259 if (*dbp == 0)
2260 continue;
2261 if ((*dbp == 'e') || (*dbp == 'E'))
2262 {
2263 if (tail ("extern")) /* superfluous, really! */
2264 {
2265 found_tag = FALSE;
2266 verify_tag = FALSE;
2267 }
2268 }
2269 else if ((*dbp == 'f') || (*dbp == 'F'))
2270 {
2271 if (tail ("forward")) /* check for forward reference */
2272 {
2273 found_tag = FALSE;
2274 verify_tag = FALSE;
2275 }
2276 }
2277 if ((found_tag) && (verify_tag)) /* not external proc, so make tag */
2278 {
2279 found_tag = FALSE;
2280 verify_tag = FALSE;
2281 pfnote (nambuf, TRUE, FALSE,
2282 tline.buffer, cp - tline.buffer + 1,
2283 save_lineno, save_lcno);
2284 continue;
2285 }
2286 }
2287 if (get_tagname) /* grab name of proc or fn */
2288 {
2289 if (*dbp == 0)
2290 continue;
2291
2292 /* save all values for later tagging */
2293 tline.size = lb.size;
2294 strcpy (tline.buffer, lb.buffer);
2295 save_lineno = lineno;
2296 save_lcno = linecharno;
2297
2298 /* grab block name */
2299 for (cp = dbp + 1; *cp && (!endtoken (*cp)); cp++)
2300 continue;
2301 c = cp[0];
2302 cp[0] = 0;
2303 strcpy (nambuf, dbp);
2304 cp[0] = c;
2305 dbp = cp; /* restore dbp to e-o-token */
2306 get_tagname = FALSE;
2307 found_tag = TRUE;
2308 continue;
2309
2310 /* and proceed to check for "extern" */
2311 }
2312 if ((!incomm1) && (!incomm2) && (!inquote) &&
2313 (!found_tag) && (!get_tagname))
2314 {
2315 /* check for proc/fn keywords */
2316 switch (c | ' ')
2317 {
2318 case 'p':
2319 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2320 get_tagname = TRUE;
2321 continue;
2322 case 'f':
2323 if (tail ("unction"))
2324 get_tagname = TRUE;
2325 continue;
2326 }
2327 }
2328 } /* while not e-o-f */
2329 }
2330 \f
2331 /*
2332 * lisp tag functions
2333 * just look for (def or (DEF
2334 */
2335
2336 void
2337 L_funcs (fi)
2338 FILE *fi;
2339 {
2340 lineno = 0;
2341 charno = 0;
2342 pfcnt = 0;
2343
2344 while (!feof (fi))
2345 {
2346 lineno++;
2347 linecharno = charno;
2348 charno += readline (&lb, fi);
2349 dbp = lb.buffer;
2350 if (dbp[0] == '(')
2351 {
2352 if (L_isdef (dbp))
2353 {
2354 while (!isspace (*dbp))
2355 dbp++;
2356 while (isspace (*dbp))
2357 dbp++;
2358 L_getit ();
2359 }
2360 else
2361 {
2362 /* Check for (foo::defmumble name-defined ... */
2363 while (*dbp && *dbp != ':' && !isspace (*dbp)
2364 && *dbp != '(' && *dbp != ')')
2365 dbp++;
2366 if (*dbp == ':')
2367 {
2368 while (*dbp == ':')
2369 dbp++;
2370
2371 if (L_isdef (dbp))
2372 {
2373 while (!isspace (*dbp))
2374 dbp++;
2375 while (isspace (*dbp))
2376 dbp++;
2377 L_getit ();
2378 }
2379 }
2380 }
2381 }
2382 }
2383 }
2384
2385 int
2386 L_isdef (dbp)
2387 char *dbp;
2388 {
2389 return ((dbp[1] == 'D' || dbp[1] == 'd') &&
2390 (dbp[2] == 'E' || dbp[2] == 'e') &&
2391 (dbp[3] == 'F' || dbp[3] == 'f'));
2392 }
2393
2394 void
2395 L_getit ()
2396 {
2397 register char *cp;
2398 char c;
2399 char nambuf[BUFSIZ];
2400
2401 if (*dbp == 0)
2402 return;
2403 for (cp = dbp + 1; *cp && *cp != '(' && *cp != ' '; cp++)
2404 continue;
2405 c = cp[0];
2406 cp[0] = 0;
2407 (void) strcpy (nambuf, dbp);
2408 cp[0] = c;
2409 pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
2410 pfcnt++;
2411 }
2412 \f
2413 /*
2414 * Scheme tag functions
2415 * look for (def... xyzzy
2416 * look for (def... (xyzzy
2417 * look for (def ... ((...(xyzzy ....
2418 * look for (set! xyzzy
2419 */
2420
2421 static void get_scheme ();
2422
2423 void
2424 Scheme_funcs (fi)
2425 FILE *fi;
2426 {
2427 lineno = 0;
2428 charno = 0;
2429 pfcnt = 0;
2430
2431 while (!feof (fi))
2432 {
2433 lineno++;
2434 linecharno = charno;
2435 charno += readline (&lb, fi);
2436 dbp = lb.buffer;
2437 if (dbp[0] == '(' &&
2438 (dbp[1] == 'D' || dbp[1] == 'd') &&
2439 (dbp[2] == 'E' || dbp[2] == 'e') &&
2440 (dbp[3] == 'F' || dbp[3] == 'f'))
2441 {
2442 while (!isspace (*dbp))
2443 dbp++;
2444 /* Skip over open parens and white space */
2445 while (*dbp && (isspace (*dbp) || *dbp == '('))
2446 dbp++;
2447 get_scheme ();
2448 }
2449 if (dbp[0] == '(' &&
2450 (dbp[1] == 'S' || dbp[1] == 's') &&
2451 (dbp[2] == 'E' || dbp[2] == 'e') &&
2452 (dbp[3] == 'T' || dbp[3] == 't') &&
2453 (dbp[4] == '!' || dbp[4] == '!') &&
2454 (isspace (dbp[5])))
2455 {
2456 while (!isspace (*dbp))
2457 dbp++;
2458 /* Skip over white space */
2459 while (isspace (*dbp))
2460 dbp++;
2461 get_scheme ();
2462 }
2463 }
2464 }
2465
2466 static void
2467 get_scheme ()
2468 {
2469 register char *cp;
2470 char c;
2471 char nambuf[BUFSIZ];
2472
2473 if (*dbp == 0)
2474 return;
2475 /* Go till you get to white space or a syntactic break */
2476 for (cp = dbp + 1; *cp && *cp != '(' && *cp != ')' && !isspace (*cp); cp++)
2477 continue;
2478 /* Null terminate the string there. */
2479 c = cp[0];
2480 cp[0] = 0;
2481 /* Copy the string */
2482 strcpy (nambuf, dbp);
2483 /* Unterminate the string */
2484 cp[0] = c;
2485 /* Announce the change */
2486 pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
2487 pfcnt++;
2488 }
2489 \f
2490 /* Find tags in TeX and LaTeX input files. */
2491
2492 /* TEX_toktab is a table of TeX control sequences that define tags.
2493 Each TEX_tabent records one such control sequence.
2494 CONVERT THIS TO USE THE Stab TYPE!! */
2495
2496 struct TEX_tabent
2497 {
2498 char *name;
2499 int len;
2500 };
2501
2502 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
2503
2504 /* Default set of control sequences to put into TEX_toktab.
2505 The value of environment var TEXTAGS is prepended to this. */
2506
2507 static char *TEX_defenv =
2508 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2509
2510 void TEX_mode ();
2511 struct TEX_tabent *TEX_decode_env ();
2512 void TEX_getit ();
2513 int TEX_Token ();
2514
2515 static char TEX_esc = '\\';
2516 static char TEX_opgrp = '{';
2517 static char TEX_clgrp = '}';
2518
2519 /*
2520 * TeX/LaTeX scanning loop.
2521 */
2522
2523 void
2524 TEX_funcs (fi)
2525 FILE *fi;
2526 {
2527 char *lasthit;
2528
2529 lineno = 0;
2530 charno = 0;
2531 pfcnt = 0;
2532
2533 /* Select either \ or ! as escape character. */
2534 TEX_mode (fi);
2535
2536 /* Initialize token table once from environment. */
2537 if (!TEX_toktab)
2538 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
2539
2540 while (!feof (fi))
2541 { /* Scan each line in file */
2542 lineno++;
2543 linecharno = charno;
2544 charno += readline (&lb, fi);
2545 dbp = lb.buffer;
2546 lasthit = dbp;
2547 while (dbp = etags_index (dbp, TEX_esc)) /* Look at each escape in line */
2548 {
2549 register int i;
2550
2551 if (!*(++dbp))
2552 break;
2553 linecharno += dbp - lasthit;
2554 lasthit = dbp;
2555 i = TEX_Token (lasthit);
2556 if (0 <= i)
2557 {
2558 TEX_getit (lasthit, TEX_toktab[i].len);
2559 break; /* We only save a line once */
2560 }
2561 }
2562 }
2563 }
2564
2565 #define TEX_LESC '\\'
2566 #define TEX_SESC '!'
2567 #define TEX_cmt '%'
2568
2569 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2570 /* chars accordingly. */
2571
2572 void
2573 TEX_mode (f)
2574 FILE *f;
2575 {
2576 int c;
2577
2578 while ((c = getc (f)) != EOF)
2579 {
2580 /* Skip to next line if we hit the TeX comment char. */
2581 if (c == TEX_cmt)
2582 while (c != '\n')
2583 c = getc (f);
2584 else if (c == TEX_LESC || c == TEX_SESC )
2585 break;
2586 }
2587
2588 if (c == TEX_LESC)
2589 {
2590 TEX_esc = TEX_LESC;
2591 TEX_opgrp = '{';
2592 TEX_clgrp = '}';
2593 }
2594 else
2595 {
2596 TEX_esc = TEX_SESC;
2597 TEX_opgrp = '<';
2598 TEX_clgrp = '>';
2599 }
2600 rewind (f);
2601 }
2602
2603 /* Read environment and prepend it to the default string. */
2604 /* Build token table. */
2605
2606 struct TEX_tabent *
2607 TEX_decode_env (evarname, defenv)
2608 char *evarname;
2609 char *defenv;
2610 {
2611 register char *env, *p;
2612
2613 struct TEX_tabent *tab;
2614 int size, i;
2615
2616 /* Append default string to environment. */
2617 env = getenv (evarname);
2618 if (!env)
2619 env = defenv;
2620 else
2621 env = concat (env, defenv, "");
2622
2623 /* Allocate a token table */
2624 for (size = 1, p = env; p;)
2625 if ((p = etags_index (p, ':')) && *(++p))
2626 size++;
2627 /* Add 1 to leave room for null terminator. */
2628 tab = xnew (size + 1, struct TEX_tabent);
2629
2630 /* Unpack environment string into token table. Be careful about */
2631 /* zero-length strings (leading ':', "::" and trailing ':') */
2632 for (i = 0; *env;)
2633 {
2634 p = etags_index (env, ':');
2635 if (!p) /* End of environment string. */
2636 p = env + strlen (env);
2637 if (p - env > 0)
2638 { /* Only non-zero strings. */
2639 tab[i].name = savenstr (env, p - env);
2640 tab[i].len = strlen (tab[i].name);
2641 i++;
2642 }
2643 if (*p)
2644 env = p + 1;
2645 else
2646 {
2647 tab[i].name = NULL; /* Mark end of table. */
2648 tab[i].len = 0;
2649 break;
2650 }
2651 }
2652 return tab;
2653 }
2654
2655 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2656 The name being defined actually starts at (NAME + LEN + 1).
2657 But we seem to include the TeX command in the tag name. */
2658
2659 void
2660 TEX_getit (name, len)
2661 char *name;
2662 int len;
2663 {
2664 char *p = name + len;
2665 char nambuf[BUFSIZ];
2666
2667 if (*name == 0)
2668 return;
2669
2670 /* Let tag name extend to next group close (or end of line) */
2671 while (*p && *p != TEX_clgrp)
2672 p++;
2673 (void) strncpy (nambuf, name, p - name);
2674 nambuf[p - name] = 0;
2675
2676 pfnote (nambuf, TRUE, FALSE, lb.buffer, strlen (lb.buffer), lineno, linecharno);
2677 pfcnt++;
2678 }
2679
2680 /* If the text at CP matches one of the tag-defining TeX command names,
2681 return the etags_index of that command in TEX_toktab.
2682 Otherwise return -1. */
2683
2684 /* Keep the capital `T' in `Token' for dumb truncating compilers
2685 (this distinguishes it from `TEX_toktab' */
2686 int
2687 TEX_Token (cp)
2688 char *cp;
2689 {
2690 int i;
2691
2692 for (i = 0; TEX_toktab[i].len > 0; i++)
2693 if (strncmp (TEX_toktab[i].name, cp, TEX_toktab[i].len) == 0)
2694 return i;
2695 return -1;
2696 }
2697 \f
2698 /* Support for Prolog. */
2699
2700 /* whole head (not only functor, but also arguments)
2701 is gotten in compound term. */
2702
2703 void
2704 prolog_getit (s, lineno, linecharno)
2705 char *s;
2706 int lineno;
2707 long linecharno;
2708 {
2709 char nambuf[BUFSIZ], *save_s, tmpc;
2710 int insquote, npar;
2711
2712 save_s = s;
2713 insquote = FALSE;
2714 npar = 0;
2715 while (1)
2716 {
2717 if (*s == '\0') /* syntax error. */
2718 return;
2719 else if (insquote && *s == '\'' && *(s + 1) == '\'')
2720 s += 2;
2721 else if (*s == '\'')
2722 {
2723 insquote = !insquote;
2724 s++;
2725 }
2726 else if (!insquote && *s == '(')
2727 {
2728 npar++;
2729 s++;
2730 }
2731 else if (!insquote && *s == ')')
2732 {
2733 npar--;
2734 s++;
2735 if (npar == 0)
2736 break;
2737 else if (npar < 0) /* syntax error. */
2738 return;
2739 }
2740 else if (!insquote && *s == '.' && (isspace (*(s + 1)) || *(s + 1) == '\0'))
2741 { /* fullstop. */
2742 if (npar != 0) /* syntax error. */
2743 return;
2744 s++;
2745 break;
2746 }
2747 else
2748 s++;
2749 }
2750 tmpc = *s;
2751 *s = '\0';
2752 strcpy (nambuf, save_s);
2753 *s = tmpc;
2754 pfnote (nambuf, TRUE, save_s, strlen (nambuf), lineno, linecharno);
2755 }
2756
2757 /* It is assumed that prolog predicate starts from column 0. */
2758
2759 void
2760 prolog_funcs (fi)
2761 FILE *fi;
2762 {
2763 void skip_comment (), prolog_getit ();
2764
2765 lineno = linecharno = charno = 0;
2766 while (!feof (fi))
2767 {
2768 lineno++;
2769 linecharno += charno;
2770 charno = readline (&lb, fi) + 1; /* 1 for newline. */
2771 dbp = lb.buffer;
2772 if (isspace (dbp[0])) /* not predicate header. */
2773 continue;
2774 else if (dbp[0] == '%') /* comment. */
2775 continue;
2776 else if (dbp[0] == '/' && dbp[1] == '*') /* comment. */
2777 skip_comment (&lb, fi, &lineno, &linecharno);
2778 else /* found. */
2779 prolog_getit (dbp, lineno, linecharno);
2780 }
2781 }
2782
2783 void
2784 skip_comment (plb, fi, plineno, plinecharno)
2785 struct linebuffer *plb;
2786 FILE *fi;
2787 int *plineno; /* result */
2788 long *plinecharno; /* result */
2789 {
2790 while (!substr ("*/", plb->buffer))
2791 {
2792 (*plineno)++;
2793 *plinecharno += readline (plb, fi) + 1;
2794 } /* 1 for newline. */
2795 }
2796
2797 /* Return TRUE if 'sub' exists somewhere in 's'. */
2798
2799 int
2800 substr (sub, s)
2801 char *sub;
2802 char *s;
2803 {
2804 while (*s && (s = etags_index (s, *sub)))
2805 if (prestr (sub, s))
2806 return (TRUE);
2807 else
2808 s++;
2809 return (FALSE);
2810 }
2811
2812 /* Return TRUE if 'pre' is prefix of string 's'. */
2813
2814 int
2815 prestr (pre, s)
2816 char *pre;
2817 char *s;
2818 {
2819 if (*pre == '\0')
2820 return (TRUE);
2821 else if (*pre == *s)
2822 return (prestr (pre + 1, s + 1));
2823 else
2824 return (FALSE);
2825 }
2826 \f
2827 /* Initialize a linebuffer for use */
2828
2829 void
2830 initbuffer (linebuffer)
2831 struct linebuffer *linebuffer;
2832 {
2833 linebuffer->size = 200;
2834 linebuffer->buffer = xnew (200, char);
2835 }
2836
2837 /*
2838 * Read a line of text from `stream' into `linebuffer'.
2839 * Return the number of characters read from `stream',
2840 * which is the length of the line including the newline, if any.
2841 */
2842 long
2843 readline (linebuffer, stream)
2844 struct linebuffer *linebuffer;
2845 register FILE *stream;
2846 {
2847 char *buffer = linebuffer->buffer;
2848 register char *p = linebuffer->buffer;
2849 register char *pend;
2850 int newline; /* 1 if ended with newline, 0 if ended with EOF */
2851
2852 pend = p + linebuffer->size; /* Separate to avoid 386/IX compiler bug. */
2853
2854 while (1)
2855 {
2856 register int c = getc (stream);
2857 if (p == pend)
2858 {
2859 linebuffer->size *= 2;
2860 buffer = (char *) xrealloc (buffer, linebuffer->size);
2861 p += buffer - linebuffer->buffer;
2862 pend = buffer + linebuffer->size;
2863 linebuffer->buffer = buffer;
2864 }
2865 if (c < 0 || c == '\n')
2866 {
2867 *p = 0;
2868 newline = (c == '\n' ? 1 : 0);
2869 break;
2870 }
2871 *p++ = c;
2872 }
2873
2874 return p - buffer + newline;
2875 }
2876 \f
2877 char *
2878 savestr (cp)
2879 char *cp;
2880 {
2881 return savenstr (cp, strlen (cp));
2882 }
2883
2884 char *
2885 savenstr (cp, len)
2886 char *cp;
2887 int len;
2888 {
2889 register char *dp;
2890
2891 dp = xnew (len + 1, char);
2892 (void) strncpy (dp, cp, len);
2893 dp[len] = '\0';
2894 return dp;
2895 }
2896
2897 /*
2898 * Return the ptr in sp at which the character c last
2899 * appears; NULL if not found
2900 *
2901 * Identical to v7 rindex, included for portability.
2902 */
2903
2904 char *
2905 etags_rindex (sp, c)
2906 register char *sp, c;
2907 {
2908 register char *r;
2909
2910 r = NULL;
2911 do
2912 {
2913 if (*sp == c)
2914 r = sp;
2915 } while (*sp++);
2916 return (r);
2917 }
2918
2919
2920 /*
2921 * Return the ptr in sp at which the character c first
2922 * appears; NULL if not found
2923 *
2924 * Identical to v7 index, included for portability.
2925 */
2926
2927 char *
2928 etags_index (sp, c)
2929 register char *sp, c;
2930 {
2931 do
2932 {
2933 if (*sp == c)
2934 return (sp);
2935 } while (*sp++);
2936 return (NULL);
2937 }
2938
2939 /* Print error message and exit. */
2940
2941 /* VARARGS1 */
2942 void
2943 fatal (s1, s2)
2944 char *s1, *s2;
2945 {
2946 error (s1, s2);
2947 exit (1);
2948 }
2949
2950 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
2951
2952 /* VARARGS1 */
2953 void
2954 error (s1, s2)
2955 char *s1, *s2;
2956 {
2957 fprintf (stderr, "%s: ", progname);
2958 fprintf (stderr, s1, s2);
2959 fprintf (stderr, "\n");
2960 }
2961
2962 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
2963
2964 char *
2965 concat (s1, s2, s3)
2966 char *s1, *s2, *s3;
2967 {
2968 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
2969 char *result = xnew (len1 + len2 + len3 + 1, char);
2970
2971 (void) strcpy (result, s1);
2972 (void) strcpy (result + len1, s2);
2973 (void) strcpy (result + len1 + len2, s3);
2974 *(result + len1 + len2 + len3) = 0;
2975
2976 return result;
2977 }
2978
2979 /* Like malloc but get fatal error if memory is exhausted. */
2980
2981 char *
2982 xmalloc (size)
2983 int size;
2984 {
2985 char *result = malloc (size);
2986 if (!result)
2987 fatal ("virtual memory exhausted", 0);
2988 return result;
2989 }
2990
2991 char *
2992 xrealloc (ptr, size)
2993 char *ptr;
2994 int size;
2995 {
2996 char *result = realloc (ptr, size);
2997 if (!result)
2998 fatal ("virtual memory exhausted");
2999 return result;
3000 }