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>
42 #define MAXPATHLEN _MAX_PATH
46 #include <../src/config.h>
47 /* On some systems, Emacs defines static as nothing
48 for the sake of unexec. We don't want that here
49 since we don't use unexec. */
59 #include <sys/types.h>
62 #if !defined (S_ISREG) && defined (S_IFREG)
63 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
68 extern char *getenv ();
70 /* Define CTAGS to make the program "ctags" compatible with the usual one.
71 Let it undefined to make the program "etags", which makes emacs-style
72 tag tables and tags typedefs, #defines and struct/union/enum by default. */
80 /* Exit codes for success and failure. */
90 * The FILEPOS abstract type, which represents a position in a file,
91 * plus the following accessor functions:
93 * long GET_CHARNO (pos)
94 * returns absolute char number.
95 * void SET_FILEPOS (pos, fp, charno)
96 * FILE *fp; long charno;
97 * sets `pos' from the current file
98 * position of `fp' and from `charno',
99 * which must be the absolute character
100 * number corresponding to the current
103 * The `pos' parameter is an lvalue expression of type FILEPOS.
104 * Parameters to the accessor functions are evaluated 0 or more times,
105 * and so must have no side effects.
107 * FILEPOS objects can also be assigned and passed to and from
108 * functions in the normal C manner.
110 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
114 /* real implementation */
115 typedef long FILEPOS
;
116 #define GET_CHARNO(pos) ((pos) + 0)
117 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
119 /* debugging implementation */
125 #define GET_CHARNO(pos) ((pos).charno + 0)
126 #define SET_FILEPOS(pos, fp, cno) \
127 ((void) ((pos).charno = (cno), \
128 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
132 #define streq(s, t) (strcmp (s, t) == 0)
133 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
139 #define iswhite(arg) (_wht[arg]) /* T if char is white */
140 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
141 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
142 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
144 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
147 { /* sorting structure */
148 char *name
; /* function or type name */
149 char *file
; /* file name */
150 logical is_func
; /* use pattern or line no */
151 logical named
; /* list name separately */
152 logical been_warned
; /* set if noticed dup */
153 int lno
; /* line number tag is on */
154 long cno
; /* character number line starts on */
155 char *pat
; /* search pattern */
156 struct nd_st
*left
, *right
; /* left and right sons */
159 typedef struct nd_st NODE
;
161 logical header_file
; /* TRUE if .h file, FALSE o.w. */
162 /* boolean "functions" (see init) */
163 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
165 char *cwd
; /* current working directory */
166 char *tagfiledir
; /* directory of tagfile */
169 char *savenstr (), *savestr ();
170 char *etags_strchr (), *etags_strrchr ();
171 char *etags_getcwd ();
172 char *relative_filename (), *absolute_filename (), *absolute_dirname ();
173 char *xmalloc (), *xrealloc ();
174 int total_size_of_entries ();
175 int string_numeric_p ();
182 int Fortran_functions ();
183 void Lisp_functions ();
184 void Pascal_functions ();
185 void Prolog_functions ();
186 void Scheme_functions ();
187 void TeX_functions ();
191 logical
find_entries ();
198 void process_file ();
204 * xnew -- allocate storage
207 * Type *xnew (int n, Type);
209 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
212 * Symbol table types.
216 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
233 #define C_PLPL 0x00001 /* C++ */
234 #define C_STAR 0x00003 /* C* */
235 #define YACC 0x10000 /* yacc file */
237 char searchar
= '/'; /* use /.../ searches */
239 LINENO lineno
; /* line number of current line */
240 long charno
; /* current character number */
242 long linecharno
; /* charno of start of line; not used by C, but
243 * by every other language.
246 char *curfile
, /* current input file name */
247 *tagfile
, /* output file */
248 *white
= " \f\t\n\013", /* white chars */
249 *endtk
= " \t\n\013\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
250 /* token starting chars */
251 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
252 /* valid in-token chars */
253 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
255 int append_to_tagfile
; /* -a: append to tags */
256 /* The following three default to 1 for etags, but to 0 for ctags. */
257 int typedefs
; /* -t: create tags for typedefs */
258 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
259 /* 0 struct/enum/union decls, and C++ */
260 /* member functions. */
261 int constantypedefs
; /* -d: create tags for C #define and enum */
262 /* constants. Enum consts not implemented. */
263 /* -D: opposite of -d. Default under ctags. */
264 int update
; /* -u: update tags */
265 int vgrind_style
; /* -v: create vgrind style index output */
266 int no_warnings
; /* -w: suppress warnings */
267 int cxref_style
; /* -x: create cxref style output */
268 int cplusplus
; /* .[hc] means C++, not C */
269 int noindentypedefs
; /* -S: ignore indentation in C */
271 /* Name this program was invoked with. */
274 struct option longopts
[] = {
275 { "append", no_argument
, NULL
, 'a' },
276 { "backward-search", no_argument
, NULL
, 'B' },
277 { "c++", no_argument
, NULL
, 'C' },
278 { "cxref", no_argument
, NULL
, 'x' },
279 { "defines", no_argument
, NULL
, 'd' },
280 { "help", no_argument
, NULL
, 'H' },
281 { "ignore-indentation", no_argument
, NULL
, 'S' },
282 { "include", required_argument
, NULL
, 'i' },
283 { "no-defines", no_argument
, NULL
, 'D' },
284 { "no-warn", no_argument
, NULL
, 'w' },
285 { "output", required_argument
, NULL
, 'o' },
286 { "typedefs", no_argument
, NULL
, 't' },
287 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
288 { "update", no_argument
, NULL
, 'u' },
289 { "version", no_argument
, NULL
, 'V' },
290 { "vgrind", no_argument
, NULL
, 'v' },
294 FILE *tagf
; /* ioptr for tags file */
295 NODE
*head
; /* the head of the binary tree of tags */
296 logical permit_duplicates
= TRUE
; /* allow duplicate tags */
298 /* A `struct linebuffer' is a structure which holds a line of text.
299 `readline' reads a line from a stream into a linebuffer
300 and works regardless of the length of the line. */
308 struct linebuffer lb
; /* the current line */
309 struct linebuffer filename_lb
; /* used to read in filenames */
313 struct linebuffer lb
; /* used by C_entries instead of lb */
320 printf ("%s for Emacs version %s.\n", (CTAGS
) ? "CTAGS" : "ETAGS", VERSION
);
322 printf ("%s for Emacs version 19.\n", (CTAGS
) ? "CTAGS" : "ETAGS");
331 printf ("These are the options accepted by %s. You may use unambiguous\n\
332 abbreviations for the long option names. A - as file name means read file\n\
333 names from stdin.\n\n", progname
);
335 puts ("-a, --append\n\
336 Append tag entries to existing tags file.");
339 puts ("-B, --backward-search\n\
340 Write the search commands for the tag entries using '?', the\n\
341 backward-search command instead of '/', the forward-search command.");
344 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
345 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
346 extensions are always assumed to be C++ code.");
349 puts ("-d, --defines\n\
350 Create tag entries for constant C #defines, too.");
352 puts ("-D, --no-defines\n\
353 Don't create tag entries for constant C #defines. This makes\n\
354 the tags file smaller.");
357 puts ("-i FILE, --include=FILE\n\
358 Include a note in tag file indicating that, when searching for\n\
359 a tag, one should also consult the tags file FILE after\n\
360 checking the current file.");
362 puts ("-o FILE, --output=FILE\n\
363 Write the tags to FILE.");
364 puts ("-S, --ignore-indentation\n\
365 Don't rely on indentation quite as much as normal. Currently,\n\
366 this means not to assume that a closing brace in the first\n\
367 column is the final brace of a function or structure\n\
368 definition in C and C++.");
372 puts ("-t, --typedefs\n\
373 Generate tag entries for C typedefs.");
374 puts ("-T, --typedefs-and-c++\n\
375 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
376 and C++ member functions.");
377 puts ("-u, --update\n\
378 Update the tag entries for the given files, leaving tag\n\
379 entries for other files in place. Currently, this is\n\
380 implemented by deleting the existing entries for the given\n\
381 files and then rewriting the new entries at the end of the\n\
382 tags file. It is often faster to simply rebuild the entire\n\
383 tag file than to use this.");
384 puts ("-v, --vgrind\n\
385 Generates an index of items intended for human consumption,\n\
386 similar to the output of vgrind. The index is sorted, and\n\
387 gives the page number of each item.");
388 puts ("-x, --cxref\n\
389 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
390 The output uses line numbers instead of page numbers, but\n\
391 beyond that the differences are cosmetic; try both to see\n\
393 puts ("-w, --no-warn\n\
394 Suppress warning messages about entries defined in multiple\n\
398 puts ("-V, --version\n\
399 Print the version of the program.\n\
401 Print this help message.");
414 unsigned int nincluded_files
= 0;
415 char **included_files
= xnew (argc
, char *);
420 extern char *gfnames ();
421 extern char *massage_name ();
425 _fmode
= O_BINARY
; /* all of files are treated as binary files */
431 * If etags, always find typedefs and structure tags. Why not?
432 * Also default is to find macro constants.
435 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
440 opt
= getopt_long (argc
, argv
, "aCdDf:o:StTi:BuvxwVH", longopts
, 0);
448 /* If getopt returns 0, then it has already processed a
449 long-named option. We should do nothing. */
452 /* Common options. */
465 case 'f': /* for compatibility with old makefiles */
470 "%s: -%c flag may only be given once.\n", progname
, opt
);
489 typedefs_and_cplusplus
++;
496 included_files
[nincluded_files
++] = optarg
;
522 "%s: -%c flag not recognised.\n", progname
, opt
);
527 if (optind
== argc
&& nincluded_files
== 0)
529 fprintf (stderr
, "%s: No input files specified.\n", progname
);
532 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
539 tagfile
= CTAGS
? "tags" : "TAGS";
541 cwd
= etags_getcwd (); /* the current working directory */
543 if (streq (tagfile
, "-"))
549 tagfiledir
= absolute_dirname (tagfile
, cwd
);
552 init (); /* set up boolean "functions" */
555 initbuffer (&lbs
[0].lb
);
556 initbuffer (&lbs
[1].lb
);
557 initbuffer (&filename_lb
);
559 * loop through files finding functions
563 if (streq (tagfile
, "-"))
566 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
577 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
581 error ("Can't find file %s\n", this_file
);
586 this_file
= massage_name (this_file
);
589 } /* solely to balance out the ifdef'd parens above */
592 for (; optind
< argc
; optind
++)
594 this_file
= argv
[optind
];
596 /* Input file named "-" means read file names from stdin and use them. */
597 if (streq (this_file
, "-"))
599 while (!feof (stdin
))
601 (void) readline (&filename_lb
, stdin
);
602 if (strlen (filename_lb
.buffer
) > 0)
603 process_file (filename_lb
.buffer
);
607 process_file (this_file
);
612 while (nincluded_files
-- > 0)
613 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
615 (void) fclose (tagf
);
626 /* update cannot be set under VMS, so we may assume that argc
627 and argv have not been munged. */
628 for (i
= optind
; i
< argc
; i
++)
631 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
632 tagfile
, argv
[i
], tagfile
);
637 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
644 (void) fclose (tagf
);
647 sprintf (cmd
, "sort %s -o %s", tagfile
, tagfile
);
655 * This routine is called on each file argument.
661 struct stat stat_buf
;
663 if (stat (file
, &stat_buf
) == 0 && !S_ISREG (stat_buf
.st_mode
))
665 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
668 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
670 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
673 if (!find_entries (file
))
683 /* file is an absolute filename. Canonicalise it. */
684 filename
= absolute_filename (file
, cwd
);
688 /* file is a filename relative to cwd. Make it relative
689 to the directory of the tags file. */
690 filename
= relative_filename (file
, tagfiledir
);
692 fprintf (tagf
, "\f\n%s,%d\n", filename
, total_size_of_entries (head
));
700 * This routine sets up the boolean pseudo-functions which work
701 * by setting boolean flags dependent upon the corresponding character
702 * Every char which is NOT in that string is not a white char. Therefore,
703 * all of the array "_wht" is set to FALSE, and then the elements
704 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
705 * of a char is TRUE if it is the string "white", else FALSE.
713 for (i
= 0; i
< 0177; i
++)
714 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
715 for (sp
= white
; *sp
; sp
++)
717 for (sp
= endtk
; *sp
; sp
++)
719 for (sp
= intk
; *sp
; sp
++)
721 for (sp
= begtk
; *sp
; sp
++)
723 _wht
[0] = _wht
['\n'];
724 _etk
[0] = _etk
['\n'];
725 _btk
[0] = _btk
['\n'];
726 _itk
[0] = _itk
['\n'];
730 * This routine opens the specified file and calls the function
731 * which finds the function and type definitions.
740 inf
= fopen (file
, "r");
746 curfile
= savestr (file
);
747 cp
= etags_strrchr (file
, '.');
750 header_file
= (cp
&& (streq (cp1
, "h")));
752 /* .tex, .aux or .bbl implies LaTeX source code */
753 if (cp
&& (streq (cp1
, "tex") || streq (cp1
, "aux")
754 || streq (cp1
, "bbl")))
757 goto close_and_return
;
759 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
760 if (cp
&& (streq (cp1
, "l")
762 || streq (cp1
, "lsp")
763 || streq (cp1
, "lisp")
765 || streq (cp1
, "clisp")))
767 Lisp_functions (inf
);
768 goto close_and_return
;
770 /* .scm or .sm or .scheme or ... implies scheme source code */
771 if (cp
&& (streq (cp1
, "sm")
772 || streq (cp1
, "scm")
773 || streq (cp1
, "scheme")
775 || streq (cp1
, "sch")
778 || streq (cp1
, "SCM")
779 /* The `SCM' or `scm' prefix with a version number */
780 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
781 && string_numeric_p (cp1
))
782 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
783 && string_numeric_p (cp1
))))
785 Scheme_functions (inf
);
786 goto close_and_return
;
789 if (cp
&& (streq (cp1
, "s")
790 || streq (cp1
, "a") /* Unix assembler */
791 || streq (cp1
, "sa") /* Unix assembler */
792 || streq (cp1
, "asm") /* Microcontroller assembly */
793 || streq (cp1
, "src") /* BSO/Tasking C compiler output */
794 || streq (cp1
, "def") /* BSO/Tasking definition includes */
795 || streq (cp1
, "ins") /* Microcontroller include files */
796 || streq (cp1
, "inc")))/* Microcontroller include files */
799 goto close_and_return
;
801 /* .C or .H or .cxx or .hxx or .cc or .cpp: a C++ file */
802 if (cp
&& (streq (cp1
, "C")
804 || streq (cp1
, "cpp")
805 || streq (cp1
, "cxx")
806 || streq (cp1
, "hxx")
807 || streq (cp1
, "cc")))
809 C_entries (C_PLPL
, inf
); /* C++ */
810 goto close_and_return
;
812 /* .cs or .hs: a C* file */
813 if (cp
&& (streq (cp1
, "cs")
814 || streq (cp1
, "hs")))
816 C_entries (C_STAR
, inf
);
817 goto close_and_return
;
819 /* .y: a yacc file */
820 if (cp
&& (streq (cp1
, "y")))
822 C_entries (YACC
, inf
);
823 goto close_and_return
;
825 /* .pl implies prolog source code */
826 if (cp
&& streq (cp1
, "pl"))
828 Prolog_functions (inf
);
829 goto close_and_return
;
831 /* .p or .pas: a Pascal file */
832 if (cp
&& (streq (cp1
, "p")
833 || streq (cp1
, "pas")))
835 Pascal_functions (inf
);
836 goto close_and_return
;
838 /* If .f or .for, assume it is fortran or nothing. */
839 if (cp
&& (streq (cp1
, "f")
840 || streq (cp1
, "for")))
842 (void) Fortran_functions (inf
);
843 goto close_and_return
;
845 /* if not a .c or .h or .y file, try fortran */
846 if (cp
&& ((cp
[1] != 'c'
849 || (cp
[1] != 0 && cp
[2] != 0)))
851 if (Fortran_functions (inf
) != 0)
852 goto close_and_return
;
853 rewind (inf
); /* no fortran tags found, try C */
855 C_entries (cplusplus
? C_PLPL
: 0, inf
);
862 /* Nonzero if string STR is composed of digits. */
865 string_numeric_p (str
)
870 if (*str
< '0' || *str
> '9')
877 /* Should take a TOKEN* instead!! */
879 pfnote (name
, is_func
, named
, linestart
, linelen
, lno
, cno
)
880 char *name
; /* tag name */
881 logical is_func
; /* function or type name? */
882 logical named
; /* tag different from text of definition? */
898 /* It's okay to output early in etags -- it only disrupts the
899 * character count of the tag entries, which is no longer used
902 error ("too many entries to sort", 0);
909 /* If ctags mode, change name "main" to M<thisfilename>. */
910 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
912 fp
= etags_strrchr (curfile
, '/');
913 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
914 fp
= etags_strrchr (name
, '.');
915 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
919 np
->name
= savestr (name
);
921 np
->is_func
= is_func
;
924 /* UNCOMMENT THE +1 HERE: */
925 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
926 np
->left
= np
->right
= 0;
929 c
= linestart
[linelen
];
930 linestart
[linelen
] = 0;
932 else if (cxref_style
== 0)
934 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
937 np
->pat
= savestr (linestart
);
940 linestart
[linelen
] = c
;
943 add_node (np
, &head
);
948 * recurse on left children, iterate on right children.
956 register NODE
*node_right
= node
->right
;
957 free_tree (node
->left
);
960 free ((char *) node
);
967 * Adds a node to the tree of nodes. In etags mode, we don't keep
968 * it sorted; we just keep a linear list. In ctags mode, maintain
969 * an ordered tree, with no attempt at balancing.
971 * add_node is the only function allowed to add nodes, so it can
974 /* Must avoid static vars within functions since some systems
975 #define static as nothing. */
976 NODE
*last_node
= NULL
;
979 add_node (node
, cur_node_p
)
980 NODE
*node
, **cur_node_p
;
983 register NODE
*cur_node
= *cur_node_p
;
985 if (cur_node
== NULL
)
995 if (last_node
== NULL
)
996 fatal ("internal error in add_node", 0);
997 last_node
->right
= node
;
1003 dif
= strcmp (node
->name
, cur_node
->name
);
1006 * If this tag name matches an existing one, then
1007 * do not add the node, but maybe print a warning.
1011 if (node
->file
== cur_node
->file
)
1015 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1016 node
->file
, lineno
, node
->name
);
1017 fprintf (stderr
, "Second entry ignored\n");
1021 if (!cur_node
->been_warned
&& !no_warnings
)
1024 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1025 node
->file
, cur_node
->file
, node
->name
);
1027 cur_node
->been_warned
= TRUE
;
1031 /* Maybe refuse to add duplicate nodes. */
1032 if (!permit_duplicates
)
1034 if (streq (node
->name
, cur_node
->name
)
1035 && streq (node
->file
, cur_node
->file
))
1039 /* Actually add the node */
1040 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1046 register NODE
*node
;
1053 /* Output subentries that precede this one */
1054 put_entries (node
->left
);
1056 /* Output this entry */
1062 fprintf (tagf
, "%s\177%s\001%d,%d\n",
1063 node
->pat
, node
->name
,
1064 node
->lno
, node
->cno
);
1068 fprintf (tagf
, "%s\177%d,%d\n",
1070 node
->lno
, node
->cno
);
1073 else if (!cxref_style
)
1075 fprintf (tagf
, "%s\t%s\t",
1076 node
->name
, node
->file
);
1080 putc (searchar
, tagf
);
1083 for (sp
= node
->pat
; *sp
; sp
++)
1085 if (*sp
== '\\' || *sp
== searchar
)
1089 putc (searchar
, tagf
);
1092 { /* a typedef; text pattern inadequate */
1093 fprintf (tagf
, "%d", node
->lno
);
1097 else if (vgrind_style
)
1098 fprintf (stdout
, "%s %s %d\n",
1099 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1101 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1102 node
->name
, node
->lno
, node
->file
, node
->pat
);
1104 /* Output subentries that follow this one */
1105 put_entries (node
->right
);
1108 /* Length of a number's decimal representation. */
1116 for (; num
; num
/= 10)
1122 * Return total number of characters that put_entries will output for
1123 * the nodes in the subtree of the specified node. Works only if
1124 * we are not ctags, but called only in that case. This count
1125 * is irrelevant with the new tags.el, but is still supplied for
1126 * backward compatibility.
1129 total_size_of_entries (node
)
1130 register NODE
*node
;
1138 for (; node
; node
= node
->right
)
1140 /* Count left subentries. */
1141 total
+= total_size_of_entries (node
->left
);
1143 /* Count this entry */
1144 total
+= strlen (node
->pat
) + 1;
1145 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1147 total
+= 1 + strlen (node
->name
); /* \001name */
1154 * The C symbol tables.
1157 /* Feed stuff between (but not including) %[ and %] lines to:
1158 gperf -c -k1,3 -o -p -r -t
1160 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1162 class, C_PLPL, st_C_struct
1163 domain, C_STAR, st_C_struct
1164 union, 0, st_C_struct
1165 struct, 0, st_C_struct
1167 typedef, 0, st_C_typedef
1168 define, 0, st_C_define
1169 long, 0, st_C_typespec
1170 short, 0, st_C_typespec
1171 int, 0, st_C_typespec
1172 char, 0, st_C_typespec
1173 float, 0, st_C_typespec
1174 double, 0, st_C_typespec
1175 signed, 0, st_C_typespec
1176 unsigned, 0, st_C_typespec
1177 auto, 0, st_C_typespec
1178 void, 0, st_C_typespec
1179 extern, 0, st_C_typespec
1180 static, 0, st_C_typespec
1181 const, 0, st_C_typespec
1182 volatile, 0, st_C_typespec
1184 and replace lines between %< and %> with its output. */
1186 /* C code produced by gperf version 1.8.1 (K&R C version) */
1187 /* Command-line: gperf -c -k1,3 -o -p -r -t */
1190 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
1192 #define MIN_WORD_LENGTH 3
1193 #define MAX_WORD_LENGTH 8
1194 #define MIN_HASH_VALUE 10
1195 #define MAX_HASH_VALUE 62
1198 53 is the maximum key range
1206 static unsigned char hash_table
[] =
1208 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1209 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1210 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1211 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1212 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1213 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1214 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1215 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1216 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1217 62, 62, 62, 62, 62, 62, 62, 2, 62, 7,
1218 6, 9, 15, 30, 62, 24, 62, 62, 1, 24,
1219 7, 27, 13, 62, 19, 26, 18, 27, 1, 62,
1220 62, 62, 62, 62, 62, 62, 62, 62,
1222 return len
+ hash_table
[str
[2]] + hash_table
[str
[0]];
1225 struct C_stab_entry
*
1226 in_word_set (str
, len
)
1231 static struct C_stab_entry wordlist
[] =
1233 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1235 {"volatile", 0, st_C_typespec
},
1237 {"long", 0, st_C_typespec
},
1238 {"char", 0, st_C_typespec
},
1239 {"class", C_PLPL
, st_C_struct
},
1240 {"",}, {"",}, {"",}, {"",},
1241 {"const", 0, st_C_typespec
},
1242 {"",}, {"",}, {"",}, {"",},
1243 {"auto", 0, st_C_typespec
},
1245 {"define", 0, st_C_define
},
1247 {"void", 0, st_C_typespec
},
1248 {"",}, {"",}, {"",},
1249 {"extern", 0, st_C_typespec
},
1250 {"static", 0, st_C_typespec
},
1252 {"domain", C_STAR
, st_C_struct
},
1254 {"typedef", 0, st_C_typedef
},
1255 {"double", 0, st_C_typespec
},
1256 {"enum", 0, st_C_enum
},
1257 {"",}, {"",}, {"",}, {"",},
1258 {"int", 0, st_C_typespec
},
1260 {"float", 0, st_C_typespec
},
1261 {"",}, {"",}, {"",},
1262 {"struct", 0, st_C_struct
},
1263 {"",}, {"",}, {"",}, {"",},
1264 {"union", 0, st_C_struct
},
1266 {"short", 0, st_C_typespec
},
1268 {"unsigned", 0, st_C_typespec
},
1269 {"signed", 0, st_C_typespec
},
1272 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
1274 register int key
= hash (str
, len
);
1276 if (key
<= MAX_HASH_VALUE
&& key
>= MIN_HASH_VALUE
)
1278 register char *s
= wordlist
[key
].name
;
1280 if (*s
== *str
&& strneq (str
+ 1, s
+ 1, len
- 1))
1281 return &wordlist
[key
];
1289 C_symtype(str
, len
, c_ext
)
1294 register struct C_stab_entry
*se
= in_word_set(str
, len
);
1296 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
1302 * C functions are recognized using a simple finite automaton.
1303 * funcdef is its state variable.
1307 fnone
, /* nothing seen */
1308 ftagseen
, /* function-like tag seen */
1309 fstartlist
, /* just after open parenthesis */
1310 finlist
, /* in parameter list */
1311 flistseen
, /* after parameter list */
1312 fignore
/* before open brace */
1318 * typedefs are recognized using a simple finite automaton.
1319 * typeddef is its state variable.
1323 tnone
, /* nothing seen */
1324 ttypedseen
, /* typedef keyword seen */
1325 tinbody
, /* inside typedef body */
1326 tend
, /* just before typedef tag */
1327 tignore
/* junk after typedef tag */
1333 * struct-like structures (enum, struct and union) are recognized
1334 * using another simple finite automaton. `structdef' is its state
1339 snone
, /* nothing seen yet */
1340 skeyseen
, /* struct-like keyword seen */
1341 stagseen
, /* struct-like tag seen */
1342 scolonseen
, /* colon seen after struct-like tag */
1343 sinbody
/* in struct body: recognize member func defs*/
1348 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1349 * struct tag, and structtype is the type of the preceding struct-like
1352 char structtag
[BUFSIZ
];
1353 enum sym_type structtype
;
1356 * Yet another little state machine to deal with preprocessor lines.
1360 dnone
, /* nothing seen */
1361 dsharpseen
, /* '#' seen as first char on line */
1362 ddefineseen
, /* '#' and 'define' seen */
1363 dignorerest
/* ignore rest of line */
1368 * Set this to TRUE, and the next token considered is called a function.
1369 * Used only for GNUmacs's function-defining macros.
1371 logical next_token_is_func
;
1374 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1380 * checks to see if the current token is at the start of a
1381 * function, or corresponds to a typedef, or is a struct/union/enum
1384 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1385 * C_EXT is which language we are looking at.
1387 * In the future we will need some way to adjust where the end of
1388 * the token is; for instance, implementing the C++ keyword
1389 * `operator' properly will adjust the end of the token to be after
1390 * whatever follows `operator'.
1397 * next_token_is_func IN OUT
1401 consider_token (c
, tokp
, c_ext
, cblev
, is_func
)
1402 register char c
; /* IN: first char after the token */
1403 register TOKEN
*tokp
; /* IN: token pointer */
1404 int c_ext
; /* IN: C extensions mask */
1405 int cblev
; /* IN: curly brace level */
1406 logical
*is_func
; /* OUT: function found */
1408 enum sym_type toktype
= C_symtype(tokp
->p
, tokp
->len
, c_ext
);
1411 * Advance the definedef state machine.
1416 /* We're not on a preprocessor line. */
1419 if (toktype
== st_C_define
)
1421 definedef
= ddefineseen
;
1425 definedef
= dignorerest
;
1430 * Make a tag for any macro, unless it is a constant
1431 * and constantypedefs is FALSE.
1433 definedef
= dignorerest
;
1434 *is_func
= (c
== '(');
1435 if (!*is_func
&& !constantypedefs
)
1442 error ("internal error: definedef value.", 0);
1451 if (toktype
== st_C_typedef
)
1454 typdef
= ttypedseen
;
1470 /* Do not return here, so the structdef stuff has a chance. */
1484 * This structdef business is currently only invoked when cblev==0.
1485 * It should be recursively invoked whatever the curly brace level,
1486 * and a stack of states kept, to allow for definitions of structs
1489 * This structdef business is NOT invoked when we are ctags and the
1490 * file is plain C. This is because a struct tag may have the same
1491 * name as another tag, and this loses with ctags.
1493 * This if statement deals with the typdef state machine as
1494 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1495 * return (FALSE). All the other code here is for the structdef
1502 if (typdef
== ttypedseen
1503 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1505 structdef
= skeyseen
;
1506 structtype
= toktype
;
1510 if (structdef
== skeyseen
)
1512 if (structtype
== st_C_struct
)
1514 strncpy (structtag
, tokp
->p
, tokp
->len
);
1515 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1519 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1521 structdef
= stagseen
;
1525 /* Avoid entering funcdef stuff if typdef is going on. */
1526 if (typdef
!= tnone
)
1532 /* Detect GNU macros. */
1533 if (definedef
== dnone
)
1534 if (strneq (tokp
->p
, "DEFUN", 5) /* Used in emacs */
1536 These are defined inside C functions
, so currently they
1538 || strneq (tokp
->p
, "EXFUN", 5) /* Used in glibc */
1539 || strneq (tokp
->p
, "DEFVAR_", 7) /* Used in emacs */
1541 || strneq (tokp
->p
, "SYSCALL", 7) /* Used in glibc (mach) */
1542 || strneq (tokp
->p
, "ENTRY", 5) /* Used in glibc */
1543 || strneq (tokp
->p
, "PSEUDO", 6)) /* Used in glibc */
1546 next_token_is_func
= TRUE
;
1549 if (next_token_is_func
)
1551 next_token_is_func
= FALSE
;
1561 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1562 funcdef
= fnone
; /* should be useless */
1565 if (funcdef
== fnone
)
1578 * This routine finds functions, typedefs, #define's and
1579 * struct/union/enum definitions in C syntax and adds them
1583 #define curlb (lbs[curndx].lb)
1584 #define othlb (lbs[1-curndx].lb)
1585 #define newlb (lbs[newndx].lb)
1586 #define curlinepos (lbs[curndx].linepos)
1587 #define othlinepos (lbs[1-curndx].linepos)
1588 #define newlinepos (lbs[newndx].linepos)
1590 /* Save and restore token state. This is used when preprocessor defines
1591 are handled, to avoid disturbing active function/typedef/struct states. */
1592 #define TOKEN_SAVED_P (savetok.lineno > 0)
1593 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1594 savetok.len = toklen, strcpy(savenameb, nameb))
1595 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1596 toklen = tok.len, strcpy(nameb, savenameb), \
1599 #define CNL_SAVE_DEFINEDEF \
1601 SET_FILEPOS (curlinepos, inf, charno); \
1603 charno += readline (&curlb, inf); \
1604 lp = curlb.buffer; \
1611 CNL_SAVE_DEFINEDEF; \
1612 if (TOKEN_SAVED_P) \
1614 definedef = dnone; \
1617 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1618 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1619 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1620 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1623 C_entries (c_ext
, inf
)
1624 int c_ext
; /* extension of C? */
1627 register char c
; /* latest char read; '\0' for end of line */
1628 register char *lp
; /* pointer one beyond the character `c' */
1629 int curndx
, newndx
; /* indices for current and new lb */
1630 TOKEN tok
; /* latest token read for funcdef & structdef */
1631 char nameb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1632 register int tokoff
; /* offset in line of start of latest token */
1633 register int toklen
; /* length of latest token */
1634 int cblev
; /* current curly brace level */
1635 int parlev
; /* current parenthesis level */
1636 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1638 TOKEN savetok
; /* saved token during preprocessor handling */
1639 char savenameb
[BUFSIZ
]; /* ouch! */
1642 curndx
= newndx
= 0;
1648 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1649 next_token_is_func
= yacc_rules
= FALSE
;
1650 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1653 cplpl
= c_ext
& C_PLPL
;
1660 /* If we're at the end of the line, the next character is a
1661 '\0'; don't skip it, because it's the thing that tells us
1662 to read the next line. */
1683 /* Newlines inside comments do not end macro definitions in
1698 /* Newlines inside strings do not end macro definitions
1699 in traditional cpp, even though compilers don't
1700 usually accept them. */
1711 /* Hmmm, something went wrong. */
1725 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1730 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1740 else if (cplpl
&& *lp
== '/')
1748 if ((c_ext
& YACC
) && *lp
== '%')
1750 /* entering or exiting rules section in yacc file */
1752 definedef
= dnone
; funcdef
= fnone
;
1753 typdef
= tnone
; structdef
= snone
;
1754 next_token_is_func
= FALSE
;
1755 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1757 yacc_rules
= !yacc_rules
;
1763 if (definedef
== dnone
)
1766 logical cpptoken
= TRUE
;
1768 /* Look back on this line. If all blanks, or nonblanks
1769 followed by an end of comment, this is a preprocessor
1771 for (cp
= newlb
.buffer
; cp
< lp
-1; cp
++)
1774 if (*cp
== '*' && *(cp
+1) == '/')
1783 definedef
= dsharpseen
;
1784 } /* if (definedef == dnone) */
1790 /* Consider token only if some complicated conditions are satisfied. */
1791 if ((definedef
!= dnone
1792 || (cblev
== 0 && structdef
!= scolonseen
)
1793 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
1794 && typdef
!= tignore
1795 && definedef
!= dignorerest
1796 && funcdef
!= finlist
)
1802 if (cplpl
&& c
== ':' && *lp
== ':' && begtoken(*(lp
+ 1)))
1805 * This handles :: in the middle, but not at the
1806 * beginning of an identifier.
1813 logical is_func
= FALSE
;
1815 tok
.lineno
= lineno
;
1816 tok
.p
= newlb
.buffer
+ tokoff
;
1820 || consider_token (c
, &tok
, c_ext
, cblev
, &is_func
))
1822 if (structdef
== sinbody
1823 && definedef
== dnone
1825 /* function defined in C++ class body */
1827 sprintf (nameb
, "%s::%.*s",
1828 ((structtag
[0] == '\0')
1829 ? "_anonymous_" : structtag
),
1835 sprintf (nameb
, "%.*s", tok
.len
, tok
.p
);
1838 if (structdef
== stagseen
1841 && definedef
== dignorerest
)) /* macro */
1844 if (definedef
== dnone
1845 && (funcdef
== ftagseen
1846 || structdef
== stagseen
1849 if (newndx
== curndx
)
1850 curndx
= 1 - curndx
; /* switch line buffers */
1853 MAKE_TAG_FROM_NEW_LB (is_func
);
1857 } /* if (endtoken (c)) */
1858 else if (intoken (c
))
1863 } /* if (midtoken) */
1864 else if (begtoken (c
))
1875 MAKE_TAG_FROM_OTH_LB (TRUE
);
1882 if (structdef
== stagseen
)
1886 /* Take a quick peek ahead for a define directive,
1887 so we can avoid saving the token when not absolutely
1888 necessary. [This is a speed hack.] */
1889 if (c
== 'd' && strneq (lp
, "efine", 5)
1890 && iswhite (*(lp
+ 5)))
1893 definedef
= ddefineseen
;
1897 definedef
= dignorerest
;
1900 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1902 tokoff
= lp
- 1 - newlb
.buffer
;
1908 } /* if must look at token */
1911 /* Detect end of line, colon, comma, semicolon and various braces
1912 after having handled a token.*/
1916 if (definedef
!= dnone
)
1918 if (structdef
== stagseen
)
1919 structdef
= scolonseen
;
1926 MAKE_TAG_FROM_OTH_LB (FALSE
);
1936 if (definedef
!= dnone
)
1942 MAKE_TAG_FROM_OTH_LB (FALSE
);
1947 if (funcdef
!= fignore
)
1949 if (structdef
== stagseen
)
1953 if (definedef
!= dnone
)
1955 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1957 if (structdef
== stagseen
)
1961 if (definedef
!= dnone
)
1963 if (cblev
== 0 && typdef
== tend
)
1966 MAKE_TAG_FROM_OTH_LB (FALSE
);
1969 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1971 if (structdef
== stagseen
)
1975 if (definedef
!= dnone
)
1984 /* Make sure that the next char is not a '*'.
1985 This handles constructs like:
1986 typedef void OperatorFun (int fun); */
1990 MAKE_TAG_FROM_OTH_LB (FALSE
);
1993 } /* switch (typdef) */
1996 funcdef
= fstartlist
;
2005 if (definedef
!= dnone
)
2013 funcdef
= flistseen
;
2016 if (cblev
== 0 && typdef
== tend
)
2019 MAKE_TAG_FROM_OTH_LB (FALSE
);
2022 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
2026 if (definedef
!= dnone
)
2028 if (typdef
== ttypedseen
)
2032 case skeyseen
: /* unnamed struct */
2033 structtag
[0] = '\0';
2034 structdef
= sinbody
;
2037 case scolonseen
: /* named struct */
2038 structdef
= sinbody
;
2039 MAKE_TAG_FROM_OTH_LB (FALSE
);
2045 MAKE_TAG_FROM_OTH_LB (TRUE
);
2051 /* Neutralize `extern "C" {' grot and look inside structs. */
2052 if (cblev
== 0 && structdef
== snone
&& typdef
== tnone
)
2058 if (definedef
!= dnone
)
2060 if (funcdef
== fstartlist
)
2061 funcdef
= fnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
2064 if (definedef
!= dnone
)
2066 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
2068 cblev
= 0; /* reset curly brace level if first column */
2069 parlev
= 0; /* also reset paren level, just in case... */
2075 if (typdef
== tinbody
)
2078 strcpy (structtag
, "<error 2>");
2082 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
2083 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
2084 if (definedef
!= dnone
)
2086 /* These surely cannot follow a function tag. */
2087 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2091 /* If a macro spans multiple lines don't reset its state. */
2099 } /* while not eof */
2102 /* Fortran parsing */
2111 register int len
= 0;
2113 while (*cp
&& (*cp
| ' ') == (dbp
[len
] | ' '))
2126 while (isspace (*dbp
))
2131 while (isspace (*dbp
))
2135 if (!isdigit (*dbp
))
2137 --dbp
; /* force failure */
2142 while (isdigit (*dbp
));
2151 char nambuf
[BUFSIZ
];
2153 while (isspace (*dbp
))
2158 linecharno
= charno
;
2159 charno
+= readline (&lb
, inf
);
2164 while (isspace (*dbp
))
2173 && (isalpha (*cp
) || isdigit (*cp
) || (*cp
== '_') || (*cp
== '$')));
2178 strcpy (nambuf
, dbp
);
2180 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2181 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2186 Fortran_functions (inf
)
2196 linecharno
= charno
;
2197 charno
+= readline (&lb
, inf
);
2200 dbp
++; /* Ratfor escape to fortran */
2201 while (isspace (*dbp
))
2208 if (tail ("integer"))
2216 if (tail ("logical"))
2220 if (tail ("complex") || tail ("character"))
2224 if (tail ("double"))
2226 while (isspace (*dbp
))
2230 if (tail ("precision"))
2236 while (isspace (*dbp
))
2243 if (tail ("function"))
2247 if (tail ("subroutine"))
2255 if (tail ("program"))
2260 if (tail ("procedure"))
2269 * Bob Weiner, Motorola Inc., 4/3/94
2270 * Unix and microcontroller assembly tag handling
2271 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
2277 char nambuf
[BUFSIZ
];
2288 linecharno
= charno
;
2289 charno
+= readline (&lb
, inf
);
2292 /* If first char is alphabetic or one of [_.$], test for colon
2293 following identifier. */
2294 if (isalpha (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2296 /* Read past label. */
2298 while (isalnum (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2300 if (*cp
== ':' || isspace (*cp
))
2302 /* Found end of label, so copy it and add it to the table. */
2305 strcpy (nambuf
, lb
.buffer
);
2307 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2308 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2315 /* Added by Mosur Mohan, 4/22/88 */
2316 /* Pascal parsing */
2318 #define GET_NEW_LINE \
2320 linecharno = charno; lineno++; \
2321 charno += 1 + readline (&lb, inf); \
2325 /* Locates tags for procedures & functions.
2326 * Doesn't do any type- or var-definitions.
2327 * It does look for the keyword "extern" or "forward"
2328 * immediately following the procedure statement;
2329 * if found, the tag is skipped.
2333 Pascal_functions (inf
)
2336 struct linebuffer tline
; /* mostly copied from C_entries */
2340 char nambuf
[BUFSIZ
];
2342 logical
/* each of these flags is TRUE iff: */
2343 incomm1
, /* point is inside {..} comment */
2344 incomm2
, /* point is inside (*..*) comment */
2345 inquote
, /* point is inside '..' string */
2346 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2347 /* keyword, so next item = potential tag */
2348 found_tag
, /* point is after a potential tag */
2349 inparms
, /* point is within parameter-list */
2350 verify_tag
; /* point has passed the parm-list, so the */
2351 /* next token will determine whether */
2352 /* this is a FORWARD/EXTERN to be */
2353 /* ignored, or whether it is a real tag */
2359 initbuffer (&tline
);
2361 incomm1
= incomm2
= inquote
= FALSE
;
2362 found_tag
= FALSE
; /* have a proc name; check if extern */
2363 get_tagname
= FALSE
; /* have found "procedure" keyword */
2364 inparms
= FALSE
; /* found '(' after "proc" */
2365 verify_tag
= FALSE
; /* check if "extern" is ahead */
2367 /* long main loop to get next char */
2371 if (c
== 0) /* if end of line */
2376 if (!((found_tag
&& verify_tag
) ||
2378 c
= *dbp
++; /* only if don't need *dbp pointing */
2379 /* to the beginning of the name of */
2380 /* the procedure or function */
2382 if (incomm1
) /* within { - } comments */
2388 else if (incomm2
) /* within (* - *) comments */
2392 while ((c
= *dbp
++) == '*')
2411 inquote
= TRUE
; /* found first quote */
2413 case '{': /* found open-{-comment */
2417 if (*dbp
== '*') /* found open-(*-comment */
2422 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2425 case ')': /* end of parms list */
2430 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2437 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2439 /* check if this is an "extern" declaration */
2442 if ((*dbp
== 'e') || (*dbp
== 'E'))
2444 if (tail ("extern")) /* superfluous, really! */
2450 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2452 if (tail ("forward")) /* check for forward reference */
2458 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2462 pfnote (nambuf
, TRUE
, FALSE
,
2463 tline
.buffer
, cp
- tline
.buffer
+ 1,
2464 save_lineno
, save_lcno
);
2468 if (get_tagname
) /* grab name of proc or fn */
2473 /* save all values for later tagging */
2474 tline
.size
= lb
.size
;
2475 strcpy (tline
.buffer
, lb
.buffer
);
2476 save_lineno
= lineno
;
2477 save_lcno
= linecharno
;
2479 /* grab block name */
2480 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2484 strcpy (nambuf
, dbp
);
2486 dbp
= cp
; /* restore dbp to e-o-token */
2487 get_tagname
= FALSE
;
2491 /* and proceed to check for "extern" */
2493 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2494 (!found_tag
) && (!get_tagname
))
2496 /* check for proc/fn keywords */
2500 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2504 if (tail ("unction"))
2509 } /* while not eof */
2513 * lisp tag functions
2514 * just look for (def or (DEF
2521 return ((dbp
[1] == 'd' || dbp
[1] == 'D')
2522 && (dbp
[2] == 'e' || dbp
[2] == 'E')
2523 && (dbp
[3] == 'f' || dbp
[3] == 'F'));
2530 return ((*(++dbp
) == 'q' || *dbp
== 'Q')
2531 && (*(++dbp
) == 'u' || *dbp
== 'U')
2532 && (*(++dbp
) == 'o' || *dbp
== 'O')
2533 && (*(++dbp
) == 't' || *dbp
== 'T')
2534 && (*(++dbp
) == 'e' || *dbp
== 'E')
2535 && isspace(*(++dbp
)));
2543 char nambuf
[BUFSIZ
];
2545 if (*dbp
== '\'') /* Skip prefix quote */
2547 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2550 while (isspace(*dbp
))
2553 for (cp
= dbp
/*+1*/; *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')'; cp
++)
2560 strcpy (nambuf
, dbp
);
2562 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2563 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2568 Lisp_functions (inf
)
2578 linecharno
= charno
;
2579 charno
+= readline (&lb
, inf
);
2585 while (!isspace (*dbp
))
2587 while (isspace (*dbp
))
2593 /* Check for (foo::defmumble name-defined ... */
2596 while (*dbp
&& !isspace (*dbp
)
2597 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2602 while (*dbp
== ':');
2604 if (L_isdef (dbp
- 1))
2606 while (!isspace (*dbp
))
2608 while (isspace (*dbp
))
2619 * Scheme tag functions
2620 * look for (def... xyzzy
2621 * look for (def... (xyzzy
2622 * look for (def ... ((...(xyzzy ....
2623 * look for (set! xyzzy
2629 Scheme_functions (inf
)
2639 linecharno
= charno
;
2640 charno
+= readline (&lb
, inf
);
2642 if (dbp
[0] == '(' &&
2643 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2644 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2645 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2647 while (!isspace (*dbp
))
2649 /* Skip over open parens and white space */
2650 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2654 if (dbp
[0] == '(' &&
2655 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2656 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2657 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2658 (dbp
[4] == '!' || dbp
[4] == '!') &&
2661 while (!isspace (*dbp
))
2663 /* Skip over white space */
2664 while (isspace (*dbp
))
2676 char nambuf
[BUFSIZ
];
2680 /* Go till you get to white space or a syntactic break */
2681 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2683 /* Null terminate the string there. */
2686 /* Copy the string */
2687 strcpy (nambuf
, dbp
);
2688 /* Unterminate the string */
2690 /* Announce the change */
2691 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2695 /* Find tags in TeX and LaTeX input files. */
2697 /* TEX_toktab is a table of TeX control sequences that define tags.
2698 Each TEX_tabent records one such control sequence.
2699 CONVERT THIS TO USE THE Stab TYPE!! */
2707 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2709 /* Default set of control sequences to put into TEX_toktab.
2710 The value of environment var TEXTAGS is prepended to this. */
2712 char *TEX_defenv
= "\
2713 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2716 struct TEX_tabent
*TEX_decode_env ();
2720 char TEX_esc
= '\\';
2721 char TEX_opgrp
= '{';
2722 char TEX_clgrp
= '}';
2725 * TeX/LaTeX scanning loop.
2738 /* Select either \ or ! as escape character. */
2741 /* Initialize token table once from environment. */
2743 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2746 { /* Scan each line in file */
2748 linecharno
= charno
;
2749 charno
+= readline (&lb
, inf
);
2752 while (dbp
= etags_strchr (dbp
, TEX_esc
)) /* Look at each esc in line */
2758 linecharno
+= dbp
- lasthit
;
2760 i
= TEX_Token (lasthit
);
2763 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2764 break; /* We only save a line once */
2770 #define TEX_LESC '\\'
2771 #define TEX_SESC '!'
2774 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2775 /* chars accordingly. */
2783 while ((c
= getc (inf
)) != EOF
)
2785 /* Skip to next line if we hit the TeX comment char. */
2789 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2808 /* Read environment and prepend it to the default string. */
2809 /* Build token table. */
2812 TEX_decode_env (evarname
, defenv
)
2816 register char *env
, *p
;
2818 struct TEX_tabent
*tab
;
2821 /* Append default string to environment. */
2822 env
= getenv (evarname
);
2826 env
= concat (env
, defenv
, "");
2828 /* Allocate a token table */
2829 for (size
= 1, p
= env
; p
;)
2830 if ((p
= etags_strchr (p
, ':')) && *(++p
))
2832 /* Add 1 to leave room for null terminator. */
2833 tab
= xnew (size
+ 1, struct TEX_tabent
);
2835 /* Unpack environment string into token table. Be careful about */
2836 /* zero-length strings (leading ':', "::" and trailing ':') */
2839 p
= etags_strchr (env
, ':');
2840 if (!p
) /* End of environment string. */
2841 p
= env
+ strlen (env
);
2843 { /* Only non-zero strings. */
2844 tab
[i
].name
= savenstr (env
, p
- env
);
2845 tab
[i
].len
= strlen (tab
[i
].name
);
2852 tab
[i
].name
= NULL
; /* Mark end of table. */
2860 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2861 The name being defined actually starts at (NAME + LEN + 1).
2862 But we seem to include the TeX command in the tag name. */
2865 TEX_getit (name
, len
)
2869 char *p
= name
+ len
;
2870 char nambuf
[BUFSIZ
];
2875 /* Let tag name extend to next group close (or end of line) */
2876 while (*p
&& *p
!= TEX_clgrp
)
2878 strncpy (nambuf
, name
, p
- name
);
2879 nambuf
[p
- name
] = 0;
2881 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2885 /* If the text at CP matches one of the tag-defining TeX command names,
2886 return the pointer to the first occurrence of that command in TEX_toktab.
2887 Otherwise return -1. */
2889 /* Keep the capital `T' in `Token' for dumb truncating compilers
2890 (this distinguishes it from `TEX_toktab' */
2897 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2898 if (strneq (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
))
2903 /* Support for Prolog. */
2905 /* whole head (not only functor, but also arguments)
2906 is gotten in compound term. */
2909 prolog_getit (s
, lineno
, linecharno
)
2914 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2922 if (*s
== '\0') /* syntax error. */
2924 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2926 else if (*s
== '\'')
2928 insquote
= !insquote
;
2931 else if (!insquote
&& *s
== '(')
2936 else if (!insquote
&& *s
== ')')
2942 else if (npar
< 0) /* syntax error. */
2945 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2947 if (npar
!= 0) /* syntax error. */
2957 strcpy (nambuf
, save_s
);
2959 pfnote (nambuf
, TRUE
, FALSE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2962 /* It is assumed that prolog predicate starts from column 0. */
2965 Prolog_functions (inf
)
2968 void skip_comment (), prolog_getit ();
2970 lineno
= linecharno
= charno
= 0;
2974 linecharno
+= charno
;
2975 charno
= readline (&lb
, inf
) + 1; /* 1 for newline. */
2977 if (isspace (dbp
[0])) /* not predicate header. */
2979 else if (dbp
[0] == '%') /* comment. */
2981 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2982 skip_comment (&lb
, inf
, &lineno
, &linecharno
);
2984 prolog_getit (dbp
, lineno
, linecharno
);
2989 skip_comment (plb
, inf
, plineno
, plinecharno
)
2990 struct linebuffer
*plb
;
2992 int *plineno
; /* result */
2993 long *plinecharno
; /* result */
2995 while (!substr ("*/", plb
->buffer
))
2998 *plinecharno
+= readline (plb
, inf
) + 1;
2999 } /* 1 for newline. */
3002 /* Return TRUE if 'sub' exists somewhere in 's'. */
3009 while (*s
&& (s
= etags_strchr (s
, *sub
)))
3010 if (prestr (sub
, s
))
3017 /* Return TRUE if 'pre' is prefix of string 's'. */
3026 else if (*pre
== *s
)
3027 return (prestr (pre
+ 1, s
+ 1));
3032 /* Initialize a linebuffer for use */
3035 initbuffer (linebuffer
)
3036 struct linebuffer
*linebuffer
;
3038 linebuffer
->size
= 200;
3039 linebuffer
->buffer
= xnew (200, char);
3043 * Read a line of text from `stream' into `linebuffer'.
3044 * Return the number of characters read from `stream',
3045 * which is the length of the line including the newline, if any.
3048 readline (linebuffer
, stream
)
3049 struct linebuffer
*linebuffer
;
3050 register FILE *stream
;
3052 char *buffer
= linebuffer
->buffer
;
3053 register char *p
= linebuffer
->buffer
;
3054 register char *pend
;
3055 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
3057 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
3061 register int c
= getc (stream
);
3064 linebuffer
->size
*= 2;
3065 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
3066 p
+= buffer
- linebuffer
->buffer
;
3067 pend
= buffer
+ linebuffer
->size
;
3068 linebuffer
->buffer
= buffer
;
3070 if (c
== EOF
|| c
== '\n')
3073 newline
= (c
== '\n') ? 1 : 0;
3079 return p
- buffer
+ newline
;
3086 return savenstr (cp
, strlen (cp
));
3096 dp
= xnew (len
+ 1, char);
3097 strncpy (dp
, cp
, len
);
3103 * Return the ptr in sp at which the character c last
3104 * appears; NULL if not found
3106 * Identical to System V strrchr, included for portability.
3110 etags_strrchr (sp
, c
)
3111 register char *sp
, c
;
3126 * Return the ptr in sp at which the character c first
3127 * appears; NULL if not found
3129 * Identical to System V strchr, included for portability.
3133 etags_strchr (sp
, c
)
3134 register char *sp
, c
;
3144 /* Print error message and exit. */
3155 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3162 fprintf (stderr
, "%s: ", progname
);
3163 fprintf (stderr
, s1
, s2
);
3164 fprintf (stderr
, "\n");
3167 /* Return a newly-allocated string whose contents
3168 concatenate those of s1, s2, s3. */
3174 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3175 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3177 strcpy (result
, s1
);
3178 strcpy (result
+ len1
, s2
);
3179 strcpy (result
+ len1
+ len2
, s3
);
3180 result
[len1
+ len2
+ len3
] = '\0';
3189 char *p
, cwd
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
3196 *p
++ = tolower (*p
);
3197 return strdup (cwd
);
3199 #else /* not DOS_NT */
3200 /* Does the same work as the system V getcwd, but does not need to
3201 guess buffer size in advance. */
3206 char *buf
= xnew (bufsize
, char);
3209 while (getcwd (buf
, bufsize
/ 2) == NULL
)
3211 if (errno
!= ERANGE
)
3217 buf
= xnew (bufsize
, char);
3224 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
3230 if (fgets (buf
, bufsize
, pipe
) == NULL
)
3238 buf
= xnew (bufsize
, char);
3240 } while (buf
[strlen (buf
) - 1] != '\n');
3243 buf
[strlen (buf
) - 1] = '\0';
3246 #endif /* not DOS_NT */
3248 /* Return a newly allocated string containing the filename
3249 of FILE relative to the absolute directory DIR (which
3250 should end with a slash). */
3253 relative_filename (file
, dir
)
3256 char *fp
, *dp
, *res
;
3258 /* Find the common root of file and dir. */
3259 fp
= absolute_filename (file
, cwd
);
3261 while (*fp
++ == *dp
++)
3270 /* Build a sequence of "../" strings for the resulting relative filename. */
3271 for (dp
= etags_strchr (dp
+ 1, '/'), res
= "";
3273 dp
= etags_strchr (dp
+ 1, '/'))
3275 res
= concat (res
, "../", "");
3278 /* Add the filename relative to the common root of file and dir. */
3279 res
= concat (res
, fp
+ 1, "");
3281 return res
; /* temporary stub */
3284 /* Return a newly allocated string containing the
3285 absolute filename of FILE given CWD (which should
3286 end with a slash). */
3289 absolute_filename (file
, cwd
)
3292 char *slashp
, *cp
, *res
;
3295 res
= concat (file
, "", "");
3297 res
= concat (cwd
, file
, "");
3299 /* Delete the "/dirname/.." and "/." substrings. */
3300 slashp
= etags_strchr (res
, '/');
3301 while (slashp
!= NULL
&& slashp
[0] != '\0')
3303 if (slashp
[1] == '.')
3305 if (slashp
[2] == '.'
3306 && (slashp
[3] == '/' || slashp
[3] == '\0'))
3311 while (cp
>= res
&& *cp
!= '/');
3314 strcpy (cp
, slashp
+ 3);
3316 else /* else (cp == res) */
3318 if (slashp
[3] != '\0')
3319 strcpy (cp
, slashp
+ 4);
3326 else if (slashp
[2] == '/' || slashp
[2] == '\0')
3328 strcpy (slashp
, slashp
+ 2);
3333 slashp
= etags_strchr (slashp
+ 1, '/');
3339 /* Return a newly allocated string containing the absolute
3340 filename of dir where FILE resides given CWD (which should
3341 end with a slash). */
3344 absolute_dirname (file
, cwd
)
3350 slashp
= etags_strrchr (file
, '/');
3355 res
= absolute_filename (file
, cwd
);
3361 /* Like malloc but get fatal error if memory is exhausted. */
3367 char *result
= (char *) malloc (size
);
3369 fatal ("virtual memory exhausted", 0);
3374 xrealloc (ptr
, size
)
3378 char *result
= (char *) realloc (ptr
, size
);
3380 fatal ("virtual memory exhausted");