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. */
55 #include <sys/types.h>
58 #if !defined (S_ISREG) && defined (S_IFREG)
59 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
64 extern char *getenv ();
66 /* Define CTAGS to make the program "ctags" compatible with the usual one.
67 Let it undefined to make the program "etags", which makes emacs-style
68 tag tables and tags typedefs, #defines and struct/union/enum by default. */
76 /* Exit codes for success and failure. */
86 * The FILEPOS abstract type, which represents a position in a file,
87 * plus the following accessor functions:
89 * long GET_CHARNO (pos)
90 * returns absolute char number.
91 * void SET_FILEPOS (pos, fp, charno)
92 * FILE *fp; long charno;
93 * sets `pos' from the current file
94 * position of `fp' and from `charno',
95 * which must be the absolute character
96 * number corresponding to the current
99 * The `pos' parameter is an lvalue expression of type FILEPOS.
100 * Parameters to the accessor functions are evaluated 0 or more times,
101 * and so must have no side effects.
103 * FILEPOS objects can also be assigned and passed to and from
104 * functions in the normal C manner.
106 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
110 /* real implementation */
111 typedef long FILEPOS
;
112 #define GET_CHARNO(pos) ((pos) + 0)
113 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
115 /* debugging implementation */
121 #define GET_CHARNO(pos) ((pos).charno + 0)
122 #define SET_FILEPOS(pos, fp, cno) \
123 ((void) ((pos).charno = (cno), \
124 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
128 #define streq(s, t) (strcmp (s, t) == 0)
129 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
135 #define iswhite(arg) (_wht[arg]) /* T if char is white */
136 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
137 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
138 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
140 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
143 { /* sorting structure */
144 char *name
; /* function or type name */
145 char *file
; /* file name */
146 logical is_func
; /* use pattern or line no */
147 logical named
; /* list name separately */
148 logical been_warned
; /* set if noticed dup */
149 int lno
; /* line number tag is on */
150 long cno
; /* character number line starts on */
151 char *pat
; /* search pattern */
152 struct nd_st
*left
, *right
; /* left and right sons */
155 typedef struct nd_st NODE
;
157 logical header_file
; /* TRUE if .h file, FALSE o.w. */
158 /* boolean "functions" (see init) */
159 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
161 char *cwd
; /* current working directory */
162 char *tagfiledir
; /* directory of tagfile */
165 char *savenstr (), *savestr ();
166 char *etags_strchr (), *etags_strrchr ();
167 char *etags_getcwd ();
168 char *relative_filename (), *absolute_filename (), *absolute_dirname ();
169 char *xmalloc (), *xrealloc ();
170 int total_size_of_entries ();
171 int string_numeric_p ();
178 int Fortran_functions ();
179 void Lisp_functions ();
180 void Pascal_functions ();
181 void Prolog_functions ();
182 void Scheme_functions ();
183 void TeX_functions ();
187 logical
find_entries ();
194 void process_file ();
200 * xnew -- allocate storage
203 * Type *xnew (int n, Type);
205 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
208 * Symbol table types.
212 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
229 #define C_PLPL 0x00001 /* C++ */
230 #define C_STAR 0x00003 /* C* */
231 #define YACC 0x10000 /* yacc file */
233 char searchar
= '/'; /* use /.../ searches */
235 LINENO lineno
; /* line number of current line */
236 long charno
; /* current character number */
238 long linecharno
; /* charno of start of line; not used by C, but
239 * by every other language.
242 char *curfile
, /* current input file name */
243 *tagfile
, /* output file */
244 *white
= " \f\t\n\013", /* white chars */
245 *endtk
= " \t\n\013\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
246 /* token starting chars */
247 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
248 /* valid in-token chars */
249 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
251 int append_to_tagfile
; /* -a: append to tags */
252 /* The following three default to 1 for etags, but to 0 for ctags. */
253 int typedefs
; /* -t: create tags for typedefs */
254 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
255 /* 0 struct/enum/union decls, and C++ */
256 /* member functions. */
257 int constantypedefs
; /* -d: create tags for C #define and enum */
258 /* constants. Enum consts not implemented. */
259 /* -D: opposite of -d. Default under ctags. */
260 int update
; /* -u: update tags */
261 int vgrind_style
; /* -v: create vgrind style index output */
262 int no_warnings
; /* -w: suppress warnings */
263 int cxref_style
; /* -x: create cxref style output */
264 int cplusplus
; /* .[hc] means C++, not C */
265 int noindentypedefs
; /* -S: ignore indentation in C */
267 /* Name this program was invoked with. */
270 struct option longopts
[] = {
271 { "append", no_argument
, NULL
, 'a' },
272 { "backward-search", no_argument
, NULL
, 'B' },
273 { "c++", no_argument
, NULL
, 'C' },
274 { "cxref", no_argument
, NULL
, 'x' },
275 { "defines", no_argument
, NULL
, 'd' },
276 { "help", no_argument
, NULL
, 'H' },
277 { "ignore-indentation", no_argument
, NULL
, 'S' },
278 { "include", required_argument
, NULL
, 'i' },
279 { "no-defines", no_argument
, NULL
, 'D' },
280 { "no-warn", no_argument
, NULL
, 'w' },
281 { "output", required_argument
, NULL
, 'o' },
282 { "typedefs", no_argument
, NULL
, 't' },
283 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
284 { "update", no_argument
, NULL
, 'u' },
285 { "version", no_argument
, NULL
, 'V' },
286 { "vgrind", no_argument
, NULL
, 'v' },
290 FILE *tagf
; /* ioptr for tags file */
291 NODE
*head
; /* the head of the binary tree of tags */
292 logical permit_duplicates
= TRUE
; /* allow duplicate tags */
294 /* A `struct linebuffer' is a structure which holds a line of text.
295 `readline' reads a line from a stream into a linebuffer
296 and works regardless of the length of the line. */
304 struct linebuffer lb
; /* the current line */
305 struct linebuffer filename_lb
; /* used to read in filenames */
309 struct linebuffer lb
; /* used by C_entries instead of lb */
316 printf ("%s for Emacs version %s.\n", (CTAGS
) ? "CTAGS" : "ETAGS", VERSION
);
318 printf ("%s for Emacs version 19.\n", (CTAGS
) ? "CTAGS" : "ETAGS");
327 printf ("These are the options accepted by %s. You may use unambiguous\n\
328 abbreviations for the long option names. A - as file name means read file\n\
329 names from stdin.\n\n", progname
);
331 puts ("-a, --append\n\
332 Append tag entries to existing tags file.");
335 puts ("-B, --backward-search\n\
336 Write the search commands for the tag entries using '?', the\n\
337 backward-search command instead of '/', the forward-search command.");
340 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
341 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
342 extensions are always assumed to be C++ code.");
345 puts ("-d, --defines\n\
346 Create tag entries for constant C #defines, too.");
348 puts ("-D, --no-defines\n\
349 Don't create tag entries for constant C #defines. This makes\n\
350 the tags file smaller.");
353 puts ("-i FILE, --include=FILE\n\
354 Include a note in tag file indicating that, when searching for\n\
355 a tag, one should also consult the tags file FILE after\n\
356 checking the current file.");
358 puts ("-o FILE, --output=FILE\n\
359 Write the tags to FILE.");
360 puts ("-S, --ignore-indentation\n\
361 Don't rely on indentation quite as much as normal. Currently,\n\
362 this means not to assume that a closing brace in the first\n\
363 column is the final brace of a function or structure\n\
364 definition in C and C++.");
368 puts ("-t, --typedefs\n\
369 Generate tag entries for C typedefs.");
370 puts ("-T, --typedefs-and-c++\n\
371 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
372 and C++ member functions.");
373 puts ("-u, --update\n\
374 Update the tag entries for the given files, leaving tag\n\
375 entries for other files in place. Currently, this is\n\
376 implemented by deleting the existing entries for the given\n\
377 files and then rewriting the new entries at the end of the\n\
378 tags file. It is often faster to simply rebuild the entire\n\
379 tag file than to use this.");
380 puts ("-v, --vgrind\n\
381 Generates an index of items intended for human consumption,\n\
382 similar to the output of vgrind. The index is sorted, and\n\
383 gives the page number of each item.");
384 puts ("-x, --cxref\n\
385 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
386 The output uses line numbers instead of page numbers, but\n\
387 beyond that the differences are cosmetic; try both to see\n\
389 puts ("-w, --no-warn\n\
390 Suppress warning messages about entries defined in multiple\n\
394 puts ("-V, --version\n\
395 Print the version of the program.\n\
397 Print this help message.");
410 unsigned int nincluded_files
= 0;
411 char **included_files
= xnew (argc
, char *);
416 extern char *gfnames ();
417 extern char *massage_name ();
421 _fmode
= O_BINARY
; /* all of files are treated as binary files */
427 * If etags, always find typedefs and structure tags. Why not?
428 * Also default is to find macro constants.
431 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
436 opt
= getopt_long (argc
, argv
, "aCdDf:o:StTi:BuvxwVH", longopts
, 0);
444 /* If getopt returns 0, then it has already processed a
445 long-named option. We should do nothing. */
448 /* Common options. */
461 case 'f': /* for compatibility with old makefiles */
466 "%s: -%c flag may only be given once.\n", progname
, opt
);
485 typedefs_and_cplusplus
++;
492 included_files
[nincluded_files
++] = optarg
;
518 "%s: -%c flag not recognised.\n", progname
, opt
);
523 if (optind
== argc
&& nincluded_files
== 0)
525 fprintf (stderr
, "%s: No input files specified.\n", progname
);
528 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
535 tagfile
= CTAGS
? "tags" : "TAGS";
537 cwd
= etags_getcwd (); /* the current working directory */
539 if (streq (tagfile
, "-"))
545 tagfiledir
= absolute_dirname (tagfile
, cwd
);
548 init (); /* set up boolean "functions" */
551 initbuffer (&lbs
[0].lb
);
552 initbuffer (&lbs
[1].lb
);
553 initbuffer (&filename_lb
);
555 * loop through files finding functions
559 if (streq (tagfile
, "-"))
562 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
573 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
577 error ("Can't find file %s\n", this_file
);
582 this_file
= massage_name (this_file
);
585 } /* solely to balance out the ifdef'd parens above */
588 for (; optind
< argc
; optind
++)
590 this_file
= argv
[optind
];
592 /* Input file named "-" means read file names from stdin and use them. */
593 if (streq (this_file
, "-"))
595 while (!feof (stdin
))
597 (void) readline (&filename_lb
, stdin
);
598 if (strlen (filename_lb
.buffer
) > 0)
599 process_file (filename_lb
.buffer
);
603 process_file (this_file
);
608 while (nincluded_files
-- > 0)
609 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
611 (void) fclose (tagf
);
622 /* update cannot be set under VMS, so we may assume that argc
623 and argv have not been munged. */
624 for (i
= optind
; i
< argc
; i
++)
627 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
628 tagfile
, argv
[i
], tagfile
);
633 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
640 (void) fclose (tagf
);
643 sprintf (cmd
, "sort %s -o %s", tagfile
, tagfile
);
651 * This routine is called on each file argument.
657 struct stat stat_buf
;
659 if (stat (file
, &stat_buf
) == 0 && !S_ISREG (stat_buf
.st_mode
))
661 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
664 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
666 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
669 if (!find_entries (file
))
679 /* file is an absolute filename. Canonicalise it. */
680 filename
= absolute_filename (file
, cwd
);
684 /* file is a filename relative to cwd. Make it relative
685 to the directory of the tags file. */
686 filename
= relative_filename (file
, tagfiledir
);
688 fprintf (tagf
, "\f\n%s,%d\n", filename
, total_size_of_entries (head
));
696 * This routine sets up the boolean pseudo-functions which work
697 * by setting boolean flags dependent upon the corresponding character
698 * Every char which is NOT in that string is not a white char. Therefore,
699 * all of the array "_wht" is set to FALSE, and then the elements
700 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
701 * of a char is TRUE if it is the string "white", else FALSE.
709 for (i
= 0; i
< 0177; i
++)
710 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
711 for (sp
= white
; *sp
; sp
++)
713 for (sp
= endtk
; *sp
; sp
++)
715 for (sp
= intk
; *sp
; sp
++)
717 for (sp
= begtk
; *sp
; sp
++)
719 _wht
[0] = _wht
['\n'];
720 _etk
[0] = _etk
['\n'];
721 _btk
[0] = _btk
['\n'];
722 _itk
[0] = _itk
['\n'];
726 * This routine opens the specified file and calls the function
727 * which finds the function and type definitions.
736 inf
= fopen (file
, "r");
742 curfile
= savestr (file
);
743 cp
= etags_strrchr (file
, '.');
746 header_file
= (cp
&& (streq (cp1
, "h")));
748 /* .tex, .aux or .bbl implies LaTeX source code */
749 if (cp
&& (streq (cp1
, "tex") || streq (cp1
, "aux")
750 || streq (cp1
, "bbl")))
753 goto close_and_return
;
755 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
756 if (cp
&& (streq (cp1
, "l")
758 || streq (cp1
, "lsp")
759 || streq (cp1
, "lisp")
761 || streq (cp1
, "clisp")))
763 Lisp_functions (inf
);
764 goto close_and_return
;
766 /* .scm or .sm or .scheme or ... implies scheme source code */
767 if (cp
&& (streq (cp1
, "sm")
768 || streq (cp1
, "scm")
769 || streq (cp1
, "scheme")
771 || streq (cp1
, "sch")
774 || streq (cp1
, "SCM")
775 /* The `SCM' or `scm' prefix with a version number */
776 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
777 && string_numeric_p (cp1
))
778 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
779 && string_numeric_p (cp1
))))
781 Scheme_functions (inf
);
782 goto close_and_return
;
785 if (cp
&& (streq (cp1
, "s")
786 || streq (cp1
, "a") /* Unix assembler */
787 || streq (cp1
, "sa") /* Unix assembler */
788 || streq (cp1
, "asm") /* Microcontroller assembly */
789 || streq (cp1
, "src") /* BSO/Tasking C compiler output */
790 || streq (cp1
, "def") /* BSO/Tasking definition includes */
791 || streq (cp1
, "ins") /* Microcontroller include files */
792 || streq (cp1
, "inc")))/* Microcontroller include files */
795 goto close_and_return
;
797 /* .C or .H or .cxx or .hxx or .cc or .cpp: a C++ file */
798 if (cp
&& (streq (cp1
, "C")
800 || streq (cp1
, "cpp")
801 || streq (cp1
, "cxx")
802 || streq (cp1
, "hxx")
803 || streq (cp1
, "cc")))
805 C_entries (C_PLPL
, inf
); /* C++ */
806 goto close_and_return
;
808 /* .cs or .hs: a C* file */
809 if (cp
&& (streq (cp1
, "cs")
810 || streq (cp1
, "hs")))
812 C_entries (C_STAR
, inf
);
813 goto close_and_return
;
815 /* .y: a yacc file */
816 if (cp
&& (streq (cp1
, "y")))
818 C_entries (YACC
, inf
);
819 goto close_and_return
;
821 /* .pl implies prolog source code */
822 if (cp
&& streq (cp1
, "pl"))
824 Prolog_functions (inf
);
825 goto close_and_return
;
827 /* .p or .pas: a Pascal file */
828 if (cp
&& (streq (cp1
, "p")
829 || streq (cp1
, "pas")))
831 Pascal_functions (inf
);
832 goto close_and_return
;
834 /* If .f or .for, assume it is fortran or nothing. */
835 if (cp
&& (streq (cp1
, "f")
836 || streq (cp1
, "for")))
838 (void) Fortran_functions (inf
);
839 goto close_and_return
;
841 /* if not a .c or .h or .y file, try fortran */
842 if (cp
&& ((cp
[1] != 'c'
845 || (cp
[1] != 0 && cp
[2] != 0)))
847 if (Fortran_functions (inf
) != 0)
848 goto close_and_return
;
849 rewind (inf
); /* no fortran tags found, try C */
851 C_entries (cplusplus
? C_PLPL
: 0, inf
);
858 /* Nonzero if string STR is composed of digits. */
861 string_numeric_p (str
)
866 if (*str
< '0' || *str
> '9')
873 /* Should take a TOKEN* instead!! */
875 pfnote (name
, is_func
, named
, linestart
, linelen
, lno
, cno
)
876 char *name
; /* tag name */
877 logical is_func
; /* function or type name? */
878 logical named
; /* tag different from text of definition? */
894 /* It's okay to output early in etags -- it only disrupts the
895 * character count of the tag entries, which is no longer used
898 error ("too many entries to sort", 0);
905 /* If ctags mode, change name "main" to M<thisfilename>. */
906 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
908 fp
= etags_strrchr (curfile
, '/');
909 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
910 fp
= etags_strrchr (name
, '.');
911 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
915 np
->name
= savestr (name
);
917 np
->is_func
= is_func
;
920 /* UNCOMMENT THE +1 HERE: */
921 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
922 np
->left
= np
->right
= 0;
925 c
= linestart
[linelen
];
926 linestart
[linelen
] = 0;
928 else if (cxref_style
== 0)
930 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
933 np
->pat
= savestr (linestart
);
936 linestart
[linelen
] = c
;
939 add_node (np
, &head
);
944 * recurse on left children, iterate on right children.
952 register NODE
*node_right
= node
->right
;
953 free_tree (node
->left
);
956 free ((char *) node
);
963 * Adds a node to the tree of nodes. In etags mode, we don't keep
964 * it sorted; we just keep a linear list. In ctags mode, maintain
965 * an ordered tree, with no attempt at balancing.
967 * add_node is the only function allowed to add nodes, so it can
970 /* Must avoid static vars within functions since some systems
971 #define static as nothing. */
972 NODE
*last_node
= NULL
;
975 add_node (node
, cur_node_p
)
976 NODE
*node
, **cur_node_p
;
979 register NODE
*cur_node
= *cur_node_p
;
981 if (cur_node
== NULL
)
991 if (last_node
== NULL
)
992 fatal ("internal error in add_node", 0);
993 last_node
->right
= node
;
999 dif
= strcmp (node
->name
, cur_node
->name
);
1002 * If this tag name matches an existing one, then
1003 * do not add the node, but maybe print a warning.
1007 if (node
->file
== cur_node
->file
)
1011 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1012 node
->file
, lineno
, node
->name
);
1013 fprintf (stderr
, "Second entry ignored\n");
1017 if (!cur_node
->been_warned
&& !no_warnings
)
1020 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1021 node
->file
, cur_node
->file
, node
->name
);
1023 cur_node
->been_warned
= TRUE
;
1027 /* Maybe refuse to add duplicate nodes. */
1028 if (!permit_duplicates
)
1030 if (streq (node
->name
, cur_node
->name
)
1031 && streq (node
->file
, cur_node
->file
))
1035 /* Actually add the node */
1036 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1042 register NODE
*node
;
1049 /* Output subentries that precede this one */
1050 put_entries (node
->left
);
1052 /* Output this entry */
1058 fprintf (tagf
, "%s\177%s\001%d,%d\n",
1059 node
->pat
, node
->name
,
1060 node
->lno
, node
->cno
);
1064 fprintf (tagf
, "%s\177%d,%d\n",
1066 node
->lno
, node
->cno
);
1069 else if (!cxref_style
)
1071 fprintf (tagf
, "%s\t%s\t",
1072 node
->name
, node
->file
);
1076 putc (searchar
, tagf
);
1079 for (sp
= node
->pat
; *sp
; sp
++)
1081 if (*sp
== '\\' || *sp
== searchar
)
1085 putc (searchar
, tagf
);
1088 { /* a typedef; text pattern inadequate */
1089 fprintf (tagf
, "%d", node
->lno
);
1093 else if (vgrind_style
)
1094 fprintf (stdout
, "%s %s %d\n",
1095 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1097 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1098 node
->name
, node
->lno
, node
->file
, node
->pat
);
1100 /* Output subentries that follow this one */
1101 put_entries (node
->right
);
1104 /* Length of a number's decimal representation. */
1112 for (; num
; num
/= 10)
1118 * Return total number of characters that put_entries will output for
1119 * the nodes in the subtree of the specified node. Works only if
1120 * we are not ctags, but called only in that case. This count
1121 * is irrelevant with the new tags.el, but is still supplied for
1122 * backward compatibility.
1125 total_size_of_entries (node
)
1126 register NODE
*node
;
1134 for (; node
; node
= node
->right
)
1136 /* Count left subentries. */
1137 total
+= total_size_of_entries (node
->left
);
1139 /* Count this entry */
1140 total
+= strlen (node
->pat
) + 1;
1141 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1143 total
+= 1 + strlen (node
->name
); /* \001name */
1150 * The C symbol tables.
1153 /* Feed stuff between (but not including) %[ and %] lines to:
1154 gperf -c -k1,3 -o -p -r -t
1156 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1158 class, C_PLPL, st_C_struct
1159 domain, C_STAR, st_C_struct
1160 union, 0, st_C_struct
1161 struct, 0, st_C_struct
1163 typedef, 0, st_C_typedef
1164 define, 0, st_C_define
1165 long, 0, st_C_typespec
1166 short, 0, st_C_typespec
1167 int, 0, st_C_typespec
1168 char, 0, st_C_typespec
1169 float, 0, st_C_typespec
1170 double, 0, st_C_typespec
1171 signed, 0, st_C_typespec
1172 unsigned, 0, st_C_typespec
1173 auto, 0, st_C_typespec
1174 void, 0, st_C_typespec
1175 extern, 0, st_C_typespec
1176 static, 0, st_C_typespec
1177 const, 0, st_C_typespec
1178 volatile, 0, st_C_typespec
1180 and replace lines between %< and %> with its output. */
1182 /* C code produced by gperf version 1.8.1 (K&R C version) */
1183 /* Command-line: gperf -c -k1,3 -o -p -r -t */
1186 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
1188 #define MIN_WORD_LENGTH 3
1189 #define MAX_WORD_LENGTH 8
1190 #define MIN_HASH_VALUE 10
1191 #define MAX_HASH_VALUE 62
1194 53 is the maximum key range
1202 static unsigned char hash_table
[] =
1204 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1205 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1206 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1207 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1208 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1209 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1210 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1211 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1212 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1213 62, 62, 62, 62, 62, 62, 62, 2, 62, 7,
1214 6, 9, 15, 30, 62, 24, 62, 62, 1, 24,
1215 7, 27, 13, 62, 19, 26, 18, 27, 1, 62,
1216 62, 62, 62, 62, 62, 62, 62, 62,
1218 return len
+ hash_table
[str
[2]] + hash_table
[str
[0]];
1221 struct C_stab_entry
*
1222 in_word_set (str
, len
)
1227 static struct C_stab_entry wordlist
[] =
1229 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1231 {"volatile", 0, st_C_typespec
},
1233 {"long", 0, st_C_typespec
},
1234 {"char", 0, st_C_typespec
},
1235 {"class", C_PLPL
, st_C_struct
},
1236 {"",}, {"",}, {"",}, {"",},
1237 {"const", 0, st_C_typespec
},
1238 {"",}, {"",}, {"",}, {"",},
1239 {"auto", 0, st_C_typespec
},
1241 {"define", 0, st_C_define
},
1243 {"void", 0, st_C_typespec
},
1244 {"",}, {"",}, {"",},
1245 {"extern", 0, st_C_typespec
},
1246 {"static", 0, st_C_typespec
},
1248 {"domain", C_STAR
, st_C_struct
},
1250 {"typedef", 0, st_C_typedef
},
1251 {"double", 0, st_C_typespec
},
1252 {"enum", 0, st_C_enum
},
1253 {"",}, {"",}, {"",}, {"",},
1254 {"int", 0, st_C_typespec
},
1256 {"float", 0, st_C_typespec
},
1257 {"",}, {"",}, {"",},
1258 {"struct", 0, st_C_struct
},
1259 {"",}, {"",}, {"",}, {"",},
1260 {"union", 0, st_C_struct
},
1262 {"short", 0, st_C_typespec
},
1264 {"unsigned", 0, st_C_typespec
},
1265 {"signed", 0, st_C_typespec
},
1268 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
1270 register int key
= hash (str
, len
);
1272 if (key
<= MAX_HASH_VALUE
&& key
>= MIN_HASH_VALUE
)
1274 register char *s
= wordlist
[key
].name
;
1276 if (*s
== *str
&& strneq (str
+ 1, s
+ 1, len
- 1))
1277 return &wordlist
[key
];
1285 C_symtype(str
, len
, c_ext
)
1290 register struct C_stab_entry
*se
= in_word_set(str
, len
);
1292 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
1298 * C functions are recognized using a simple finite automaton.
1299 * funcdef is its state variable.
1303 fnone
, /* nothing seen */
1304 ftagseen
, /* function-like tag seen */
1305 fstartlist
, /* just after open parenthesis */
1306 finlist
, /* in parameter list */
1307 flistseen
, /* after parameter list */
1308 fignore
/* before open brace */
1314 * typedefs are recognized using a simple finite automaton.
1315 * typeddef is its state variable.
1319 tnone
, /* nothing seen */
1320 ttypedseen
, /* typedef keyword seen */
1321 tinbody
, /* inside typedef body */
1322 tend
, /* just before typedef tag */
1323 tignore
/* junk after typedef tag */
1329 * struct-like structures (enum, struct and union) are recognized
1330 * using another simple finite automaton. `structdef' is its state
1335 snone
, /* nothing seen yet */
1336 skeyseen
, /* struct-like keyword seen */
1337 stagseen
, /* struct-like tag seen */
1338 scolonseen
, /* colon seen after struct-like tag */
1339 sinbody
/* in struct body: recognize member func defs*/
1344 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1345 * struct tag, and structtype is the type of the preceding struct-like
1348 char structtag
[BUFSIZ
];
1349 enum sym_type structtype
;
1352 * Yet another little state machine to deal with preprocessor lines.
1356 dnone
, /* nothing seen */
1357 dsharpseen
, /* '#' seen as first char on line */
1358 ddefineseen
, /* '#' and 'define' seen */
1359 dignorerest
/* ignore rest of line */
1364 * Set this to TRUE, and the next token considered is called a function.
1365 * Used only for GNUmacs's function-defining macros.
1367 logical next_token_is_func
;
1370 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1376 * checks to see if the current token is at the start of a
1377 * function, or corresponds to a typedef, or is a struct/union/enum
1380 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1381 * C_EXT is which language we are looking at.
1383 * In the future we will need some way to adjust where the end of
1384 * the token is; for instance, implementing the C++ keyword
1385 * `operator' properly will adjust the end of the token to be after
1386 * whatever follows `operator'.
1393 * next_token_is_func IN OUT
1397 consider_token (c
, tokp
, c_ext
, cblev
, is_func
)
1398 register char c
; /* IN: first char after the token */
1399 register TOKEN
*tokp
; /* IN: token pointer */
1400 int c_ext
; /* IN: C extensions mask */
1401 int cblev
; /* IN: curly brace level */
1402 logical
*is_func
; /* OUT: function found */
1404 enum sym_type toktype
= C_symtype(tokp
->p
, tokp
->len
, c_ext
);
1407 * Advance the definedef state machine.
1412 /* We're not on a preprocessor line. */
1415 if (toktype
== st_C_define
)
1417 definedef
= ddefineseen
;
1421 definedef
= dignorerest
;
1426 * Make a tag for any macro, unless it is a constant
1427 * and constantypedefs is FALSE.
1429 definedef
= dignorerest
;
1430 *is_func
= (c
== '(');
1431 if (!*is_func
&& !constantypedefs
)
1438 error ("internal error: definedef value.", 0);
1447 if (toktype
== st_C_typedef
)
1450 typdef
= ttypedseen
;
1466 /* Do not return here, so the structdef stuff has a chance. */
1480 * This structdef business is currently only invoked when cblev==0.
1481 * It should be recursively invoked whatever the curly brace level,
1482 * and a stack of states kept, to allow for definitions of structs
1485 * This structdef business is NOT invoked when we are ctags and the
1486 * file is plain C. This is because a struct tag may have the same
1487 * name as another tag, and this loses with ctags.
1489 * This if statement deals with the typdef state machine as
1490 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1491 * return (FALSE). All the other code here is for the structdef
1498 if (typdef
== ttypedseen
1499 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1501 structdef
= skeyseen
;
1502 structtype
= toktype
;
1506 if (structdef
== skeyseen
)
1508 if (structtype
== st_C_struct
)
1510 strncpy (structtag
, tokp
->p
, tokp
->len
);
1511 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1515 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1517 structdef
= stagseen
;
1521 /* Avoid entering funcdef stuff if typdef is going on. */
1522 if (typdef
!= tnone
)
1528 /* Detect GNU macros. */
1529 if (definedef
== dnone
)
1530 if (strneq (tokp
->p
, "DEFUN", 5) /* Used in emacs */
1532 These are defined inside C functions
, so currently they
1534 || strneq (tokp
->p
, "EXFUN", 5) /* Used in glibc */
1535 || strneq (tokp
->p
, "DEFVAR_", 7) /* Used in emacs */
1537 || strneq (tokp
->p
, "SYSCALL", 7) /* Used in glibc (mach) */
1538 || strneq (tokp
->p
, "ENTRY", 5) /* Used in glibc */
1539 || strneq (tokp
->p
, "PSEUDO", 6)) /* Used in glibc */
1542 next_token_is_func
= TRUE
;
1545 if (next_token_is_func
)
1547 next_token_is_func
= FALSE
;
1557 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1558 funcdef
= fnone
; /* should be useless */
1561 if (funcdef
== fnone
)
1574 * This routine finds functions, typedefs, #define's and
1575 * struct/union/enum definitions in C syntax and adds them
1579 #define curlb (lbs[curndx].lb)
1580 #define othlb (lbs[1-curndx].lb)
1581 #define newlb (lbs[newndx].lb)
1582 #define curlinepos (lbs[curndx].linepos)
1583 #define othlinepos (lbs[1-curndx].linepos)
1584 #define newlinepos (lbs[newndx].linepos)
1586 /* Save and restore token state. This is used when preprocessor defines
1587 are handled, to avoid disturbing active function/typedef/struct states. */
1588 #define TOKEN_SAVED_P (savetok.lineno > 0)
1589 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1590 savetok.len = toklen, strcpy(savenameb, nameb))
1591 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1592 toklen = tok.len, strcpy(nameb, savenameb), \
1595 #define CNL_SAVE_DEFINEDEF \
1597 SET_FILEPOS (curlinepos, inf, charno); \
1599 charno += readline (&curlb, inf); \
1600 lp = curlb.buffer; \
1607 CNL_SAVE_DEFINEDEF; \
1608 if (TOKEN_SAVED_P) \
1610 definedef = dnone; \
1613 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1614 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1615 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1616 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1619 C_entries (c_ext
, inf
)
1620 int c_ext
; /* extension of C? */
1623 register char c
; /* latest char read; '\0' for end of line */
1624 register char *lp
; /* pointer one beyond the character `c' */
1625 int curndx
, newndx
; /* indices for current and new lb */
1626 TOKEN tok
; /* latest token read for funcdef & structdef */
1627 char nameb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1628 register int tokoff
; /* offset in line of start of latest token */
1629 register int toklen
; /* length of latest token */
1630 int cblev
; /* current curly brace level */
1631 int parlev
; /* current parenthesis level */
1632 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1634 TOKEN savetok
; /* saved token during preprocessor handling */
1635 char savenameb
[BUFSIZ
]; /* ouch! */
1638 curndx
= newndx
= 0;
1644 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1645 next_token_is_func
= yacc_rules
= FALSE
;
1646 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1649 cplpl
= c_ext
& C_PLPL
;
1656 /* If we're at the end of the line, the next character is a
1657 '\0'; don't skip it, because it's the thing that tells us
1658 to read the next line. */
1679 /* Newlines inside comments do not end macro definitions in
1694 /* Newlines inside strings do not end macro definitions
1695 in traditional cpp, even though compilers don't
1696 usually accept them. */
1707 /* Hmmm, something went wrong. */
1721 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1726 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1736 else if (cplpl
&& *lp
== '/')
1744 if ((c_ext
& YACC
) && *lp
== '%')
1746 /* entering or exiting rules section in yacc file */
1748 definedef
= dnone
; funcdef
= fnone
;
1749 typdef
= tnone
; structdef
= snone
;
1750 next_token_is_func
= FALSE
;
1751 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1753 yacc_rules
= !yacc_rules
;
1759 if (definedef
== dnone
)
1762 logical cpptoken
= TRUE
;
1764 /* Look back on this line. If all blanks, or nonblanks
1765 followed by an end of comment, this is a preprocessor
1767 for (cp
= newlb
.buffer
; cp
< lp
-1; cp
++)
1770 if (*cp
== '*' && *(cp
+1) == '/')
1779 definedef
= dsharpseen
;
1780 } /* if (definedef == dnone) */
1786 /* Consider token only if some complicated conditions are satisfied. */
1787 if ((definedef
!= dnone
1788 || (cblev
== 0 && structdef
!= scolonseen
)
1789 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
1790 && typdef
!= tignore
1791 && definedef
!= dignorerest
1792 && funcdef
!= finlist
)
1798 if (cplpl
&& c
== ':' && *lp
== ':' && begtoken(*(lp
+ 1)))
1801 * This handles :: in the middle, but not at the
1802 * beginning of an identifier.
1809 logical is_func
= FALSE
;
1811 tok
.lineno
= lineno
;
1812 tok
.p
= newlb
.buffer
+ tokoff
;
1816 || consider_token (c
, &tok
, c_ext
, cblev
, &is_func
))
1818 if (structdef
== sinbody
1819 && definedef
== dnone
1821 /* function defined in C++ class body */
1823 sprintf (nameb
, "%s::%.*s",
1824 ((structtag
[0] == '\0')
1825 ? "_anonymous_" : structtag
),
1831 sprintf (nameb
, "%.*s", tok
.len
, tok
.p
);
1834 if (structdef
== stagseen
1837 && definedef
== dignorerest
)) /* macro */
1840 if (definedef
== dnone
1841 && (funcdef
== ftagseen
1842 || structdef
== stagseen
1845 if (newndx
== curndx
)
1846 curndx
= 1 - curndx
; /* switch line buffers */
1849 MAKE_TAG_FROM_NEW_LB (is_func
);
1853 } /* if (endtoken (c)) */
1854 else if (intoken (c
))
1859 } /* if (midtoken) */
1860 else if (begtoken (c
))
1871 MAKE_TAG_FROM_OTH_LB (TRUE
);
1878 if (structdef
== stagseen
)
1882 /* Take a quick peek ahead for a define directive,
1883 so we can avoid saving the token when not absolutely
1884 necessary. [This is a speed hack.] */
1885 if (c
== 'd' && strneq (lp
, "efine", 5)
1886 && iswhite (*(lp
+ 5)))
1889 definedef
= ddefineseen
;
1893 definedef
= dignorerest
;
1896 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1898 tokoff
= lp
- 1 - newlb
.buffer
;
1904 } /* if must look at token */
1907 /* Detect end of line, colon, comma, semicolon and various braces
1908 after having handled a token.*/
1912 if (definedef
!= dnone
)
1914 if (structdef
== stagseen
)
1915 structdef
= scolonseen
;
1922 MAKE_TAG_FROM_OTH_LB (FALSE
);
1932 if (definedef
!= dnone
)
1938 MAKE_TAG_FROM_OTH_LB (FALSE
);
1943 if (funcdef
!= fignore
)
1945 if (structdef
== stagseen
)
1949 if (definedef
!= dnone
)
1951 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1953 if (structdef
== stagseen
)
1957 if (definedef
!= dnone
)
1959 if (cblev
== 0 && typdef
== tend
)
1962 MAKE_TAG_FROM_OTH_LB (FALSE
);
1965 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1967 if (structdef
== stagseen
)
1971 if (definedef
!= dnone
)
1980 /* Make sure that the next char is not a '*'.
1981 This handles constructs like:
1982 typedef void OperatorFun (int fun); */
1986 MAKE_TAG_FROM_OTH_LB (FALSE
);
1989 } /* switch (typdef) */
1992 funcdef
= fstartlist
;
2001 if (definedef
!= dnone
)
2009 funcdef
= flistseen
;
2012 if (cblev
== 0 && typdef
== tend
)
2015 MAKE_TAG_FROM_OTH_LB (FALSE
);
2018 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
2022 if (definedef
!= dnone
)
2024 if (typdef
== ttypedseen
)
2028 case skeyseen
: /* unnamed struct */
2029 structtag
[0] = '\0';
2030 structdef
= sinbody
;
2033 case scolonseen
: /* named struct */
2034 structdef
= sinbody
;
2035 MAKE_TAG_FROM_OTH_LB (FALSE
);
2041 MAKE_TAG_FROM_OTH_LB (TRUE
);
2047 /* Neutralize `extern "C" {' grot and look inside structs. */
2048 if (cblev
== 0 && structdef
== snone
&& typdef
== tnone
)
2054 if (definedef
!= dnone
)
2056 if (funcdef
== fstartlist
)
2057 funcdef
= fnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
2060 if (definedef
!= dnone
)
2062 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
2064 cblev
= 0; /* reset curly brace level if first column */
2065 parlev
= 0; /* also reset paren level, just in case... */
2071 if (typdef
== tinbody
)
2074 strcpy (structtag
, "<error 2>");
2078 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
2079 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
2080 if (definedef
!= dnone
)
2082 /* These surely cannot follow a function tag. */
2083 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2087 /* If a macro spans multiple lines don't reset its state. */
2095 } /* while not eof */
2098 /* Fortran parsing */
2107 register int len
= 0;
2109 while (*cp
&& (*cp
| ' ') == (dbp
[len
] | ' '))
2122 while (isspace (*dbp
))
2127 while (isspace (*dbp
))
2131 if (!isdigit (*dbp
))
2133 --dbp
; /* force failure */
2138 while (isdigit (*dbp
));
2147 char nambuf
[BUFSIZ
];
2149 while (isspace (*dbp
))
2154 linecharno
= charno
;
2155 charno
+= readline (&lb
, inf
);
2160 while (isspace (*dbp
))
2169 && (isalpha (*cp
) || isdigit (*cp
) || (*cp
== '_') || (*cp
== '$')));
2174 strcpy (nambuf
, dbp
);
2176 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2177 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2182 Fortran_functions (inf
)
2192 linecharno
= charno
;
2193 charno
+= readline (&lb
, inf
);
2196 dbp
++; /* Ratfor escape to fortran */
2197 while (isspace (*dbp
))
2204 if (tail ("integer"))
2212 if (tail ("logical"))
2216 if (tail ("complex") || tail ("character"))
2220 if (tail ("double"))
2222 while (isspace (*dbp
))
2226 if (tail ("precision"))
2232 while (isspace (*dbp
))
2239 if (tail ("function"))
2243 if (tail ("subroutine"))
2251 if (tail ("program"))
2256 if (tail ("procedure"))
2265 * Bob Weiner, Motorola Inc., 4/3/94
2266 * Unix and microcontroller assembly tag handling
2267 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
2273 char nambuf
[BUFSIZ
];
2284 linecharno
= charno
;
2285 charno
+= readline (&lb
, inf
);
2288 /* If first char is alphabetic or one of [_.$], test for colon
2289 following identifier. */
2290 if (isalpha (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2292 /* Read past label. */
2294 while (isalnum (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2296 if (*cp
== ':' || isspace (*cp
))
2298 /* Found end of label, so copy it and add it to the table. */
2301 strcpy (nambuf
, lb
.buffer
);
2303 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2304 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2311 /* Added by Mosur Mohan, 4/22/88 */
2312 /* Pascal parsing */
2314 #define GET_NEW_LINE \
2316 linecharno = charno; lineno++; \
2317 charno += 1 + readline (&lb, inf); \
2321 /* Locates tags for procedures & functions.
2322 * Doesn't do any type- or var-definitions.
2323 * It does look for the keyword "extern" or "forward"
2324 * immediately following the procedure statement;
2325 * if found, the tag is skipped.
2329 Pascal_functions (inf
)
2332 struct linebuffer tline
; /* mostly copied from C_entries */
2336 char nambuf
[BUFSIZ
];
2338 logical
/* each of these flags is TRUE iff: */
2339 incomm1
, /* point is inside {..} comment */
2340 incomm2
, /* point is inside (*..*) comment */
2341 inquote
, /* point is inside '..' string */
2342 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2343 /* keyword, so next item = potential tag */
2344 found_tag
, /* point is after a potential tag */
2345 inparms
, /* point is within parameter-list */
2346 verify_tag
; /* point has passed the parm-list, so the */
2347 /* next token will determine whether */
2348 /* this is a FORWARD/EXTERN to be */
2349 /* ignored, or whether it is a real tag */
2355 initbuffer (&tline
);
2357 incomm1
= incomm2
= inquote
= FALSE
;
2358 found_tag
= FALSE
; /* have a proc name; check if extern */
2359 get_tagname
= FALSE
; /* have found "procedure" keyword */
2360 inparms
= FALSE
; /* found '(' after "proc" */
2361 verify_tag
= FALSE
; /* check if "extern" is ahead */
2363 /* long main loop to get next char */
2367 if (c
== 0) /* if end of line */
2372 if (!((found_tag
&& verify_tag
) ||
2374 c
= *dbp
++; /* only if don't need *dbp pointing */
2375 /* to the beginning of the name of */
2376 /* the procedure or function */
2378 if (incomm1
) /* within { - } comments */
2384 else if (incomm2
) /* within (* - *) comments */
2388 while ((c
= *dbp
++) == '*')
2407 inquote
= TRUE
; /* found first quote */
2409 case '{': /* found open-{-comment */
2413 if (*dbp
== '*') /* found open-(*-comment */
2418 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2421 case ')': /* end of parms list */
2426 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2433 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2435 /* check if this is an "extern" declaration */
2438 if ((*dbp
== 'e') || (*dbp
== 'E'))
2440 if (tail ("extern")) /* superfluous, really! */
2446 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2448 if (tail ("forward")) /* check for forward reference */
2454 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2458 pfnote (nambuf
, TRUE
, FALSE
,
2459 tline
.buffer
, cp
- tline
.buffer
+ 1,
2460 save_lineno
, save_lcno
);
2464 if (get_tagname
) /* grab name of proc or fn */
2469 /* save all values for later tagging */
2470 tline
.size
= lb
.size
;
2471 strcpy (tline
.buffer
, lb
.buffer
);
2472 save_lineno
= lineno
;
2473 save_lcno
= linecharno
;
2475 /* grab block name */
2476 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2480 strcpy (nambuf
, dbp
);
2482 dbp
= cp
; /* restore dbp to e-o-token */
2483 get_tagname
= FALSE
;
2487 /* and proceed to check for "extern" */
2489 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2490 (!found_tag
) && (!get_tagname
))
2492 /* check for proc/fn keywords */
2496 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2500 if (tail ("unction"))
2505 } /* while not eof */
2509 * lisp tag functions
2510 * just look for (def or (DEF
2517 return ((dbp
[1] == 'd' || dbp
[1] == 'D')
2518 && (dbp
[2] == 'e' || dbp
[2] == 'E')
2519 && (dbp
[3] == 'f' || dbp
[3] == 'F'));
2526 return ((*(++dbp
) == 'q' || *dbp
== 'Q')
2527 && (*(++dbp
) == 'u' || *dbp
== 'U')
2528 && (*(++dbp
) == 'o' || *dbp
== 'O')
2529 && (*(++dbp
) == 't' || *dbp
== 'T')
2530 && (*(++dbp
) == 'e' || *dbp
== 'E')
2531 && isspace(*(++dbp
)));
2539 char nambuf
[BUFSIZ
];
2541 if (*dbp
== '\'') /* Skip prefix quote */
2543 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2546 while (isspace(*dbp
))
2549 for (cp
= dbp
/*+1*/; *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')'; cp
++)
2556 strcpy (nambuf
, dbp
);
2558 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2559 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2564 Lisp_functions (inf
)
2574 linecharno
= charno
;
2575 charno
+= readline (&lb
, inf
);
2581 while (!isspace (*dbp
))
2583 while (isspace (*dbp
))
2589 /* Check for (foo::defmumble name-defined ... */
2592 while (*dbp
&& !isspace (*dbp
)
2593 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2598 while (*dbp
== ':');
2600 if (L_isdef (dbp
- 1))
2602 while (!isspace (*dbp
))
2604 while (isspace (*dbp
))
2615 * Scheme tag functions
2616 * look for (def... xyzzy
2617 * look for (def... (xyzzy
2618 * look for (def ... ((...(xyzzy ....
2619 * look for (set! xyzzy
2625 Scheme_functions (inf
)
2635 linecharno
= charno
;
2636 charno
+= readline (&lb
, inf
);
2638 if (dbp
[0] == '(' &&
2639 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2640 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2641 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2643 while (!isspace (*dbp
))
2645 /* Skip over open parens and white space */
2646 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2650 if (dbp
[0] == '(' &&
2651 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2652 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2653 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2654 (dbp
[4] == '!' || dbp
[4] == '!') &&
2657 while (!isspace (*dbp
))
2659 /* Skip over white space */
2660 while (isspace (*dbp
))
2672 char nambuf
[BUFSIZ
];
2676 /* Go till you get to white space or a syntactic break */
2677 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2679 /* Null terminate the string there. */
2682 /* Copy the string */
2683 strcpy (nambuf
, dbp
);
2684 /* Unterminate the string */
2686 /* Announce the change */
2687 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2691 /* Find tags in TeX and LaTeX input files. */
2693 /* TEX_toktab is a table of TeX control sequences that define tags.
2694 Each TEX_tabent records one such control sequence.
2695 CONVERT THIS TO USE THE Stab TYPE!! */
2703 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2705 /* Default set of control sequences to put into TEX_toktab.
2706 The value of environment var TEXTAGS is prepended to this. */
2708 char *TEX_defenv
= "\
2709 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2712 struct TEX_tabent
*TEX_decode_env ();
2716 char TEX_esc
= '\\';
2717 char TEX_opgrp
= '{';
2718 char TEX_clgrp
= '}';
2721 * TeX/LaTeX scanning loop.
2734 /* Select either \ or ! as escape character. */
2737 /* Initialize token table once from environment. */
2739 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2742 { /* Scan each line in file */
2744 linecharno
= charno
;
2745 charno
+= readline (&lb
, inf
);
2748 while (dbp
= etags_strchr (dbp
, TEX_esc
)) /* Look at each esc in line */
2754 linecharno
+= dbp
- lasthit
;
2756 i
= TEX_Token (lasthit
);
2759 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2760 break; /* We only save a line once */
2766 #define TEX_LESC '\\'
2767 #define TEX_SESC '!'
2770 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2771 /* chars accordingly. */
2779 while ((c
= getc (inf
)) != EOF
)
2781 /* Skip to next line if we hit the TeX comment char. */
2785 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2804 /* Read environment and prepend it to the default string. */
2805 /* Build token table. */
2808 TEX_decode_env (evarname
, defenv
)
2812 register char *env
, *p
;
2814 struct TEX_tabent
*tab
;
2817 /* Append default string to environment. */
2818 env
= getenv (evarname
);
2822 env
= concat (env
, defenv
, "");
2824 /* Allocate a token table */
2825 for (size
= 1, p
= env
; p
;)
2826 if ((p
= etags_strchr (p
, ':')) && *(++p
))
2828 /* Add 1 to leave room for null terminator. */
2829 tab
= xnew (size
+ 1, struct TEX_tabent
);
2831 /* Unpack environment string into token table. Be careful about */
2832 /* zero-length strings (leading ':', "::" and trailing ':') */
2835 p
= etags_strchr (env
, ':');
2836 if (!p
) /* End of environment string. */
2837 p
= env
+ strlen (env
);
2839 { /* Only non-zero strings. */
2840 tab
[i
].name
= savenstr (env
, p
- env
);
2841 tab
[i
].len
= strlen (tab
[i
].name
);
2848 tab
[i
].name
= NULL
; /* Mark end of table. */
2856 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2857 The name being defined actually starts at (NAME + LEN + 1).
2858 But we seem to include the TeX command in the tag name. */
2861 TEX_getit (name
, len
)
2865 char *p
= name
+ len
;
2866 char nambuf
[BUFSIZ
];
2871 /* Let tag name extend to next group close (or end of line) */
2872 while (*p
&& *p
!= TEX_clgrp
)
2874 strncpy (nambuf
, name
, p
- name
);
2875 nambuf
[p
- name
] = 0;
2877 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2881 /* If the text at CP matches one of the tag-defining TeX command names,
2882 return the pointer to the first occurrence of that command in TEX_toktab.
2883 Otherwise return -1. */
2885 /* Keep the capital `T' in `Token' for dumb truncating compilers
2886 (this distinguishes it from `TEX_toktab' */
2893 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2894 if (strneq (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
))
2899 /* Support for Prolog. */
2901 /* whole head (not only functor, but also arguments)
2902 is gotten in compound term. */
2905 prolog_getit (s
, lineno
, linecharno
)
2910 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2918 if (*s
== '\0') /* syntax error. */
2920 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2922 else if (*s
== '\'')
2924 insquote
= !insquote
;
2927 else if (!insquote
&& *s
== '(')
2932 else if (!insquote
&& *s
== ')')
2938 else if (npar
< 0) /* syntax error. */
2941 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2943 if (npar
!= 0) /* syntax error. */
2953 strcpy (nambuf
, save_s
);
2955 pfnote (nambuf
, TRUE
, FALSE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2958 /* It is assumed that prolog predicate starts from column 0. */
2961 Prolog_functions (inf
)
2964 void skip_comment (), prolog_getit ();
2966 lineno
= linecharno
= charno
= 0;
2970 linecharno
+= charno
;
2971 charno
= readline (&lb
, inf
) + 1; /* 1 for newline. */
2973 if (isspace (dbp
[0])) /* not predicate header. */
2975 else if (dbp
[0] == '%') /* comment. */
2977 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2978 skip_comment (&lb
, inf
, &lineno
, &linecharno
);
2980 prolog_getit (dbp
, lineno
, linecharno
);
2985 skip_comment (plb
, inf
, plineno
, plinecharno
)
2986 struct linebuffer
*plb
;
2988 int *plineno
; /* result */
2989 long *plinecharno
; /* result */
2991 while (!substr ("*/", plb
->buffer
))
2994 *plinecharno
+= readline (plb
, inf
) + 1;
2995 } /* 1 for newline. */
2998 /* Return TRUE if 'sub' exists somewhere in 's'. */
3005 while (*s
&& (s
= etags_strchr (s
, *sub
)))
3006 if (prestr (sub
, s
))
3013 /* Return TRUE if 'pre' is prefix of string 's'. */
3022 else if (*pre
== *s
)
3023 return (prestr (pre
+ 1, s
+ 1));
3028 /* Initialize a linebuffer for use */
3031 initbuffer (linebuffer
)
3032 struct linebuffer
*linebuffer
;
3034 linebuffer
->size
= 200;
3035 linebuffer
->buffer
= xnew (200, char);
3039 * Read a line of text from `stream' into `linebuffer'.
3040 * Return the number of characters read from `stream',
3041 * which is the length of the line including the newline, if any.
3044 readline (linebuffer
, stream
)
3045 struct linebuffer
*linebuffer
;
3046 register FILE *stream
;
3048 char *buffer
= linebuffer
->buffer
;
3049 register char *p
= linebuffer
->buffer
;
3050 register char *pend
;
3051 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
3053 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
3057 register int c
= getc (stream
);
3060 linebuffer
->size
*= 2;
3061 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
3062 p
+= buffer
- linebuffer
->buffer
;
3063 pend
= buffer
+ linebuffer
->size
;
3064 linebuffer
->buffer
= buffer
;
3066 if (c
== EOF
|| c
== '\n')
3069 newline
= (c
== '\n') ? 1 : 0;
3075 return p
- buffer
+ newline
;
3082 return savenstr (cp
, strlen (cp
));
3092 dp
= xnew (len
+ 1, char);
3093 strncpy (dp
, cp
, len
);
3099 * Return the ptr in sp at which the character c last
3100 * appears; NULL if not found
3102 * Identical to System V strrchr, included for portability.
3106 etags_strrchr (sp
, c
)
3107 register char *sp
, c
;
3122 * Return the ptr in sp at which the character c first
3123 * appears; NULL if not found
3125 * Identical to System V strchr, included for portability.
3129 etags_strchr (sp
, c
)
3130 register char *sp
, c
;
3140 /* Print error message and exit. */
3151 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3158 fprintf (stderr
, "%s: ", progname
);
3159 fprintf (stderr
, s1
, s2
);
3160 fprintf (stderr
, "\n");
3163 /* Return a newly-allocated string whose contents
3164 concatenate those of s1, s2, s3. */
3170 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3171 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3173 strcpy (result
, s1
);
3174 strcpy (result
+ len1
, s2
);
3175 strcpy (result
+ len1
+ len2
, s3
);
3176 result
[len1
+ len2
+ len3
] = '\0';
3185 char *p
, cwd
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
3192 *p
++ = tolower (*p
);
3193 return strdup (cwd
);
3195 #else /* not DOS_NT */
3196 /* Does the same work as the system V getcwd, but does not need to
3197 guess buffer size in advance. Included mostly for compatibility. */
3207 buf
= xnew (bufsize
, char);
3210 while (getcwd (buf
, bufsize
/ 2) == NULL
);
3215 buf
= xnew (bufsize
, char);
3217 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
3223 if (fgets (buf
, bufsize
, pipe
) == NULL
)
3232 } while (buf
[strlen (buf
) - 1] != '\n');
3235 buf
[strlen (buf
) - 1] = '\0';
3238 #endif /* not DOS_NT */
3240 /* Return a newly allocated string containing the filename
3241 of FILE relative to the absolute directory DIR (which
3242 should end with a slash). */
3245 relative_filename (file
, dir
)
3248 char *fp
, *dp
, *res
;
3250 /* Find the common root of file and dir. */
3251 fp
= absolute_filename (file
, cwd
);
3253 while (*fp
++ == *dp
++)
3262 /* Build a sequence of "../" strings for the resulting relative filename. */
3263 for (dp
= etags_strchr (dp
+ 1, '/'), res
= "";
3265 dp
= etags_strchr (dp
+ 1, '/'))
3267 res
= concat (res
, "../", "");
3270 /* Add the filename relative to the common root of file and dir. */
3271 res
= concat (res
, fp
+ 1, "");
3273 return res
; /* temporary stub */
3276 /* Return a newly allocated string containing the
3277 absolute filename of FILE given CWD (which should
3278 end with a slash). */
3281 absolute_filename (file
, cwd
)
3284 char *slashp
, *cp
, *res
;
3287 res
= concat (file
, "", "");
3289 res
= concat (cwd
, file
, "");
3291 /* Delete the "/dirname/.." and "/." substrings. */
3292 slashp
= etags_strchr (res
, '/');
3293 while (slashp
!= NULL
&& slashp
[0] != '\0')
3295 if (slashp
[1] == '.')
3297 if (slashp
[2] == '.'
3298 && (slashp
[3] == '/' || slashp
[3] == '\0'))
3303 while (cp
>= res
&& *cp
!= '/');
3306 strcpy (cp
, slashp
+ 3);
3308 else /* else (cp == res) */
3310 if (slashp
[3] != '\0')
3311 strcpy (cp
, slashp
+ 4);
3318 else if (slashp
[2] == '/' || slashp
[2] == '\0')
3320 strcpy (slashp
, slashp
+ 2);
3325 slashp
= etags_strchr (slashp
+ 1, '/');
3331 /* Return a newly allocated string containing the absolute
3332 filename of dir where FILE resides given CWD (which should
3333 end with a slash). */
3336 absolute_dirname (file
, cwd
)
3342 slashp
= etags_strrchr (file
, '/');
3347 res
= absolute_filename (file
, cwd
);
3353 /* Like malloc but get fatal error if memory is exhausted. */
3359 char *result
= (char *) malloc (size
);
3361 fatal ("virtual memory exhausted", 0);
3366 xrealloc (ptr
, size
)
3370 char *result
= (char *) realloc (ptr
, size
);
3372 fatal ("virtual memory exhausted");