1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984,87,88,89,93,94 Free Software Foundation, Inc. and Ken Arnold
4 This file is not considered part of GNU Emacs.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22 * Ctags originally by Ken Arnold.
23 * Fortran added by Jim Kleckner.
24 * Ed Pelegri-Llopart added C typedefs.
25 * Gnu Emacs TAGS format and modifications by RMS?
26 * Sam Kendall added C++.
28 * Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer.
31 char pot_etags_version
[] = "@(#) pot revision number is 10.32";
35 #include <sys/param.h>
39 #include <../src/config.h>
40 /* On some systems, Emacs defines static as nothing
41 for the sake of unexec. We don't want that here
42 since we don't use unexec. */
48 #include <sys/types.h>
51 #if !defined (S_ISREG) && defined (S_IFREG)
52 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
57 extern char *getenv ();
60 /* Define CTAGS to make the program "ctags" compatible with the usual one.
61 Let it undefined to make the program "etags", which makes emacs-style
62 tag tables and tags typedefs, #defines and struct/union/enum by default. */
70 /* Exit codes for success and failure. */
80 * The FILEPOS abstract type, which represents a position in a file,
81 * plus the following accessor functions:
83 * long GET_CHARNO (pos)
84 * returns absolute char number.
85 * void SET_FILEPOS (pos, fp, charno)
86 * FILE *fp; long charno;
87 * sets `pos' from the current file
88 * position of `fp' and from `charno',
89 * which must be the absolute character
90 * number corresponding to the current
93 * The `pos' parameter is an lvalue expression of type FILEPOS.
94 * Parameters to the accessor functions are evaluated 0 or more times,
95 * and so must have no side effects.
97 * FILEPOS objects can also be assigned and passed to and from
98 * functions in the normal C manner.
100 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
104 /* real implementation */
105 typedef long FILEPOS
;
106 #define GET_CHARNO(pos) ((pos) + 0)
107 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
109 /* debugging implementation */
115 #define GET_CHARNO(pos) ((pos).charno + 0)
116 #define SET_FILEPOS(pos, fp, cno) \
117 ((void) ((pos).charno = (cno), \
118 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
122 #define streq(s, t) (strcmp (s, t) == 0)
123 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
129 #define iswhite(arg) (_wht[arg]) /* T if char is white */
130 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
131 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
132 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
134 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
137 { /* sorting structure */
138 char *name
; /* function or type name */
139 char *file
; /* file name */
140 logical is_func
; /* use pattern or line no */
141 logical named
; /* list name separately */
142 logical been_warned
; /* set if noticed dup */
143 int lno
; /* line number tag is on */
144 long cno
; /* character number line starts on */
145 char *pat
; /* search pattern */
146 struct nd_st
*left
, *right
; /* left and right sons */
149 typedef struct nd_st NODE
;
151 logical header_file
; /* TRUE if .h file, FALSE o.w. */
152 /* boolean "functions" (see init) */
153 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
155 char *cwd
; /* current working directory */
156 char *tagfiledir
; /* directory of tagfile */
159 char *savenstr (), *savestr ();
160 char *etags_strchr (), *etags_strrchr ();
161 char *etags_getcwd ();
162 char *relative_filename (), *absolute_filename (), *absolute_dirname ();
163 char *xmalloc (), *xrealloc ();
164 int total_size_of_entries ();
169 int Fortran_functions ();
170 void Lisp_functions ();
171 void Pascal_functions ();
172 void Prolog_functions ();
173 void Scheme_functions ();
174 void TeX_functions ();
178 logical
find_entries ();
185 void process_file ();
191 * xnew -- allocate storage
194 * Type *xnew (int n, Type);
196 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
199 * Symbol table types.
203 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
220 #define C_PLPL 0x00001 /* C++ */
221 #define C_STAR 0x00003 /* C* */
222 #define YACC 0x10000 /* yacc file */
224 char searchar
= '/'; /* use /.../ searches */
226 LINENO lineno
; /* line number of current line */
227 long charno
; /* current character number */
229 long linecharno
; /* charno of start of line; not used by C, but
230 * by every other language.
233 char *curfile
, /* current input file name */
234 *tagfile
, /* output file */
235 *white
= " \f\t\n", /* white chars */
236 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
237 /* token starting chars */
238 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
239 /* valid in-token chars */
240 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
242 int append_to_tagfile
; /* -a: append to tags */
243 /* The following three default to 1 for etags, but to 0 for ctags. */
244 int typedefs
; /* -t: create tags for typedefs */
245 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
246 /* 0 struct/enum/union decls, and C++ */
247 /* member functions. */
248 int constantypedefs
; /* -d: create tags for C #define and enum */
249 /* constants. Enum consts not implemented. */
250 /* -D: opposite of -d. Default under ctags. */
251 int update
; /* -u: update tags */
252 int vgrind_style
; /* -v: create vgrind style index output */
253 int no_warnings
; /* -w: suppress warnings */
254 int cxref_style
; /* -x: create cxref style output */
255 int cplusplus
; /* .[hc] means C++, not C */
256 int noindentypedefs
; /* -S: ignore indentation in C */
258 /* Name this program was invoked with. */
261 struct option longopts
[] = {
262 { "append", no_argument
, NULL
, 'a' },
263 { "backward-search", no_argument
, NULL
, 'B' },
264 { "c++", no_argument
, NULL
, 'C' },
265 { "cxref", no_argument
, NULL
, 'x' },
266 { "defines", no_argument
, NULL
, 'd' },
267 { "help", no_argument
, NULL
, 'H' },
268 { "ignore-indentation", no_argument
, NULL
, 'S' },
269 { "include", required_argument
, NULL
, 'i' },
270 { "no-defines", no_argument
, NULL
, 'D' },
271 { "no-warn", no_argument
, NULL
, 'w' },
272 { "output", required_argument
, NULL
, 'o' },
273 { "typedefs", no_argument
, NULL
, 't' },
274 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
275 { "update", no_argument
, NULL
, 'u' },
276 { "version", no_argument
, NULL
, 'V' },
277 { "vgrind", no_argument
, NULL
, 'v' },
281 FILE *tagf
; /* ioptr for tags file */
282 NODE
*head
; /* the head of the binary tree of tags */
283 logical permit_duplicates
= TRUE
; /* allow duplicate tags */
285 /* A `struct linebuffer' is a structure which holds a line of text.
286 `readline' reads a line from a stream into a linebuffer
287 and works regardless of the length of the line. */
295 struct linebuffer lb
; /* the current line */
296 struct linebuffer filename_lb
; /* used to read in filenames */
300 struct linebuffer lb
; /* used by C_entries instead of lb */
307 printf ("%s for Emacs version %s.\n", (CTAGS
) ? "CTAGS" : "ETAGS", VERSION
);
309 printf ("%s for Emacs version 19.\n", (CTAGS
) ? "CTAGS" : "ETAGS");
318 printf ("These are the options accepted by %s. You may use unambiguous\n\
319 abbreviations for the long option names. A - as file name means read file\n\
320 names from stdin.\n\n", progname
);
322 puts ("-a, --append\n\
323 Append tag entries to existing tags file.");
326 puts ("-B, --backward-search\n\
327 Write the search commands for the tag entries using '?', the\n\
328 backward-search command instead of '/', the forward-search command.");
331 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
332 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
333 extensions are always assumed to be C++ code.");
336 puts ("-d, --defines\n\
337 Create tag entries for C #defines, too.");
339 puts ("-D, --no-defines\n\
340 Don't create tag entries for C #defines. This makes the tags\n\
344 puts ("-i FILE, --include=FILE\n\
345 Include a note in tag file indicating that, when searching for\n\
346 a tag, one should also consult the tags file FILE after\n\
347 checking the current file.");
349 puts ("-o FILE, --output=FILE\n\
350 Write the tags to FILE.");
351 puts ("-S, --ignore-indentation\n\
352 Don't rely on indentation quite as much as normal. Currently,\n\
353 this means not to assume that a closing brace in the first\n\
354 column is the final brace of a function or structure\n\
355 definition in C and C++.");
359 puts ("-t, --typedefs\n\
360 Generate tag entries for C typedefs.");
361 puts ("-T, --typedefs-and-c++\n\
362 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
363 and C++ member functions.");
364 puts ("-u, --update\n\
365 Update the tag entries for the given files, leaving tag\n\
366 entries for other files in place. Currently, this is\n\
367 implemented by deleting the existing entries for the given\n\
368 files and then rewriting the new entries at the end of the\n\
369 tags file. It is often faster to simply rebuild the entire\n\
370 tag file than to use this.");
371 puts ("-v, --vgrind\n\
372 Generates an index of items intended for human consumption,\n\
373 similar to the output of vgrind. The index is sorted, and\n\
374 gives the page number of each item.");
375 puts ("-x, --cxref\n\
376 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
377 The output uses line numbers instead of page numbers, but\n\
378 beyond that the differences are cosmetic; try both to see\n\
380 puts ("-w, --no-warn\n\
381 Suppress warning messages about entries defined in multiple\n\
385 puts ("-V, --version\n\
386 Print the version of the program.\n\
388 Print this help message.");
401 unsigned int nincluded_files
= 0;
402 char **included_files
= xnew (argc
, char *);
407 extern char *gfnames ();
408 extern char *massage_name ();
412 _fmode
= O_BINARY
; /* all of files are treated as binary files */
418 * If etags, always find typedefs and structure tags. Why not?
419 * Also default is to find macro constants.
422 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
427 opt
= getopt_long (argc
, argv
, "aCdDf:o:StTi:BuvxwVH", longopts
, 0);
435 /* If getopt returns 0, then it has already processed a
436 long-named option. We should do nothing. */
439 /* Common options. */
452 case 'f': /* for compatibility with old makefiles */
457 "%s: -%c flag may only be given once\n", progname
, opt
);
476 included_files
[nincluded_files
++] = optarg
;
490 typedefs_and_cplusplus
++;
512 if (optind
== argc
&& nincluded_files
== 0)
514 fprintf (stderr
, "%s: No input files specified.\n", progname
);
517 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
524 tagfile
= CTAGS
? "tags" : "TAGS";
526 cwd
= etags_getcwd (); /* the current working directory */
528 if (streq (tagfile
, "-"))
534 tagfiledir
= absolute_dirname (tagfile
, cwd
);
537 init (); /* set up boolean "functions" */
540 initbuffer (&lbs
[0].lb
);
541 initbuffer (&lbs
[1].lb
);
542 initbuffer (&filename_lb
);
544 * loop through files finding functions
548 if (streq (tagfile
, "-"))
551 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
562 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
566 error ("Can't find file %s\n", this_file
);
571 this_file
= massage_name (this_file
);
574 } /* solely to balance out the ifdef'd parens above */
577 for (; optind
< argc
; optind
++)
579 this_file
= argv
[optind
];
581 /* Input file named "-" means read file names from stdin and use them. */
582 if (streq (this_file
, "-"))
584 while (!feof (stdin
))
586 (void) readline (&filename_lb
, stdin
);
587 if (strlen (filename_lb
.buffer
) > 0)
588 process_file (filename_lb
.buffer
);
592 process_file (this_file
);
597 while (nincluded_files
-- > 0)
598 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
600 (void) fclose (tagf
);
611 /* update cannot be set under VMS, so we may assume that argc
612 and argv have not been munged. */
613 for (i
= optind
; i
< argc
; i
++)
616 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
617 tagfile
, argv
[i
], tagfile
);
622 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
629 (void) fclose (tagf
);
632 sprintf (cmd
, "sort %s -o %s", tagfile
, tagfile
);
640 * This routine is called on each file argument.
646 struct stat stat_buf
;
648 if (stat (file
, &stat_buf
) == 0 && !S_ISREG (stat_buf
.st_mode
))
650 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
653 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
655 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
658 if (!find_entries (file
))
668 /* file is an absolute filename. Canonicalise it. */
669 filename
= absolute_filename (file
, cwd
);
673 /* file is a filename relative to cwd. Make it relative
674 to the directory of the tags file. */
675 filename
= relative_filename (file
, tagfiledir
);
677 fprintf (tagf
, "\f\n%s,%d\n", filename
, total_size_of_entries (head
));
685 * This routine sets up the boolean pseudo-functions which work
686 * by setting boolean flags dependent upon the corresponding character
687 * Every char which is NOT in that string is not a white char. Therefore,
688 * all of the array "_wht" is set to FALSE, and then the elements
689 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
690 * of a char is TRUE if it is the string "white", else FALSE.
698 for (i
= 0; i
< 0177; i
++)
699 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
700 for (sp
= white
; *sp
; sp
++)
702 for (sp
= endtk
; *sp
; sp
++)
704 for (sp
= intk
; *sp
; sp
++)
706 for (sp
= begtk
; *sp
; sp
++)
708 _wht
[0] = _wht
['\n'];
709 _etk
[0] = _etk
['\n'];
710 _btk
[0] = _btk
['\n'];
711 _itk
[0] = _itk
['\n'];
715 * This routine opens the specified file and calls the function
716 * which finds the function and type definitions.
725 inf
= fopen (file
, "r");
731 curfile
= savestr (file
);
732 cp
= etags_strrchr (file
, '.');
735 header_file
= (cp
&& (streq (cp1
, "h")));
737 /* .tex, .aux or .bbl implies LaTeX source code */
738 if (cp
&& (streq (cp1
, "tex") || streq (cp1
, "aux")
739 || streq (cp1
, "bbl")))
742 goto close_and_return
;
744 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
745 if (cp
&& (streq (cp1
, "l")
747 || streq (cp1
, "lsp")
748 || streq (cp1
, "lisp")
750 || streq (cp1
, "clisp")))
752 Lisp_functions (inf
);
753 goto close_and_return
;
755 /* .scm or .sm or .scheme or ... implies scheme source code */
756 if (cp
&& (streq (cp1
, "sm")
757 || streq (cp1
, "scm")
758 || streq (cp1
, "scheme")
760 || streq (cp1
, "sch")
763 || streq (cp1
, "SCM")
764 /* The `SCM' or `scm' prefix with a version number */
765 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
766 && string_numeric_p (cp1
))
767 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
768 && string_numeric_p (cp1
))))
770 Scheme_functions (inf
);
771 goto close_and_return
;
774 if (cp
&& (streq (cp1
, "s")
775 || streq (cp1
, "a") /* Unix assembler */
776 || streq (cp1
, "sa") /* Unix assembler */
777 || streq (cp1
, "asm") /* Microcontroller assembly */
778 || streq (cp1
, "src") /* BSO/Tasking C compiler output */
779 || streq (cp1
, "def") /* BSO/Tasking definition includes */
780 || streq (cp1
, "ins") /* Microcontroller include files */
781 || streq (cp1
, "inc")))/* Microcontroller include files */
784 goto close_and_return
;
786 /* .C or .H or .cxx or .hxx or .cc or .cpp: a C++ file */
787 if (cp
&& (streq (cp1
, "C")
789 || streq (cp1
, "cpp")
790 || streq (cp1
, "cxx")
791 || streq (cp1
, "hxx")
792 || streq (cp1
, "cc")))
794 C_entries (C_PLPL
, inf
); /* C++ */
795 goto close_and_return
;
797 /* .cs or .hs: a C* file */
798 if (cp
&& (streq (cp1
, "cs")
799 || streq (cp1
, "hs")))
801 C_entries (C_STAR
, inf
);
802 goto close_and_return
;
804 /* .y: a yacc file */
805 if (cp
&& (streq (cp1
, "y")))
807 C_entries (YACC
, inf
);
808 goto close_and_return
;
810 /* .pl implies prolog source code */
811 if (cp
&& streq (cp1
, "pl"))
813 Prolog_functions (inf
);
814 goto close_and_return
;
816 /* .p or .pas: a Pascal file */
817 if (cp
&& (streq (cp1
, "p")
818 || streq (cp1
, "pas")))
820 Pascal_functions (inf
);
821 goto close_and_return
;
823 /* If .f or .for, assume it is fortran or nothing. */
824 if (cp
&& (streq (cp1
, "f")
825 || streq (cp1
, "for")))
827 (void) Fortran_functions (inf
);
828 goto close_and_return
;
830 /* if not a .c or .h or .y file, try fortran */
831 if (cp
&& ((cp
[1] != 'c'
834 || (cp
[1] != 0 && cp
[2] != 0)))
836 if (Fortran_functions (inf
) != 0)
837 goto close_and_return
;
838 rewind (inf
); /* no fortran tags found, try C */
840 C_entries (cplusplus
? C_PLPL
: 0, inf
);
847 /* Nonzero if string STR is composed of digits. */
850 string_numeric_p (str
)
855 if (*str
< '0' || *str
> '9')
862 /* Should take a TOKEN* instead!! */
864 pfnote (name
, is_func
, named
, linestart
, linelen
, lno
, cno
)
865 char *name
; /* tag name */
866 logical is_func
; /* function or type name? */
867 logical named
; /* tag different from text of definition? */
883 /* It's okay to output early in etags -- it only disrupts the
884 * character count of the tag entries, which is no longer used
887 error ("too many entries to sort", 0);
894 /* If ctags mode, change name "main" to M<thisfilename>. */
895 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
897 fp
= etags_strrchr (curfile
, '/');
898 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
899 fp
= etags_strrchr (name
, '.');
900 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
904 np
->name
= savestr (name
);
906 np
->is_func
= is_func
;
909 /* UNCOMMENT THE +1 HERE: */
910 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
911 np
->left
= np
->right
= 0;
914 c
= linestart
[linelen
];
915 linestart
[linelen
] = 0;
917 else if (cxref_style
== 0)
919 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
922 np
->pat
= savestr (linestart
);
925 linestart
[linelen
] = c
;
928 add_node (np
, &head
);
933 * recurse on left children, iterate on right children.
941 register NODE
*node_right
= node
->right
;
942 free_tree (node
->left
);
945 free ((char *) node
);
952 * Adds a node to the tree of nodes. In etags mode, we don't keep
953 * it sorted; we just keep a linear list. In ctags mode, maintain
954 * an ordered tree, with no attempt at balancing.
956 * add_node is the only function allowed to add nodes, so it can
959 /* Must avoid static vars within functions since some systems
960 #define static as nothing. */
961 NODE
*last_node
= NULL
;
964 add_node (node
, cur_node_p
)
965 NODE
*node
, **cur_node_p
;
968 register NODE
*cur_node
= *cur_node_p
;
970 if (cur_node
== NULL
)
980 if (last_node
== NULL
)
981 fatal ("internal error in add_node", 0);
982 last_node
->right
= node
;
988 dif
= strcmp (node
->name
, cur_node
->name
);
991 * If this tag name matches an existing one, then
992 * do not add the node, but maybe print a warning.
996 if (node
->file
== cur_node
->file
)
1000 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1001 node
->file
, lineno
, node
->name
);
1002 fprintf (stderr
, "Second entry ignored\n");
1006 if (!cur_node
->been_warned
&& !no_warnings
)
1009 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1010 node
->file
, cur_node
->file
, node
->name
);
1012 cur_node
->been_warned
= TRUE
;
1016 /* Maybe refuse to add duplicate nodes. */
1017 if (!permit_duplicates
)
1019 if (streq (node
->name
, cur_node
->name
)
1020 && streq (node
->file
, cur_node
->file
))
1024 /* Actually add the node */
1025 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1031 register NODE
*node
;
1038 /* Output subentries that precede this one */
1039 put_entries (node
->left
);
1041 /* Output this entry */
1047 fprintf (tagf
, "%s\177%s\001%d,%d\n",
1048 node
->pat
, node
->name
,
1049 node
->lno
, node
->cno
);
1053 fprintf (tagf
, "%s\177%d,%d\n",
1055 node
->lno
, node
->cno
);
1058 else if (!cxref_style
)
1060 fprintf (tagf
, "%s\t%s\t",
1061 node
->name
, node
->file
);
1065 putc (searchar
, tagf
);
1068 for (sp
= node
->pat
; *sp
; sp
++)
1070 if (*sp
== '\\' || *sp
== searchar
)
1074 putc (searchar
, tagf
);
1077 { /* a typedef; text pattern inadequate */
1078 fprintf (tagf
, "%d", node
->lno
);
1082 else if (vgrind_style
)
1083 fprintf (stdout
, "%s %s %d\n",
1084 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1086 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1087 node
->name
, node
->lno
, node
->file
, node
->pat
);
1089 /* Output subentries that follow this one */
1090 put_entries (node
->right
);
1093 /* Length of a number's decimal representation. */
1101 for (; num
; num
/= 10)
1107 * Return total number of characters that put_entries will output for
1108 * the nodes in the subtree of the specified node. Works only if
1109 * we are not ctags, but called only in that case. This count
1110 * is irrelevant with the new tags.el, but is still supplied for
1111 * backward compatibility.
1114 total_size_of_entries (node
)
1115 register NODE
*node
;
1123 for (; node
; node
= node
->right
)
1125 /* Count left subentries. */
1126 total
+= total_size_of_entries (node
->left
);
1128 /* Count this entry */
1129 total
+= strlen (node
->pat
) + 1;
1130 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1132 total
+= 1 + strlen (node
->name
); /* \001name */
1139 * The C symbol tables.
1142 /* Feed stuff between (but not including) %[ and %] lines to:
1143 gperf -c -k1,3 -o -p -r -t
1145 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1147 class, C_PLPL, st_C_struct
1148 domain, C_STAR, st_C_struct
1149 union, 0, st_C_struct
1150 struct, 0, st_C_struct
1152 typedef, 0, st_C_typedef
1153 define, 0, st_C_define
1154 long, 0, st_C_typespec
1155 short, 0, st_C_typespec
1156 int, 0, st_C_typespec
1157 char, 0, st_C_typespec
1158 float, 0, st_C_typespec
1159 double, 0, st_C_typespec
1160 signed, 0, st_C_typespec
1161 unsigned, 0, st_C_typespec
1162 auto, 0, st_C_typespec
1163 void, 0, st_C_typespec
1164 extern, 0, st_C_typespec
1165 static, 0, st_C_typespec
1166 const, 0, st_C_typespec
1167 volatile, 0, st_C_typespec
1169 and replace lines between %< and %> with its output. */
1171 /* C code produced by gperf version 1.8.1 (K&R C version) */
1172 /* Command-line: gperf -c -k1,3 -o -p -r -t */
1175 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
1177 #define MIN_WORD_LENGTH 3
1178 #define MAX_WORD_LENGTH 8
1179 #define MIN_HASH_VALUE 10
1180 #define MAX_HASH_VALUE 62
1183 53 is the maximum key range
1191 static unsigned char hash_table
[] =
1193 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1194 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1195 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1196 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1197 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1198 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1199 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1200 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1201 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1202 62, 62, 62, 62, 62, 62, 62, 2, 62, 7,
1203 6, 9, 15, 30, 62, 24, 62, 62, 1, 24,
1204 7, 27, 13, 62, 19, 26, 18, 27, 1, 62,
1205 62, 62, 62, 62, 62, 62, 62, 62,
1207 return len
+ hash_table
[str
[2]] + hash_table
[str
[0]];
1210 struct C_stab_entry
*
1211 in_word_set (str
, len
)
1216 static struct C_stab_entry wordlist
[] =
1218 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1220 {"volatile", 0, st_C_typespec
},
1222 {"long", 0, st_C_typespec
},
1223 {"char", 0, st_C_typespec
},
1224 {"class", C_PLPL
, st_C_struct
},
1225 {"",}, {"",}, {"",}, {"",},
1226 {"const", 0, st_C_typespec
},
1227 {"",}, {"",}, {"",}, {"",},
1228 {"auto", 0, st_C_typespec
},
1230 {"define", 0, st_C_define
},
1232 {"void", 0, st_C_typespec
},
1233 {"",}, {"",}, {"",},
1234 {"extern", 0, st_C_typespec
},
1235 {"static", 0, st_C_typespec
},
1237 {"domain", C_STAR
, st_C_struct
},
1239 {"typedef", 0, st_C_typedef
},
1240 {"double", 0, st_C_typespec
},
1241 {"enum", 0, st_C_enum
},
1242 {"",}, {"",}, {"",}, {"",},
1243 {"int", 0, st_C_typespec
},
1245 {"float", 0, st_C_typespec
},
1246 {"",}, {"",}, {"",},
1247 {"struct", 0, st_C_struct
},
1248 {"",}, {"",}, {"",}, {"",},
1249 {"union", 0, st_C_struct
},
1251 {"short", 0, st_C_typespec
},
1253 {"unsigned", 0, st_C_typespec
},
1254 {"signed", 0, st_C_typespec
},
1257 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
1259 register int key
= hash (str
, len
);
1261 if (key
<= MAX_HASH_VALUE
&& key
>= MIN_HASH_VALUE
)
1263 register char *s
= wordlist
[key
].name
;
1265 if (*s
== *str
&& strneq (str
+ 1, s
+ 1, len
- 1))
1266 return &wordlist
[key
];
1274 C_symtype(str
, len
, c_ext
)
1279 register struct C_stab_entry
*se
= in_word_set(str
, len
);
1281 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
1287 * C functions are recognized using a simple finite automaton.
1288 * funcdef is its state variable.
1292 fnone
, /* nothing seen */
1293 ftagseen
, /* function-like tag seen */
1294 fstartlist
, /* just after open parenthesis */
1295 finlist
, /* in parameter list */
1296 flistseen
, /* after parameter list */
1297 fignore
/* before open brace */
1303 * typedefs are recognized using a simple finite automaton.
1304 * typeddef is its state variable.
1308 tnone
, /* nothing seen */
1309 ttypedseen
, /* typedef keyword seen */
1310 tinbody
, /* inside typedef body */
1311 tend
, /* just before typedef tag */
1312 tignore
/* junk after typedef tag */
1318 * struct-like structures (enum, struct and union) are recognized
1319 * using another simple finite automaton. `structdef' is its state
1324 snone
, /* nothing seen yet */
1325 skeyseen
, /* struct-like keyword seen */
1326 stagseen
, /* struct-like tag seen */
1327 scolonseen
, /* colon seen after struct-like tag */
1328 sinbody
/* in struct body: recognize member func defs*/
1333 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1334 * struct tag, and structtype is the type of the preceding struct-like
1337 char structtag
[BUFSIZ
];
1338 enum sym_type structtype
;
1341 * Yet another little state machine to deal with preprocessor lines.
1345 dnone
, /* nothing seen */
1346 dsharpseen
, /* '#' seen as first char on line */
1347 ddefineseen
, /* '#' and 'define' seen */
1348 dignorerest
/* ignore rest of line */
1353 * Set this to TRUE, and the next token considered is called a function.
1354 * Used only for GNUmacs's function-defining macros.
1356 logical next_token_is_func
;
1359 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1365 * checks to see if the current token is at the start of a
1366 * function, or corresponds to a typedef, or is a struct/union/enum
1369 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1370 * C_EXT is which language we are looking at.
1372 * In the future we will need some way to adjust where the end of
1373 * the token is; for instance, implementing the C++ keyword
1374 * `operator' properly will adjust the end of the token to be after
1375 * whatever follows `operator'.
1382 * next_token_is_func IN OUT
1386 consider_token (c
, tokp
, c_ext
, cblev
, is_func
)
1387 register char c
; /* IN: first char after the token */
1388 register TOKEN
*tokp
; /* IN: token pointer */
1389 int c_ext
; /* IN: C extensions mask */
1390 int cblev
; /* IN: curly brace level */
1391 logical
*is_func
; /* OUT */
1393 enum sym_type toktype
= C_symtype(tokp
->p
, tokp
->len
, c_ext
);
1396 * Advance the definedef state machine.
1401 /* We're not on a preprocessor line. */
1404 if (toktype
== st_C_define
)
1406 definedef
= ddefineseen
;
1410 definedef
= dignorerest
;
1415 * Make a tag for any macro.
1417 definedef
= dignorerest
;
1418 *is_func
= (c
== '(');
1419 if (!*is_func
&& !constantypedefs
)
1426 error ("internal error: definedef value.", 0);
1435 if (toktype
== st_C_typedef
)
1438 typdef
= ttypedseen
;
1454 /* Do not return here, so the structdef stuff has a chance. */
1468 * This structdef business is currently only invoked when cblev==0.
1469 * It should be recursively invoked whatever the curly brace level,
1470 * and a stack of states kept, to allow for definitions of structs
1473 * This structdef business is NOT invoked when we are ctags and the
1474 * file is plain C. This is because a struct tag may have the same
1475 * name as another tag, and this loses with ctags.
1477 * This if statement deals with the typdef state machine as
1478 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1479 * return (FALSE). All the other code here is for the structdef
1486 if (typdef
== ttypedseen
1487 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1489 structdef
= skeyseen
;
1490 structtype
= toktype
;
1494 if (structdef
== skeyseen
)
1496 if (structtype
== st_C_struct
)
1498 strncpy (structtag
, tokp
->p
, tokp
->len
);
1499 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1503 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1505 structdef
= stagseen
;
1509 /* Avoid entering funcdef stuff if typdef is going on. */
1510 if (typdef
!= tnone
)
1516 /* Detect GNUmacs's function-defining macros. */
1517 if (definedef
== dnone
)
1519 if (strneq (tokp
->p
, "DEF", 3)
1520 || strneq (tokp
->p
, "ENTRY", 5)
1521 || strneq (tokp
->p
, "SYSCALL", 7)
1522 || strneq (tokp
->p
, "PSEUDO", 6))
1524 next_token_is_func
= TRUE
;
1527 if (strneq (tokp
->p
, "EXFUN", 5))
1529 next_token_is_func
= FALSE
;
1533 if (next_token_is_func
)
1535 next_token_is_func
= FALSE
;
1537 *is_func
= TRUE
; /* to force search string in ctags */
1545 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1546 funcdef
= fnone
; /* should be useless */
1549 if (funcdef
== fnone
)
1562 * This routine finds functions, typedefs, #define's and
1563 * struct/union/enum definitions in C syntax and adds them
1567 #define curlb (lbs[curndx].lb)
1568 #define othlb (lbs[1-curndx].lb)
1569 #define newlb (lbs[newndx].lb)
1570 #define curlinepos (lbs[curndx].linepos)
1571 #define othlinepos (lbs[1-curndx].linepos)
1572 #define newlinepos (lbs[newndx].linepos)
1574 /* Save and restore token state. This is used when preprocessor defines
1575 are handled, to avoid disturbing active function/typedef/struct states. */
1576 #define TOKEN_SAVED_P (savetok.lineno > 0)
1577 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1578 savetok.len = toklen, strcpy(savenameb, nameb))
1579 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1580 toklen = tok.len, strcpy(nameb, savenameb), \
1583 #define CNL_SAVE_DEFINEDEF \
1585 SET_FILEPOS (curlinepos, inf, charno); \
1587 charno += readline (&curlb, inf); \
1588 lp = curlb.buffer; \
1595 CNL_SAVE_DEFINEDEF; \
1596 if (TOKEN_SAVED_P) \
1598 definedef = dnone; \
1601 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1602 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1603 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1604 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1607 C_entries (c_ext
, inf
)
1608 int c_ext
; /* extension of C? */
1611 register char c
; /* latest char read; '\0' for end of line */
1612 register char *lp
; /* pointer one beyond the character `c' */
1613 int curndx
, newndx
; /* indices for current and new lb */
1614 TOKEN tok
; /* latest token read for funcdef & structdef */
1615 char nameb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1616 register int tokoff
; /* offset in line of start of latest token */
1617 register int toklen
; /* length of latest token */
1618 int cblev
; /* current curly brace level */
1619 int parlev
; /* current parenthesis level */
1620 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1622 TOKEN savetok
; /* saved token during preprocessor handling */
1623 char savenameb
[BUFSIZ
]; /* ouch! */
1626 curndx
= newndx
= 0;
1632 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1633 next_token_is_func
= yacc_rules
= FALSE
;
1634 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1637 cplpl
= c_ext
& C_PLPL
;
1644 /* If we're at the end of the line, the next character is a
1645 '\0'; don't skip it, because it's the thing that tells us
1646 to read the next line. */
1667 /* Newlines inside comments do not end macro definitions in
1682 /* Newlines inside strings do not end macro definitions
1683 in traditional cpp, even though compilers don't
1684 usually accept them. */
1695 /* Hmmm, something went wrong. */
1709 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1714 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1724 else if (cplpl
&& *lp
== '/')
1732 if ((c_ext
& YACC
) && *lp
== '%')
1734 /* entering or exiting rules section in yacc file */
1736 definedef
= dnone
; funcdef
= fnone
;
1737 typdef
= tnone
; structdef
= snone
;
1738 next_token_is_func
= FALSE
;
1739 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1741 yacc_rules
= !yacc_rules
;
1747 if (lp
== newlb
.buffer
+ 1 && definedef
== dnone
)
1748 definedef
= dsharpseen
;
1753 /* Consider token only if some complicated conditions are satisfied. */
1754 if (((cblev
== 0 && structdef
!= scolonseen
)
1755 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
1756 && typdef
!= tignore
1757 && definedef
!= dignorerest
1758 && (funcdef
!= finlist
1759 || definedef
!= dnone
))
1765 if (cplpl
&& c
== ':' && *lp
== ':' && begtoken(*(lp
+ 1)))
1768 * This handles :: in the middle, but not at beginning
1776 logical is_func
= FALSE
;
1778 tok
.lineno
= lineno
;
1779 tok
.p
= newlb
.buffer
+ tokoff
;
1783 || consider_token (c
, &tok
, c_ext
, cblev
, &is_func
))
1785 if (structdef
== sinbody
1786 && definedef
== dnone
1788 /* function defined in C++ class body */
1791 sprintf (nameb
, "%s::%.*s",
1792 ((structtag
[0] == '\0')
1793 ? "_anonymous_" : structtag
),
1798 sprintf (nameb
, "%.*s", tok
.len
, tok
.p
);
1801 if (structdef
== stagseen
1805 if (definedef
== dnone
1806 && (funcdef
== ftagseen
1807 || structdef
== stagseen
1810 if (newndx
== curndx
)
1811 curndx
= 1 - curndx
; /* switch line buffers */
1814 MAKE_TAG_FROM_NEW_LB (is_func
);
1818 } /* if (endtoken (c)) */
1819 else if (intoken (c
))
1824 } /* if (midtoken) */
1825 else if (begtoken (c
))
1836 MAKE_TAG_FROM_OTH_LB (TRUE
);
1843 if (structdef
== stagseen
)
1847 /* Take a quick peek ahead for define directive,
1848 so we can avoid saving the token when not absolutely
1849 necessary. [This is a speed hack.] */
1850 if (c
== 'd' && strneq(lp
, "efine", 5)
1851 && iswhite(*(lp
+ 5)))
1854 definedef
= ddefineseen
;
1858 definedef
= dignorerest
;
1861 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1863 tokoff
= lp
- 1 - newlb
.buffer
;
1869 } /* if must look at token */
1872 /* Detect end of line, colon, comma, semicolon and various braces
1873 after having handled a token.*/
1877 if (definedef
!= dnone
)
1879 if (structdef
== stagseen
)
1880 structdef
= scolonseen
;
1887 MAKE_TAG_FROM_OTH_LB (FALSE
);
1897 if (definedef
!= dnone
)
1903 MAKE_TAG_FROM_OTH_LB (FALSE
);
1908 if (funcdef
!= fignore
)
1910 if (structdef
== stagseen
)
1914 if (definedef
!= dnone
)
1916 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1918 if (structdef
== stagseen
)
1922 if (definedef
!= dnone
)
1924 if (cblev
== 0 && typdef
== tend
)
1927 MAKE_TAG_FROM_OTH_LB (FALSE
);
1930 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1932 if (structdef
== stagseen
)
1936 if (definedef
!= dnone
)
1941 funcdef
= fstartlist
;
1950 if (definedef
!= dnone
)
1958 funcdef
= flistseen
;
1961 if (cblev
== 0 && typdef
== tend
)
1964 MAKE_TAG_FROM_OTH_LB (FALSE
);
1967 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
1971 if (definedef
!= dnone
)
1973 if (typdef
== ttypedseen
)
1977 case skeyseen
: /* unnamed struct */
1978 structtag
[0] = '\0';
1979 structdef
= sinbody
;
1982 case scolonseen
: /* named struct */
1983 structdef
= sinbody
;
1984 MAKE_TAG_FROM_OTH_LB (FALSE
);
1990 MAKE_TAG_FROM_OTH_LB (TRUE
);
1996 /* Neutralize `extern "C" {' grot.
1997 if (cblev == 0 && structdef == snone && typdef == tnone)
2003 if (definedef
!= dnone
)
2005 if (funcdef
== fstartlist
)
2006 funcdef
= fnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
2009 if (definedef
!= dnone
)
2011 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
2013 cblev
= 0; /* reset curly brace level if first column */
2014 parlev
= 0; /* also reset paren level, just in case... */
2020 if (typdef
== tinbody
)
2023 strcpy (structtag
, "<error 2>");
2027 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
2028 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
2029 if (definedef
!= dnone
)
2031 /* These surely cannot follow a function tag. */
2032 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2036 /* If a macro spans multiple lines don't reset its state. */
2044 } /* while not eof */
2047 /* Fortran parsing */
2056 register int len
= 0;
2058 while (*cp
&& (*cp
| ' ') == (dbp
[len
] | ' '))
2071 while (isspace (*dbp
))
2076 while (isspace (*dbp
))
2078 if (!isdigit (*dbp
))
2080 --dbp
; /* force failure */
2085 while (isdigit (*dbp
));
2094 char nambuf
[BUFSIZ
];
2096 while (isspace (*dbp
))
2101 linecharno
= charno
;
2102 charno
+= readline (&lb
, inf
);
2107 while (isspace (*dbp
))
2116 && (isalpha (*cp
) || isdigit (*cp
) || (*cp
== '_') || (*cp
== '$')));
2121 strcpy (nambuf
, dbp
);
2123 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2124 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2129 Fortran_functions (inf
)
2139 linecharno
= charno
;
2140 charno
+= readline (&lb
, inf
);
2143 dbp
++; /* Ratfor escape to fortran */
2144 while (isspace (*dbp
))
2151 if (tail ("integer"))
2159 if (tail ("logical"))
2163 if (tail ("complex") || tail ("character"))
2167 if (tail ("double"))
2169 while (isspace (*dbp
))
2173 if (tail ("precision"))
2179 while (isspace (*dbp
))
2186 if (tail ("function"))
2190 if (tail ("subroutine"))
2198 if (tail ("program"))
2203 if (tail ("procedure"))
2212 * Bob Weiner, Motorola Inc., 4/3/94
2213 * Unix and microcontroller assembly tag handling
2214 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
2220 char nambuf
[BUFSIZ
];
2231 linecharno
= charno
;
2232 charno
+= readline (&lb
, inf
);
2235 /* If first char is alphabetic or one of [_.$], test for colon
2236 following identifier. */
2237 if (isalpha (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2239 /* Read past label. */
2241 while (isalnum (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2243 if (*cp
== ':' || isspace (*cp
))
2245 /* Found end of label, so copy it and add it to the table. */
2248 strcpy (nambuf
, lb
.buffer
);
2250 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2251 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2258 /* Added by Mosur Mohan, 4/22/88 */
2259 /* Pascal parsing */
2261 #define GET_NEW_LINE \
2263 linecharno = charno; lineno++; \
2264 charno += 1 + readline (&lb, inf); \
2268 /* Locates tags for procedures & functions.
2269 * Doesn't do any type- or var-definitions.
2270 * It does look for the keyword "extern" or "forward"
2271 * immediately following the procedure statement;
2272 * if found, the tag is skipped.
2276 Pascal_functions (inf
)
2279 struct linebuffer tline
; /* mostly copied from C_entries */
2283 char nambuf
[BUFSIZ
];
2285 logical
/* each of these flags is TRUE iff: */
2286 incomm1
, /* point is inside {..} comment */
2287 incomm2
, /* point is inside (*..*) comment */
2288 inquote
, /* point is inside '..' string */
2289 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2290 /* keyword, so next item = potential tag */
2291 found_tag
, /* point is after a potential tag */
2292 inparms
, /* point is within parameter-list */
2293 verify_tag
; /* point has passed the parm-list, so the */
2294 /* next token will determine whether */
2295 /* this is a FORWARD/EXTERN to be */
2296 /* ignored, or whether it is a real tag */
2302 initbuffer (&tline
);
2304 incomm1
= incomm2
= inquote
= FALSE
;
2305 found_tag
= FALSE
; /* have a proc name; check if extern */
2306 get_tagname
= FALSE
; /* have found "procedure" keyword */
2307 inparms
= FALSE
; /* found '(' after "proc" */
2308 verify_tag
= FALSE
; /* check if "extern" is ahead */
2310 /* long main loop to get next char */
2314 if (c
== 0) /* if end of line */
2319 if (!((found_tag
&& verify_tag
) ||
2321 c
= *dbp
++; /* only if don't need *dbp pointing */
2322 /* to the beginning of the name of */
2323 /* the procedure or function */
2325 if (incomm1
) /* within { - } comments */
2331 else if (incomm2
) /* within (* - *) comments */
2335 while ((c
= *dbp
++) == '*')
2354 inquote
= TRUE
; /* found first quote */
2356 case '{': /* found open-{-comment */
2360 if (*dbp
== '*') /* found open-(*-comment */
2365 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2368 case ')': /* end of parms list */
2373 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2380 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2382 /* check if this is an "extern" declaration */
2385 if ((*dbp
== 'e') || (*dbp
== 'E'))
2387 if (tail ("extern")) /* superfluous, really! */
2393 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2395 if (tail ("forward")) /* check for forward reference */
2401 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2405 pfnote (nambuf
, TRUE
, FALSE
,
2406 tline
.buffer
, cp
- tline
.buffer
+ 1,
2407 save_lineno
, save_lcno
);
2411 if (get_tagname
) /* grab name of proc or fn */
2416 /* save all values for later tagging */
2417 tline
.size
= lb
.size
;
2418 strcpy (tline
.buffer
, lb
.buffer
);
2419 save_lineno
= lineno
;
2420 save_lcno
= linecharno
;
2422 /* grab block name */
2423 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2427 strcpy (nambuf
, dbp
);
2429 dbp
= cp
; /* restore dbp to e-o-token */
2430 get_tagname
= FALSE
;
2434 /* and proceed to check for "extern" */
2436 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2437 (!found_tag
) && (!get_tagname
))
2439 /* check for proc/fn keywords */
2443 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2447 if (tail ("unction"))
2452 } /* while not eof */
2456 * lisp tag functions
2457 * just look for (def or (DEF
2464 return ((dbp
[1] == 'd' || dbp
[1] == 'D')
2465 && (dbp
[2] == 'e' || dbp
[2] == 'E')
2466 && (dbp
[3] == 'f' || dbp
[3] == 'F'));
2473 return ((*(++dbp
) == 'q' || *dbp
== 'Q')
2474 && (*(++dbp
) == 'u' || *dbp
== 'U')
2475 && (*(++dbp
) == 'o' || *dbp
== 'O')
2476 && (*(++dbp
) == 't' || *dbp
== 'T')
2477 && (*(++dbp
) == 'e' || *dbp
== 'E')
2478 && isspace(*(++dbp
)));
2486 char nambuf
[BUFSIZ
];
2488 if (*dbp
== '\'') /* Skip prefix quote */
2490 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2493 while (isspace(*dbp
))
2496 for (cp
= dbp
/*+1*/; *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')'; cp
++)
2503 strcpy (nambuf
, dbp
);
2505 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2506 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2511 Lisp_functions (inf
)
2521 linecharno
= charno
;
2522 charno
+= readline (&lb
, inf
);
2528 while (!isspace (*dbp
))
2530 while (isspace (*dbp
))
2536 /* Check for (foo::defmumble name-defined ... */
2539 while (*dbp
&& !isspace (*dbp
)
2540 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2545 while (*dbp
== ':');
2547 if (L_isdef (dbp
- 1))
2549 while (!isspace (*dbp
))
2551 while (isspace (*dbp
))
2562 * Scheme tag functions
2563 * look for (def... xyzzy
2564 * look for (def... (xyzzy
2565 * look for (def ... ((...(xyzzy ....
2566 * look for (set! xyzzy
2572 Scheme_functions (inf
)
2582 linecharno
= charno
;
2583 charno
+= readline (&lb
, inf
);
2585 if (dbp
[0] == '(' &&
2586 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2587 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2588 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2590 while (!isspace (*dbp
))
2592 /* Skip over open parens and white space */
2593 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2597 if (dbp
[0] == '(' &&
2598 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2599 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2600 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2601 (dbp
[4] == '!' || dbp
[4] == '!') &&
2604 while (!isspace (*dbp
))
2606 /* Skip over white space */
2607 while (isspace (*dbp
))
2619 char nambuf
[BUFSIZ
];
2623 /* Go till you get to white space or a syntactic break */
2624 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2626 /* Null terminate the string there. */
2629 /* Copy the string */
2630 strcpy (nambuf
, dbp
);
2631 /* Unterminate the string */
2633 /* Announce the change */
2634 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2638 /* Find tags in TeX and LaTeX input files. */
2640 /* TEX_toktab is a table of TeX control sequences that define tags.
2641 Each TEX_tabent records one such control sequence.
2642 CONVERT THIS TO USE THE Stab TYPE!! */
2650 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2652 /* Default set of control sequences to put into TEX_toktab.
2653 The value of environment var TEXTAGS is prepended to this. */
2655 char *TEX_defenv
= "\
2656 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2659 struct TEX_tabent
*TEX_decode_env ();
2663 char TEX_esc
= '\\';
2664 char TEX_opgrp
= '{';
2665 char TEX_clgrp
= '}';
2668 * TeX/LaTeX scanning loop.
2681 /* Select either \ or ! as escape character. */
2684 /* Initialize token table once from environment. */
2686 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2689 { /* Scan each line in file */
2691 linecharno
= charno
;
2692 charno
+= readline (&lb
, inf
);
2695 while (dbp
= etags_strchr (dbp
, TEX_esc
)) /* Look at each esc in line */
2701 linecharno
+= dbp
- lasthit
;
2703 i
= TEX_Token (lasthit
);
2706 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2707 break; /* We only save a line once */
2713 #define TEX_LESC '\\'
2714 #define TEX_SESC '!'
2717 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2718 /* chars accordingly. */
2726 while ((c
= getc (inf
)) != EOF
)
2728 /* Skip to next line if we hit the TeX comment char. */
2732 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2751 /* Read environment and prepend it to the default string. */
2752 /* Build token table. */
2755 TEX_decode_env (evarname
, defenv
)
2759 register char *env
, *p
;
2761 struct TEX_tabent
*tab
;
2764 /* Append default string to environment. */
2765 env
= getenv (evarname
);
2769 env
= concat (env
, defenv
, "");
2771 /* Allocate a token table */
2772 for (size
= 1, p
= env
; p
;)
2773 if ((p
= etags_strchr (p
, ':')) && *(++p
))
2775 /* Add 1 to leave room for null terminator. */
2776 tab
= xnew (size
+ 1, struct TEX_tabent
);
2778 /* Unpack environment string into token table. Be careful about */
2779 /* zero-length strings (leading ':', "::" and trailing ':') */
2782 p
= etags_strchr (env
, ':');
2783 if (!p
) /* End of environment string. */
2784 p
= env
+ strlen (env
);
2786 { /* Only non-zero strings. */
2787 tab
[i
].name
= savenstr (env
, p
- env
);
2788 tab
[i
].len
= strlen (tab
[i
].name
);
2795 tab
[i
].name
= NULL
; /* Mark end of table. */
2803 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2804 The name being defined actually starts at (NAME + LEN + 1).
2805 But we seem to include the TeX command in the tag name. */
2808 TEX_getit (name
, len
)
2812 char *p
= name
+ len
;
2813 char nambuf
[BUFSIZ
];
2818 /* Let tag name extend to next group close (or end of line) */
2819 while (*p
&& *p
!= TEX_clgrp
)
2821 strncpy (nambuf
, name
, p
- name
);
2822 nambuf
[p
- name
] = 0;
2824 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2828 /* If the text at CP matches one of the tag-defining TeX command names,
2829 return the pointer to the first occurrence of that command in TEX_toktab.
2830 Otherwise return -1. */
2832 /* Keep the capital `T' in `Token' for dumb truncating compilers
2833 (this distinguishes it from `TEX_toktab' */
2840 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2841 if (strneq (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
))
2846 /* Support for Prolog. */
2848 /* whole head (not only functor, but also arguments)
2849 is gotten in compound term. */
2852 prolog_getit (s
, lineno
, linecharno
)
2857 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2865 if (*s
== '\0') /* syntax error. */
2867 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2869 else if (*s
== '\'')
2871 insquote
= !insquote
;
2874 else if (!insquote
&& *s
== '(')
2879 else if (!insquote
&& *s
== ')')
2885 else if (npar
< 0) /* syntax error. */
2888 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2890 if (npar
!= 0) /* syntax error. */
2900 strcpy (nambuf
, save_s
);
2902 pfnote (nambuf
, TRUE
, FALSE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2905 /* It is assumed that prolog predicate starts from column 0. */
2908 Prolog_functions (inf
)
2911 void skip_comment (), prolog_getit ();
2913 lineno
= linecharno
= charno
= 0;
2917 linecharno
+= charno
;
2918 charno
= readline (&lb
, inf
) + 1; /* 1 for newline. */
2920 if (isspace (dbp
[0])) /* not predicate header. */
2922 else if (dbp
[0] == '%') /* comment. */
2924 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2925 skip_comment (&lb
, inf
, &lineno
, &linecharno
);
2927 prolog_getit (dbp
, lineno
, linecharno
);
2932 skip_comment (plb
, inf
, plineno
, plinecharno
)
2933 struct linebuffer
*plb
;
2935 int *plineno
; /* result */
2936 long *plinecharno
; /* result */
2938 while (!substr ("*/", plb
->buffer
))
2941 *plinecharno
+= readline (plb
, inf
) + 1;
2942 } /* 1 for newline. */
2945 /* Return TRUE if 'sub' exists somewhere in 's'. */
2952 while (*s
&& (s
= etags_strchr (s
, *sub
)))
2953 if (prestr (sub
, s
))
2960 /* Return TRUE if 'pre' is prefix of string 's'. */
2969 else if (*pre
== *s
)
2970 return (prestr (pre
+ 1, s
+ 1));
2975 /* Initialize a linebuffer for use */
2978 initbuffer (linebuffer
)
2979 struct linebuffer
*linebuffer
;
2981 linebuffer
->size
= 200;
2982 linebuffer
->buffer
= xnew (200, char);
2986 * Read a line of text from `stream' into `linebuffer'.
2987 * Return the number of characters read from `stream',
2988 * which is the length of the line including the newline, if any.
2991 readline (linebuffer
, stream
)
2992 struct linebuffer
*linebuffer
;
2993 register FILE *stream
;
2995 char *buffer
= linebuffer
->buffer
;
2996 register char *p
= linebuffer
->buffer
;
2997 register char *pend
;
2998 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
3000 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
3004 register int c
= getc (stream
);
3007 linebuffer
->size
*= 2;
3008 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
3009 p
+= buffer
- linebuffer
->buffer
;
3010 pend
= buffer
+ linebuffer
->size
;
3011 linebuffer
->buffer
= buffer
;
3013 if (c
== EOF
|| c
== '\n')
3016 newline
= (c
== '\n') ? 1 : 0;
3022 return p
- buffer
+ newline
;
3029 return savenstr (cp
, strlen (cp
));
3039 dp
= xnew (len
+ 1, char);
3040 strncpy (dp
, cp
, len
);
3046 * Return the ptr in sp at which the character c last
3047 * appears; NULL if not found
3049 * Identical to System V strrchr, included for portability.
3053 etags_strrchr (sp
, c
)
3054 register char *sp
, c
;
3069 * Return the ptr in sp at which the character c first
3070 * appears; NULL if not found
3072 * Identical to System V strchr, included for portability.
3076 etags_strchr (sp
, c
)
3077 register char *sp
, c
;
3087 /* Print error message and exit. */
3098 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3105 fprintf (stderr
, "%s: ", progname
);
3106 fprintf (stderr
, s1
, s2
);
3107 fprintf (stderr
, "\n");
3110 /* Return a newly-allocated string whose contents
3111 concatenate those of s1, s2, s3. */
3117 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3118 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3120 strcpy (result
, s1
);
3121 strcpy (result
+ len1
, s2
);
3122 strcpy (result
+ len1
+ len2
, s3
);
3123 result
[len1
+ len2
+ len3
] = '\0';
3132 char *p
, cwd
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
3139 *p
++ = tolower (*p
);
3140 return strdup (cwd
);
3142 #else /* not MSDOS */
3143 /* Does the same work as the system V getcwd, but does not need to
3144 guess buffer size in advance. Included mostly for compatibility. */
3154 buf
= xnew (bufsize
, char);
3156 pipe
= popen ("pwd 2>/dev/null", "r");
3162 if (fgets (buf
, bufsize
, pipe
) == NULL
)
3171 } while (buf
[strlen (buf
) - 1] != '\n');
3175 #endif /* not MSDOS */
3177 /* Return a newly allocated string containing the filename
3178 of FILE relative to the absolute directory DIR (which
3179 should end with a slash). */
3182 relative_filename (file
, dir
)
3185 char *fp
, *dp
, *res
;
3187 /* Find the common root of file and dir. */
3188 fp
= absolute_filename (file
, cwd
);
3190 while (*fp
++ == *dp
++)
3199 /* Build a sequence of "../" strings for the resulting relative filename. */
3200 for (dp
= etags_strchr (dp
+ 1, '/'), res
= "";
3202 dp
= etags_strchr (dp
+ 1, '/'))
3204 res
= concat (res
, "../", "");
3207 /* Add the filename relative to the common root of file and dir. */
3208 res
= concat (res
, fp
+ 1, "");
3210 return res
; /* temporary stub */
3213 /* Return a newly allocated string containing the
3214 absolute filename of FILE given CWD (which should
3215 end with a slash). */
3218 absolute_filename (file
, cwd
)
3221 char *slashp
, *cp
, *res
;
3224 res
= concat (file
, "", "");
3226 res
= concat (cwd
, file
, "");
3228 /* Delete the "/dirname/.." and "/." substrings. */
3229 slashp
= etags_strchr (res
, '/');
3230 while (slashp
!= NULL
&& slashp
[0] != '\0')
3232 if (slashp
[1] == '.')
3234 if (slashp
[2] == '.'
3235 && (slashp
[3] == '/' || slashp
[3] == '\0'))
3240 while (cp
>= res
&& *cp
!= '/');
3243 strcpy (cp
, slashp
+ 3);
3245 else /* else (cp == res) */
3247 if (slashp
[3] != '\0')
3248 strcpy (cp
, slashp
+ 4);
3254 else if (slashp
[2] == '/' || slashp
[2] == '\0')
3256 strcpy (slashp
, slashp
+ 2);
3261 slashp
= etags_strchr (slashp
+ 1, '/');
3268 /* Return a newly allocated string containing the absolute
3269 filename of dir where FILE resides given CWD (which should
3270 end with a slash). */
3273 absolute_dirname (file
, cwd
)
3279 slashp
= etags_strrchr (file
, '/');
3284 res
= absolute_filename (file
, cwd
);
3290 /* Like malloc but get fatal error if memory is exhausted. */
3296 char *result
= (char *) malloc (size
);
3298 fatal ("virtual memory exhausted", 0);
3303 xrealloc (ptr
, size
)
3307 char *result
= (char *) realloc (ptr
, size
);
3309 fatal ("virtual memory exhausted");