1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 1987, 1988, 1989, 1993 Free Software Foundation, Inc. and Ken Arnold
4 This file is not considered part of GNU Emacs.
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.
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.
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. */
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++.
28 * Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer. 10.7
36 #include <../src/config.h>
41 #include <sys/types.h>
44 #if !defined (S_ISREG) && defined (S_IFREG)
45 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
50 extern char *getenv ();
52 char *etags_index (), *etags_rindex ();
55 /* Define the symbol ETAGS to make the program "etags",
56 which makes emacs-style tag tables by default.
57 Define CTAGS to make the program "ctags" compatible with the usual one.
58 Define neither one to get behavior that depends
59 on the name with which the program is invoked
60 (but we don't normally compile it that way). */
62 #if !defined(ETAGS) && !defined(CTAGS)
63 /* If neither is defined, program can be run as either. */
68 /* On VMS, CTAGS is not useful, so always do ETAGS. */
75 /* Exit codes for success and failure. */
85 * The FILEPOS abstract type, which represents a position in a file,
86 * plus the following accessor functions:
88 * long GET_CHARNO (pos)
89 * returns absolute char number.
90 * void SET_FILEPOS (pos, fp, charno)
91 * FILE *fp; long charno;
92 * sets `pos' from the current file
93 * position of `fp' and from `charno',
94 * which must be the absolute character
95 * number corresponding to the current
98 * The `pos' parameter is an lvalue expression of type FILEPOS.
99 * Parameters to the accessor functions are evaluated 0 or more times,
100 * and so must have no side effects.
102 * FILEPOS objects can also be assigned and passed to and from
103 * functions in the normal C manner.
105 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
109 /* real implementation */
110 typedef long FILEPOS
;
111 #define GET_CHARNO(pos) ((pos) + 0)
112 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
114 /* debugging implementation */
120 #define GET_CHARNO(pos) ((pos).charno + 0)
121 #define SET_FILEPOS(pos, fp, cno) \
122 ((void) ((pos).charno = (cno), \
123 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
127 #define streq(s, t) (strcmp (s, t) == 0)
128 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
134 #define iswhite(arg) (_wht[arg]) /* T if char is white */
135 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
136 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
137 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
139 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
142 { /* sorting structure */
143 char *name
; /* function or type name */
144 char *file
; /* file name */
145 logical is_func
; /* use pattern or line no */
146 logical named
; /* list name separately */
147 logical been_warned
; /* set if noticed dup */
148 int lno
; /* line number tag is on */
149 long cno
; /* character number line starts on */
150 char *pat
; /* search pattern */
151 struct nd_st
*left
, *right
; /* left and right sons */
155 typedef struct nd_st NODE
;
157 logical header_file
; /* TRUE if .h file, FALSE o.w. */
158 /* boolean "functions" (see init) */
159 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
167 int L_isdef (), L_isquote ();
169 int total_size_of_entries ();
170 logical
consider_token ();
178 void Scheme_funcs ();
183 logical
find_entries ();
190 void process_file ();
196 * xnew -- allocate storage
199 * Type *xnew (int n, Type);
201 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
204 * Symbol table types.
208 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
225 #define C_PLPL 0x00001 /* C++ */
226 #define C_STAR 0x00003 /* C* */
227 #define YACC 0x10000 /* yacc file */
229 char searchar
= '/'; /* use /.../ searches */
231 LINENO lineno
; /* line number of current line */
232 long charno
; /* current character number */
234 long linecharno
; /* charno of start of line; not used by C, but
235 * by every other language.
238 char *curfile
, /* current input file name */
239 *outfile
, /* output file */
240 *white
= " \f\t\n", /* white chars */
241 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
242 /* token starting chars */
243 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
244 /* valid in-token chars */
245 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
247 int append_to_tagfile
; /* -a: append to tags */
248 int emacs_tags_format
; /* emacs style output (no -e option any more) */
249 /* The following three default to 1 for etags, but to 0 for ctags. */
250 int typedefs
; /* -t: create tags for typedefs */
251 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
252 /* 0 struct/enum/union decls, and C++ */
253 /* member functions */
254 int constantypedefs
; /* -d: create tags for C #define and enum */
255 /* constants. Default under etags. Enum */
256 /* constants not implemented. */
257 /* -D: opposite of -d. Default under ctags. */
258 int update
; /* -u: update tags */
259 int vgrind_style
; /* -v: create vgrind style index output */
260 int no_warnings
; /* -w: suppress warnings */
261 int cxref_style
; /* -x: create cxref style output */
262 int cplusplus
; /* .[hc] means C++, not C */
263 int noindentypedefs
; /* -S: ignore indentation in C */
265 /* Name this program was invoked with. */
268 struct option longopts
[] = {
269 { "append", no_argument
, NULL
, 'a' },
270 { "backward-search", no_argument
, NULL
, 'B' },
271 { "c++", no_argument
, NULL
, 'C' },
272 { "cxref", no_argument
, NULL
, 'x' },
273 { "defines", no_argument
, NULL
, 'd' },
274 { "forward-search", no_argument
, NULL
, 'F' },
275 { "help", no_argument
, NULL
, 'H' },
276 { "ignore-indentation", no_argument
, NULL
, 'S' },
277 { "include", required_argument
, NULL
, 'i' },
278 { "no-defines", no_argument
, NULL
, 'D' },
279 { "no-warn", no_argument
, NULL
, 'w' },
280 { "output", required_argument
, NULL
, 'o' },
281 { "typedefs", no_argument
, NULL
, 't' },
282 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
283 { "update", no_argument
, NULL
, 'u' },
284 { "version", no_argument
, NULL
, 'V' },
285 { "vgrind", no_argument
, NULL
, 'v' },
289 FILE *inf
, /* ioptr for current input file */
290 *outf
; /* ioptr for tags file */
292 NODE
*head
; /* the head of the binary tree of tags */
294 int permit_duplicates
= 1; /* Nonzero means allow duplicate tags. */
296 /* A `struct linebuffer' is a structure which holds a line of text.
297 `readline' reads a line from a stream into a linebuffer
298 and works regardless of the length of the line. */
306 struct linebuffer lb
; /* the current line */
307 struct linebuffer filename_lb
; /* used to read in filenames */
311 struct linebuffer lb
; /* used by C_entries instead of lb */
326 printf ("for Emacs version 19.\n");
334 printf ("These are the options accepted by %s. You may use unambiguous\n\
335 abbreviations for the long option names. A - as file name means read file\n\
336 names from stdin.\n\n", progname
);
338 puts ("-a, --append\n\
339 Append tag entries to existing tags file.");
342 puts ("-B, --backward-search\n\
343 Write the search commands for the tag entries using '?', the\n\
344 backward-search command.");
348 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
349 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
350 extensions are always assumed to be C++ code.");
353 puts ("-d, --defines\n\
354 Create tag entries for #defines, too. This is the default\n\
357 puts ("-d, --defines\n\
358 Create tag entries for #defines, too.");
362 puts ("-D, --no-defines\n\
363 Don't create tag entries for #defines. This is the default\n\
366 puts ("-D, --no-defines\n\
367 Don't create tag entries for #defines.");
371 puts ("-F, --forward-search\n\
372 Write the search commands for the tag entries using '/', the\n\
373 forward-search command.");
378 puts ("-i FILE, --include=FILE\n\
379 Include a note in tag file indicating that, when searching for\n\
380 a tag, one should also consult the tags file FILE after\n\
381 checking the current file.");
384 puts ("-o FILE, --output=FILE\n\
385 Write the tags to FILE.");
386 puts ("-S, --ignore-indentation\n\
387 Don't rely on indentation quite as much as normal. Currently,\n\
388 this means not to assume that a closing brace in the first\n\
389 column is the final brace of a function or structure\n\
391 puts ("-t, --typedefs\n\
392 Generate tag entries for typedefs. This is the default\n\
394 puts ("-T, --typedefs-and-c++\n\
395 Generate tag entries for typedefs, struct/enum/union tags, and\n\
396 C++ member functions.");
399 puts ("-u, --update\n\
400 Update the tag entries for the given files, leaving tag\n\
401 entries for other files in place. Currently, this is\n\
402 implemented by deleting the existing entries for the given\n\
403 files and then rewriting the new entries at the end of the\n\
404 tags file. It is often faster to simply rebuild the entire\n\
405 tag file than to use this.");
406 puts ("-v, --vgrind\n\
407 Generates an index of items intended for human consumption,\n\
408 similar to the output of vgrind. The index is sorted, and\n\
409 gives the page number of each item.");
410 puts ("-x, --cxref\n\
411 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
412 The output uses line numbers instead of page numbers, but\n\
413 beyond that the differences are cosmetic; try both to see\n\
415 puts ("-w, --no-warn\n\
416 Suppress warning messages about entries defined in multiple\n\
420 puts ("-V, --version\n\
421 Print the version of the program.\n\
423 Print this help message.");
436 unsigned int nincluded_files
= 0;
437 char **included_files
= xnew (argc
, char *);
442 extern char *gfnames ();
443 extern char *massage_name ();
447 _fmode
= O_BINARY
; /* all of files are treated as binary files */
453 emacs_tags_format
= 1;
455 emacs_tags_format
= 0;
459 * If etags, always find typedefs and structure tags. Why not?
460 * Also default is to find macro constants.
462 if (emacs_tags_format
)
463 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
468 opt
= getopt_long (argc
, argv
, "aACdDo:f:StTi:BFuvxwVH", longopts
, 0);
476 /* If getopt returns '\0', then it has already processed a
477 long-named option. We should do nothing. */
480 /* Common options. */
498 "%s: -%c flag may only be given once\n", progname
, opt
);
511 typedefs_and_cplusplus
++;
522 if (!emacs_tags_format
)
524 included_files
[nincluded_files
++] = optarg
;
530 if (emacs_tags_format
)
535 if (emacs_tags_format
)
540 if (emacs_tags_format
)
548 if (emacs_tags_format
)
553 if (emacs_tags_format
)
562 if (optind
== argc
&& nincluded_files
== 0)
564 fprintf (stderr
, "%s: No input files specified.\n", progname
);
567 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
574 outfile
= emacs_tags_format
? "TAGS" : "tags";
577 init (); /* set up boolean "functions" */
580 initbuffer (&lbs
[0].lb
);
581 initbuffer (&lbs
[1].lb
);
582 initbuffer (&filename_lb
);
584 * loop through files finding functions
586 if (emacs_tags_format
)
588 if (streq (outfile
, "-"))
591 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
602 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
606 error ("Can't find file %s\n", this_file
);
611 this_file
= massage_name (this_file
);
614 } /* solely to balance out the ifdef'd parens above */
617 for (; optind
< argc
; optind
++)
619 this_file
= argv
[optind
];
621 /* Input file named "-" means read file names from stdin and use them. */
622 if (streq (this_file
, "-"))
624 while (!feof (stdin
))
626 (void) readline (&filename_lb
, stdin
);
627 if (strlen (filename_lb
.buffer
) > 0)
628 process_file (filename_lb
.buffer
);
632 process_file (this_file
);
635 if (emacs_tags_format
)
637 while (nincluded_files
-- > 0)
638 fprintf (outf
, "\f\n%s,include\n", *included_files
++);
640 (void) fclose (outf
);
651 /* update cannot be set under VMS, so we may assume that argc
652 and argv have not been munged. */
653 for (i
= optind
; i
< argc
; i
++)
656 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
657 outfile
, argv
[i
], outfile
);
662 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
669 (void) fclose (outf
);
672 sprintf (cmd
, "sort %s -o %s", outfile
, outfile
);
680 * This routine is called on each file argument.
686 struct stat stat_buf
;
688 if (stat (file
, &stat_buf
) == 0 && !S_ISREG (stat_buf
.st_mode
))
690 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
693 if (streq (file
, outfile
) && !streq (outfile
, "-"))
695 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
698 if (!find_entries (file
))
702 if (emacs_tags_format
)
704 fprintf (outf
, "\f\n%s,%d\n", file
, total_size_of_entries (head
));
712 * This routine sets up the boolean pseudo-functions which work
713 * by setting boolean flags dependent upon the corresponding character
714 * Every char which is NOT in that string is not a white char. Therefore,
715 * all of the array "_wht" is set to FALSE, and then the elements
716 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
717 * of a char is TRUE if it is the string "white", else FALSE.
725 for (i
= 0; i
< 0177; i
++)
726 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
727 for (sp
= white
; *sp
; sp
++)
729 for (sp
= endtk
; *sp
; sp
++)
731 for (sp
= intk
; *sp
; sp
++)
733 for (sp
= begtk
; *sp
; sp
++)
735 _wht
[0] = _wht
['\n'];
736 _etk
[0] = _etk
['\n'];
737 _btk
[0] = _btk
['\n'];
738 _itk
[0] = _itk
['\n'];
742 * This routine opens the specified file and calls the function
743 * which finds the function and type definitions.
750 void prolog_funcs ();
752 inf
= fopen (file
, "r");
758 curfile
= savestr (file
);
759 cp
= etags_rindex (file
, '.');
761 header_file
= (cp
&& (streq (cp
+ 1, "h")));
763 /* .tex, .aux or .bbl implies LaTeX source code */
764 if (cp
&& (streq (cp
+ 1, "tex") || streq (cp
+ 1, "aux")
765 || streq (cp
+ 1, "bbl")))
768 goto close_and_return
;
770 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
771 if (cp
&& (streq (cp
+ 1, "l")
772 || streq (cp
+ 1, "el")
773 || streq (cp
+ 1, "lsp")
774 || streq (cp
+ 1, "lisp")
775 || streq (cp
+ 1, "cl")
776 || streq (cp
+ 1, "clisp")))
779 goto close_and_return
;
781 /* .scm or .sm or .scheme or ... implies scheme source code */
782 if (cp
&& (streq (cp
+ 1, "sm")
783 || streq (cp
+ 1, "scm")
784 || streq (cp
+ 1, "scheme")
785 || streq (cp
+ 1, "t")
786 || streq (cp
+ 1, "sch")
787 || streq (cp
+ 1, "SM")
788 || streq (cp
+ 1, "SCM")
789 /* The `SCM' or `scm' prefix with a version number */
790 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
791 && string_numeric_p (cp
+ 1))
792 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
793 && string_numeric_p (cp
+ 1))))
796 goto close_and_return
;
798 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
800 if (cp
&& (streq (cp
+ 1, "s")
801 || streq (cp
+ 1, "a")
802 || streq (cp
+ 1, "sa")))
805 goto close_and_return
;
807 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
808 if (cp
&& (streq (cp
+ 1, "C")
809 || streq (cp
+ 1, "H")
810 || streq (cp
+ 1, "cxx")
811 || streq (cp
+ 1, "hxx")
812 || streq (cp
+ 1, "cc")))
814 C_entries (C_PLPL
); /* C++ */
815 goto close_and_return
;
817 /* .cs or .hs: a C* file */
818 if (cp
&& (streq (cp
+ 1, "cs")
819 || streq (cp
+ 1, "hs")))
822 goto close_and_return
;
824 /* .y: a yacc file */
825 if (cp
&& (streq (cp
+ 1, "y")))
828 goto close_and_return
;
830 /* .pl implies prolog source code */
831 if (cp
&& streq (cp
+ 1, "pl"))
834 goto close_and_return
;
836 /* .p or .pas: a Pascal file */
837 if (cp
&& (streq (cp
+ 1, "p")
838 || streq (cp
+ 1, "pas")))
841 goto close_and_return
;
843 /* If .f or .for, assume it is fortran or nothing. */
844 if (cp
&& (streq (cp
+ 1, "f")
845 || streq (cp
+ 1, "for")))
847 (void) PF_funcs (inf
);
848 goto close_and_return
;
850 /* if not a .c or .h or .y file, try fortran */
851 if (cp
&& ((cp
[1] != 'c'
854 || (cp
[1] != 0 && cp
[2] != 0)))
856 if (PF_funcs (inf
) != 0)
857 goto close_and_return
;
858 rewind (inf
); /* no fortran tags found, try C */
860 C_entries (cplusplus
? C_PLPL
: 0);
867 /* Nonzero if string STR is composed of digits. */
870 string_numeric_p (str
)
875 if (*str
< '0' || *str
> '9')
882 /* Should take a TOKEN* instead!! */
884 pfnote (name
, is_func
, named
, linestart
, linelen
, lno
, cno
)
885 char *name
; /* tag name */
886 logical is_func
; /* function or type name? */
887 logical named
; /* tag different from text of definition? */
901 if (!emacs_tags_format
)
903 /* It's okay to output early in etags -- it only disrupts the
904 * character count of the tag entries, which is no longer used
907 error ("too many entries to sort", 0);
914 /* If ctags mode, change name "main" to M<thisfilename>. */
915 if (!emacs_tags_format
&& !cxref_style
&& streq (name
, "main"))
917 fp
= etags_rindex (curfile
, '/');
918 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
919 fp
= etags_rindex (name
, '.');
920 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
924 np
->name
= savestr (name
);
926 np
->is_func
= is_func
;
929 /* UNCOMMENT THE +1 HERE: */
930 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
931 np
->left
= np
->right
= 0;
932 if (emacs_tags_format
)
934 c
= linestart
[linelen
];
935 linestart
[linelen
] = 0;
937 else if (cxref_style
== 0)
939 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
942 np
->pat
= savestr (linestart
);
943 if (emacs_tags_format
)
945 linestart
[linelen
] = c
;
948 add_node (np
, &head
);
953 * recurse on left children, iterate on right children.
961 register NODE
*node_right
= node
->right
;
962 free_tree (node
->left
);
965 free ((char *) node
);
972 * Adds a node to the tree of nodes. In etags mode, we don't keep
973 * it sorted; we just keep a linear list. In ctags mode, maintain
974 * an ordered tree, with no attempt at balancing.
976 * add_node is the only function allowed to add nodes, so it can
979 /* Must avoid static vars within functions since some systems
980 #define static as nothing. */
981 static NODE
*last_node
= NULL
;
984 add_node (node
, cur_node_p
)
985 NODE
*node
, **cur_node_p
;
988 register NODE
*cur_node
= *cur_node_p
;
990 if (cur_node
== NULL
)
997 if (emacs_tags_format
)
1000 if (last_node
== NULL
)
1001 fatal ("internal error in add_node", 0);
1002 last_node
->right
= node
;
1008 dif
= strcmp (node
->name
, cur_node
->name
);
1011 * If this tag name matches an existing one, then
1012 * do not add the node, but maybe print a warning.
1016 if (node
->file
== cur_node
->file
)
1020 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1021 node
->file
, lineno
, node
->name
);
1022 fprintf (stderr
, "Second entry ignored\n");
1026 if (!cur_node
->been_warned
&& !no_warnings
)
1029 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1030 node
->file
, cur_node
->file
, node
->name
);
1032 cur_node
->been_warned
= TRUE
;
1036 /* Maybe refuse to add duplicate nodes. */
1037 if (!permit_duplicates
)
1039 if (streq (node
->name
, cur_node
->name
)
1040 && streq (node
->file
, cur_node
->file
))
1044 /* Actually add the node */
1045 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1051 register NODE
*node
;
1058 /* Output subentries that precede this one */
1059 put_entries (node
->left
);
1061 /* Output this entry */
1063 if (emacs_tags_format
)
1067 fprintf (outf
, "%s\177%s\001%d,%d\n",
1068 node
->pat
, node
->name
,
1069 node
->lno
, node
->cno
);
1073 fprintf (outf
, "%s\177%d,%d\n",
1075 node
->lno
, node
->cno
);
1078 else if (!cxref_style
)
1080 fprintf (outf
, "%s\t%s\t",
1081 node
->name
, node
->file
);
1085 putc (searchar
, outf
);
1088 for (sp
= node
->pat
; *sp
; sp
++)
1090 if (*sp
== '\\' || *sp
== searchar
)
1094 putc (searchar
, outf
);
1097 { /* a typedef; text pattern inadequate */
1098 fprintf (outf
, "%d", node
->lno
);
1102 else if (vgrind_style
)
1103 fprintf (stdout
, "%s %s %d\n",
1104 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1106 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1107 node
->name
, node
->lno
, node
->file
, node
->pat
);
1109 /* Output subentries that follow this one */
1110 put_entries (node
->right
);
1113 /* Length of a number's decimal representation. */
1121 for (; num
; num
/= 10)
1127 * Return total number of characters that put_entries will output for
1128 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1129 * is set, but called only in that case. This count is irrelevant with
1130 * the new tags.el, but is still supplied for backward compatibility.
1133 total_size_of_entries (node
)
1134 register NODE
*node
;
1142 for (; node
; node
= node
->right
)
1144 /* Count left subentries. */
1145 total
+= total_size_of_entries (node
->left
);
1147 /* Count this entry */
1148 total
+= strlen (node
->pat
) + 1;
1149 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1151 total
+= 1 + strlen (node
->name
); /* \001name */
1158 * The C symbol tables.
1161 /* Feed stuff between (but not including) %[ and %] lines to:
1162 gperf -c -k1,3 -o -p -r -t
1164 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1166 class, C_PLPL, st_C_struct
1167 domain, C_STAR, st_C_struct
1168 union, 0, st_C_struct
1169 struct, 0, st_C_struct
1171 typedef, 0, st_C_typedef
1172 define, 0, st_C_define
1173 long, 0, st_C_typespec
1174 short, 0, st_C_typespec
1175 int, 0, st_C_typespec
1176 char, 0, st_C_typespec
1177 float, 0, st_C_typespec
1178 double, 0, st_C_typespec
1179 signed, 0, st_C_typespec
1180 unsigned, 0, st_C_typespec
1181 auto, 0, st_C_typespec
1182 void, 0, st_C_typespec
1183 extern, 0, st_C_typespec
1184 static, 0, st_C_typespec
1185 const, 0, st_C_typespec
1186 volatile, 0, st_C_typespec
1188 and replace lines between %< and %> with its output. */
1190 /* C code produced by gperf version 1.8.1 (K&R C version) */
1191 /* Command-line: gperf -c -k1,3 -o -p -r -t */
1194 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
1196 #define MIN_WORD_LENGTH 3
1197 #define MAX_WORD_LENGTH 8
1198 #define MIN_HASH_VALUE 10
1199 #define MAX_HASH_VALUE 62
1202 53 is the maximum key range
1210 static unsigned char hash_table
[] =
1212 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1213 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1214 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1215 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1216 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1217 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1218 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1219 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1220 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1221 62, 62, 62, 62, 62, 62, 62, 2, 62, 7,
1222 6, 9, 15, 30, 62, 24, 62, 62, 1, 24,
1223 7, 27, 13, 62, 19, 26, 18, 27, 1, 62,
1224 62, 62, 62, 62, 62, 62, 62, 62,
1226 return len
+ hash_table
[str
[2]] + hash_table
[str
[0]];
1229 struct C_stab_entry
*
1230 in_word_set (str
, len
)
1235 static struct C_stab_entry wordlist
[] =
1237 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1239 {"volatile", 0, st_C_typespec
},
1241 {"long", 0, st_C_typespec
},
1242 {"char", 0, st_C_typespec
},
1243 {"class", C_PLPL
, st_C_struct
},
1244 {"",}, {"",}, {"",}, {"",},
1245 {"const", 0, st_C_typespec
},
1246 {"",}, {"",}, {"",}, {"",},
1247 {"auto", 0, st_C_typespec
},
1249 {"define", 0, st_C_define
},
1251 {"void", 0, st_C_typespec
},
1252 {"",}, {"",}, {"",},
1253 {"extern", 0, st_C_typespec
},
1254 {"static", 0, st_C_typespec
},
1256 {"domain", C_STAR
, st_C_struct
},
1258 {"typedef", 0, st_C_typedef
},
1259 {"double", 0, st_C_typespec
},
1260 {"enum", 0, st_C_enum
},
1261 {"",}, {"",}, {"",}, {"",},
1262 {"int", 0, st_C_typespec
},
1264 {"float", 0, st_C_typespec
},
1265 {"",}, {"",}, {"",},
1266 {"struct", 0, st_C_struct
},
1267 {"",}, {"",}, {"",}, {"",},
1268 {"union", 0, st_C_struct
},
1270 {"short", 0, st_C_typespec
},
1272 {"unsigned", 0, st_C_typespec
},
1273 {"signed", 0, st_C_typespec
},
1276 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
1278 register int key
= hash (str
, len
);
1280 if (key
<= MAX_HASH_VALUE
&& key
>= MIN_HASH_VALUE
)
1282 register char *s
= wordlist
[key
].name
;
1284 if (*s
== *str
&& strneq (str
+ 1, s
+ 1, len
- 1))
1285 return &wordlist
[key
];
1293 C_symtype(str
, len
, c_ext
)
1298 register struct C_stab_entry
*se
= in_word_set(str
, len
);
1300 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
1306 * C functions are recognized using a simple finite automaton.
1307 * funcdef is its state variable.
1311 fnone
, /* nothing seen */
1312 ftagseen
, /* function-like tag seen */
1313 fstartlist
, /* just after open parenthesis */
1314 finlist
, /* in parameter list */
1315 flistseen
, /* after parameter list */
1316 fignore
/* before open brace */
1321 /* typedefs are recognized using a simple finite automaton.
1322 * typeddef is its state variable.
1326 tnone
, /* nothing seen */
1327 ttypedseen
, /* typedef keyword seen */
1328 tinbody
, /* inside typedef body */
1329 tend
/* just before typedef tag */
1334 /* struct tags for C++ are recognized using another simple
1335 * finite automaton. `structdef' is its state variable.
1336 * This machinery is only invoked for C++; otherwise structdef
1337 * should remain snone. However, this machinery can easily be
1338 * adapted to find structure tags in normal C code.
1342 snone
, /* nothing seen yet */
1343 skeyseen
, /* struct-like keyword seen */
1344 stagseen
, /* struct-like tag seen */
1345 scolonseen
, /* colon seen after struct-like tag */
1346 sinbody
/* in struct body: recognize member func defs*/
1350 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1351 * struct tag, and structtype is the type of the preceding struct-like
1354 char structtag
[BUFSIZ
];
1355 enum sym_type structtype
;
1358 * Yet another little state machine to deal with preprocessor lines.
1362 dnone
, /* nothing seen */
1363 dsharpseen
, /* '#' seen as first char on line */
1364 ddefineseen
, /* '#' and 'define' seen */
1365 dignorerest
/* ignore rest of line */
1370 * Set this to TRUE, and the next token considered is called a function.
1371 * Used only for GNUmacs's function-defining macros.
1373 logical next_token_is_func
;
1376 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1382 * This routine finds functions, typedefs, #define's and
1383 * struct/union/enum definitions in C syntax and adds them
1387 #define curlb (lbs[curndx].lb)
1388 #define othlb (lbs[1-curndx].lb)
1389 #define newlb (lbs[newndx].lb)
1390 #define curlinepos (lbs[curndx].linepos)
1391 #define othlinepos (lbs[1-curndx].linepos)
1392 #define newlinepos (lbs[newndx].linepos)
1394 /* Save and restore token state. This is used when preprocessor defines
1395 are handled, to avoid disturbing active function/typedef/struct states. */
1396 #define TOKEN_SAVED_P (savetok.lineno > 0)
1397 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1398 savetok.len = toklen, strcpy(savenameb, nameb))
1399 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1400 toklen = tok.len, strcpy(nameb, savenameb), \
1403 #define CNL_SAVE_DEFINEDEF \
1405 SET_FILEPOS (curlinepos, inf, charno); \
1407 charno += readline (&curlb, inf); \
1408 lp = curlb.buffer; \
1415 CNL_SAVE_DEFINEDEF; \
1416 if (TOKEN_SAVED_P) \
1418 definedef = dnone; \
1421 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1422 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1423 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1424 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1428 int c_ext
; /* extension of C? */
1430 register char c
; /* latest char read; '\0' for end of line */
1431 register char *lp
; /* pointer one beyond the character `c' */
1432 int curndx
, newndx
; /* indices for current and new lb */
1433 TOKEN tok
; /* latest token read for funcdef & structdef */
1434 char nameb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1435 register int tokoff
; /* offset in line of start of latest token */
1436 register int toklen
; /* length of latest token */
1437 int cblev
; /* current curly brace level */
1438 int parlev
; /* current parenthesis level */
1439 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1441 TOKEN savetok
; /* saved token during preprocessor handling */
1442 char savenameb
[BUFSIZ
]; /* ouch! */
1445 curndx
= newndx
= 0;
1451 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1452 next_token_is_func
= yacc_rules
= FALSE
;
1453 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1456 cplpl
= c_ext
& C_PLPL
;
1463 /* If we're at the end of the line, the next character is a
1464 '\0'; don't skip it, because it's the thing that tells us
1465 to read the next line. */
1486 /* Newlines inside comments do not end macro definitions in
1501 /* Newlines inside strings do not end macro definitions
1502 in traditional cpp, even though compilers don't
1503 usually accept them. */
1514 /* Hmmm, something went wrong. */
1528 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1533 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1543 else if (cplpl
&& *lp
== '/')
1551 if ((c_ext
& YACC
) && *lp
== '%')
1553 /* entering or exiting rules section in yacc file */
1555 definedef
= dnone
; funcdef
= fnone
;
1556 typdef
= tnone
; structdef
= snone
;
1557 next_token_is_func
= FALSE
;
1558 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1560 yacc_rules
= !yacc_rules
;
1566 if (lp
== newlb
.buffer
+ 1 && definedef
== dnone
)
1567 definedef
= dsharpseen
;
1572 /* Consider token only if some complicated conditions are satisfied. */
1573 if (((cblev
== 0 && structdef
!= scolonseen
)
1574 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
1575 && definedef
!= dignorerest
1576 && (funcdef
!= finlist
1577 || (definedef
!= dnone
&& definedef
!= dignorerest
)))
1583 if (cplpl
&& c
== ':' && *lp
== ':' && begtoken(*(lp
+ 1)))
1586 * This handles :: in the middle, but not at beginning
1594 logical is_func
= FALSE
;
1596 tok
.lineno
= lineno
;
1597 tok
.p
= newlb
.buffer
+ tokoff
;
1601 || consider_token (c
, &tok
, c_ext
, cblev
, &is_func
))
1603 if (structdef
== sinbody
1604 && definedef
== dnone
1606 /* function defined in C++ class body */
1609 sprintf (nameb
, "%s::%.*s",
1610 ((structtag
[0] == '\0')
1611 ? "_anonymous_" : structtag
),
1616 sprintf (nameb
, "%.*s", tok
.len
, tok
.p
);
1619 if (structdef
== stagseen
1623 if (definedef
== dnone
1624 && (funcdef
== ftagseen
1625 || structdef
== stagseen
1628 if (newndx
== curndx
)
1629 curndx
= 1 - curndx
; /* switch line buffers */
1632 MAKE_TAG_FROM_NEW_LB (is_func
);
1636 } /* if (endtoken (c)) */
1637 else if (intoken (c
))
1642 } /* if (midtoken) */
1643 else if (begtoken (c
))
1654 MAKE_TAG_FROM_OTH_LB (TRUE
);
1661 if (structdef
== stagseen
)
1665 /* Take a quick peek ahead for define directive,
1666 so we can avoid saving the token when not absolutely
1667 necessary. [This is a speed hack.] */
1668 if (c
== 'd' && strneq(lp
, "efine", 5)
1669 && iswhite(*(lp
+ 5)))
1672 definedef
= ddefineseen
;
1676 definedef
= dignorerest
;
1679 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1681 tokoff
= lp
- 1 - newlb
.buffer
;
1687 } /* if must look at token */
1690 /* Detect end of line, colon, comma, semicolon and various braces
1691 after having handled a token.*/
1695 if (definedef
!= dnone
)
1697 if (structdef
== stagseen
)
1698 structdef
= scolonseen
;
1705 MAKE_TAG_FROM_OTH_LB (FALSE
);
1715 if (definedef
!= dnone
)
1717 if (cblev
== 0 && typdef
== tend
)
1720 MAKE_TAG_FROM_OTH_LB (FALSE
);
1722 if (funcdef
!= fignore
)
1728 if (definedef
!= dnone
)
1730 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1732 if (structdef
== stagseen
)
1736 if (definedef
!= dnone
)
1741 funcdef
= fstartlist
;
1750 if (definedef
!= dnone
)
1758 funcdef
= flistseen
;
1762 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
1766 if (definedef
!= dnone
)
1768 if (typdef
== ttypedseen
)
1772 case skeyseen
: /* unnamed struct */
1773 structtag
[0] = '\0';
1774 structdef
= sinbody
;
1777 case scolonseen
: /* named struct */
1778 structdef
= sinbody
;
1779 MAKE_TAG_FROM_OTH_LB (FALSE
);
1785 MAKE_TAG_FROM_OTH_LB (TRUE
);
1793 if (definedef
!= dnone
)
1795 if (funcdef
== fstartlist
)
1796 funcdef
= fnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
1799 if (definedef
!= dnone
)
1801 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
1803 cblev
= 0; /* reset curly brace level if first column */
1804 parlev
= 0; /* also reset paren level, just in case... */
1810 if (typdef
== tinbody
)
1813 strcpy (structtag
, "<error 2>");
1817 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
1818 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
1819 if (definedef
!= dnone
)
1821 /* These surely cannot follow a function tag. */
1822 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1826 /* If a macro spans multiple lines don't reset its state. */
1834 } /* while not eof */
1839 * checks to see if the current token is at the start of a
1840 * function, or corresponds to a typedef, or is a struct/union/enum
1843 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1844 * C_EXT is which language we are looking at.
1846 * In the future we will need some way to adjust where the end of
1847 * the token is; for instance, implementing the C++ keyword
1848 * `operator' properly will adjust the end of the token to be after
1849 * whatever follows `operator'.
1856 * next_token_is_func IN OUT
1860 consider_token (c
, tokp
, c_ext
, cblev
, is_func
)
1861 register char c
; /* IN: first char after the token */
1862 register TOKEN
*tokp
; /* IN: token pointer */
1863 int c_ext
; /* IN: C extensions mask */
1864 int cblev
; /* IN: curly brace level */
1865 logical
*is_func
; /* OUT */
1867 enum sym_type toktype
= C_symtype(tokp
->p
, tokp
->len
, c_ext
);
1870 * Advance the definedef state machine.
1875 /* We're not on a preprocessor line. */
1878 if (toktype
== st_C_define
)
1880 definedef
= ddefineseen
;
1884 definedef
= dignorerest
;
1889 * Make a tag for any macro.
1891 definedef
= dignorerest
;
1892 *is_func
= (c
== '(');
1893 if (!*is_func
&& !constantypedefs
)
1900 error ("internal error: definedef value.", 0);
1909 if (toktype
== st_C_typedef
)
1912 typdef
= ttypedseen
;
1927 /* Do not return here, so the structdef stuff has a chance. */
1941 * This structdef business is currently only invoked when cblev==0.
1942 * It should be recursively invoked whatever the curly brace level,
1943 * and a stack of states kept, to allow for definitions of structs
1946 * This structdef business is NOT invoked when we are ctags and the
1947 * file is plain C. This is because a struct tag may have the same
1948 * name as another tag, and this loses with ctags.
1950 * This if statement deals with the typdef state machine as
1951 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1952 * return (FALSE). All the other code here is for the structdef
1959 if (typdef
== ttypedseen
1960 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1962 structdef
= skeyseen
;
1963 structtype
= toktype
;
1967 if (structdef
== skeyseen
)
1969 if (structtype
== st_C_struct
)
1971 strncpy (structtag
, tokp
->p
, tokp
->len
);
1972 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1976 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1978 structdef
= stagseen
;
1982 /* Avoid entering funcdef stuff if typdef is going on. */
1983 if (typdef
!= tnone
)
1989 /* Detect GNUmacs's function-defining macros. */
1990 if (definedef
== dnone
)
1992 if (strneq (tokp
->p
, "DEF", 3)
1993 || strneq (tokp
->p
, "ENTRY", 5)
1994 || strneq (tokp
->p
, "SYSCALL", 7)
1995 || strneq (tokp
->p
, "PSEUDO", 6))
1997 next_token_is_func
= TRUE
;
2000 if (strneq (tokp
->p
, "EXFUN", 5))
2002 next_token_is_func
= FALSE
;
2006 if (next_token_is_func
)
2008 next_token_is_func
= FALSE
;
2010 *is_func
= TRUE
; /* to force search string in ctags */
2018 funcdef
= fnone
; /* should be useless */
2021 if (funcdef
== fnone
)
2032 /* Fortran parsing */
2048 linecharno
= charno
;
2049 charno
+= readline (&lb
, fi
);
2052 dbp
++; /* Ratfor escape to fortran */
2053 while (isspace (*dbp
))
2060 if (tail ("integer"))
2068 if (tail ("logical"))
2072 if (tail ("complex") || tail ("character"))
2076 if (tail ("double"))
2078 while (isspace (*dbp
))
2082 if (tail ("precision"))
2088 while (isspace (*dbp
))
2095 if (tail ("function"))
2099 if (tail ("subroutine"))
2107 if (tail ("program"))
2112 if (tail ("procedure"))
2124 register int len
= 0;
2126 while (*cp
&& (*cp
| ' ') == (dbp
[len
] | ' '))
2139 while (isspace (*dbp
))
2144 while (isspace (*dbp
))
2146 if (!isdigit (*dbp
))
2148 --dbp
; /* force failure */
2153 while (isdigit (*dbp
));
2162 char nambuf
[BUFSIZ
];
2164 while (isspace (*dbp
))
2169 linecharno
= charno
;
2170 charno
+= readline (&lb
, fi
);
2175 while (isspace (*dbp
))
2184 && (isalpha (*cp
) || isdigit (*cp
) || (*cp
== '_') || (*cp
== '$')));
2189 strcpy (nambuf
, dbp
);
2191 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2192 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2196 /* Handle a file of assembler code. */
2212 linecharno
= charno
;
2213 charno
+= readline (&lb
, fi
);
2216 for (i
= 0; ((c
= dbp
[i
]) && !isspace (c
)) && (c
!= ':'); i
++)
2219 if ((i
> 0) && (c
== ':'))
2224 /* Added by Mosur Mohan, 4/22/88 */
2225 /* Pascal parsing */
2227 #define GET_NEW_LINE \
2229 linecharno = charno; lineno++; \
2230 charno += 1 + readline (&lb, inf); \
2234 /* Locates tags for procedures & functions.
2235 * Doesn't do any type- or var-definitions.
2236 * It does look for the keyword "extern" or "forward"
2237 * immediately following the procedure statement;
2238 * if found, the tag is skipped.
2245 struct linebuffer tline
; /* mostly copied from C_entries */
2249 char nambuf
[BUFSIZ
];
2251 logical
/* each of these flags is TRUE iff: */
2252 incomm1
, /* point is inside {..} comment */
2253 incomm2
, /* point is inside (*..*) comment */
2254 inquote
, /* point is inside '..' string */
2255 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2256 /* keyword, so next item = potential tag */
2257 found_tag
, /* point is after a potential tag */
2258 inparms
, /* point is within parameter-list */
2259 verify_tag
; /* point has passed the parm-list, so the */
2260 /* next token will determine whether */
2261 /* this is a FORWARD/EXTERN to be */
2262 /* ignored, or whether it is a real tag */
2268 initbuffer (&tline
);
2270 incomm1
= incomm2
= inquote
= FALSE
;
2271 found_tag
= FALSE
; /* have a proc name; check if extern */
2272 get_tagname
= FALSE
; /* have found "procedure" keyword */
2273 inparms
= FALSE
; /* found '(' after "proc" */
2274 verify_tag
= FALSE
; /* check if "extern" is ahead */
2276 /* long main loop to get next char */
2280 if (c
== 0) /* if end of line */
2285 if (!((found_tag
&& verify_tag
) ||
2287 c
= *dbp
++; /* only if don't need *dbp pointing */
2288 /* to the beginning of the name of */
2289 /* the procedure or function */
2291 if (incomm1
) /* within { - } comments */
2297 else if (incomm2
) /* within (* - *) comments */
2301 while ((c
= *dbp
++) == '*')
2320 inquote
= TRUE
; /* found first quote */
2322 case '{': /* found open-{-comment */
2326 if (*dbp
== '*') /* found open-(*-comment */
2331 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2334 case ')': /* end of parms list */
2339 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2346 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2348 /* check if this is an "extern" declaration */
2351 if ((*dbp
== 'e') || (*dbp
== 'E'))
2353 if (tail ("extern")) /* superfluous, really! */
2359 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2361 if (tail ("forward")) /* check for forward reference */
2367 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2371 pfnote (nambuf
, TRUE
, FALSE
,
2372 tline
.buffer
, cp
- tline
.buffer
+ 1,
2373 save_lineno
, save_lcno
);
2377 if (get_tagname
) /* grab name of proc or fn */
2382 /* save all values for later tagging */
2383 tline
.size
= lb
.size
;
2384 strcpy (tline
.buffer
, lb
.buffer
);
2385 save_lineno
= lineno
;
2386 save_lcno
= linecharno
;
2388 /* grab block name */
2389 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2393 strcpy (nambuf
, dbp
);
2395 dbp
= cp
; /* restore dbp to e-o-token */
2396 get_tagname
= FALSE
;
2400 /* and proceed to check for "extern" */
2402 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2403 (!found_tag
) && (!get_tagname
))
2405 /* check for proc/fn keywords */
2409 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2413 if (tail ("unction"))
2418 } /* while not e-o-f */
2422 * lisp tag functions
2423 * just look for (def or (DEF
2437 linecharno
= charno
;
2438 charno
+= readline (&lb
, fi
);
2444 while (!isspace (*dbp
))
2446 while (isspace (*dbp
))
2452 /* Check for (foo::defmumble name-defined ... */
2455 while (*dbp
&& !isspace (*dbp
)
2456 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2461 while (*dbp
== ':');
2463 if (L_isdef (dbp
- 1))
2465 while (!isspace (*dbp
))
2467 while (isspace (*dbp
))
2481 return ((dbp
[1] == 'd' || dbp
[1] == 'D')
2482 && (dbp
[2] == 'e' || dbp
[2] == 'E')
2483 && (dbp
[3] == 'f' || dbp
[3] == 'F'));
2490 return ((*(++dbp
) == 'q' || *dbp
== 'Q')
2491 && (*(++dbp
) == 'u' || *dbp
== 'U')
2492 && (*(++dbp
) == 'o' || *dbp
== 'O')
2493 && (*(++dbp
) == 't' || *dbp
== 'T')
2494 && (*(++dbp
) == 'e' || *dbp
== 'E')
2495 && isspace(*(++dbp
)));
2503 char nambuf
[BUFSIZ
];
2505 if (*dbp
== '\'') /* Skip prefix quote */
2507 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2510 while (isspace(*dbp
))
2513 for (cp
= dbp
/*+1*/; *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')'; cp
++)
2520 strcpy (nambuf
, dbp
);
2522 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2523 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2528 * Scheme tag functions
2529 * look for (def... xyzzy
2530 * look for (def... (xyzzy
2531 * look for (def ... ((...(xyzzy ....
2532 * look for (set! xyzzy
2535 static void get_scheme ();
2548 linecharno
= charno
;
2549 charno
+= readline (&lb
, fi
);
2551 if (dbp
[0] == '(' &&
2552 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2553 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2554 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2556 while (!isspace (*dbp
))
2558 /* Skip over open parens and white space */
2559 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2563 if (dbp
[0] == '(' &&
2564 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2565 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2566 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2567 (dbp
[4] == '!' || dbp
[4] == '!') &&
2570 while (!isspace (*dbp
))
2572 /* Skip over white space */
2573 while (isspace (*dbp
))
2585 char nambuf
[BUFSIZ
];
2589 /* Go till you get to white space or a syntactic break */
2590 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2592 /* Null terminate the string there. */
2595 /* Copy the string */
2596 strcpy (nambuf
, dbp
);
2597 /* Unterminate the string */
2599 /* Announce the change */
2600 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2604 /* Find tags in TeX and LaTeX input files. */
2606 /* TEX_toktab is a table of TeX control sequences that define tags.
2607 Each TEX_tabent records one such control sequence.
2608 CONVERT THIS TO USE THE Stab TYPE!! */
2616 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2618 /* Default set of control sequences to put into TEX_toktab.
2619 The value of environment var TEXTAGS is prepended to this. */
2621 static char *TEX_defenv
=
2622 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2625 struct TEX_tabent
*TEX_decode_env ();
2629 static char TEX_esc
= '\\';
2630 static char TEX_opgrp
= '{';
2631 static char TEX_clgrp
= '}';
2634 * TeX/LaTeX scanning loop.
2647 /* Select either \ or ! as escape character. */
2650 /* Initialize token table once from environment. */
2652 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2655 { /* Scan each line in file */
2657 linecharno
= charno
;
2658 charno
+= readline (&lb
, fi
);
2661 while (dbp
= etags_index (dbp
, TEX_esc
)) /* Look at each escape in line */
2667 linecharno
+= dbp
- lasthit
;
2669 i
= TEX_Token (lasthit
);
2672 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2673 break; /* We only save a line once */
2679 #define TEX_LESC '\\'
2680 #define TEX_SESC '!'
2683 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2684 /* chars accordingly. */
2692 while ((c
= getc (f
)) != EOF
)
2694 /* Skip to next line if we hit the TeX comment char. */
2698 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2717 /* Read environment and prepend it to the default string. */
2718 /* Build token table. */
2721 TEX_decode_env (evarname
, defenv
)
2725 register char *env
, *p
;
2727 struct TEX_tabent
*tab
;
2730 /* Append default string to environment. */
2731 env
= getenv (evarname
);
2735 env
= concat (env
, defenv
, "");
2737 /* Allocate a token table */
2738 for (size
= 1, p
= env
; p
;)
2739 if ((p
= etags_index (p
, ':')) && *(++p
))
2741 /* Add 1 to leave room for null terminator. */
2742 tab
= xnew (size
+ 1, struct TEX_tabent
);
2744 /* Unpack environment string into token table. Be careful about */
2745 /* zero-length strings (leading ':', "::" and trailing ':') */
2748 p
= etags_index (env
, ':');
2749 if (!p
) /* End of environment string. */
2750 p
= env
+ strlen (env
);
2752 { /* Only non-zero strings. */
2753 tab
[i
].name
= savenstr (env
, p
- env
);
2754 tab
[i
].len
= strlen (tab
[i
].name
);
2761 tab
[i
].name
= NULL
; /* Mark end of table. */
2769 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2770 The name being defined actually starts at (NAME + LEN + 1).
2771 But we seem to include the TeX command in the tag name. */
2774 TEX_getit (name
, len
)
2778 char *p
= name
+ len
;
2779 char nambuf
[BUFSIZ
];
2784 /* Let tag name extend to next group close (or end of line) */
2785 while (*p
&& *p
!= TEX_clgrp
)
2787 strncpy (nambuf
, name
, p
- name
);
2788 nambuf
[p
- name
] = 0;
2790 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2794 /* If the text at CP matches one of the tag-defining TeX command names,
2795 return the etags_index of that command in TEX_toktab.
2796 Otherwise return -1. */
2798 /* Keep the capital `T' in `Token' for dumb truncating compilers
2799 (this distinguishes it from `TEX_toktab' */
2806 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2807 if (strneq (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
))
2812 /* Support for Prolog. */
2814 /* whole head (not only functor, but also arguments)
2815 is gotten in compound term. */
2818 prolog_getit (s
, lineno
, linecharno
)
2823 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2831 if (*s
== '\0') /* syntax error. */
2833 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2835 else if (*s
== '\'')
2837 insquote
= !insquote
;
2840 else if (!insquote
&& *s
== '(')
2845 else if (!insquote
&& *s
== ')')
2851 else if (npar
< 0) /* syntax error. */
2854 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2856 if (npar
!= 0) /* syntax error. */
2866 strcpy (nambuf
, save_s
);
2868 pfnote (nambuf
, TRUE
, FALSE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2871 /* It is assumed that prolog predicate starts from column 0. */
2877 void skip_comment (), prolog_getit ();
2879 lineno
= linecharno
= charno
= 0;
2883 linecharno
+= charno
;
2884 charno
= readline (&lb
, fi
) + 1; /* 1 for newline. */
2886 if (isspace (dbp
[0])) /* not predicate header. */
2888 else if (dbp
[0] == '%') /* comment. */
2890 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2891 skip_comment (&lb
, fi
, &lineno
, &linecharno
);
2893 prolog_getit (dbp
, lineno
, linecharno
);
2898 skip_comment (plb
, fi
, plineno
, plinecharno
)
2899 struct linebuffer
*plb
;
2901 int *plineno
; /* result */
2902 long *plinecharno
; /* result */
2904 while (!substr ("*/", plb
->buffer
))
2907 *plinecharno
+= readline (plb
, fi
) + 1;
2908 } /* 1 for newline. */
2911 /* Return TRUE if 'sub' exists somewhere in 's'. */
2918 while (*s
&& (s
= etags_index (s
, *sub
)))
2919 if (prestr (sub
, s
))
2926 /* Return TRUE if 'pre' is prefix of string 's'. */
2935 else if (*pre
== *s
)
2936 return (prestr (pre
+ 1, s
+ 1));
2941 /* Initialize a linebuffer for use */
2944 initbuffer (linebuffer
)
2945 struct linebuffer
*linebuffer
;
2947 linebuffer
->size
= 200;
2948 linebuffer
->buffer
= xnew (200, char);
2952 * Read a line of text from `stream' into `linebuffer'.
2953 * Return the number of characters read from `stream',
2954 * which is the length of the line including the newline, if any.
2957 readline (linebuffer
, stream
)
2958 struct linebuffer
*linebuffer
;
2959 register FILE *stream
;
2961 char *buffer
= linebuffer
->buffer
;
2962 register char *p
= linebuffer
->buffer
;
2963 register char *pend
;
2964 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2966 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
2970 register int c
= getc (stream
);
2973 linebuffer
->size
*= 2;
2974 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
2975 p
+= buffer
- linebuffer
->buffer
;
2976 pend
= buffer
+ linebuffer
->size
;
2977 linebuffer
->buffer
= buffer
;
2979 if (c
== EOF
|| c
== '\n')
2982 newline
= (c
== '\n') ? 1 : 0;
2988 return p
- buffer
+ newline
;
2995 return savenstr (cp
, strlen (cp
));
3005 dp
= xnew (len
+ 1, char);
3006 strncpy (dp
, cp
, len
);
3012 * Return the ptr in sp at which the character c last
3013 * appears; NULL if not found
3015 * Identical to v7 rindex, included for portability.
3019 etags_rindex (sp
, c
)
3020 register char *sp
, c
;
3035 * Return the ptr in sp at which the character c first
3036 * appears; NULL if not found
3038 * Identical to v7 index, included for portability.
3043 register char *sp
, c
;
3053 /* Print error message and exit. */
3064 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3071 fprintf (stderr
, "%s: ", progname
);
3072 fprintf (stderr
, s1
, s2
);
3073 fprintf (stderr
, "\n");
3076 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
3082 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3083 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3085 strcpy (result
, s1
);
3086 strcpy (result
+ len1
, s2
);
3087 strcpy (result
+ len1
+ len2
, s3
);
3088 *(result
+ len1
+ len2
+ len3
) = 0;
3093 /* Like malloc but get fatal error if memory is exhausted. */
3099 char *result
= (char *) malloc (size
);
3101 fatal ("virtual memory exhausted", 0);
3106 xrealloc (ptr
, size
)
3110 char *result
= (char *) realloc (ptr
, size
);
3112 fatal ("virtual memory exhausted");