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.6
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 *malloc (), *realloc ();
51 extern char *getenv ();
52 extern char *strcpy (), *strncpy ();
55 char *etags_index (), *etags_rindex ();
58 /* Define the symbol ETAGS to make the program "etags",
59 which makes emacs-style tag tables by default.
60 Define CTAGS to make the program "ctags" compatible with the usual one.
61 Define neither one to get behavior that depends
62 on the name with which the program is invoked
63 (but we don't normally compile it that way). */
65 #if !defined(ETAGS) && !defined(CTAGS)
66 /* If neither is defined, program can be run as either. */
71 /* On VMS, CTAGS is not useful, so always do ETAGS. */
78 /* Exit codes for success and failure. */
88 * The FILEPOS abstract type, which represents a position in a file,
89 * plus the following accessor functions:
91 * long GET_CHARNO (pos)
92 * returns absolute char number.
93 * void SET_FILEPOS (pos, fp, charno)
94 * FILE *fp; long charno;
95 * sets `pos' from the current file
96 * position of `fp' and from `charno',
97 * which must be the absolute character
98 * number corresponding to the current
101 * The `pos' parameter is an lvalue expression of type FILEPOS.
102 * Parameters to the accessor functions are evaluated 0 or more times,
103 * and so must have no side effects.
105 * FILEPOS objects can also be assigned and passed to and from
106 * functions in the normal C manner.
108 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
112 /* real implementation */
113 typedef long FILEPOS
;
114 #define GET_CHARNO(pos) ((pos) + 0)
115 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
117 /* debugging implementation */
123 #define GET_CHARNO(pos) ((pos).charno + 0)
124 #define SET_FILEPOS(pos, fp, cno) \
125 ((void) ((pos).charno = (cno), \
126 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
130 #define streq(s, t) (strcmp (s, t) == 0)
131 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
137 #define iswhite(arg) (_wht[arg]) /* T if char is white */
138 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
139 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
140 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
142 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
145 { /* sorting structure */
146 char *name
; /* function or type name */
147 char *file
; /* file name */
148 logical is_func
; /* use pattern or line no */
149 logical named
; /* list name separately */
150 logical been_warned
; /* set if noticed dup */
151 int lno
; /* line number tag is on */
152 long cno
; /* character number line starts on */
153 char *pat
; /* search pattern */
154 struct nd_st
*left
, *right
; /* left and right sons */
158 typedef struct nd_st NODE
;
160 logical header_file
; /* TRUE if .h file, FALSE o.w. */
161 /* boolean "functions" (see init) */
162 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
170 int L_isdef (), L_isquote ();
172 int total_size_of_entries ();
173 logical
consider_token ();
181 void Scheme_funcs ();
186 logical
find_entries ();
193 void process_file ();
199 * xnew -- allocate storage
202 * Type *xnew (int n, Type);
204 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
207 * Symbol table types.
211 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
228 #define C_PLPL 0x00001 /* C++ */
229 #define C_STAR 0x00003 /* C* */
230 #define YACC 0x10000 /* yacc file */
232 char searchar
= '/'; /* use /.../ searches */
234 LINENO lineno
; /* line number of current line */
235 long charno
; /* current character number */
237 long linecharno
; /* charno of start of line; not used by C, but
238 * by every other language.
241 char *curfile
, /* current input file name */
242 *outfile
, /* output file */
243 *white
= " \f\t\n", /* white chars */
244 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
245 /* token starting chars */
246 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
247 /* valid in-token chars */
248 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
250 int append_to_tagfile
; /* -a: append to tags */
251 int emacs_tags_format
; /* emacs style output (no -e option any more) */
252 /* The following three default to 1 for etags, but to 0 for ctags. */
253 int typedefs
; /* -t: create tags for typedefs */
254 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
255 /* 0 struct/enum/union decls, and C++ */
256 /* member functions */
257 int constantypedefs
; /* -d: create tags for C #define and enum */
258 /* constants. Default under etags. Enum */
259 /* constants not implemented. */
260 /* -D: opposite of -d. Default under ctags. */
261 int update
; /* -u: update tags */
262 int vgrind_style
; /* -v: create vgrind style index output */
263 int no_warnings
; /* -w: suppress warnings */
264 int cxref_style
; /* -x: create cxref style output */
265 int cplusplus
; /* .[hc] means C++, not C */
266 int noindentypedefs
; /* -S: ignore indentation in C */
268 /* Name this program was invoked with. */
271 struct option longopts
[] = {
272 { "append", no_argument
, NULL
, 'a' },
273 { "backward-search", no_argument
, NULL
, 'B' },
274 { "c++", no_argument
, NULL
, 'C' },
275 { "cxref", no_argument
, NULL
, 'x' },
276 { "defines", no_argument
, NULL
, 'd' },
277 { "forward-search", no_argument
, NULL
, 'F' },
278 { "help", no_argument
, NULL
, 'H' },
279 { "ignore-indentation", no_argument
, NULL
, 'S' },
280 { "include", required_argument
, NULL
, 'i' },
281 { "no-defines", no_argument
, NULL
, 'D' },
282 { "no-warn", no_argument
, NULL
, 'w' },
283 { "output", required_argument
, NULL
, 'o' },
284 { "typedefs", no_argument
, NULL
, 't' },
285 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
286 { "update", no_argument
, NULL
, 'u' },
287 { "version", no_argument
, NULL
, 'V' },
288 { "vgrind", no_argument
, NULL
, 'v' },
292 FILE *inf
, /* ioptr for current input file */
293 *outf
; /* ioptr for tags file */
295 NODE
*head
; /* the head of the binary tree of tags */
297 int permit_duplicates
= 1; /* Nonzero means allow duplicate tags. */
299 /* A `struct linebuffer' is a structure which holds a line of text.
300 `readline' reads a line from a stream into a linebuffer
301 and works regardless of the length of the line. */
309 struct linebuffer lb
; /* the current line */
310 struct linebuffer filename_lb
; /* used to read in filenames */
314 struct linebuffer lb
; /* used by C_entries instead of lb */
329 printf ("for Emacs version 19.\n");
337 printf ("These are the options accepted by %s. You may use unambiguous\n\
338 abbreviations for the long option names.\n\n", progname
);
340 puts ("-a, --append\n\
341 Append tag entries to existing tags file.");
343 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
344 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
345 extensions are always assumed to be C++ code.");
346 fputs ("-d, --defines\n\
347 Create tag entries for #defines, too.", stdout
);
350 fputs (" This is the default\n\
356 Don't create tag entries for #defines.", stdout
);
359 fputs (" This is the default\n\
364 -o FILE, --output=FILE\n\
365 Write the tags to FILE.\n\
366 -S, --ignore-indentation\n\
367 Don't rely on indentation quite as much as normal. Currently,\n\
368 this means not to assume that a closing brace in the first\n\
369 column is the final brace of a function or structure\n\
371 puts ("-t, --typedefs\n\
372 Generate tag entries for typedefs. This is the default\n\
374 puts ("-T, --typedefs-and-c++\n\
375 Generate tag entries for typedefs, struct/enum/union tags, and\n\
376 C++ member functions.");
379 puts ("-i FILE, --include=FILE\n\
380 Include a note in tag file indicating that, when searching for\n\
381 a tag, one should also consult the tags file FILE after\n\
382 checking the current file.");
386 puts ("-B, --backward-search\n\
387 Write the search commands for the tag entries using '?', the\n\
388 backward-search command.");
389 puts ("-F, --forward-search\n\
390 Write the search commands for the tag entries using '/', the\n\
391 forward-search command.");
392 puts ("-u, --update\n\
393 Update the tag entries for the given files, leaving tag\n\
394 entries for other files in place. Currently, this is\n\
395 implemented by deleting the existing entries for the given\n\
396 files and then rewriting the new entries at the end of the\n\
397 tags file. It is often faster to simply rebuild the entire\n\
398 tag file than to use this.");
399 puts ("-v, --vgrind\n\
400 Generates an index of items intended for human consumption,\n\
401 similar to the output of vgrind. The index is sorted, and\n\
402 gives the page number of each item.");
403 puts ("-x, --cxref\n\
404 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
405 The output uses line numbers instead of page numbers, but\n\
406 beyond that the differences are cosmetic; try both to see\n\
408 puts ("-w, --no-warn\n\
409 Suppress warning messages about entries defined in multiple\n\
413 puts ("-V, --version\n\
414 Print the version of the program.\n\
416 Print this help message.");
429 unsigned int nincluded_files
= 0;
430 char **included_files
= xnew (argc
, char *);
435 extern char *gfnames ();
436 extern char *massage_name ();
440 _fmode
= O_BINARY
; /* all of files are treated as binary files */
446 emacs_tags_format
= 1;
448 emacs_tags_format
= 0;
452 * If etags, always find typedefs and structure tags. Why not?
453 * Also default is to find macro constants.
455 if (emacs_tags_format
)
456 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
461 opt
= getopt_long (argc
, argv
, "aCdDo:f:StTi:BFuvxwVH", longopts
, 0);
469 /* If getopt returns '\0', then it has already processed a
470 long-named option. We should do nothing. */
473 /* Common options. */
491 "%s: -%c flag may only be given once\n", progname
, opt
);
504 typedefs_and_cplusplus
++;
515 if (!emacs_tags_format
)
517 included_files
[nincluded_files
++] = optarg
;
523 if (emacs_tags_format
)
528 if (emacs_tags_format
)
533 if (emacs_tags_format
)
541 if (emacs_tags_format
)
546 if (emacs_tags_format
)
555 if (optind
== argc
&& nincluded_files
== 0)
557 fprintf (stderr
, "%s: No input files specified.\n", progname
);
560 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
567 outfile
= emacs_tags_format
? "TAGS" : "tags";
570 init (); /* set up boolean "functions" */
573 initbuffer (&lbs
[0].lb
);
574 initbuffer (&lbs
[1].lb
);
575 initbuffer (&filename_lb
);
577 * loop through files finding functions
579 if (emacs_tags_format
)
581 if (streq (outfile
, "-"))
584 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
595 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
599 error ("Can't find file %s\n", this_file
);
604 this_file
= massage_name (this_file
);
607 } /* solely to balance out the ifdef'd parens above */
610 for (; optind
< argc
; optind
++)
612 this_file
= argv
[optind
];
614 /* Input file named "-" means read file names from stdin and use them. */
615 if (streq (this_file
, "-"))
617 while (!feof (stdin
))
619 (void) readline (&filename_lb
, stdin
);
620 if (strlen (filename_lb
.buffer
) > 0)
621 process_file (filename_lb
.buffer
);
625 process_file (this_file
);
628 if (emacs_tags_format
)
630 while (nincluded_files
-- > 0)
631 fprintf (outf
, "\f\n%s,include\n", *included_files
++);
633 (void) fclose (outf
);
644 /* update cannot be set under VMS, so we may assume that argc
645 and argv have not been munged. */
646 for (i
= optind
; i
< argc
; i
++)
649 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
650 outfile
, argv
[i
], outfile
);
655 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
662 (void) fclose (outf
);
665 sprintf (cmd
, "sort %s -o %s", outfile
, outfile
);
673 * This routine is called on each file argument.
679 struct stat stat_buf
;
681 if (stat (file
, &stat_buf
) == 0 && !S_ISREG (stat_buf
.st_mode
))
683 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
686 if (streq (file
, outfile
) && !streq (outfile
, "-"))
688 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
691 if (!find_entries (file
))
695 if (emacs_tags_format
)
697 fprintf (outf
, "\f\n%s,%d\n", file
, total_size_of_entries (head
));
705 * This routine sets up the boolean pseudo-functions which work
706 * by setting boolean flags dependent upon the corresponding character
707 * Every char which is NOT in that string is not a white char. Therefore,
708 * all of the array "_wht" is set to FALSE, and then the elements
709 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
710 * of a char is TRUE if it is the string "white", else FALSE.
718 for (i
= 0; i
< 0177; i
++)
719 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
720 for (sp
= white
; *sp
; sp
++)
722 for (sp
= endtk
; *sp
; sp
++)
724 for (sp
= intk
; *sp
; sp
++)
726 for (sp
= begtk
; *sp
; sp
++)
728 _wht
[0] = _wht
['\n'];
729 _etk
[0] = _etk
['\n'];
730 _btk
[0] = _btk
['\n'];
731 _itk
[0] = _itk
['\n'];
735 * This routine opens the specified file and calls the function
736 * which finds the function and type definitions.
743 void prolog_funcs ();
745 inf
= fopen (file
, "r");
751 curfile
= savestr (file
);
752 cp
= etags_rindex (file
, '.');
754 header_file
= (cp
&& (streq (cp
+ 1, "h")));
756 /* .tex, .aux or .bbl implies LaTeX source code */
757 if (cp
&& (streq (cp
+ 1, "tex") || streq (cp
+ 1, "aux")
758 || streq (cp
+ 1, "bbl")))
761 goto close_and_return
;
763 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
764 if (cp
&& (streq (cp
+ 1, "l")
765 || streq (cp
+ 1, "el")
766 || streq (cp
+ 1, "lsp")
767 || streq (cp
+ 1, "lisp")
768 || streq (cp
+ 1, "cl")
769 || streq (cp
+ 1, "clisp")))
772 goto close_and_return
;
774 /* .scm or .sm or .scheme or ... implies scheme source code */
775 if (cp
&& (streq (cp
+ 1, "sm")
776 || streq (cp
+ 1, "scm")
777 || streq (cp
+ 1, "scheme")
778 || streq (cp
+ 1, "t")
779 || streq (cp
+ 1, "sch")
780 || streq (cp
+ 1, "SM")
781 || streq (cp
+ 1, "SCM")
782 /* The `SCM' or `scm' prefix with a version number */
783 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
784 && string_numeric_p (cp
+ 1))
785 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
786 && string_numeric_p (cp
+ 1))))
789 goto close_and_return
;
791 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
793 if (cp
&& (streq (cp
+ 1, "s")
794 || streq (cp
+ 1, "a")
795 || streq (cp
+ 1, "sa")))
798 goto close_and_return
;
800 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
801 if (cp
&& (streq (cp
+ 1, "C")
802 || streq (cp
+ 1, "H")
803 || streq (cp
+ 1, "cxx")
804 || streq (cp
+ 1, "hxx")
805 || streq (cp
+ 1, "cc")))
807 C_entries (C_PLPL
); /* C++ */
808 goto close_and_return
;
810 /* .cs or .hs: a C* file */
811 if (cp
&& (streq (cp
+ 1, "cs")
812 || streq (cp
+ 1, "hs")))
815 goto close_and_return
;
817 /* .y: a yacc file */
818 if (cp
&& (streq (cp
+ 1, "y")))
821 goto close_and_return
;
823 /* .pl implies prolog source code */
824 if (cp
&& streq (cp
+ 1, "pl"))
827 goto close_and_return
;
829 /* .p or .pas: a Pascal file */
830 if (cp
&& (streq (cp
+ 1, "p")
831 || streq (cp
+ 1, "pas")))
834 goto close_and_return
;
836 /* If .f or .for, assume it is fortran or nothing. */
837 if (cp
&& (streq (cp
+ 1, "f")
838 || streq (cp
+ 1, "for")))
840 (void) PF_funcs (inf
);
841 goto close_and_return
;
843 /* if not a .c or .h or .y file, try fortran */
844 if (cp
&& ((cp
[1] != 'c'
847 || (cp
[1] != 0 && cp
[2] != 0)))
849 if (PF_funcs (inf
) != 0)
850 goto close_and_return
;
851 rewind (inf
); /* no fortran tags found, try C */
853 C_entries (cplusplus
? C_PLPL
: 0);
860 /* Nonzero if string STR is composed of digits. */
863 string_numeric_p (str
)
868 if (*str
< '0' || *str
> '9')
875 /* Should take a TOKEN* instead!! */
877 pfnote (name
, is_func
, named
, linestart
, linelen
, lno
, cno
)
878 char *name
; /* tag name */
879 logical is_func
; /* function or type name? */
880 logical named
; /* tag different from text of definition? */
891 np
= (NODE
*) malloc (sizeof (NODE
));
894 if (!emacs_tags_format
)
896 /* It's okay to output early in etags -- it only disrupts the
897 * character count of the tag entries, which is no longer used
900 error ("too many entries to sort");
907 /* If ctags mode, change name "main" to M<thisfilename>. */
908 if (!emacs_tags_format
&& !cxref_style
&& streq (name
, "main"))
910 fp
= etags_rindex (curfile
, '/');
911 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
912 fp
= etags_rindex (name
, '.');
913 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
917 np
->name
= savestr (name
);
919 np
->is_func
= is_func
;
922 /* UNCOMMENT THE +1 HERE: */
923 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
924 np
->left
= np
->right
= 0;
925 if (emacs_tags_format
)
927 c
= linestart
[linelen
];
928 linestart
[linelen
] = 0;
930 else if (cxref_style
== 0)
932 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
935 np
->pat
= savestr (linestart
);
936 if (emacs_tags_format
)
938 linestart
[linelen
] = c
;
941 add_node (np
, &head
);
946 * recurse on left children, iterate on right children.
954 register NODE
*node_right
= node
->right
;
955 free_tree (node
->left
);
958 free ((char *) node
);
965 * Adds a node to the tree of nodes. In etags mode, we don't keep
966 * it sorted; we just keep a linear list. In ctags mode, maintain
967 * an ordered tree, with no attempt at balancing.
969 * add_node is the only function allowed to add nodes, so it can
972 /* Must avoid static vars within functions since some systems
973 #define static as nothing. */
974 static NODE
*last_node
= NULL
;
977 add_node (node
, cur_node_p
)
978 NODE
*node
, **cur_node_p
;
981 register NODE
*cur_node
= *cur_node_p
;
983 if (cur_node
== NULL
)
990 if (emacs_tags_format
)
994 fatal ("internal error in add_node");
995 last_node
->right
= node
;
1001 dif
= strcmp (node
->name
, cur_node
->name
);
1004 * If this tag name matches an existing one, then
1005 * do not add the node, but maybe print a warning.
1009 if (node
->file
== cur_node
->file
)
1013 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1014 node
->file
, lineno
, node
->name
);
1015 fprintf (stderr
, "Second entry ignored\n");
1019 if (!cur_node
->been_warned
&& !no_warnings
)
1022 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1023 node
->file
, cur_node
->file
, node
->name
);
1025 cur_node
->been_warned
= TRUE
;
1029 /* Maybe refuse to add duplicate nodes. */
1030 if (!permit_duplicates
)
1032 if (!strcmp (node
->name
, cur_node
->name
)
1033 && !strcmp (node
->file
, cur_node
->file
))
1037 /* Actually add the node */
1038 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1044 register NODE
*node
;
1051 /* Output subentries that precede this one */
1052 put_entries (node
->left
);
1054 /* Output this entry */
1056 if (emacs_tags_format
)
1060 fprintf (outf
, "%s\177%s\001%d,%d\n",
1061 node
->pat
, node
->name
,
1062 node
->lno
, node
->cno
);
1066 fprintf (outf
, "%s\177%d,%d\n",
1068 node
->lno
, node
->cno
);
1071 else if (!cxref_style
)
1073 fprintf (outf
, "%s\t%s\t",
1074 node
->name
, node
->file
);
1078 putc (searchar
, outf
);
1081 for (sp
= node
->pat
; *sp
; sp
++)
1083 if (*sp
== '\\' || *sp
== searchar
)
1087 putc (searchar
, outf
);
1090 { /* a typedef; text pattern inadequate */
1091 fprintf (outf
, "%d", node
->lno
);
1095 else if (vgrind_style
)
1096 fprintf (stdout
, "%s %s %d\n",
1097 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1099 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1100 node
->name
, node
->lno
, node
->file
, node
->pat
);
1102 /* Output subentries that follow this one */
1103 put_entries (node
->right
);
1106 /* Length of a number's decimal representation. */
1114 for (; num
; num
/= 10)
1120 * Return total number of characters that put_entries will output for
1121 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1122 * is set, but called only in that case. This count is irrelevant with
1123 * the new tags.el, but is still supplied for backward compatibility.
1126 total_size_of_entries (node
)
1127 register NODE
*node
;
1135 for (; node
; node
= node
->right
)
1137 /* Count left subentries. */
1138 total
+= total_size_of_entries (node
->left
);
1140 /* Count this entry */
1141 total
+= strlen (node
->pat
) + 1;
1142 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1144 total
+= 1 + strlen (node
->name
); /* \001name */
1151 * The C symbol tables.
1154 /* Feed stuff between (but not including) %[ and %] lines to:
1155 gperf -c -k1,3 -o -p -r -t
1157 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1159 class, C_PLPL, st_C_struct
1160 domain, C_STAR, st_C_struct
1161 union, 0, st_C_struct
1162 struct, 0, st_C_struct
1164 typedef, 0, st_C_typedef
1165 define, 0, st_C_define
1166 long, 0, st_C_typespec
1167 short, 0, st_C_typespec
1168 int, 0, st_C_typespec
1169 char, 0, st_C_typespec
1170 float, 0, st_C_typespec
1171 double, 0, st_C_typespec
1172 signed, 0, st_C_typespec
1173 unsigned, 0, st_C_typespec
1174 auto, 0, st_C_typespec
1175 void, 0, st_C_typespec
1176 extern, 0, st_C_typespec
1177 static, 0, st_C_typespec
1178 const, 0, st_C_typespec
1179 volatile, 0, st_C_typespec
1181 and replace lines between %< and %> with its output. */
1183 /* C code produced by gperf version 1.8.1 (K&R C version) */
1184 /* Command-line: gperf -c -k1,3 -o -p -r -t */
1187 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
1189 #define MIN_WORD_LENGTH 3
1190 #define MAX_WORD_LENGTH 8
1191 #define MIN_HASH_VALUE 10
1192 #define MAX_HASH_VALUE 62
1195 53 is the maximum key range
1203 static unsigned char hash_table
[] =
1205 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1206 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1207 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1208 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1209 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1210 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1211 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
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, 2, 62, 7,
1215 6, 9, 15, 30, 62, 24, 62, 62, 1, 24,
1216 7, 27, 13, 62, 19, 26, 18, 27, 1, 62,
1217 62, 62, 62, 62, 62, 62, 62, 62,
1219 return len
+ hash_table
[str
[2]] + hash_table
[str
[0]];
1222 struct C_stab_entry
*
1223 in_word_set (str
, len
)
1228 static struct C_stab_entry wordlist
[] =
1230 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1232 {"volatile", 0, st_C_typespec
},
1234 {"long", 0, st_C_typespec
},
1235 {"char", 0, st_C_typespec
},
1236 {"class", C_PLPL
, st_C_struct
},
1237 {"",}, {"",}, {"",}, {"",},
1238 {"const", 0, st_C_typespec
},
1239 {"",}, {"",}, {"",}, {"",},
1240 {"auto", 0, st_C_typespec
},
1242 {"define", 0, st_C_define
},
1244 {"void", 0, st_C_typespec
},
1245 {"",}, {"",}, {"",},
1246 {"extern", 0, st_C_typespec
},
1247 {"static", 0, st_C_typespec
},
1249 {"domain", C_STAR
, st_C_struct
},
1251 {"typedef", 0, st_C_typedef
},
1252 {"double", 0, st_C_typespec
},
1253 {"enum", 0, st_C_enum
},
1254 {"",}, {"",}, {"",}, {"",},
1255 {"int", 0, st_C_typespec
},
1257 {"float", 0, st_C_typespec
},
1258 {"",}, {"",}, {"",},
1259 {"struct", 0, st_C_struct
},
1260 {"",}, {"",}, {"",}, {"",},
1261 {"union", 0, st_C_struct
},
1263 {"short", 0, st_C_typespec
},
1265 {"unsigned", 0, st_C_typespec
},
1266 {"signed", 0, st_C_typespec
},
1269 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
1271 register int key
= hash (str
, len
);
1273 if (key
<= MAX_HASH_VALUE
&& key
>= MIN_HASH_VALUE
)
1275 register char *s
= wordlist
[key
].name
;
1277 if (*s
== *str
&& !strncmp (str
+ 1, s
+ 1, len
- 1))
1278 return &wordlist
[key
];
1286 C_symtype(str
, len
, c_ext
)
1291 register struct C_stab_entry
*se
= in_word_set(str
, len
);
1293 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
1299 * C functions are recognized using a simple finite automaton.
1300 * funcdef is its state variable.
1304 fnone
, /* nothing seen */
1305 ftagseen
, /* function-like tag seen */
1306 fstartlist
, /* just after open parenthesis */
1307 finlist
, /* in parameter list */
1308 flistseen
, /* after parameter list */
1309 fignore
/* before open brace */
1314 /* typedefs are recognized using a simple finite automaton.
1315 * typeddef is its state variable.
1319 tnone
, /* nothing seen */
1320 ttypedseen
, /* typedef keyword seen */
1321 tinbody
, /* inside typedef body */
1322 tend
/* just before typedef tag */
1327 /* struct tags for C++ are recognized using another simple
1328 * finite automaton. `structdef' is its state variable.
1329 * This machinery is only invoked for C++; otherwise structdef
1330 * should remain snone. However, this machinery can easily be
1331 * adapted to find structure tags in normal C code.
1335 snone
, /* nothing seen yet */
1336 skeyseen
, /* struct-like keyword seen */
1337 stagseen
, /* struct-like tag seen */
1338 scolonseen
, /* colon seen after struct-like tag */
1339 sinbody
/* in struct body: recognize member func defs*/
1343 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1344 * struct tag, and structtype is the type of the preceding struct-like
1347 char structtag
[BUFSIZ
];
1348 enum sym_type structtype
;
1351 * Yet another little state machine to deal with preprocessor lines.
1355 dnone
, /* nothing seen */
1356 dsharpseen
, /* '#' seen as first char on line */
1357 ddefineseen
, /* '#' and 'define' seen */
1358 dignorerest
/* ignore rest of line */
1363 * Set this to TRUE, and the next token considered is called a function.
1364 * Used only for GNUmacs's function-defining macros.
1366 logical next_token_is_func
;
1369 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1375 * This routine finds functions, typedefs, #define's and
1376 * struct/union/enum definitions in C syntax and adds them
1380 #define curlb (lbs[curndx].lb)
1381 #define othlb (lbs[1-curndx].lb)
1382 #define newlb (lbs[newndx].lb)
1383 #define curlinepos (lbs[curndx].linepos)
1384 #define othlinepos (lbs[1-curndx].linepos)
1385 #define newlinepos (lbs[newndx].linepos)
1387 /* Save and restore token state. This is used when preprocessor defines
1388 are handled, to avoid disturbing active function/typedef/struct states. */
1389 #define TOKEN_SAVED_P (savetok.lineno > 0)
1390 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1391 savetok.len = toklen, strcpy(savenameb, nameb))
1392 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1393 toklen = tok.len, strcpy(nameb, savenameb), \
1396 #define CNL_SAVE_DEFINEDEF \
1398 SET_FILEPOS (curlinepos, inf, charno); \
1400 charno += readline (&curlb, inf); \
1401 lp = curlb.buffer; \
1408 CNL_SAVE_DEFINEDEF; \
1409 if (TOKEN_SAVED_P) \
1411 definedef = dnone; \
1414 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1415 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1416 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1417 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1421 int c_ext
; /* extension of C? */
1423 register char c
; /* latest char read; '\0' for end of line */
1424 register char *lp
; /* pointer one beyond the character `c' */
1425 int curndx
, newndx
; /* indices for current and new lb */
1426 TOKEN tok
; /* latest token read for funcdef & structdef */
1427 char nameb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1428 register int tokoff
; /* offset in line of start of latest token */
1429 register int toklen
; /* length of latest token */
1430 int cblev
; /* current curly brace level */
1431 int parlev
; /* current parenthesis level */
1432 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1434 TOKEN savetok
; /* saved token during preprocessor handling */
1435 char savenameb
[BUFSIZ
]; /* ouch! */
1438 curndx
= newndx
= 0;
1444 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1445 next_token_is_func
= yacc_rules
= FALSE
;
1446 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1449 cplpl
= c_ext
& C_PLPL
;
1456 /* If we're at the end of the line, the next character is a
1457 '\0'; don't skip it, because it's the thing that tells us
1458 to read the next line. */
1479 /* Newlines inside comments do not end macro definitions in
1494 /* Newlines inside strings do not end macro definitions
1495 in traditional cpp, even though compilers don't
1496 usually accept them. */
1507 /* Hmmm, something went wrong. */
1521 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1526 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1536 else if (cplpl
&& *lp
== '/')
1544 if ((c_ext
& YACC
) && *lp
== '%')
1546 /* entering or exiting rules section in yacc file */
1548 definedef
= dnone
; funcdef
= fnone
;
1549 typdef
= tnone
; structdef
= snone
;
1550 next_token_is_func
= FALSE
;
1551 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1553 yacc_rules
= !yacc_rules
;
1559 if (lp
== newlb
.buffer
+ 1 && definedef
== dnone
)
1560 definedef
= dsharpseen
;
1565 /* Consider token only if some complicated conditions are satisfied. */
1566 if (((cblev
== 0 && structdef
!= scolonseen
)
1567 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
1568 && definedef
!= dignorerest
1569 && (funcdef
!= finlist
1570 || (definedef
!= dnone
&& definedef
!= dignorerest
)))
1576 if (cplpl
&& c
== ':' && *lp
== ':' && begtoken(*(lp
+ 1)))
1579 * This handles :: in the middle, but not at beginning
1587 logical is_func
= FALSE
;
1589 tok
.lineno
= lineno
;
1590 tok
.p
= newlb
.buffer
+ tokoff
;
1594 || consider_token (c
, &tok
, c_ext
, cblev
, &is_func
))
1596 if (structdef
== sinbody
1597 && definedef
== dnone
1599 /* function defined in C++ class body */
1602 sprintf (nameb
, "%s::%.*s",
1603 ((structtag
[0] == '\0')
1604 ? "_anonymous_" : structtag
),
1609 sprintf (nameb
, "%.*s", tok
.len
, tok
.p
);
1612 if (structdef
== stagseen
1616 if (definedef
== dnone
1617 && (funcdef
== ftagseen
1618 || structdef
== stagseen
1621 if (newndx
== curndx
)
1622 curndx
= 1 - curndx
; /* switch line buffers */
1625 MAKE_TAG_FROM_NEW_LB (is_func
);
1629 } /* if (endtoken (c)) */
1630 else if (intoken (c
))
1635 } /* if (midtoken) */
1636 else if (begtoken (c
))
1647 MAKE_TAG_FROM_OTH_LB (TRUE
);
1654 if (structdef
== stagseen
)
1658 /* Take a quick peek ahead for define directive,
1659 so we can avoid saving the token when not absolutely
1660 necessary. [This is a speed hack.] */
1661 if (c
== 'd' && strneq(lp
, "efine", 5)
1662 && iswhite(*(lp
+ 5)))
1665 definedef
= ddefineseen
;
1669 definedef
= dignorerest
;
1672 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1674 tokoff
= lp
- 1 - newlb
.buffer
;
1680 } /* if must look at token */
1683 /* Detect end of line, colon, comma, semicolon and various braces
1684 after having handled a token.*/
1688 if (definedef
!= dnone
)
1690 if (structdef
== stagseen
)
1691 structdef
= scolonseen
;
1698 MAKE_TAG_FROM_OTH_LB (FALSE
);
1708 if (definedef
!= dnone
)
1710 if (cblev
== 0 && typdef
== tend
)
1713 MAKE_TAG_FROM_OTH_LB (FALSE
);
1715 if (funcdef
!= fignore
)
1721 if (definedef
!= dnone
)
1723 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1725 if (structdef
== stagseen
)
1729 if (definedef
!= dnone
)
1734 funcdef
= fstartlist
;
1743 if (definedef
!= dnone
)
1751 funcdef
= flistseen
;
1755 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
1759 if (definedef
!= dnone
)
1761 if (typdef
== ttypedseen
)
1765 case skeyseen
: /* unnamed struct */
1766 structtag
[0] = '\0';
1767 structdef
= sinbody
;
1770 case scolonseen
: /* named struct */
1771 structdef
= sinbody
;
1772 MAKE_TAG_FROM_OTH_LB (FALSE
);
1778 MAKE_TAG_FROM_OTH_LB (TRUE
);
1786 if (definedef
!= dnone
)
1788 if (funcdef
== fstartlist
)
1789 funcdef
= fnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
1792 if (definedef
!= dnone
)
1794 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
1796 cblev
= 0; /* reset curly brace level if first column */
1797 parlev
= 0; /* also reset paren level, just in case... */
1803 if (typdef
== tinbody
)
1806 (void) strcpy (structtag
, "<error 2>");
1810 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
1811 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
1812 if (definedef
!= dnone
)
1814 /* These surely cannot follow a function tag. */
1815 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1819 /* If a macro spans multiple lines don't reset its state. */
1827 } /* while not eof */
1832 * checks to see if the current token is at the start of a
1833 * function, or corresponds to a typedef, or is a struct/union/enum
1836 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1837 * C_EXT is which language we are looking at.
1839 * In the future we will need some way to adjust where the end of
1840 * the token is; for instance, implementing the C++ keyword
1841 * `operator' properly will adjust the end of the token to be after
1842 * whatever follows `operator'.
1849 * next_token_is_func IN OUT
1853 consider_token (c
, tokp
, c_ext
, cblev
, is_func
)
1854 register char c
; /* IN: first char after the token */
1855 register TOKEN
*tokp
; /* IN: token pointer */
1856 int c_ext
; /* IN: C extensions mask */
1857 int cblev
; /* IN: curly brace level */
1858 logical
*is_func
; /* OUT */
1860 enum sym_type toktype
= C_symtype(tokp
->p
, tokp
->len
, c_ext
);
1863 * Advance the definedef state machine.
1868 /* We're not on a preprocessor line. */
1871 if (toktype
== st_C_define
)
1873 definedef
= ddefineseen
;
1877 definedef
= dignorerest
;
1882 * Make a tag for any macro.
1884 definedef
= dignorerest
;
1885 *is_func
= (c
== '(');
1886 if (!*is_func
&& !constantypedefs
)
1893 error ("internal error: definedef value");
1902 if (toktype
== st_C_typedef
)
1905 typdef
= ttypedseen
;
1920 /* Do not return here, so the structdef stuff has a chance. */
1934 * This structdef business is currently only invoked when cblev==0.
1935 * It should be recursively invoked whatever the curly brace level,
1936 * and a stack of states kept, to allow for definitions of structs
1939 * This structdef business is NOT invoked when we are ctags and the
1940 * file is plain C. This is because a struct tag may have the same
1941 * name as another tag, and this loses with ctags.
1943 * This if statement deals with the typdef state machine as
1944 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1945 * return (FALSE). All the other code here is for the structdef
1952 if (typdef
== ttypedseen
1953 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1955 structdef
= skeyseen
;
1956 structtype
= toktype
;
1960 if (structdef
== skeyseen
)
1962 if (structtype
== st_C_struct
)
1964 (void) strncpy (structtag
, tokp
->p
, tokp
->len
);
1965 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1969 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1971 structdef
= stagseen
;
1975 /* Avoid entering funcdef stuff if typdef is going on. */
1976 if (typdef
!= tnone
)
1982 /* Detect GNUmacs's function-defining macros. */
1983 if (definedef
== dnone
)
1985 if (strneq (tokp
->p
, "DEF", 3)
1986 || strneq (tokp
->p
, "ENTRY", 5)
1987 || strneq (tokp
->p
, "SYSCALL", 7)
1988 || strneq (tokp
->p
, "PSEUDO", 6))
1990 next_token_is_func
= TRUE
;
1993 if (strneq (tokp
->p
, "EXFUN", 5))
1995 next_token_is_func
= FALSE
;
1999 if (next_token_is_func
)
2001 next_token_is_func
= FALSE
;
2003 *is_func
= TRUE
; /* to force search string in ctags */
2011 funcdef
= fnone
; /* should be useless */
2014 if (funcdef
== fnone
)
2025 /* Fortran parsing */
2041 linecharno
= charno
;
2042 charno
+= readline (&lb
, fi
);
2045 dbp
++; /* Ratfor escape to fortran */
2046 while (isspace (*dbp
))
2053 if (tail ("integer"))
2061 if (tail ("logical"))
2065 if (tail ("complex") || tail ("character"))
2069 if (tail ("double"))
2071 while (isspace (*dbp
))
2075 if (tail ("precision"))
2081 while (isspace (*dbp
))
2088 if (tail ("function"))
2092 if (tail ("subroutine"))
2100 if (tail ("program"))
2105 if (tail ("procedure"))
2117 register int len
= 0;
2119 while (*cp
&& (*cp
| ' ') == (dbp
[len
] | ' '))
2132 while (isspace (*dbp
))
2137 while (isspace (*dbp
))
2139 if (!isdigit (*dbp
))
2141 --dbp
; /* force failure */
2146 while (isdigit (*dbp
));
2155 char nambuf
[BUFSIZ
];
2157 while (isspace (*dbp
))
2162 linecharno
= charno
;
2163 charno
+= readline (&lb
, fi
);
2168 while (isspace (*dbp
))
2177 && (isalpha (*cp
) || isdigit (*cp
) || (*cp
== '_') || (*cp
== '$')));
2182 (void) strcpy (nambuf
, dbp
);
2184 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2185 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2189 /* Handle a file of assembler code. */
2205 linecharno
= charno
;
2206 charno
+= readline (&lb
, fi
);
2209 for (i
= 0; ((c
= dbp
[i
]) && !isspace (c
)) && (c
!= ':'); i
++)
2212 if ((i
> 0) && (c
== ':'))
2217 /* Added by Mosur Mohan, 4/22/88 */
2218 /* Pascal parsing */
2220 #define GET_NEW_LINE \
2222 linecharno = charno; lineno++; \
2223 charno += 1 + readline (&lb, inf); \
2227 /* Locates tags for procedures & functions.
2228 * Doesn't do any type- or var-definitions.
2229 * It does look for the keyword "extern" or "forward"
2230 * immediately following the procedure statement;
2231 * if found, the tag is skipped.
2238 struct linebuffer tline
; /* mostly copied from C_entries */
2242 char nambuf
[BUFSIZ
];
2244 logical
/* each of these flags is TRUE iff: */
2245 incomm1
, /* point is inside {..} comment */
2246 incomm2
, /* point is inside (*..*) comment */
2247 inquote
, /* point is inside '..' string */
2248 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2249 /* keyword, so next item = potential tag */
2250 found_tag
, /* point is after a potential tag */
2251 inparms
, /* point is within parameter-list */
2252 verify_tag
; /* point has passed the parm-list, so the */
2253 /* next token will determine whether */
2254 /* this is a FORWARD/EXTERN to be */
2255 /* ignored, or whether it is a real tag */
2261 initbuffer (&tline
);
2263 incomm1
= incomm2
= inquote
= FALSE
;
2264 found_tag
= FALSE
; /* have a proc name; check if extern */
2265 get_tagname
= FALSE
; /* have found "procedure" keyword */
2266 inparms
= FALSE
; /* found '(' after "proc" */
2267 verify_tag
= FALSE
; /* check if "extern" is ahead */
2269 /* long main loop to get next char */
2273 if (c
== 0) /* if end of line */
2278 if (!((found_tag
&& verify_tag
) ||
2280 c
= *dbp
++; /* only if don't need *dbp pointing */
2281 /* to the beginning of the name of */
2282 /* the procedure or function */
2284 if (incomm1
) /* within { - } comments */
2290 else if (incomm2
) /* within (* - *) comments */
2294 while ((c
= *dbp
++) == '*')
2313 inquote
= TRUE
; /* found first quote */
2315 case '{': /* found open-{-comment */
2319 if (*dbp
== '*') /* found open-(*-comment */
2324 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2327 case ')': /* end of parms list */
2332 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2339 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2341 /* check if this is an "extern" declaration */
2344 if ((*dbp
== 'e') || (*dbp
== 'E'))
2346 if (tail ("extern")) /* superfluous, really! */
2352 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2354 if (tail ("forward")) /* check for forward reference */
2360 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2364 pfnote (nambuf
, TRUE
, FALSE
,
2365 tline
.buffer
, cp
- tline
.buffer
+ 1,
2366 save_lineno
, save_lcno
);
2370 if (get_tagname
) /* grab name of proc or fn */
2375 /* save all values for later tagging */
2376 tline
.size
= lb
.size
;
2377 strcpy (tline
.buffer
, lb
.buffer
);
2378 save_lineno
= lineno
;
2379 save_lcno
= linecharno
;
2381 /* grab block name */
2382 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2386 strcpy (nambuf
, dbp
);
2388 dbp
= cp
; /* restore dbp to e-o-token */
2389 get_tagname
= FALSE
;
2393 /* and proceed to check for "extern" */
2395 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2396 (!found_tag
) && (!get_tagname
))
2398 /* check for proc/fn keywords */
2402 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2406 if (tail ("unction"))
2411 } /* while not e-o-f */
2415 * lisp tag functions
2416 * just look for (def or (DEF
2430 linecharno
= charno
;
2431 charno
+= readline (&lb
, fi
);
2437 while (!isspace (*dbp
))
2439 while (isspace (*dbp
))
2445 /* Check for (foo::defmumble name-defined ... */
2448 while (*dbp
&& !isspace (*dbp
)
2449 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2454 while (*dbp
== ':');
2456 if (L_isdef (dbp
- 1))
2458 while (!isspace (*dbp
))
2460 while (isspace (*dbp
))
2474 return ((dbp
[1] == 'd' || dbp
[1] == 'D')
2475 && (dbp
[2] == 'e' || dbp
[2] == 'E')
2476 && (dbp
[3] == 'f' || dbp
[3] == 'F'));
2483 return ((*(++dbp
) == 'q' || *dbp
== 'Q')
2484 && (*(++dbp
) == 'u' || *dbp
== 'U')
2485 && (*(++dbp
) == 'o' || *dbp
== 'O')
2486 && (*(++dbp
) == 't' || *dbp
== 'T')
2487 && (*(++dbp
) == 'e' || *dbp
== 'E')
2488 && isspace(*(++dbp
)));
2496 char nambuf
[BUFSIZ
];
2498 if (*dbp
== '\'') /* Skip prefix quote */
2500 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2503 while (isspace(*dbp
))
2506 for (cp
= dbp
/*+1*/; *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')'; cp
++)
2513 (void) strcpy (nambuf
, dbp
);
2515 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2516 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2521 * Scheme tag functions
2522 * look for (def... xyzzy
2523 * look for (def... (xyzzy
2524 * look for (def ... ((...(xyzzy ....
2525 * look for (set! xyzzy
2528 static void get_scheme ();
2541 linecharno
= charno
;
2542 charno
+= readline (&lb
, fi
);
2544 if (dbp
[0] == '(' &&
2545 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2546 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2547 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2549 while (!isspace (*dbp
))
2551 /* Skip over open parens and white space */
2552 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2556 if (dbp
[0] == '(' &&
2557 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2558 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2559 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2560 (dbp
[4] == '!' || dbp
[4] == '!') &&
2563 while (!isspace (*dbp
))
2565 /* Skip over white space */
2566 while (isspace (*dbp
))
2578 char nambuf
[BUFSIZ
];
2582 /* Go till you get to white space or a syntactic break */
2583 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2585 /* Null terminate the string there. */
2588 /* Copy the string */
2589 strcpy (nambuf
, dbp
);
2590 /* Unterminate the string */
2592 /* Announce the change */
2593 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2597 /* Find tags in TeX and LaTeX input files. */
2599 /* TEX_toktab is a table of TeX control sequences that define tags.
2600 Each TEX_tabent records one such control sequence.
2601 CONVERT THIS TO USE THE Stab TYPE!! */
2609 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2611 /* Default set of control sequences to put into TEX_toktab.
2612 The value of environment var TEXTAGS is prepended to this. */
2614 static char *TEX_defenv
=
2615 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2618 struct TEX_tabent
*TEX_decode_env ();
2622 static char TEX_esc
= '\\';
2623 static char TEX_opgrp
= '{';
2624 static char TEX_clgrp
= '}';
2627 * TeX/LaTeX scanning loop.
2640 /* Select either \ or ! as escape character. */
2643 /* Initialize token table once from environment. */
2645 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2648 { /* Scan each line in file */
2650 linecharno
= charno
;
2651 charno
+= readline (&lb
, fi
);
2654 while (dbp
= etags_index (dbp
, TEX_esc
)) /* Look at each escape in line */
2660 linecharno
+= dbp
- lasthit
;
2662 i
= TEX_Token (lasthit
);
2665 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2666 break; /* We only save a line once */
2672 #define TEX_LESC '\\'
2673 #define TEX_SESC '!'
2676 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2677 /* chars accordingly. */
2685 while ((c
= getc (f
)) != EOF
)
2687 /* Skip to next line if we hit the TeX comment char. */
2691 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2710 /* Read environment and prepend it to the default string. */
2711 /* Build token table. */
2714 TEX_decode_env (evarname
, defenv
)
2718 register char *env
, *p
;
2720 struct TEX_tabent
*tab
;
2723 /* Append default string to environment. */
2724 env
= getenv (evarname
);
2728 env
= concat (env
, defenv
, "");
2730 /* Allocate a token table */
2731 for (size
= 1, p
= env
; p
;)
2732 if ((p
= etags_index (p
, ':')) && *(++p
))
2734 /* Add 1 to leave room for null terminator. */
2735 tab
= xnew (size
+ 1, struct TEX_tabent
);
2737 /* Unpack environment string into token table. Be careful about */
2738 /* zero-length strings (leading ':', "::" and trailing ':') */
2741 p
= etags_index (env
, ':');
2742 if (!p
) /* End of environment string. */
2743 p
= env
+ strlen (env
);
2745 { /* Only non-zero strings. */
2746 tab
[i
].name
= savenstr (env
, p
- env
);
2747 tab
[i
].len
= strlen (tab
[i
].name
);
2754 tab
[i
].name
= NULL
; /* Mark end of table. */
2762 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2763 The name being defined actually starts at (NAME + LEN + 1).
2764 But we seem to include the TeX command in the tag name. */
2767 TEX_getit (name
, len
)
2771 char *p
= name
+ len
;
2772 char nambuf
[BUFSIZ
];
2777 /* Let tag name extend to next group close (or end of line) */
2778 while (*p
&& *p
!= TEX_clgrp
)
2780 (void) strncpy (nambuf
, name
, p
- name
);
2781 nambuf
[p
- name
] = 0;
2783 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2787 /* If the text at CP matches one of the tag-defining TeX command names,
2788 return the etags_index of that command in TEX_toktab.
2789 Otherwise return -1. */
2791 /* Keep the capital `T' in `Token' for dumb truncating compilers
2792 (this distinguishes it from `TEX_toktab' */
2799 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2800 if (strncmp (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
) == 0)
2805 /* Support for Prolog. */
2807 /* whole head (not only functor, but also arguments)
2808 is gotten in compound term. */
2811 prolog_getit (s
, lineno
, linecharno
)
2816 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2824 if (*s
== '\0') /* syntax error. */
2826 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2828 else if (*s
== '\'')
2830 insquote
= !insquote
;
2833 else if (!insquote
&& *s
== '(')
2838 else if (!insquote
&& *s
== ')')
2844 else if (npar
< 0) /* syntax error. */
2847 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2849 if (npar
!= 0) /* syntax error. */
2859 strcpy (nambuf
, save_s
);
2861 pfnote (nambuf
, TRUE
, FALSE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2864 /* It is assumed that prolog predicate starts from column 0. */
2870 void skip_comment (), prolog_getit ();
2872 lineno
= linecharno
= charno
= 0;
2876 linecharno
+= charno
;
2877 charno
= readline (&lb
, fi
) + 1; /* 1 for newline. */
2879 if (isspace (dbp
[0])) /* not predicate header. */
2881 else if (dbp
[0] == '%') /* comment. */
2883 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2884 skip_comment (&lb
, fi
, &lineno
, &linecharno
);
2886 prolog_getit (dbp
, lineno
, linecharno
);
2891 skip_comment (plb
, fi
, plineno
, plinecharno
)
2892 struct linebuffer
*plb
;
2894 int *plineno
; /* result */
2895 long *plinecharno
; /* result */
2897 while (!substr ("*/", plb
->buffer
))
2900 *plinecharno
+= readline (plb
, fi
) + 1;
2901 } /* 1 for newline. */
2904 /* Return TRUE if 'sub' exists somewhere in 's'. */
2911 while (*s
&& (s
= etags_index (s
, *sub
)))
2912 if (prestr (sub
, s
))
2919 /* Return TRUE if 'pre' is prefix of string 's'. */
2928 else if (*pre
== *s
)
2929 return (prestr (pre
+ 1, s
+ 1));
2934 /* Initialize a linebuffer for use */
2937 initbuffer (linebuffer
)
2938 struct linebuffer
*linebuffer
;
2940 linebuffer
->size
= 200;
2941 linebuffer
->buffer
= xnew (200, char);
2945 * Read a line of text from `stream' into `linebuffer'.
2946 * Return the number of characters read from `stream',
2947 * which is the length of the line including the newline, if any.
2950 readline (linebuffer
, stream
)
2951 struct linebuffer
*linebuffer
;
2952 register FILE *stream
;
2954 char *buffer
= linebuffer
->buffer
;
2955 register char *p
= linebuffer
->buffer
;
2956 register char *pend
;
2957 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2959 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
2963 register int c
= getc (stream
);
2966 linebuffer
->size
*= 2;
2967 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
2968 p
+= buffer
- linebuffer
->buffer
;
2969 pend
= buffer
+ linebuffer
->size
;
2970 linebuffer
->buffer
= buffer
;
2972 if (c
== EOF
|| c
== '\n')
2975 newline
= (c
== '\n') ? 1 : 0;
2981 return p
- buffer
+ newline
;
2988 return savenstr (cp
, strlen (cp
));
2998 dp
= xnew (len
+ 1, char);
2999 (void) strncpy (dp
, cp
, len
);
3005 * Return the ptr in sp at which the character c last
3006 * appears; NULL if not found
3008 * Identical to v7 rindex, included for portability.
3012 etags_rindex (sp
, c
)
3013 register char *sp
, c
;
3028 * Return the ptr in sp at which the character c first
3029 * appears; NULL if not found
3031 * Identical to v7 index, included for portability.
3036 register char *sp
, c
;
3046 /* Print error message and exit. */
3057 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3064 fprintf (stderr
, "%s: ", progname
);
3065 fprintf (stderr
, s1
, s2
);
3066 fprintf (stderr
, "\n");
3069 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
3075 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3076 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3078 (void) strcpy (result
, s1
);
3079 (void) strcpy (result
+ len1
, s2
);
3080 (void) strcpy (result
+ len1
+ len2
, s3
);
3081 *(result
+ len1
+ len2
+ len3
) = 0;
3086 /* Like malloc but get fatal error if memory is exhausted. */
3092 char *result
= malloc (size
);
3094 fatal ("virtual memory exhausted", 0);
3099 xrealloc (ptr
, size
)
3103 char *result
= realloc (ptr
, size
);
3105 fatal ("virtual memory exhausted");