1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984,87,88,89,93,94 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";
35 #include <sys/param.h>
39 #include <../src/config.h>
40 /* On some systems, Emacs defines static as nothing
41 for the sake of unexec. We don't want that here
42 since we don't use unexec. */
48 #include <sys/types.h>
51 #if !defined (S_ISREG) && defined (S_IFREG)
52 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
57 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 %s.\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 or .cpp: a C++ file */
786 if (cp
&& (streq (cp1
, "C")
788 || streq (cp1
, "cpp")
789 || streq (cp1
, "cxx")
790 || streq (cp1
, "hxx")
791 || streq (cp1
, "cc")))
793 C_entries (C_PLPL
, inf
); /* C++ */
794 goto close_and_return
;
796 /* .cs or .hs: a C* file */
797 if (cp
&& (streq (cp1
, "cs")
798 || streq (cp1
, "hs")))
800 C_entries (C_STAR
, inf
);
801 goto close_and_return
;
803 /* .y: a yacc file */
804 if (cp
&& (streq (cp1
, "y")))
806 C_entries (YACC
, inf
);
807 goto close_and_return
;
809 /* .pl implies prolog source code */
810 if (cp
&& streq (cp1
, "pl"))
812 Prolog_functions (inf
);
813 goto close_and_return
;
815 /* .p or .pas: a Pascal file */
816 if (cp
&& (streq (cp1
, "p")
817 || streq (cp1
, "pas")))
819 Pascal_functions (inf
);
820 goto close_and_return
;
822 /* If .f or .for, assume it is fortran or nothing. */
823 if (cp
&& (streq (cp1
, "f")
824 || streq (cp1
, "for")))
826 (void) Fortran_functions (inf
);
827 goto close_and_return
;
829 /* if not a .c or .h or .y file, try fortran */
830 if (cp
&& ((cp
[1] != 'c'
833 || (cp
[1] != 0 && cp
[2] != 0)))
835 if (Fortran_functions (inf
) != 0)
836 goto close_and_return
;
837 rewind (inf
); /* no fortran tags found, try C */
839 C_entries (cplusplus
? C_PLPL
: 0, inf
);
846 /* Nonzero if string STR is composed of digits. */
849 string_numeric_p (str
)
854 if (*str
< '0' || *str
> '9')
861 /* Should take a TOKEN* instead!! */
863 pfnote (name
, is_func
, named
, linestart
, linelen
, lno
, cno
)
864 char *name
; /* tag name */
865 logical is_func
; /* function or type name? */
866 logical named
; /* tag different from text of definition? */
882 /* It's okay to output early in etags -- it only disrupts the
883 * character count of the tag entries, which is no longer used
886 error ("too many entries to sort", 0);
893 /* If ctags mode, change name "main" to M<thisfilename>. */
894 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
896 fp
= etags_strrchr (curfile
, '/');
897 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
898 fp
= etags_strrchr (name
, '.');
899 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
903 np
->name
= savestr (name
);
905 np
->is_func
= is_func
;
908 /* UNCOMMENT THE +1 HERE: */
909 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
910 np
->left
= np
->right
= 0;
913 c
= linestart
[linelen
];
914 linestart
[linelen
] = 0;
916 else if (cxref_style
== 0)
918 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
921 np
->pat
= savestr (linestart
);
924 linestart
[linelen
] = c
;
927 add_node (np
, &head
);
932 * recurse on left children, iterate on right children.
940 register NODE
*node_right
= node
->right
;
941 free_tree (node
->left
);
944 free ((char *) node
);
951 * Adds a node to the tree of nodes. In etags mode, we don't keep
952 * it sorted; we just keep a linear list. In ctags mode, maintain
953 * an ordered tree, with no attempt at balancing.
955 * add_node is the only function allowed to add nodes, so it can
958 /* Must avoid static vars within functions since some systems
959 #define static as nothing. */
960 NODE
*last_node
= NULL
;
963 add_node (node
, cur_node_p
)
964 NODE
*node
, **cur_node_p
;
967 register NODE
*cur_node
= *cur_node_p
;
969 if (cur_node
== NULL
)
979 if (last_node
== NULL
)
980 fatal ("internal error in add_node", 0);
981 last_node
->right
= node
;
987 dif
= strcmp (node
->name
, cur_node
->name
);
990 * If this tag name matches an existing one, then
991 * do not add the node, but maybe print a warning.
995 if (node
->file
== cur_node
->file
)
999 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1000 node
->file
, lineno
, node
->name
);
1001 fprintf (stderr
, "Second entry ignored\n");
1005 if (!cur_node
->been_warned
&& !no_warnings
)
1008 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1009 node
->file
, cur_node
->file
, node
->name
);
1011 cur_node
->been_warned
= TRUE
;
1015 /* Maybe refuse to add duplicate nodes. */
1016 if (!permit_duplicates
)
1018 if (streq (node
->name
, cur_node
->name
)
1019 && streq (node
->file
, cur_node
->file
))
1023 /* Actually add the node */
1024 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1030 register NODE
*node
;
1037 /* Output subentries that precede this one */
1038 put_entries (node
->left
);
1040 /* Output this entry */
1046 fprintf (tagf
, "%s\177%s\001%d,%d\n",
1047 node
->pat
, node
->name
,
1048 node
->lno
, node
->cno
);
1052 fprintf (tagf
, "%s\177%d,%d\n",
1054 node
->lno
, node
->cno
);
1057 else if (!cxref_style
)
1059 fprintf (tagf
, "%s\t%s\t",
1060 node
->name
, node
->file
);
1064 putc (searchar
, tagf
);
1067 for (sp
= node
->pat
; *sp
; sp
++)
1069 if (*sp
== '\\' || *sp
== searchar
)
1073 putc (searchar
, tagf
);
1076 { /* a typedef; text pattern inadequate */
1077 fprintf (tagf
, "%d", node
->lno
);
1081 else if (vgrind_style
)
1082 fprintf (stdout
, "%s %s %d\n",
1083 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1085 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1086 node
->name
, node
->lno
, node
->file
, node
->pat
);
1088 /* Output subentries that follow this one */
1089 put_entries (node
->right
);
1092 /* Length of a number's decimal representation. */
1100 for (; num
; num
/= 10)
1106 * Return total number of characters that put_entries will output for
1107 * the nodes in the subtree of the specified node. Works only if
1108 * we are not ctags, but called only in that case. This count
1109 * is irrelevant with the new tags.el, but is still supplied for
1110 * backward compatibility.
1113 total_size_of_entries (node
)
1114 register NODE
*node
;
1122 for (; node
; node
= node
->right
)
1124 /* Count left subentries. */
1125 total
+= total_size_of_entries (node
->left
);
1127 /* Count this entry */
1128 total
+= strlen (node
->pat
) + 1;
1129 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1131 total
+= 1 + strlen (node
->name
); /* \001name */
1138 * The C symbol tables.
1141 /* Feed stuff between (but not including) %[ and %] lines to:
1142 gperf -c -k1,3 -o -p -r -t
1144 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1146 class, C_PLPL, st_C_struct
1147 domain, C_STAR, st_C_struct
1148 union, 0, st_C_struct
1149 struct, 0, st_C_struct
1151 typedef, 0, st_C_typedef
1152 define, 0, st_C_define
1153 long, 0, st_C_typespec
1154 short, 0, st_C_typespec
1155 int, 0, st_C_typespec
1156 char, 0, st_C_typespec
1157 float, 0, st_C_typespec
1158 double, 0, st_C_typespec
1159 signed, 0, st_C_typespec
1160 unsigned, 0, st_C_typespec
1161 auto, 0, st_C_typespec
1162 void, 0, st_C_typespec
1163 extern, 0, st_C_typespec
1164 static, 0, st_C_typespec
1165 const, 0, st_C_typespec
1166 volatile, 0, st_C_typespec
1168 and replace lines between %< and %> with its output. */
1170 /* C code produced by gperf version 1.8.1 (K&R C version) */
1171 /* Command-line: gperf -c -k1,3 -o -p -r -t */
1174 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
1176 #define MIN_WORD_LENGTH 3
1177 #define MAX_WORD_LENGTH 8
1178 #define MIN_HASH_VALUE 10
1179 #define MAX_HASH_VALUE 62
1182 53 is the maximum key range
1190 static unsigned char hash_table
[] =
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, 62, 62, 62,
1201 62, 62, 62, 62, 62, 62, 62, 2, 62, 7,
1202 6, 9, 15, 30, 62, 24, 62, 62, 1, 24,
1203 7, 27, 13, 62, 19, 26, 18, 27, 1, 62,
1204 62, 62, 62, 62, 62, 62, 62, 62,
1206 return len
+ hash_table
[str
[2]] + hash_table
[str
[0]];
1209 struct C_stab_entry
*
1210 in_word_set (str
, len
)
1215 static struct C_stab_entry wordlist
[] =
1217 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1219 {"volatile", 0, st_C_typespec
},
1221 {"long", 0, st_C_typespec
},
1222 {"char", 0, st_C_typespec
},
1223 {"class", C_PLPL
, st_C_struct
},
1224 {"",}, {"",}, {"",}, {"",},
1225 {"const", 0, st_C_typespec
},
1226 {"",}, {"",}, {"",}, {"",},
1227 {"auto", 0, st_C_typespec
},
1229 {"define", 0, st_C_define
},
1231 {"void", 0, st_C_typespec
},
1232 {"",}, {"",}, {"",},
1233 {"extern", 0, st_C_typespec
},
1234 {"static", 0, st_C_typespec
},
1236 {"domain", C_STAR
, st_C_struct
},
1238 {"typedef", 0, st_C_typedef
},
1239 {"double", 0, st_C_typespec
},
1240 {"enum", 0, st_C_enum
},
1241 {"",}, {"",}, {"",}, {"",},
1242 {"int", 0, st_C_typespec
},
1244 {"float", 0, st_C_typespec
},
1245 {"",}, {"",}, {"",},
1246 {"struct", 0, st_C_struct
},
1247 {"",}, {"",}, {"",}, {"",},
1248 {"union", 0, st_C_struct
},
1250 {"short", 0, st_C_typespec
},
1252 {"unsigned", 0, st_C_typespec
},
1253 {"signed", 0, st_C_typespec
},
1256 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
1258 register int key
= hash (str
, len
);
1260 if (key
<= MAX_HASH_VALUE
&& key
>= MIN_HASH_VALUE
)
1262 register char *s
= wordlist
[key
].name
;
1264 if (*s
== *str
&& strneq (str
+ 1, s
+ 1, len
- 1))
1265 return &wordlist
[key
];
1273 C_symtype(str
, len
, c_ext
)
1278 register struct C_stab_entry
*se
= in_word_set(str
, len
);
1280 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
1286 * C functions are recognized using a simple finite automaton.
1287 * funcdef is its state variable.
1291 fnone
, /* nothing seen */
1292 ftagseen
, /* function-like tag seen */
1293 fstartlist
, /* just after open parenthesis */
1294 finlist
, /* in parameter list */
1295 flistseen
, /* after parameter list */
1296 fignore
/* before open brace */
1302 * typedefs are recognized using a simple finite automaton.
1303 * typeddef is its state variable.
1307 tnone
, /* nothing seen */
1308 ttypedseen
, /* typedef keyword seen */
1309 tinbody
, /* inside typedef body */
1310 tend
, /* just before typedef tag */
1311 tignore
/* junk after typedef tag */
1317 * struct-like structures (enum, struct and union) are recognized
1318 * using another simple finite automaton. `structdef' is its state
1323 snone
, /* nothing seen yet */
1324 skeyseen
, /* struct-like keyword seen */
1325 stagseen
, /* struct-like tag seen */
1326 scolonseen
, /* colon seen after struct-like tag */
1327 sinbody
/* in struct body: recognize member func defs*/
1332 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1333 * struct tag, and structtype is the type of the preceding struct-like
1336 char structtag
[BUFSIZ
];
1337 enum sym_type structtype
;
1340 * Yet another little state machine to deal with preprocessor lines.
1344 dnone
, /* nothing seen */
1345 dsharpseen
, /* '#' seen as first char on line */
1346 ddefineseen
, /* '#' and 'define' seen */
1347 dignorerest
/* ignore rest of line */
1352 * Set this to TRUE, and the next token considered is called a function.
1353 * Used only for GNUmacs's function-defining macros.
1355 logical next_token_is_func
;
1358 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1364 * checks to see if the current token is at the start of a
1365 * function, or corresponds to a typedef, or is a struct/union/enum
1368 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1369 * C_EXT is which language we are looking at.
1371 * In the future we will need some way to adjust where the end of
1372 * the token is; for instance, implementing the C++ keyword
1373 * `operator' properly will adjust the end of the token to be after
1374 * whatever follows `operator'.
1381 * next_token_is_func IN OUT
1385 consider_token (c
, tokp
, c_ext
, cblev
, is_func
)
1386 register char c
; /* IN: first char after the token */
1387 register TOKEN
*tokp
; /* IN: token pointer */
1388 int c_ext
; /* IN: C extensions mask */
1389 int cblev
; /* IN: curly brace level */
1390 logical
*is_func
; /* OUT */
1392 enum sym_type toktype
= C_symtype(tokp
->p
, tokp
->len
, c_ext
);
1395 * Advance the definedef state machine.
1400 /* We're not on a preprocessor line. */
1403 if (toktype
== st_C_define
)
1405 definedef
= ddefineseen
;
1409 definedef
= dignorerest
;
1414 * Make a tag for any macro.
1416 definedef
= dignorerest
;
1417 *is_func
= (c
== '(');
1418 if (!*is_func
&& !constantypedefs
)
1425 error ("internal error: definedef value.", 0);
1434 if (toktype
== st_C_typedef
)
1437 typdef
= ttypedseen
;
1453 /* Do not return here, so the structdef stuff has a chance. */
1467 * This structdef business is currently only invoked when cblev==0.
1468 * It should be recursively invoked whatever the curly brace level,
1469 * and a stack of states kept, to allow for definitions of structs
1472 * This structdef business is NOT invoked when we are ctags and the
1473 * file is plain C. This is because a struct tag may have the same
1474 * name as another tag, and this loses with ctags.
1476 * This if statement deals with the typdef state machine as
1477 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1478 * return (FALSE). All the other code here is for the structdef
1485 if (typdef
== ttypedseen
1486 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1488 structdef
= skeyseen
;
1489 structtype
= toktype
;
1493 if (structdef
== skeyseen
)
1495 if (structtype
== st_C_struct
)
1497 strncpy (structtag
, tokp
->p
, tokp
->len
);
1498 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1502 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1504 structdef
= stagseen
;
1508 /* Avoid entering funcdef stuff if typdef is going on. */
1509 if (typdef
!= tnone
)
1515 /* Detect GNUmacs's function-defining macros. */
1516 if (definedef
== dnone
)
1518 if (strneq (tokp
->p
, "DEF", 3)
1519 || strneq (tokp
->p
, "ENTRY", 5)
1520 || strneq (tokp
->p
, "SYSCALL", 7)
1521 || strneq (tokp
->p
, "PSEUDO", 6))
1523 next_token_is_func
= TRUE
;
1526 if (strneq (tokp
->p
, "EXFUN", 5))
1528 next_token_is_func
= FALSE
;
1532 if (next_token_is_func
)
1534 next_token_is_func
= FALSE
;
1536 *is_func
= TRUE
; /* to force search string in ctags */
1544 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1545 funcdef
= fnone
; /* should be useless */
1548 if (funcdef
== fnone
)
1561 * This routine finds functions, typedefs, #define's and
1562 * struct/union/enum definitions in C syntax and adds them
1566 #define curlb (lbs[curndx].lb)
1567 #define othlb (lbs[1-curndx].lb)
1568 #define newlb (lbs[newndx].lb)
1569 #define curlinepos (lbs[curndx].linepos)
1570 #define othlinepos (lbs[1-curndx].linepos)
1571 #define newlinepos (lbs[newndx].linepos)
1573 /* Save and restore token state. This is used when preprocessor defines
1574 are handled, to avoid disturbing active function/typedef/struct states. */
1575 #define TOKEN_SAVED_P (savetok.lineno > 0)
1576 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1577 savetok.len = toklen, strcpy(savenameb, nameb))
1578 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1579 toklen = tok.len, strcpy(nameb, savenameb), \
1582 #define CNL_SAVE_DEFINEDEF \
1584 SET_FILEPOS (curlinepos, inf, charno); \
1586 charno += readline (&curlb, inf); \
1587 lp = curlb.buffer; \
1594 CNL_SAVE_DEFINEDEF; \
1595 if (TOKEN_SAVED_P) \
1597 definedef = dnone; \
1600 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1601 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1602 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1603 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1606 C_entries (c_ext
, inf
)
1607 int c_ext
; /* extension of C? */
1610 register char c
; /* latest char read; '\0' for end of line */
1611 register char *lp
; /* pointer one beyond the character `c' */
1612 int curndx
, newndx
; /* indices for current and new lb */
1613 TOKEN tok
; /* latest token read for funcdef & structdef */
1614 char nameb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1615 register int tokoff
; /* offset in line of start of latest token */
1616 register int toklen
; /* length of latest token */
1617 int cblev
; /* current curly brace level */
1618 int parlev
; /* current parenthesis level */
1619 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1621 TOKEN savetok
; /* saved token during preprocessor handling */
1622 char savenameb
[BUFSIZ
]; /* ouch! */
1625 curndx
= newndx
= 0;
1631 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1632 next_token_is_func
= yacc_rules
= FALSE
;
1633 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1636 cplpl
= c_ext
& C_PLPL
;
1643 /* If we're at the end of the line, the next character is a
1644 '\0'; don't skip it, because it's the thing that tells us
1645 to read the next line. */
1666 /* Newlines inside comments do not end macro definitions in
1681 /* Newlines inside strings do not end macro definitions
1682 in traditional cpp, even though compilers don't
1683 usually accept them. */
1694 /* Hmmm, something went wrong. */
1708 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1713 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1723 else if (cplpl
&& *lp
== '/')
1731 if ((c_ext
& YACC
) && *lp
== '%')
1733 /* entering or exiting rules section in yacc file */
1735 definedef
= dnone
; funcdef
= fnone
;
1736 typdef
= tnone
; structdef
= snone
;
1737 next_token_is_func
= FALSE
;
1738 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1740 yacc_rules
= !yacc_rules
;
1746 if (lp
== newlb
.buffer
+ 1 && definedef
== dnone
)
1747 definedef
= dsharpseen
;
1752 /* Consider token only if some complicated conditions are satisfied. */
1753 if (((cblev
== 0 && structdef
!= scolonseen
)
1754 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
1755 && typdef
!= tignore
1756 && definedef
!= dignorerest
1757 && (funcdef
!= finlist
1758 || definedef
!= dnone
))
1764 if (cplpl
&& c
== ':' && *lp
== ':' && begtoken(*(lp
+ 1)))
1767 * This handles :: in the middle, but not at beginning
1775 logical is_func
= FALSE
;
1777 tok
.lineno
= lineno
;
1778 tok
.p
= newlb
.buffer
+ tokoff
;
1782 || consider_token (c
, &tok
, c_ext
, cblev
, &is_func
))
1784 if (structdef
== sinbody
1785 && definedef
== dnone
1787 /* function defined in C++ class body */
1790 sprintf (nameb
, "%s::%.*s",
1791 ((structtag
[0] == '\0')
1792 ? "_anonymous_" : structtag
),
1797 sprintf (nameb
, "%.*s", tok
.len
, tok
.p
);
1800 if (structdef
== stagseen
1804 if (definedef
== dnone
1805 && (funcdef
== ftagseen
1806 || structdef
== stagseen
1809 if (newndx
== curndx
)
1810 curndx
= 1 - curndx
; /* switch line buffers */
1813 MAKE_TAG_FROM_NEW_LB (is_func
);
1817 } /* if (endtoken (c)) */
1818 else if (intoken (c
))
1823 } /* if (midtoken) */
1824 else if (begtoken (c
))
1835 MAKE_TAG_FROM_OTH_LB (TRUE
);
1842 if (structdef
== stagseen
)
1846 /* Take a quick peek ahead for define directive,
1847 so we can avoid saving the token when not absolutely
1848 necessary. [This is a speed hack.] */
1849 if (c
== 'd' && strneq(lp
, "efine", 5)
1850 && iswhite(*(lp
+ 5)))
1853 definedef
= ddefineseen
;
1857 definedef
= dignorerest
;
1860 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1862 tokoff
= lp
- 1 - newlb
.buffer
;
1868 } /* if must look at token */
1871 /* Detect end of line, colon, comma, semicolon and various braces
1872 after having handled a token.*/
1876 if (definedef
!= dnone
)
1878 if (structdef
== stagseen
)
1879 structdef
= scolonseen
;
1886 MAKE_TAG_FROM_OTH_LB (FALSE
);
1896 if (definedef
!= dnone
)
1902 MAKE_TAG_FROM_OTH_LB (FALSE
);
1907 if (funcdef
!= fignore
)
1909 if (structdef
== stagseen
)
1913 if (definedef
!= dnone
)
1915 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1917 if (structdef
== stagseen
)
1921 if (definedef
!= dnone
)
1923 if (cblev
== 0 && typdef
== tend
)
1926 MAKE_TAG_FROM_OTH_LB (FALSE
);
1929 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1931 if (structdef
== stagseen
)
1935 if (definedef
!= dnone
)
1940 funcdef
= fstartlist
;
1949 if (definedef
!= dnone
)
1957 funcdef
= flistseen
;
1960 if (cblev
== 0 && typdef
== tend
)
1963 MAKE_TAG_FROM_OTH_LB (FALSE
);
1966 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
1970 if (definedef
!= dnone
)
1972 if (typdef
== ttypedseen
)
1976 case skeyseen
: /* unnamed struct */
1977 structtag
[0] = '\0';
1978 structdef
= sinbody
;
1981 case scolonseen
: /* named struct */
1982 structdef
= sinbody
;
1983 MAKE_TAG_FROM_OTH_LB (FALSE
);
1989 MAKE_TAG_FROM_OTH_LB (TRUE
);
1995 /* Neutralize `extern "C" {' grot.
1996 if (cblev == 0 && structdef == snone && typdef == tnone)
2002 if (definedef
!= dnone
)
2004 if (funcdef
== fstartlist
)
2005 funcdef
= fnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
2008 if (definedef
!= dnone
)
2010 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
2012 cblev
= 0; /* reset curly brace level if first column */
2013 parlev
= 0; /* also reset paren level, just in case... */
2019 if (typdef
== tinbody
)
2022 strcpy (structtag
, "<error 2>");
2026 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
2027 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
2028 if (definedef
!= dnone
)
2030 /* These surely cannot follow a function tag. */
2031 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2035 /* If a macro spans multiple lines don't reset its state. */
2043 } /* while not eof */
2046 /* Fortran parsing */
2055 register int len
= 0;
2057 while (*cp
&& (*cp
| ' ') == (dbp
[len
] | ' '))
2070 while (isspace (*dbp
))
2075 while (isspace (*dbp
))
2077 if (!isdigit (*dbp
))
2079 --dbp
; /* force failure */
2084 while (isdigit (*dbp
));
2093 char nambuf
[BUFSIZ
];
2095 while (isspace (*dbp
))
2100 linecharno
= charno
;
2101 charno
+= readline (&lb
, inf
);
2106 while (isspace (*dbp
))
2115 && (isalpha (*cp
) || isdigit (*cp
) || (*cp
== '_') || (*cp
== '$')));
2120 strcpy (nambuf
, dbp
);
2122 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2123 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2128 Fortran_functions (inf
)
2138 linecharno
= charno
;
2139 charno
+= readline (&lb
, inf
);
2142 dbp
++; /* Ratfor escape to fortran */
2143 while (isspace (*dbp
))
2150 if (tail ("integer"))
2158 if (tail ("logical"))
2162 if (tail ("complex") || tail ("character"))
2166 if (tail ("double"))
2168 while (isspace (*dbp
))
2172 if (tail ("precision"))
2178 while (isspace (*dbp
))
2185 if (tail ("function"))
2189 if (tail ("subroutine"))
2197 if (tail ("program"))
2202 if (tail ("procedure"))
2211 * Bob Weiner, Motorola Inc., 4/3/94
2212 * Unix and microcontroller assembly tag handling
2213 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
2219 char nambuf
[BUFSIZ
];
2230 linecharno
= charno
;
2231 charno
+= readline (&lb
, inf
);
2234 /* If first char is alphabetic or one of [_.$], test for colon
2235 following identifier. */
2236 if (isalpha (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2238 /* Read past label. */
2240 while (isalnum (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2242 if (*cp
== ':' || isspace (*cp
))
2244 /* Found end of label, so copy it and add it to the table. */
2247 strcpy (nambuf
, lb
.buffer
);
2249 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2250 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2257 /* Added by Mosur Mohan, 4/22/88 */
2258 /* Pascal parsing */
2260 #define GET_NEW_LINE \
2262 linecharno = charno; lineno++; \
2263 charno += 1 + readline (&lb, inf); \
2267 /* Locates tags for procedures & functions.
2268 * Doesn't do any type- or var-definitions.
2269 * It does look for the keyword "extern" or "forward"
2270 * immediately following the procedure statement;
2271 * if found, the tag is skipped.
2275 Pascal_functions (inf
)
2278 struct linebuffer tline
; /* mostly copied from C_entries */
2282 char nambuf
[BUFSIZ
];
2284 logical
/* each of these flags is TRUE iff: */
2285 incomm1
, /* point is inside {..} comment */
2286 incomm2
, /* point is inside (*..*) comment */
2287 inquote
, /* point is inside '..' string */
2288 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2289 /* keyword, so next item = potential tag */
2290 found_tag
, /* point is after a potential tag */
2291 inparms
, /* point is within parameter-list */
2292 verify_tag
; /* point has passed the parm-list, so the */
2293 /* next token will determine whether */
2294 /* this is a FORWARD/EXTERN to be */
2295 /* ignored, or whether it is a real tag */
2301 initbuffer (&tline
);
2303 incomm1
= incomm2
= inquote
= FALSE
;
2304 found_tag
= FALSE
; /* have a proc name; check if extern */
2305 get_tagname
= FALSE
; /* have found "procedure" keyword */
2306 inparms
= FALSE
; /* found '(' after "proc" */
2307 verify_tag
= FALSE
; /* check if "extern" is ahead */
2309 /* long main loop to get next char */
2313 if (c
== 0) /* if end of line */
2318 if (!((found_tag
&& verify_tag
) ||
2320 c
= *dbp
++; /* only if don't need *dbp pointing */
2321 /* to the beginning of the name of */
2322 /* the procedure or function */
2324 if (incomm1
) /* within { - } comments */
2330 else if (incomm2
) /* within (* - *) comments */
2334 while ((c
= *dbp
++) == '*')
2353 inquote
= TRUE
; /* found first quote */
2355 case '{': /* found open-{-comment */
2359 if (*dbp
== '*') /* found open-(*-comment */
2364 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2367 case ')': /* end of parms list */
2372 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2379 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2381 /* check if this is an "extern" declaration */
2384 if ((*dbp
== 'e') || (*dbp
== 'E'))
2386 if (tail ("extern")) /* superfluous, really! */
2392 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2394 if (tail ("forward")) /* check for forward reference */
2400 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2404 pfnote (nambuf
, TRUE
, FALSE
,
2405 tline
.buffer
, cp
- tline
.buffer
+ 1,
2406 save_lineno
, save_lcno
);
2410 if (get_tagname
) /* grab name of proc or fn */
2415 /* save all values for later tagging */
2416 tline
.size
= lb
.size
;
2417 strcpy (tline
.buffer
, lb
.buffer
);
2418 save_lineno
= lineno
;
2419 save_lcno
= linecharno
;
2421 /* grab block name */
2422 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2426 strcpy (nambuf
, dbp
);
2428 dbp
= cp
; /* restore dbp to e-o-token */
2429 get_tagname
= FALSE
;
2433 /* and proceed to check for "extern" */
2435 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2436 (!found_tag
) && (!get_tagname
))
2438 /* check for proc/fn keywords */
2442 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2446 if (tail ("unction"))
2451 } /* while not eof */
2455 * lisp tag functions
2456 * just look for (def or (DEF
2463 return ((dbp
[1] == 'd' || dbp
[1] == 'D')
2464 && (dbp
[2] == 'e' || dbp
[2] == 'E')
2465 && (dbp
[3] == 'f' || dbp
[3] == 'F'));
2472 return ((*(++dbp
) == 'q' || *dbp
== 'Q')
2473 && (*(++dbp
) == 'u' || *dbp
== 'U')
2474 && (*(++dbp
) == 'o' || *dbp
== 'O')
2475 && (*(++dbp
) == 't' || *dbp
== 'T')
2476 && (*(++dbp
) == 'e' || *dbp
== 'E')
2477 && isspace(*(++dbp
)));
2485 char nambuf
[BUFSIZ
];
2487 if (*dbp
== '\'') /* Skip prefix quote */
2489 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2492 while (isspace(*dbp
))
2495 for (cp
= dbp
/*+1*/; *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')'; cp
++)
2502 strcpy (nambuf
, dbp
);
2504 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2505 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2510 Lisp_functions (inf
)
2520 linecharno
= charno
;
2521 charno
+= readline (&lb
, inf
);
2527 while (!isspace (*dbp
))
2529 while (isspace (*dbp
))
2535 /* Check for (foo::defmumble name-defined ... */
2538 while (*dbp
&& !isspace (*dbp
)
2539 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2544 while (*dbp
== ':');
2546 if (L_isdef (dbp
- 1))
2548 while (!isspace (*dbp
))
2550 while (isspace (*dbp
))
2561 * Scheme tag functions
2562 * look for (def... xyzzy
2563 * look for (def... (xyzzy
2564 * look for (def ... ((...(xyzzy ....
2565 * look for (set! xyzzy
2571 Scheme_functions (inf
)
2581 linecharno
= charno
;
2582 charno
+= readline (&lb
, inf
);
2584 if (dbp
[0] == '(' &&
2585 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2586 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2587 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2589 while (!isspace (*dbp
))
2591 /* Skip over open parens and white space */
2592 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2596 if (dbp
[0] == '(' &&
2597 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2598 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2599 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2600 (dbp
[4] == '!' || dbp
[4] == '!') &&
2603 while (!isspace (*dbp
))
2605 /* Skip over white space */
2606 while (isspace (*dbp
))
2618 char nambuf
[BUFSIZ
];
2622 /* Go till you get to white space or a syntactic break */
2623 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2625 /* Null terminate the string there. */
2628 /* Copy the string */
2629 strcpy (nambuf
, dbp
);
2630 /* Unterminate the string */
2632 /* Announce the change */
2633 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2637 /* Find tags in TeX and LaTeX input files. */
2639 /* TEX_toktab is a table of TeX control sequences that define tags.
2640 Each TEX_tabent records one such control sequence.
2641 CONVERT THIS TO USE THE Stab TYPE!! */
2649 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2651 /* Default set of control sequences to put into TEX_toktab.
2652 The value of environment var TEXTAGS is prepended to this. */
2654 char *TEX_defenv
= "\
2655 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2658 struct TEX_tabent
*TEX_decode_env ();
2662 char TEX_esc
= '\\';
2663 char TEX_opgrp
= '{';
2664 char TEX_clgrp
= '}';
2667 * TeX/LaTeX scanning loop.
2680 /* Select either \ or ! as escape character. */
2683 /* Initialize token table once from environment. */
2685 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2688 { /* Scan each line in file */
2690 linecharno
= charno
;
2691 charno
+= readline (&lb
, inf
);
2694 while (dbp
= etags_strchr (dbp
, TEX_esc
)) /* Look at each esc in line */
2700 linecharno
+= dbp
- lasthit
;
2702 i
= TEX_Token (lasthit
);
2705 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2706 break; /* We only save a line once */
2712 #define TEX_LESC '\\'
2713 #define TEX_SESC '!'
2716 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2717 /* chars accordingly. */
2725 while ((c
= getc (inf
)) != EOF
)
2727 /* Skip to next line if we hit the TeX comment char. */
2731 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2750 /* Read environment and prepend it to the default string. */
2751 /* Build token table. */
2754 TEX_decode_env (evarname
, defenv
)
2758 register char *env
, *p
;
2760 struct TEX_tabent
*tab
;
2763 /* Append default string to environment. */
2764 env
= getenv (evarname
);
2768 env
= concat (env
, defenv
, "");
2770 /* Allocate a token table */
2771 for (size
= 1, p
= env
; p
;)
2772 if ((p
= etags_strchr (p
, ':')) && *(++p
))
2774 /* Add 1 to leave room for null terminator. */
2775 tab
= xnew (size
+ 1, struct TEX_tabent
);
2777 /* Unpack environment string into token table. Be careful about */
2778 /* zero-length strings (leading ':', "::" and trailing ':') */
2781 p
= etags_strchr (env
, ':');
2782 if (!p
) /* End of environment string. */
2783 p
= env
+ strlen (env
);
2785 { /* Only non-zero strings. */
2786 tab
[i
].name
= savenstr (env
, p
- env
);
2787 tab
[i
].len
= strlen (tab
[i
].name
);
2794 tab
[i
].name
= NULL
; /* Mark end of table. */
2802 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2803 The name being defined actually starts at (NAME + LEN + 1).
2804 But we seem to include the TeX command in the tag name. */
2807 TEX_getit (name
, len
)
2811 char *p
= name
+ len
;
2812 char nambuf
[BUFSIZ
];
2817 /* Let tag name extend to next group close (or end of line) */
2818 while (*p
&& *p
!= TEX_clgrp
)
2820 strncpy (nambuf
, name
, p
- name
);
2821 nambuf
[p
- name
] = 0;
2823 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2827 /* If the text at CP matches one of the tag-defining TeX command names,
2828 return the pointer to the first occurrence of that command in TEX_toktab.
2829 Otherwise return -1. */
2831 /* Keep the capital `T' in `Token' for dumb truncating compilers
2832 (this distinguishes it from `TEX_toktab' */
2839 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2840 if (strneq (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
))
2845 /* Support for Prolog. */
2847 /* whole head (not only functor, but also arguments)
2848 is gotten in compound term. */
2851 prolog_getit (s
, lineno
, linecharno
)
2856 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2864 if (*s
== '\0') /* syntax error. */
2866 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2868 else if (*s
== '\'')
2870 insquote
= !insquote
;
2873 else if (!insquote
&& *s
== '(')
2878 else if (!insquote
&& *s
== ')')
2884 else if (npar
< 0) /* syntax error. */
2887 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2889 if (npar
!= 0) /* syntax error. */
2899 strcpy (nambuf
, save_s
);
2901 pfnote (nambuf
, TRUE
, FALSE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2904 /* It is assumed that prolog predicate starts from column 0. */
2907 Prolog_functions (inf
)
2910 void skip_comment (), prolog_getit ();
2912 lineno
= linecharno
= charno
= 0;
2916 linecharno
+= charno
;
2917 charno
= readline (&lb
, inf
) + 1; /* 1 for newline. */
2919 if (isspace (dbp
[0])) /* not predicate header. */
2921 else if (dbp
[0] == '%') /* comment. */
2923 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2924 skip_comment (&lb
, inf
, &lineno
, &linecharno
);
2926 prolog_getit (dbp
, lineno
, linecharno
);
2931 skip_comment (plb
, inf
, plineno
, plinecharno
)
2932 struct linebuffer
*plb
;
2934 int *plineno
; /* result */
2935 long *plinecharno
; /* result */
2937 while (!substr ("*/", plb
->buffer
))
2940 *plinecharno
+= readline (plb
, inf
) + 1;
2941 } /* 1 for newline. */
2944 /* Return TRUE if 'sub' exists somewhere in 's'. */
2951 while (*s
&& (s
= etags_strchr (s
, *sub
)))
2952 if (prestr (sub
, s
))
2959 /* Return TRUE if 'pre' is prefix of string 's'. */
2968 else if (*pre
== *s
)
2969 return (prestr (pre
+ 1, s
+ 1));
2974 /* Initialize a linebuffer for use */
2977 initbuffer (linebuffer
)
2978 struct linebuffer
*linebuffer
;
2980 linebuffer
->size
= 200;
2981 linebuffer
->buffer
= xnew (200, char);
2985 * Read a line of text from `stream' into `linebuffer'.
2986 * Return the number of characters read from `stream',
2987 * which is the length of the line including the newline, if any.
2990 readline (linebuffer
, stream
)
2991 struct linebuffer
*linebuffer
;
2992 register FILE *stream
;
2994 char *buffer
= linebuffer
->buffer
;
2995 register char *p
= linebuffer
->buffer
;
2996 register char *pend
;
2997 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2999 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
3003 register int c
= getc (stream
);
3006 linebuffer
->size
*= 2;
3007 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
3008 p
+= buffer
- linebuffer
->buffer
;
3009 pend
= buffer
+ linebuffer
->size
;
3010 linebuffer
->buffer
= buffer
;
3012 if (c
== EOF
|| c
== '\n')
3015 newline
= (c
== '\n') ? 1 : 0;
3021 return p
- buffer
+ newline
;
3028 return savenstr (cp
, strlen (cp
));
3038 dp
= xnew (len
+ 1, char);
3039 strncpy (dp
, cp
, len
);
3045 * Return the ptr in sp at which the character c last
3046 * appears; NULL if not found
3048 * Identical to System V strrchr, included for portability.
3052 etags_strrchr (sp
, c
)
3053 register char *sp
, c
;
3068 * Return the ptr in sp at which the character c first
3069 * appears; NULL if not found
3071 * Identical to System V strchr, included for portability.
3075 etags_strchr (sp
, c
)
3076 register char *sp
, c
;
3086 /* Print error message and exit. */
3097 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3104 fprintf (stderr
, "%s: ", progname
);
3105 fprintf (stderr
, s1
, s2
);
3106 fprintf (stderr
, "\n");
3109 /* Return a newly-allocated string whose contents
3110 concatenate those of s1, s2, s3. */
3116 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3117 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3119 strcpy (result
, s1
);
3120 strcpy (result
+ len1
, s2
);
3121 strcpy (result
+ len1
+ len2
, s3
);
3122 result
[len1
+ len2
+ len3
] = '\0';
3131 char *p
, cwd
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
3138 *p
++ = tolower (*p
);
3139 return strdup (cwd
);
3141 #else /* not MSDOS */
3142 /* Does the same work as the system V getcwd, but does not need to
3143 guess buffer size in advance. Included mostly for compatibility. */
3153 buf
= xnew (bufsize
, char);
3155 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
3161 if (fgets (buf
, bufsize
, pipe
) == NULL
)
3170 } while (buf
[strlen (buf
) - 1] != '\n');
3174 #endif /* not MSDOS */
3176 /* Return a newly allocated string containing the filename
3177 of FILE relative to the absolute directory DIR (which
3178 should end with a slash). */
3181 relative_filename (file
, dir
)
3184 char *fp
, *dp
, *res
;
3186 /* Find the common root of file and dir. */
3187 fp
= absolute_filename (file
, cwd
);
3189 while (*fp
++ == *dp
++)
3198 /* Build a sequence of "../" strings for the resulting relative filename. */
3199 for (dp
= etags_strchr (dp
+ 1, '/'), res
= "";
3201 dp
= etags_strchr (dp
+ 1, '/'))
3203 res
= concat (res
, "../", "");
3206 /* Add the filename relative to the common root of file and dir. */
3207 res
= concat (res
, fp
+ 1, "");
3209 return res
; /* temporary stub */
3212 /* Return a newly allocated string containing the
3213 absolute filename of FILE given CWD (which should
3214 end with a slash). */
3217 absolute_filename (file
, cwd
)
3220 char *slashp
, *cp
, *res
;
3223 res
= concat (file
, "", "");
3225 res
= concat (cwd
, file
, "");
3227 /* Delete the "/dirname/.." and "/." substrings. */
3228 slashp
= etags_strchr (res
, '/');
3229 while (slashp
!= NULL
&& slashp
[0] != '\0')
3231 if (slashp
[1] == '.')
3233 if (slashp
[2] == '.'
3234 && (slashp
[3] == '/' || slashp
[3] == '\0'))
3239 while (cp
>= res
&& *cp
!= '/');
3242 strcpy (cp
, slashp
+ 3);
3244 else /* else (cp == res) */
3246 if (slashp
[3] != '\0')
3247 strcpy (cp
, slashp
+ 4);
3253 else if (slashp
[2] == '/' || slashp
[2] == '\0')
3255 strcpy (slashp
, slashp
+ 2);
3260 slashp
= etags_strchr (slashp
+ 1, '/');
3267 /* Return a newly allocated string containing the absolute
3268 filename of dir where FILE resides given CWD (which should
3269 end with a slash). */
3272 absolute_dirname (file
, cwd
)
3278 slashp
= etags_strrchr (file
, '/');
3283 res
= absolute_filename (file
, cwd
);
3289 /* Like malloc but get fatal error if memory is exhausted. */
3295 char *result
= (char *) malloc (size
);
3297 fatal ("virtual memory exhausted", 0);
3302 xrealloc (ptr
, size
)
3306 char *result
= (char *) realloc (ptr
, size
);
3308 fatal ("virtual memory exhausted");