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.
31 char pot_etags_version
[] = "@(#) pot revision number is 10.32";
38 #include <../src/config.h>
39 /* On some systems, Emacs defines static as nothing
40 for the sake of unexec. We don't want that here
41 since we don't use unexec. */
47 #include <sys/types.h>
50 #if !defined (S_ISREG) && defined (S_IFREG)
51 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
56 extern char *getenv ();
59 /* Define CTAGS to make the program "ctags" compatible with the usual one.
60 Let it undefined to make the program "etags", which makes emacs-style
61 tag tables and tags typedefs, #defines and struct/union/enum by default. */
69 /* Exit codes for success and failure. */
79 * The FILEPOS abstract type, which represents a position in a file,
80 * plus the following accessor functions:
82 * long GET_CHARNO (pos)
83 * returns absolute char number.
84 * void SET_FILEPOS (pos, fp, charno)
85 * FILE *fp; long charno;
86 * sets `pos' from the current file
87 * position of `fp' and from `charno',
88 * which must be the absolute character
89 * number corresponding to the current
92 * The `pos' parameter is an lvalue expression of type FILEPOS.
93 * Parameters to the accessor functions are evaluated 0 or more times,
94 * and so must have no side effects.
96 * FILEPOS objects can also be assigned and passed to and from
97 * functions in the normal C manner.
99 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
103 /* real implementation */
104 typedef long FILEPOS
;
105 #define GET_CHARNO(pos) ((pos) + 0)
106 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
108 /* debugging implementation */
114 #define GET_CHARNO(pos) ((pos).charno + 0)
115 #define SET_FILEPOS(pos, fp, cno) \
116 ((void) ((pos).charno = (cno), \
117 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
121 #define streq(s, t) (strcmp (s, t) == 0)
122 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
128 #define iswhite(arg) (_wht[arg]) /* T if char is white */
129 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
130 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
131 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
133 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
136 { /* sorting structure */
137 char *name
; /* function or type name */
138 char *file
; /* file name */
139 logical is_func
; /* use pattern or line no */
140 logical named
; /* list name separately */
141 logical been_warned
; /* set if noticed dup */
142 int lno
; /* line number tag is on */
143 long cno
; /* character number line starts on */
144 char *pat
; /* search pattern */
145 struct nd_st
*left
, *right
; /* left and right sons */
148 typedef struct nd_st NODE
;
150 logical header_file
; /* TRUE if .h file, FALSE o.w. */
151 /* boolean "functions" (see init) */
152 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
154 char *cwd
; /* current working directory */
155 char *tagfiledir
; /* directory of tagfile */
158 char *savenstr (), *savestr ();
159 char *etags_strchr (), *etags_strrchr ();
160 char *etags_getcwd ();
161 char *relative_filename (), *absolute_filename (), *absolute_dirname ();
162 char *xmalloc (), *xrealloc ();
163 int total_size_of_entries ();
168 int Fortran_functions ();
169 void Lisp_functions ();
170 void Pascal_functions ();
171 void Prolog_functions ();
172 void Scheme_functions ();
173 void TeX_functions ();
177 logical
find_entries ();
184 void process_file ();
190 * xnew -- allocate storage
193 * Type *xnew (int n, Type);
195 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
198 * Symbol table types.
202 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
219 #define C_PLPL 0x00001 /* C++ */
220 #define C_STAR 0x00003 /* C* */
221 #define YACC 0x10000 /* yacc file */
223 char searchar
= '/'; /* use /.../ searches */
225 LINENO lineno
; /* line number of current line */
226 long charno
; /* current character number */
228 long linecharno
; /* charno of start of line; not used by C, but
229 * by every other language.
232 char *curfile
, /* current input file name */
233 *tagfile
, /* output file */
234 *white
= " \f\t\n", /* white chars */
235 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
236 /* token starting chars */
237 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
238 /* valid in-token chars */
239 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
241 int append_to_tagfile
; /* -a: append to tags */
242 /* The following three default to 1 for etags, but to 0 for ctags. */
243 int typedefs
; /* -t: create tags for typedefs */
244 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
245 /* 0 struct/enum/union decls, and C++ */
246 /* member functions. */
247 int constantypedefs
; /* -d: create tags for C #define and enum */
248 /* constants. Enum consts not implemented. */
249 /* -D: opposite of -d. Default under ctags. */
250 int update
; /* -u: update tags */
251 int vgrind_style
; /* -v: create vgrind style index output */
252 int no_warnings
; /* -w: suppress warnings */
253 int cxref_style
; /* -x: create cxref style output */
254 int cplusplus
; /* .[hc] means C++, not C */
255 int noindentypedefs
; /* -S: ignore indentation in C */
257 /* Name this program was invoked with. */
260 struct option longopts
[] = {
261 { "append", no_argument
, NULL
, 'a' },
262 { "backward-search", no_argument
, NULL
, 'B' },
263 { "c++", no_argument
, NULL
, 'C' },
264 { "cxref", no_argument
, NULL
, 'x' },
265 { "defines", no_argument
, NULL
, 'd' },
266 { "help", no_argument
, NULL
, 'H' },
267 { "ignore-indentation", no_argument
, NULL
, 'S' },
268 { "include", required_argument
, NULL
, 'i' },
269 { "no-defines", no_argument
, NULL
, 'D' },
270 { "no-warn", no_argument
, NULL
, 'w' },
271 { "output", required_argument
, NULL
, 'o' },
272 { "typedefs", no_argument
, NULL
, 't' },
273 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
274 { "update", no_argument
, NULL
, 'u' },
275 { "version", no_argument
, NULL
, 'V' },
276 { "vgrind", no_argument
, NULL
, 'v' },
280 FILE *tagf
; /* ioptr for tags file */
281 NODE
*head
; /* the head of the binary tree of tags */
282 logical permit_duplicates
= TRUE
; /* allow duplicate tags */
284 /* A `struct linebuffer' is a structure which holds a line of text.
285 `readline' reads a line from a stream into a linebuffer
286 and works regardless of the length of the line. */
294 struct linebuffer lb
; /* the current line */
295 struct linebuffer filename_lb
; /* used to read in filenames */
299 struct linebuffer lb
; /* used by C_entries instead of lb */
306 printf ("%s for Emacs version %g.\n", (CTAGS
) ? "CTAGS" : "ETAGS", VERSION
);
308 printf ("%s for Emacs version 19.\n", (CTAGS
) ? "CTAGS" : "ETAGS");
317 printf ("These are the options accepted by %s. You may use unambiguous\n\
318 abbreviations for the long option names. A - as file name means read file\n\
319 names from stdin.\n\n", progname
);
321 puts ("-a, --append\n\
322 Append tag entries to existing tags file.");
325 puts ("-B, --backward-search\n\
326 Write the search commands for the tag entries using '?', the\n\
327 backward-search command instead of '/', the forward-search command.");
330 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
331 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
332 extensions are always assumed to be C++ code.");
335 puts ("-d, --defines\n\
336 Create tag entries for C #defines, too.");
338 puts ("-D, --no-defines\n\
339 Don't create tag entries for C #defines. This makes the tags\n\
343 puts ("-i FILE, --include=FILE\n\
344 Include a note in tag file indicating that, when searching for\n\
345 a tag, one should also consult the tags file FILE after\n\
346 checking the current file.");
348 puts ("-o FILE, --output=FILE\n\
349 Write the tags to FILE.");
350 puts ("-S, --ignore-indentation\n\
351 Don't rely on indentation quite as much as normal. Currently,\n\
352 this means not to assume that a closing brace in the first\n\
353 column is the final brace of a function or structure\n\
354 definition in C and C++.");
358 puts ("-t, --typedefs\n\
359 Generate tag entries for C typedefs.");
360 puts ("-T, --typedefs-and-c++\n\
361 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
362 and C++ member functions.");
363 puts ("-u, --update\n\
364 Update the tag entries for the given files, leaving tag\n\
365 entries for other files in place. Currently, this is\n\
366 implemented by deleting the existing entries for the given\n\
367 files and then rewriting the new entries at the end of the\n\
368 tags file. It is often faster to simply rebuild the entire\n\
369 tag file than to use this.");
370 puts ("-v, --vgrind\n\
371 Generates an index of items intended for human consumption,\n\
372 similar to the output of vgrind. The index is sorted, and\n\
373 gives the page number of each item.");
374 puts ("-x, --cxref\n\
375 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
376 The output uses line numbers instead of page numbers, but\n\
377 beyond that the differences are cosmetic; try both to see\n\
379 puts ("-w, --no-warn\n\
380 Suppress warning messages about entries defined in multiple\n\
384 puts ("-V, --version\n\
385 Print the version of the program.\n\
387 Print this help message.");
400 unsigned int nincluded_files
= 0;
401 char **included_files
= xnew (argc
, char *);
406 extern char *gfnames ();
407 extern char *massage_name ();
411 _fmode
= O_BINARY
; /* all of files are treated as binary files */
417 * If etags, always find typedefs and structure tags. Why not?
418 * Also default is to find macro constants.
421 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
426 opt
= getopt_long (argc
, argv
, "aCdDf:o:StTi:BuvxwVH", longopts
, 0);
434 /* If getopt returns 0, then it has already processed a
435 long-named option. We should do nothing. */
438 /* Common options. */
451 case 'f': /* for compatibility with old makefiles */
456 "%s: -%c flag may only be given once\n", progname
, opt
);
475 included_files
[nincluded_files
++] = optarg
;
489 typedefs_and_cplusplus
++;
511 if (optind
== argc
&& nincluded_files
== 0)
513 fprintf (stderr
, "%s: No input files specified.\n", progname
);
516 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
523 tagfile
= CTAGS
? "tags" : "TAGS";
525 cwd
= etags_getcwd (); /* the current working directory */
527 if (streq (tagfile
, "-"))
533 tagfiledir
= absolute_dirname (tagfile
, cwd
);
536 init (); /* set up boolean "functions" */
539 initbuffer (&lbs
[0].lb
);
540 initbuffer (&lbs
[1].lb
);
541 initbuffer (&filename_lb
);
543 * loop through files finding functions
547 if (streq (tagfile
, "-"))
550 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
561 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
565 error ("Can't find file %s\n", this_file
);
570 this_file
= massage_name (this_file
);
573 } /* solely to balance out the ifdef'd parens above */
576 for (; optind
< argc
; optind
++)
578 this_file
= argv
[optind
];
580 /* Input file named "-" means read file names from stdin and use them. */
581 if (streq (this_file
, "-"))
583 while (!feof (stdin
))
585 (void) readline (&filename_lb
, stdin
);
586 if (strlen (filename_lb
.buffer
) > 0)
587 process_file (filename_lb
.buffer
);
591 process_file (this_file
);
596 while (nincluded_files
-- > 0)
597 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
599 (void) fclose (tagf
);
610 /* update cannot be set under VMS, so we may assume that argc
611 and argv have not been munged. */
612 for (i
= optind
; i
< argc
; i
++)
615 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
616 tagfile
, argv
[i
], tagfile
);
621 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
628 (void) fclose (tagf
);
631 sprintf (cmd
, "sort %s -o %s", tagfile
, tagfile
);
639 * This routine is called on each file argument.
645 struct stat stat_buf
;
647 if (stat (file
, &stat_buf
) == 0 && !S_ISREG (stat_buf
.st_mode
))
649 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
652 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
654 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
657 if (!find_entries (file
))
667 /* file is an absolute filename. Canonicalise it. */
668 filename
= absolute_filename (file
, cwd
);
672 /* file is a filename relative to cwd. Make it relative
673 to the directory of the tags file. */
674 filename
= relative_filename (file
, tagfiledir
);
676 fprintf (tagf
, "\f\n%s,%d\n", filename
, total_size_of_entries (head
));
684 * This routine sets up the boolean pseudo-functions which work
685 * by setting boolean flags dependent upon the corresponding character
686 * Every char which is NOT in that string is not a white char. Therefore,
687 * all of the array "_wht" is set to FALSE, and then the elements
688 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
689 * of a char is TRUE if it is the string "white", else FALSE.
697 for (i
= 0; i
< 0177; i
++)
698 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
699 for (sp
= white
; *sp
; sp
++)
701 for (sp
= endtk
; *sp
; sp
++)
703 for (sp
= intk
; *sp
; sp
++)
705 for (sp
= begtk
; *sp
; sp
++)
707 _wht
[0] = _wht
['\n'];
708 _etk
[0] = _etk
['\n'];
709 _btk
[0] = _btk
['\n'];
710 _itk
[0] = _itk
['\n'];
714 * This routine opens the specified file and calls the function
715 * which finds the function and type definitions.
724 inf
= fopen (file
, "r");
730 curfile
= savestr (file
);
731 cp
= etags_strrchr (file
, '.');
734 header_file
= (cp
&& (streq (cp1
, "h")));
736 /* .tex, .aux or .bbl implies LaTeX source code */
737 if (cp
&& (streq (cp1
, "tex") || streq (cp1
, "aux")
738 || streq (cp1
, "bbl")))
741 goto close_and_return
;
743 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
744 if (cp
&& (streq (cp1
, "l")
746 || streq (cp1
, "lsp")
747 || streq (cp1
, "lisp")
749 || streq (cp1
, "clisp")))
751 Lisp_functions (inf
);
752 goto close_and_return
;
754 /* .scm or .sm or .scheme or ... implies scheme source code */
755 if (cp
&& (streq (cp1
, "sm")
756 || streq (cp1
, "scm")
757 || streq (cp1
, "scheme")
759 || streq (cp1
, "sch")
762 || streq (cp1
, "SCM")
763 /* The `SCM' or `scm' prefix with a version number */
764 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
765 && string_numeric_p (cp1
))
766 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
767 && string_numeric_p (cp1
))))
769 Scheme_functions (inf
);
770 goto close_and_return
;
773 if (cp
&& (streq (cp1
, "s")
774 || streq (cp1
, "a") /* Unix assembler */
775 || streq (cp1
, "sa") /* Unix assembler */
776 || streq (cp1
, "asm") /* Microcontroller assembly */
777 || streq (cp1
, "src") /* BSO/Tasking C compiler output */
778 || streq (cp1
, "def") /* BSO/Tasking definition includes */
779 || streq (cp1
, "ins") /* Microcontroller include files */
780 || streq (cp1
, "inc")))/* Microcontroller include files */
783 goto close_and_return
;
785 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
786 if (cp
&& (streq (cp1
, "C")
788 || streq (cp1
, "cxx")
789 || streq (cp1
, "hxx")
790 || streq (cp1
, "cc")))
792 C_entries (C_PLPL
, inf
); /* C++ */
793 goto close_and_return
;
795 /* .cs or .hs: a C* file */
796 if (cp
&& (streq (cp1
, "cs")
797 || streq (cp1
, "hs")))
799 C_entries (C_STAR
, inf
);
800 goto close_and_return
;
802 /* .y: a yacc file */
803 if (cp
&& (streq (cp1
, "y")))
805 C_entries (YACC
, inf
);
806 goto close_and_return
;
808 /* .pl implies prolog source code */
809 if (cp
&& streq (cp1
, "pl"))
811 Prolog_functions (inf
);
812 goto close_and_return
;
814 /* .p or .pas: a Pascal file */
815 if (cp
&& (streq (cp1
, "p")
816 || streq (cp1
, "pas")))
818 Pascal_functions (inf
);
819 goto close_and_return
;
821 /* If .f or .for, assume it is fortran or nothing. */
822 if (cp
&& (streq (cp1
, "f")
823 || streq (cp1
, "for")))
825 (void) Fortran_functions (inf
);
826 goto close_and_return
;
828 /* if not a .c or .h or .y file, try fortran */
829 if (cp
&& ((cp
[1] != 'c'
832 || (cp
[1] != 0 && cp
[2] != 0)))
834 if (Fortran_functions (inf
) != 0)
835 goto close_and_return
;
836 rewind (inf
); /* no fortran tags found, try C */
838 C_entries (cplusplus
? C_PLPL
: 0, inf
);
845 /* Nonzero if string STR is composed of digits. */
848 string_numeric_p (str
)
853 if (*str
< '0' || *str
> '9')
860 /* Should take a TOKEN* instead!! */
862 pfnote (name
, is_func
, named
, linestart
, linelen
, lno
, cno
)
863 char *name
; /* tag name */
864 logical is_func
; /* function or type name? */
865 logical named
; /* tag different from text of definition? */
881 /* It's okay to output early in etags -- it only disrupts the
882 * character count of the tag entries, which is no longer used
885 error ("too many entries to sort", 0);
892 /* If ctags mode, change name "main" to M<thisfilename>. */
893 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
895 fp
= etags_strrchr (curfile
, '/');
896 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
897 fp
= etags_strrchr (name
, '.');
898 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
902 np
->name
= savestr (name
);
904 np
->is_func
= is_func
;
907 /* UNCOMMENT THE +1 HERE: */
908 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
909 np
->left
= np
->right
= 0;
912 c
= linestart
[linelen
];
913 linestart
[linelen
] = 0;
915 else if (cxref_style
== 0)
917 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
920 np
->pat
= savestr (linestart
);
923 linestart
[linelen
] = c
;
926 add_node (np
, &head
);
931 * recurse on left children, iterate on right children.
939 register NODE
*node_right
= node
->right
;
940 free_tree (node
->left
);
943 free ((char *) node
);
950 * Adds a node to the tree of nodes. In etags mode, we don't keep
951 * it sorted; we just keep a linear list. In ctags mode, maintain
952 * an ordered tree, with no attempt at balancing.
954 * add_node is the only function allowed to add nodes, so it can
957 /* Must avoid static vars within functions since some systems
958 #define static as nothing. */
959 NODE
*last_node
= NULL
;
962 add_node (node
, cur_node_p
)
963 NODE
*node
, **cur_node_p
;
966 register NODE
*cur_node
= *cur_node_p
;
968 if (cur_node
== NULL
)
978 if (last_node
== NULL
)
979 fatal ("internal error in add_node", 0);
980 last_node
->right
= node
;
986 dif
= strcmp (node
->name
, cur_node
->name
);
989 * If this tag name matches an existing one, then
990 * do not add the node, but maybe print a warning.
994 if (node
->file
== cur_node
->file
)
998 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
999 node
->file
, lineno
, node
->name
);
1000 fprintf (stderr
, "Second entry ignored\n");
1004 if (!cur_node
->been_warned
&& !no_warnings
)
1007 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1008 node
->file
, cur_node
->file
, node
->name
);
1010 cur_node
->been_warned
= TRUE
;
1014 /* Maybe refuse to add duplicate nodes. */
1015 if (!permit_duplicates
)
1017 if (streq (node
->name
, cur_node
->name
)
1018 && streq (node
->file
, cur_node
->file
))
1022 /* Actually add the node */
1023 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1029 register NODE
*node
;
1036 /* Output subentries that precede this one */
1037 put_entries (node
->left
);
1039 /* Output this entry */
1045 fprintf (tagf
, "%s\177%s\001%d,%d\n",
1046 node
->pat
, node
->name
,
1047 node
->lno
, node
->cno
);
1051 fprintf (tagf
, "%s\177%d,%d\n",
1053 node
->lno
, node
->cno
);
1056 else if (!cxref_style
)
1058 fprintf (tagf
, "%s\t%s\t",
1059 node
->name
, node
->file
);
1063 putc (searchar
, tagf
);
1066 for (sp
= node
->pat
; *sp
; sp
++)
1068 if (*sp
== '\\' || *sp
== searchar
)
1072 putc (searchar
, tagf
);
1075 { /* a typedef; text pattern inadequate */
1076 fprintf (tagf
, "%d", node
->lno
);
1080 else if (vgrind_style
)
1081 fprintf (stdout
, "%s %s %d\n",
1082 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1084 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1085 node
->name
, node
->lno
, node
->file
, node
->pat
);
1087 /* Output subentries that follow this one */
1088 put_entries (node
->right
);
1091 /* Length of a number's decimal representation. */
1099 for (; num
; num
/= 10)
1105 * Return total number of characters that put_entries will output for
1106 * the nodes in the subtree of the specified node. Works only if
1107 * we are not ctags, but called only in that case. This count
1108 * is irrelevant with the new tags.el, but is still supplied for
1109 * backward compatibility.
1112 total_size_of_entries (node
)
1113 register NODE
*node
;
1121 for (; node
; node
= node
->right
)
1123 /* Count left subentries. */
1124 total
+= total_size_of_entries (node
->left
);
1126 /* Count this entry */
1127 total
+= strlen (node
->pat
) + 1;
1128 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1130 total
+= 1 + strlen (node
->name
); /* \001name */
1137 * The C symbol tables.
1140 /* Feed stuff between (but not including) %[ and %] lines to:
1141 gperf -c -k1,3 -o -p -r -t
1143 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1145 class, C_PLPL, st_C_struct
1146 domain, C_STAR, st_C_struct
1147 union, 0, st_C_struct
1148 struct, 0, st_C_struct
1150 typedef, 0, st_C_typedef
1151 define, 0, st_C_define
1152 long, 0, st_C_typespec
1153 short, 0, st_C_typespec
1154 int, 0, st_C_typespec
1155 char, 0, st_C_typespec
1156 float, 0, st_C_typespec
1157 double, 0, st_C_typespec
1158 signed, 0, st_C_typespec
1159 unsigned, 0, st_C_typespec
1160 auto, 0, st_C_typespec
1161 void, 0, st_C_typespec
1162 extern, 0, st_C_typespec
1163 static, 0, st_C_typespec
1164 const, 0, st_C_typespec
1165 volatile, 0, st_C_typespec
1167 and replace lines between %< and %> with its output. */
1169 /* C code produced by gperf version 1.8.1 (K&R C version) */
1170 /* Command-line: gperf -c -k1,3 -o -p -r -t */
1173 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
1175 #define MIN_WORD_LENGTH 3
1176 #define MAX_WORD_LENGTH 8
1177 #define MIN_HASH_VALUE 10
1178 #define MAX_HASH_VALUE 62
1181 53 is the maximum key range
1189 static unsigned char hash_table
[] =
1191 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1192 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1193 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1194 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1195 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1196 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1197 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1198 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1199 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1200 62, 62, 62, 62, 62, 62, 62, 2, 62, 7,
1201 6, 9, 15, 30, 62, 24, 62, 62, 1, 24,
1202 7, 27, 13, 62, 19, 26, 18, 27, 1, 62,
1203 62, 62, 62, 62, 62, 62, 62, 62,
1205 return len
+ hash_table
[str
[2]] + hash_table
[str
[0]];
1208 struct C_stab_entry
*
1209 in_word_set (str
, len
)
1214 static struct C_stab_entry wordlist
[] =
1216 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1218 {"volatile", 0, st_C_typespec
},
1220 {"long", 0, st_C_typespec
},
1221 {"char", 0, st_C_typespec
},
1222 {"class", C_PLPL
, st_C_struct
},
1223 {"",}, {"",}, {"",}, {"",},
1224 {"const", 0, st_C_typespec
},
1225 {"",}, {"",}, {"",}, {"",},
1226 {"auto", 0, st_C_typespec
},
1228 {"define", 0, st_C_define
},
1230 {"void", 0, st_C_typespec
},
1231 {"",}, {"",}, {"",},
1232 {"extern", 0, st_C_typespec
},
1233 {"static", 0, st_C_typespec
},
1235 {"domain", C_STAR
, st_C_struct
},
1237 {"typedef", 0, st_C_typedef
},
1238 {"double", 0, st_C_typespec
},
1239 {"enum", 0, st_C_enum
},
1240 {"",}, {"",}, {"",}, {"",},
1241 {"int", 0, st_C_typespec
},
1243 {"float", 0, st_C_typespec
},
1244 {"",}, {"",}, {"",},
1245 {"struct", 0, st_C_struct
},
1246 {"",}, {"",}, {"",}, {"",},
1247 {"union", 0, st_C_struct
},
1249 {"short", 0, st_C_typespec
},
1251 {"unsigned", 0, st_C_typespec
},
1252 {"signed", 0, st_C_typespec
},
1255 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
1257 register int key
= hash (str
, len
);
1259 if (key
<= MAX_HASH_VALUE
&& key
>= MIN_HASH_VALUE
)
1261 register char *s
= wordlist
[key
].name
;
1263 if (*s
== *str
&& strneq (str
+ 1, s
+ 1, len
- 1))
1264 return &wordlist
[key
];
1272 C_symtype(str
, len
, c_ext
)
1277 register struct C_stab_entry
*se
= in_word_set(str
, len
);
1279 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
1285 * C functions are recognized using a simple finite automaton.
1286 * funcdef is its state variable.
1290 fnone
, /* nothing seen */
1291 ftagseen
, /* function-like tag seen */
1292 fstartlist
, /* just after open parenthesis */
1293 finlist
, /* in parameter list */
1294 flistseen
, /* after parameter list */
1295 fignore
/* before open brace */
1301 * typedefs are recognized using a simple finite automaton.
1302 * typeddef is its state variable.
1306 tnone
, /* nothing seen */
1307 ttypedseen
, /* typedef keyword seen */
1308 tinbody
, /* inside typedef body */
1309 tend
, /* just before typedef tag */
1310 tignore
/* junk after typedef tag */
1316 * struct-like structures (enum, struct and union) are recognized
1317 * using another simple finite automaton. `structdef' is its state
1322 snone
, /* nothing seen yet */
1323 skeyseen
, /* struct-like keyword seen */
1324 stagseen
, /* struct-like tag seen */
1325 scolonseen
, /* colon seen after struct-like tag */
1326 sinbody
/* in struct body: recognize member func defs*/
1331 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1332 * struct tag, and structtype is the type of the preceding struct-like
1335 char structtag
[BUFSIZ
];
1336 enum sym_type structtype
;
1339 * Yet another little state machine to deal with preprocessor lines.
1343 dnone
, /* nothing seen */
1344 dsharpseen
, /* '#' seen as first char on line */
1345 ddefineseen
, /* '#' and 'define' seen */
1346 dignorerest
/* ignore rest of line */
1351 * Set this to TRUE, and the next token considered is called a function.
1352 * Used only for GNUmacs's function-defining macros.
1354 logical next_token_is_func
;
1357 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1363 * checks to see if the current token is at the start of a
1364 * function, or corresponds to a typedef, or is a struct/union/enum
1367 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1368 * C_EXT is which language we are looking at.
1370 * In the future we will need some way to adjust where the end of
1371 * the token is; for instance, implementing the C++ keyword
1372 * `operator' properly will adjust the end of the token to be after
1373 * whatever follows `operator'.
1380 * next_token_is_func IN OUT
1384 consider_token (c
, tokp
, c_ext
, cblev
, is_func
)
1385 register char c
; /* IN: first char after the token */
1386 register TOKEN
*tokp
; /* IN: token pointer */
1387 int c_ext
; /* IN: C extensions mask */
1388 int cblev
; /* IN: curly brace level */
1389 logical
*is_func
; /* OUT */
1391 enum sym_type toktype
= C_symtype(tokp
->p
, tokp
->len
, c_ext
);
1394 * Advance the definedef state machine.
1399 /* We're not on a preprocessor line. */
1402 if (toktype
== st_C_define
)
1404 definedef
= ddefineseen
;
1408 definedef
= dignorerest
;
1413 * Make a tag for any macro.
1415 definedef
= dignorerest
;
1416 *is_func
= (c
== '(');
1417 if (!*is_func
&& !constantypedefs
)
1424 error ("internal error: definedef value.", 0);
1433 if (toktype
== st_C_typedef
)
1436 typdef
= ttypedseen
;
1452 /* Do not return here, so the structdef stuff has a chance. */
1466 * This structdef business is currently only invoked when cblev==0.
1467 * It should be recursively invoked whatever the curly brace level,
1468 * and a stack of states kept, to allow for definitions of structs
1471 * This structdef business is NOT invoked when we are ctags and the
1472 * file is plain C. This is because a struct tag may have the same
1473 * name as another tag, and this loses with ctags.
1475 * This if statement deals with the typdef state machine as
1476 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1477 * return (FALSE). All the other code here is for the structdef
1484 if (typdef
== ttypedseen
1485 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1487 structdef
= skeyseen
;
1488 structtype
= toktype
;
1492 if (structdef
== skeyseen
)
1494 if (structtype
== st_C_struct
)
1496 strncpy (structtag
, tokp
->p
, tokp
->len
);
1497 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1501 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1503 structdef
= stagseen
;
1507 /* Avoid entering funcdef stuff if typdef is going on. */
1508 if (typdef
!= tnone
)
1514 /* Detect GNUmacs's function-defining macros. */
1515 if (definedef
== dnone
)
1517 if (strneq (tokp
->p
, "DEF", 3)
1518 || strneq (tokp
->p
, "ENTRY", 5)
1519 || strneq (tokp
->p
, "SYSCALL", 7)
1520 || strneq (tokp
->p
, "PSEUDO", 6))
1522 next_token_is_func
= TRUE
;
1525 if (strneq (tokp
->p
, "EXFUN", 5))
1527 next_token_is_func
= FALSE
;
1531 if (next_token_is_func
)
1533 next_token_is_func
= FALSE
;
1535 *is_func
= TRUE
; /* to force search string in ctags */
1543 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1544 funcdef
= fnone
; /* should be useless */
1547 if (funcdef
== fnone
)
1560 * This routine finds functions, typedefs, #define's and
1561 * struct/union/enum definitions in C syntax and adds them
1565 #define curlb (lbs[curndx].lb)
1566 #define othlb (lbs[1-curndx].lb)
1567 #define newlb (lbs[newndx].lb)
1568 #define curlinepos (lbs[curndx].linepos)
1569 #define othlinepos (lbs[1-curndx].linepos)
1570 #define newlinepos (lbs[newndx].linepos)
1572 /* Save and restore token state. This is used when preprocessor defines
1573 are handled, to avoid disturbing active function/typedef/struct states. */
1574 #define TOKEN_SAVED_P (savetok.lineno > 0)
1575 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1576 savetok.len = toklen, strcpy(savenameb, nameb))
1577 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1578 toklen = tok.len, strcpy(nameb, savenameb), \
1581 #define CNL_SAVE_DEFINEDEF \
1583 SET_FILEPOS (curlinepos, inf, charno); \
1585 charno += readline (&curlb, inf); \
1586 lp = curlb.buffer; \
1593 CNL_SAVE_DEFINEDEF; \
1594 if (TOKEN_SAVED_P) \
1596 definedef = dnone; \
1599 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1600 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1601 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1602 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1605 C_entries (c_ext
, inf
)
1606 int c_ext
; /* extension of C? */
1609 register char c
; /* latest char read; '\0' for end of line */
1610 register char *lp
; /* pointer one beyond the character `c' */
1611 int curndx
, newndx
; /* indices for current and new lb */
1612 TOKEN tok
; /* latest token read for funcdef & structdef */
1613 char nameb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1614 register int tokoff
; /* offset in line of start of latest token */
1615 register int toklen
; /* length of latest token */
1616 int cblev
; /* current curly brace level */
1617 int parlev
; /* current parenthesis level */
1618 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1620 TOKEN savetok
; /* saved token during preprocessor handling */
1621 char savenameb
[BUFSIZ
]; /* ouch! */
1624 curndx
= newndx
= 0;
1630 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1631 next_token_is_func
= yacc_rules
= FALSE
;
1632 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1635 cplpl
= c_ext
& C_PLPL
;
1642 /* If we're at the end of the line, the next character is a
1643 '\0'; don't skip it, because it's the thing that tells us
1644 to read the next line. */
1665 /* Newlines inside comments do not end macro definitions in
1680 /* Newlines inside strings do not end macro definitions
1681 in traditional cpp, even though compilers don't
1682 usually accept them. */
1693 /* Hmmm, something went wrong. */
1707 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1712 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1722 else if (cplpl
&& *lp
== '/')
1730 if ((c_ext
& YACC
) && *lp
== '%')
1732 /* entering or exiting rules section in yacc file */
1734 definedef
= dnone
; funcdef
= fnone
;
1735 typdef
= tnone
; structdef
= snone
;
1736 next_token_is_func
= FALSE
;
1737 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1739 yacc_rules
= !yacc_rules
;
1745 if (lp
== newlb
.buffer
+ 1 && definedef
== dnone
)
1746 definedef
= dsharpseen
;
1751 /* Consider token only if some complicated conditions are satisfied. */
1752 if (((cblev
== 0 && structdef
!= scolonseen
)
1753 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
1754 && typdef
!= tignore
1755 && definedef
!= dignorerest
1756 && (funcdef
!= finlist
1757 || definedef
!= dnone
))
1763 if (cplpl
&& c
== ':' && *lp
== ':' && begtoken(*(lp
+ 1)))
1766 * This handles :: in the middle, but not at beginning
1774 logical is_func
= FALSE
;
1776 tok
.lineno
= lineno
;
1777 tok
.p
= newlb
.buffer
+ tokoff
;
1781 || consider_token (c
, &tok
, c_ext
, cblev
, &is_func
))
1783 if (structdef
== sinbody
1784 && definedef
== dnone
1786 /* function defined in C++ class body */
1789 sprintf (nameb
, "%s::%.*s",
1790 ((structtag
[0] == '\0')
1791 ? "_anonymous_" : structtag
),
1796 sprintf (nameb
, "%.*s", tok
.len
, tok
.p
);
1799 if (structdef
== stagseen
1803 if (definedef
== dnone
1804 && (funcdef
== ftagseen
1805 || structdef
== stagseen
1808 if (newndx
== curndx
)
1809 curndx
= 1 - curndx
; /* switch line buffers */
1812 MAKE_TAG_FROM_NEW_LB (is_func
);
1816 } /* if (endtoken (c)) */
1817 else if (intoken (c
))
1822 } /* if (midtoken) */
1823 else if (begtoken (c
))
1834 MAKE_TAG_FROM_OTH_LB (TRUE
);
1841 if (structdef
== stagseen
)
1845 /* Take a quick peek ahead for define directive,
1846 so we can avoid saving the token when not absolutely
1847 necessary. [This is a speed hack.] */
1848 if (c
== 'd' && strneq(lp
, "efine", 5)
1849 && iswhite(*(lp
+ 5)))
1852 definedef
= ddefineseen
;
1856 definedef
= dignorerest
;
1859 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1861 tokoff
= lp
- 1 - newlb
.buffer
;
1867 } /* if must look at token */
1870 /* Detect end of line, colon, comma, semicolon and various braces
1871 after having handled a token.*/
1875 if (definedef
!= dnone
)
1877 if (structdef
== stagseen
)
1878 structdef
= scolonseen
;
1885 MAKE_TAG_FROM_OTH_LB (FALSE
);
1895 if (definedef
!= dnone
)
1901 MAKE_TAG_FROM_OTH_LB (FALSE
);
1906 if (funcdef
!= fignore
)
1908 if (structdef
== stagseen
)
1912 if (definedef
!= dnone
)
1914 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1916 if (structdef
== stagseen
)
1920 if (definedef
!= dnone
)
1922 if (cblev
== 0 && typdef
== tend
)
1925 MAKE_TAG_FROM_OTH_LB (FALSE
);
1928 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1930 if (structdef
== stagseen
)
1934 if (definedef
!= dnone
)
1939 funcdef
= fstartlist
;
1948 if (definedef
!= dnone
)
1956 funcdef
= flistseen
;
1959 if (cblev
== 0 && typdef
== tend
)
1962 MAKE_TAG_FROM_OTH_LB (FALSE
);
1965 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
1969 if (definedef
!= dnone
)
1971 if (typdef
== ttypedseen
)
1975 case skeyseen
: /* unnamed struct */
1976 structtag
[0] = '\0';
1977 structdef
= sinbody
;
1980 case scolonseen
: /* named struct */
1981 structdef
= sinbody
;
1982 MAKE_TAG_FROM_OTH_LB (FALSE
);
1988 MAKE_TAG_FROM_OTH_LB (TRUE
);
1994 /* Neutralize `extern "C" {' grot.
1995 if (cblev == 0 && structdef == snone && typdef == tnone)
2001 if (definedef
!= dnone
)
2003 if (funcdef
== fstartlist
)
2004 funcdef
= fnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
2007 if (definedef
!= dnone
)
2009 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
2011 cblev
= 0; /* reset curly brace level if first column */
2012 parlev
= 0; /* also reset paren level, just in case... */
2018 if (typdef
== tinbody
)
2021 strcpy (structtag
, "<error 2>");
2025 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
2026 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
2027 if (definedef
!= dnone
)
2029 /* These surely cannot follow a function tag. */
2030 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2034 /* If a macro spans multiple lines don't reset its state. */
2042 } /* while not eof */
2045 /* Fortran parsing */
2054 register int len
= 0;
2056 while (*cp
&& (*cp
| ' ') == (dbp
[len
] | ' '))
2069 while (isspace (*dbp
))
2074 while (isspace (*dbp
))
2076 if (!isdigit (*dbp
))
2078 --dbp
; /* force failure */
2083 while (isdigit (*dbp
));
2092 char nambuf
[BUFSIZ
];
2094 while (isspace (*dbp
))
2099 linecharno
= charno
;
2100 charno
+= readline (&lb
, inf
);
2105 while (isspace (*dbp
))
2114 && (isalpha (*cp
) || isdigit (*cp
) || (*cp
== '_') || (*cp
== '$')));
2119 strcpy (nambuf
, dbp
);
2121 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2122 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2127 Fortran_functions (inf
)
2137 linecharno
= charno
;
2138 charno
+= readline (&lb
, inf
);
2141 dbp
++; /* Ratfor escape to fortran */
2142 while (isspace (*dbp
))
2149 if (tail ("integer"))
2157 if (tail ("logical"))
2161 if (tail ("complex") || tail ("character"))
2165 if (tail ("double"))
2167 while (isspace (*dbp
))
2171 if (tail ("precision"))
2177 while (isspace (*dbp
))
2184 if (tail ("function"))
2188 if (tail ("subroutine"))
2196 if (tail ("program"))
2201 if (tail ("procedure"))
2210 * Bob Weiner, Motorola Inc., 4/3/94
2211 * Unix and microcontroller assembly tag handling
2212 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
2218 char nambuf
[BUFSIZ
];
2229 linecharno
= charno
;
2230 charno
+= readline (&lb
, inf
);
2233 /* If first char is alphabetic or one of [_.$], test for colon
2234 following identifier. */
2235 if (isalpha (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2237 /* Read past label. */
2239 while (isalnum (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2241 if (*cp
== ':' || isspace (*cp
))
2243 /* Found end of label, so copy it and add it to the table. */
2246 strcpy (nambuf
, lb
.buffer
);
2248 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2249 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2256 /* Added by Mosur Mohan, 4/22/88 */
2257 /* Pascal parsing */
2259 #define GET_NEW_LINE \
2261 linecharno = charno; lineno++; \
2262 charno += 1 + readline (&lb, inf); \
2266 /* Locates tags for procedures & functions.
2267 * Doesn't do any type- or var-definitions.
2268 * It does look for the keyword "extern" or "forward"
2269 * immediately following the procedure statement;
2270 * if found, the tag is skipped.
2274 Pascal_functions (inf
)
2277 struct linebuffer tline
; /* mostly copied from C_entries */
2281 char nambuf
[BUFSIZ
];
2283 logical
/* each of these flags is TRUE iff: */
2284 incomm1
, /* point is inside {..} comment */
2285 incomm2
, /* point is inside (*..*) comment */
2286 inquote
, /* point is inside '..' string */
2287 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2288 /* keyword, so next item = potential tag */
2289 found_tag
, /* point is after a potential tag */
2290 inparms
, /* point is within parameter-list */
2291 verify_tag
; /* point has passed the parm-list, so the */
2292 /* next token will determine whether */
2293 /* this is a FORWARD/EXTERN to be */
2294 /* ignored, or whether it is a real tag */
2300 initbuffer (&tline
);
2302 incomm1
= incomm2
= inquote
= FALSE
;
2303 found_tag
= FALSE
; /* have a proc name; check if extern */
2304 get_tagname
= FALSE
; /* have found "procedure" keyword */
2305 inparms
= FALSE
; /* found '(' after "proc" */
2306 verify_tag
= FALSE
; /* check if "extern" is ahead */
2308 /* long main loop to get next char */
2312 if (c
== 0) /* if end of line */
2317 if (!((found_tag
&& verify_tag
) ||
2319 c
= *dbp
++; /* only if don't need *dbp pointing */
2320 /* to the beginning of the name of */
2321 /* the procedure or function */
2323 if (incomm1
) /* within { - } comments */
2329 else if (incomm2
) /* within (* - *) comments */
2333 while ((c
= *dbp
++) == '*')
2352 inquote
= TRUE
; /* found first quote */
2354 case '{': /* found open-{-comment */
2358 if (*dbp
== '*') /* found open-(*-comment */
2363 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2366 case ')': /* end of parms list */
2371 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2378 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2380 /* check if this is an "extern" declaration */
2383 if ((*dbp
== 'e') || (*dbp
== 'E'))
2385 if (tail ("extern")) /* superfluous, really! */
2391 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2393 if (tail ("forward")) /* check for forward reference */
2399 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2403 pfnote (nambuf
, TRUE
, FALSE
,
2404 tline
.buffer
, cp
- tline
.buffer
+ 1,
2405 save_lineno
, save_lcno
);
2409 if (get_tagname
) /* grab name of proc or fn */
2414 /* save all values for later tagging */
2415 tline
.size
= lb
.size
;
2416 strcpy (tline
.buffer
, lb
.buffer
);
2417 save_lineno
= lineno
;
2418 save_lcno
= linecharno
;
2420 /* grab block name */
2421 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2425 strcpy (nambuf
, dbp
);
2427 dbp
= cp
; /* restore dbp to e-o-token */
2428 get_tagname
= FALSE
;
2432 /* and proceed to check for "extern" */
2434 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2435 (!found_tag
) && (!get_tagname
))
2437 /* check for proc/fn keywords */
2441 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2445 if (tail ("unction"))
2450 } /* while not eof */
2454 * lisp tag functions
2455 * just look for (def or (DEF
2462 return ((dbp
[1] == 'd' || dbp
[1] == 'D')
2463 && (dbp
[2] == 'e' || dbp
[2] == 'E')
2464 && (dbp
[3] == 'f' || dbp
[3] == 'F'));
2471 return ((*(++dbp
) == 'q' || *dbp
== 'Q')
2472 && (*(++dbp
) == 'u' || *dbp
== 'U')
2473 && (*(++dbp
) == 'o' || *dbp
== 'O')
2474 && (*(++dbp
) == 't' || *dbp
== 'T')
2475 && (*(++dbp
) == 'e' || *dbp
== 'E')
2476 && isspace(*(++dbp
)));
2484 char nambuf
[BUFSIZ
];
2486 if (*dbp
== '\'') /* Skip prefix quote */
2488 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2491 while (isspace(*dbp
))
2494 for (cp
= dbp
/*+1*/; *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')'; cp
++)
2501 strcpy (nambuf
, dbp
);
2503 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2504 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2509 Lisp_functions (inf
)
2519 linecharno
= charno
;
2520 charno
+= readline (&lb
, inf
);
2526 while (!isspace (*dbp
))
2528 while (isspace (*dbp
))
2534 /* Check for (foo::defmumble name-defined ... */
2537 while (*dbp
&& !isspace (*dbp
)
2538 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2543 while (*dbp
== ':');
2545 if (L_isdef (dbp
- 1))
2547 while (!isspace (*dbp
))
2549 while (isspace (*dbp
))
2560 * Scheme tag functions
2561 * look for (def... xyzzy
2562 * look for (def... (xyzzy
2563 * look for (def ... ((...(xyzzy ....
2564 * look for (set! xyzzy
2570 Scheme_functions (inf
)
2580 linecharno
= charno
;
2581 charno
+= readline (&lb
, inf
);
2583 if (dbp
[0] == '(' &&
2584 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2585 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2586 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2588 while (!isspace (*dbp
))
2590 /* Skip over open parens and white space */
2591 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2595 if (dbp
[0] == '(' &&
2596 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2597 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2598 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2599 (dbp
[4] == '!' || dbp
[4] == '!') &&
2602 while (!isspace (*dbp
))
2604 /* Skip over white space */
2605 while (isspace (*dbp
))
2617 char nambuf
[BUFSIZ
];
2621 /* Go till you get to white space or a syntactic break */
2622 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2624 /* Null terminate the string there. */
2627 /* Copy the string */
2628 strcpy (nambuf
, dbp
);
2629 /* Unterminate the string */
2631 /* Announce the change */
2632 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2636 /* Find tags in TeX and LaTeX input files. */
2638 /* TEX_toktab is a table of TeX control sequences that define tags.
2639 Each TEX_tabent records one such control sequence.
2640 CONVERT THIS TO USE THE Stab TYPE!! */
2648 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2650 /* Default set of control sequences to put into TEX_toktab.
2651 The value of environment var TEXTAGS is prepended to this. */
2653 char *TEX_defenv
= "\
2654 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2657 struct TEX_tabent
*TEX_decode_env ();
2661 char TEX_esc
= '\\';
2662 char TEX_opgrp
= '{';
2663 char TEX_clgrp
= '}';
2666 * TeX/LaTeX scanning loop.
2679 /* Select either \ or ! as escape character. */
2682 /* Initialize token table once from environment. */
2684 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2687 { /* Scan each line in file */
2689 linecharno
= charno
;
2690 charno
+= readline (&lb
, inf
);
2693 while (dbp
= etags_strchr (dbp
, TEX_esc
)) /* Look at each esc in line */
2699 linecharno
+= dbp
- lasthit
;
2701 i
= TEX_Token (lasthit
);
2704 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2705 break; /* We only save a line once */
2711 #define TEX_LESC '\\'
2712 #define TEX_SESC '!'
2715 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2716 /* chars accordingly. */
2724 while ((c
= getc (inf
)) != EOF
)
2726 /* Skip to next line if we hit the TeX comment char. */
2730 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2749 /* Read environment and prepend it to the default string. */
2750 /* Build token table. */
2753 TEX_decode_env (evarname
, defenv
)
2757 register char *env
, *p
;
2759 struct TEX_tabent
*tab
;
2762 /* Append default string to environment. */
2763 env
= getenv (evarname
);
2767 env
= concat (env
, defenv
, "");
2769 /* Allocate a token table */
2770 for (size
= 1, p
= env
; p
;)
2771 if ((p
= etags_strchr (p
, ':')) && *(++p
))
2773 /* Add 1 to leave room for null terminator. */
2774 tab
= xnew (size
+ 1, struct TEX_tabent
);
2776 /* Unpack environment string into token table. Be careful about */
2777 /* zero-length strings (leading ':', "::" and trailing ':') */
2780 p
= etags_strchr (env
, ':');
2781 if (!p
) /* End of environment string. */
2782 p
= env
+ strlen (env
);
2784 { /* Only non-zero strings. */
2785 tab
[i
].name
= savenstr (env
, p
- env
);
2786 tab
[i
].len
= strlen (tab
[i
].name
);
2793 tab
[i
].name
= NULL
; /* Mark end of table. */
2801 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2802 The name being defined actually starts at (NAME + LEN + 1).
2803 But we seem to include the TeX command in the tag name. */
2806 TEX_getit (name
, len
)
2810 char *p
= name
+ len
;
2811 char nambuf
[BUFSIZ
];
2816 /* Let tag name extend to next group close (or end of line) */
2817 while (*p
&& *p
!= TEX_clgrp
)
2819 strncpy (nambuf
, name
, p
- name
);
2820 nambuf
[p
- name
] = 0;
2822 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2826 /* If the text at CP matches one of the tag-defining TeX command names,
2827 return the pointer to the first occurrence of that command in TEX_toktab.
2828 Otherwise return -1. */
2830 /* Keep the capital `T' in `Token' for dumb truncating compilers
2831 (this distinguishes it from `TEX_toktab' */
2838 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2839 if (strneq (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
))
2844 /* Support for Prolog. */
2846 /* whole head (not only functor, but also arguments)
2847 is gotten in compound term. */
2850 prolog_getit (s
, lineno
, linecharno
)
2855 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2863 if (*s
== '\0') /* syntax error. */
2865 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2867 else if (*s
== '\'')
2869 insquote
= !insquote
;
2872 else if (!insquote
&& *s
== '(')
2877 else if (!insquote
&& *s
== ')')
2883 else if (npar
< 0) /* syntax error. */
2886 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2888 if (npar
!= 0) /* syntax error. */
2898 strcpy (nambuf
, save_s
);
2900 pfnote (nambuf
, TRUE
, FALSE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2903 /* It is assumed that prolog predicate starts from column 0. */
2906 Prolog_functions (inf
)
2909 void skip_comment (), prolog_getit ();
2911 lineno
= linecharno
= charno
= 0;
2915 linecharno
+= charno
;
2916 charno
= readline (&lb
, inf
) + 1; /* 1 for newline. */
2918 if (isspace (dbp
[0])) /* not predicate header. */
2920 else if (dbp
[0] == '%') /* comment. */
2922 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2923 skip_comment (&lb
, inf
, &lineno
, &linecharno
);
2925 prolog_getit (dbp
, lineno
, linecharno
);
2930 skip_comment (plb
, inf
, plineno
, plinecharno
)
2931 struct linebuffer
*plb
;
2933 int *plineno
; /* result */
2934 long *plinecharno
; /* result */
2936 while (!substr ("*/", plb
->buffer
))
2939 *plinecharno
+= readline (plb
, inf
) + 1;
2940 } /* 1 for newline. */
2943 /* Return TRUE if 'sub' exists somewhere in 's'. */
2950 while (*s
&& (s
= etags_strchr (s
, *sub
)))
2951 if (prestr (sub
, s
))
2958 /* Return TRUE if 'pre' is prefix of string 's'. */
2967 else if (*pre
== *s
)
2968 return (prestr (pre
+ 1, s
+ 1));
2973 /* Initialize a linebuffer for use */
2976 initbuffer (linebuffer
)
2977 struct linebuffer
*linebuffer
;
2979 linebuffer
->size
= 200;
2980 linebuffer
->buffer
= xnew (200, char);
2984 * Read a line of text from `stream' into `linebuffer'.
2985 * Return the number of characters read from `stream',
2986 * which is the length of the line including the newline, if any.
2989 readline (linebuffer
, stream
)
2990 struct linebuffer
*linebuffer
;
2991 register FILE *stream
;
2993 char *buffer
= linebuffer
->buffer
;
2994 register char *p
= linebuffer
->buffer
;
2995 register char *pend
;
2996 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2998 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
3002 register int c
= getc (stream
);
3005 linebuffer
->size
*= 2;
3006 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
3007 p
+= buffer
- linebuffer
->buffer
;
3008 pend
= buffer
+ linebuffer
->size
;
3009 linebuffer
->buffer
= buffer
;
3011 if (c
== EOF
|| c
== '\n')
3014 newline
= (c
== '\n') ? 1 : 0;
3020 return p
- buffer
+ newline
;
3027 return savenstr (cp
, strlen (cp
));
3037 dp
= xnew (len
+ 1, char);
3038 strncpy (dp
, cp
, len
);
3044 * Return the ptr in sp at which the character c last
3045 * appears; NULL if not found
3047 * Identical to System V strrchr, included for portability.
3051 etags_strrchr (sp
, c
)
3052 register char *sp
, c
;
3067 * Return the ptr in sp at which the character c first
3068 * appears; NULL if not found
3070 * Identical to System V strchr, included for portability.
3074 etags_strchr (sp
, c
)
3075 register char *sp
, c
;
3085 /* Print error message and exit. */
3096 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3103 fprintf (stderr
, "%s: ", progname
);
3104 fprintf (stderr
, s1
, s2
);
3105 fprintf (stderr
, "\n");
3108 /* Return a newly-allocated string whose contents
3109 concatenate those of s1, s2, s3. */
3115 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3116 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3118 strcpy (result
, s1
);
3119 strcpy (result
+ len1
, s2
);
3120 strcpy (result
+ len1
+ len2
, s3
);
3121 result
[len1
+ len2
+ len3
] = '\0';
3126 /* Does the same work as the system V getcwd, but does not need to
3127 guess buffer size in advance. Included mostly for compatibility. */
3137 buf
= xnew (bufsize
, char);
3139 pipe
= popen ("pwd 2>/dev/null", "r");
3145 if (fgets (buf
, bufsize
, pipe
) == NULL
)
3154 } while (buf
[strlen (buf
) - 1] != '\n');
3159 /* Return a newly allocated string containing the filename
3160 of FILE relative to the absolute directory DIR (which
3161 should end with a slash). */
3164 relative_filename (file
, dir
)
3167 char *fp
, *dp
, *res
;
3169 /* Find the common root of file and dir. */
3170 fp
= absolute_filename (file
, cwd
);
3172 while (*fp
++ == *dp
++)
3181 /* Build a sequence of "../" strings for the resulting relative filename. */
3182 for (dp
= etags_strchr (dp
+ 1, '/'), res
= "";
3184 dp
= etags_strchr (dp
+ 1, '/'))
3186 res
= concat (res
, "../", "");
3189 /* Add the filename relative to the common root of file and dir. */
3190 res
= concat (res
, fp
+ 1, "");
3192 return res
; /* temporary stub */
3195 /* Return a newly allocated string containing the
3196 absolute filename of FILE given CWD (which should
3197 end with a slash). */
3200 absolute_filename (file
, cwd
)
3203 char *slashp
, *cp
, *res
;
3206 res
= concat (file
, "", "");
3208 res
= concat (cwd
, file
, "");
3210 /* Delete the "/dirname/.." and "/." substrings. */
3211 slashp
= etags_strchr (res
, '/');
3212 while (slashp
!= NULL
&& slashp
[0] != '\0')
3214 if (slashp
[1] == '.')
3216 if (slashp
[2] == '.'
3217 && (slashp
[3] == '/' || slashp
[3] == '\0'))
3222 while (cp
>= res
&& *cp
!= '/');
3225 strcpy (cp
, slashp
+ 3);
3227 else /* else (cp == res) */
3229 if (slashp
[3] != '\0')
3230 strcpy (cp
, slashp
+ 4);
3236 else if (slashp
[2] == '/' || slashp
[2] == '\0')
3238 strcpy (slashp
, slashp
+ 2);
3243 slashp
= etags_strchr (slashp
+ 1, '/');
3250 /* Return a newly allocated string containing the absolute
3251 filename of dir where FILE resides given CWD (which should
3252 end with a slash). */
3255 absolute_dirname (file
, cwd
)
3261 slashp
= etags_strrchr (file
, '/');
3266 res
= absolute_filename (file
, cwd
);
3272 /* Like malloc but get fatal error if memory is exhausted. */
3278 char *result
= (char *) malloc (size
);
3280 fatal ("virtual memory exhausted", 0);
3285 xrealloc (ptr
, size
)
3289 char *result
= (char *) realloc (ptr
, size
);
3291 fatal ("virtual memory exhausted");