1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 1987, 1988, 1989, 1993 Free Software Foundation, Inc. and Ken Arnold
4 This file is not considered part of GNU Emacs.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22 * Ctags originally by Ken Arnold.
23 * Fortran added by Jim Kleckner.
24 * Ed Pelegri-Llopart added C typedefs.
25 * Gnu Emacs TAGS format and modifications by RMS?
26 * Sam Kendall added C++.
28 * Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer.
31 char pot_etags_version
[] = "@(#) pot revision number is 10.28";
38 #include <../src/config.h>
43 #include <sys/types.h>
46 #if !defined (S_ISREG) && defined (S_IFREG)
47 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
52 extern char *getenv ();
55 /* Define CTAGS to make the program "ctags" compatible with the usual one.
56 Let it undefined to make the program "etags", which makes emacs-style
57 tag tables and tags typedefs, #defines and struct/union/enum by default. */
65 /* Exit codes for success and failure. */
75 * The FILEPOS abstract type, which represents a position in a file,
76 * plus the following accessor functions:
78 * long GET_CHARNO (pos)
79 * returns absolute char number.
80 * void SET_FILEPOS (pos, fp, charno)
81 * FILE *fp; long charno;
82 * sets `pos' from the current file
83 * position of `fp' and from `charno',
84 * which must be the absolute character
85 * number corresponding to the current
88 * The `pos' parameter is an lvalue expression of type FILEPOS.
89 * Parameters to the accessor functions are evaluated 0 or more times,
90 * and so must have no side effects.
92 * FILEPOS objects can also be assigned and passed to and from
93 * functions in the normal C manner.
95 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
99 /* real implementation */
100 typedef long FILEPOS
;
101 #define GET_CHARNO(pos) ((pos) + 0)
102 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
104 /* debugging implementation */
110 #define GET_CHARNO(pos) ((pos).charno + 0)
111 #define SET_FILEPOS(pos, fp, cno) \
112 ((void) ((pos).charno = (cno), \
113 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
117 #define streq(s, t) (strcmp (s, t) == 0)
118 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
124 #define iswhite(arg) (_wht[arg]) /* T if char is white */
125 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
126 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
127 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
129 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
132 { /* sorting structure */
133 char *name
; /* function or type name */
134 char *file
; /* file name */
135 logical is_func
; /* use pattern or line no */
136 logical named
; /* list name separately */
137 logical been_warned
; /* set if noticed dup */
138 int lno
; /* line number tag is on */
139 long cno
; /* character number line starts on */
140 char *pat
; /* search pattern */
141 struct nd_st
*left
, *right
; /* left and right sons */
144 typedef struct nd_st NODE
;
146 logical header_file
; /* TRUE if .h file, FALSE o.w. */
147 /* boolean "functions" (see init) */
148 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
150 char *cwd
; /* current working directory */
151 char *tagfiledir
; /* directory of tagfile */
154 char *savenstr (), *savestr ();
155 char *etags_strchr (), *etags_strrchr ();
156 char *etags_getcwd ();
157 char *relative_filename (), *absolute_filename (), *absolute_dirname ();
158 char *xmalloc (), *xrealloc ();
159 int total_size_of_entries ();
164 int Fortran_functions ();
165 void Lisp_functions ();
166 void Pascal_functions ();
167 void Prolog_functions ();
168 void Scheme_functions ();
169 void TeX_functions ();
173 logical
find_entries ();
180 void process_file ();
186 * xnew -- allocate storage
189 * Type *xnew (int n, Type);
191 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
194 * Symbol table types.
198 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
215 #define C_PLPL 0x00001 /* C++ */
216 #define C_STAR 0x00003 /* C* */
217 #define YACC 0x10000 /* yacc file */
219 char searchar
= '/'; /* use /.../ searches */
221 LINENO lineno
; /* line number of current line */
222 long charno
; /* current character number */
224 long linecharno
; /* charno of start of line; not used by C, but
225 * by every other language.
228 char *curfile
, /* current input file name */
229 *tagfile
, /* output file */
230 *white
= " \f\t\n", /* white chars */
231 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
232 /* token starting chars */
233 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
234 /* valid in-token chars */
235 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
237 int append_to_tagfile
; /* -a: append to tags */
238 /* The following three default to 1 for etags, but to 0 for ctags. */
239 int typedefs
; /* -t: create tags for typedefs */
240 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
241 /* 0 struct/enum/union decls, and C++ */
242 /* member functions. */
243 int constantypedefs
; /* -d: create tags for C #define and enum */
244 /* constants. Enum consts not implemented. */
245 /* -D: opposite of -d. Default under ctags. */
246 int update
; /* -u: update tags */
247 int vgrind_style
; /* -v: create vgrind style index output */
248 int no_warnings
; /* -w: suppress warnings */
249 int cxref_style
; /* -x: create cxref style output */
250 int cplusplus
; /* .[hc] means C++, not C */
251 int noindentypedefs
; /* -S: ignore indentation in C */
253 /* Name this program was invoked with. */
256 struct option longopts
[] = {
257 { "append", no_argument
, NULL
, 'a' },
258 { "backward-search", no_argument
, NULL
, 'B' },
259 { "c++", no_argument
, NULL
, 'C' },
260 { "cxref", no_argument
, NULL
, 'x' },
261 { "defines", no_argument
, NULL
, 'd' },
262 { "forward-search", no_argument
, NULL
, 'F' },
263 { "help", no_argument
, NULL
, 'H' },
264 { "ignore-indentation", no_argument
, NULL
, 'S' },
265 { "include", required_argument
, NULL
, 'i' },
266 { "no-defines", no_argument
, NULL
, 'D' },
267 { "no-warn", no_argument
, NULL
, 'w' },
268 { "output", required_argument
, NULL
, 'o' },
269 { "typedefs", no_argument
, NULL
, 't' },
270 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
271 { "update", no_argument
, NULL
, 'u' },
272 { "version", no_argument
, NULL
, 'V' },
273 { "vgrind", no_argument
, NULL
, 'v' },
277 FILE *tagf
; /* ioptr for tags file */
278 NODE
*head
; /* the head of the binary tree of tags */
279 logical permit_duplicates
= TRUE
; /* allow duplicate tags */
281 /* A `struct linebuffer' is a structure which holds a line of text.
282 `readline' reads a line from a stream into a linebuffer
283 and works regardless of the length of the line. */
291 struct linebuffer lb
; /* the current line */
292 struct linebuffer filename_lb
; /* used to read in filenames */
296 struct linebuffer lb
; /* used by C_entries instead of lb */
303 printf ("%s for Emacs version %g.\n", (CTAGS
) ? "CTAGS" : "ETAGS", VERSION
);
305 printf ("%s for Emacs version 19.\n", (CTAGS
) ? "CTAGS" : "ETAGS");
314 printf ("These are the options accepted by %s. You may use unambiguous\n\
315 abbreviations for the long option names. A - as file name means read file\n\
316 names from stdin.\n\n", progname
);
318 puts ("-a, --append\n\
319 Append tag entries to existing tags file.");
322 puts ("-B, --backward-search\n\
323 Write the search commands for the tag entries using '?', the\n\
324 backward-search command.");
327 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
328 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
329 extensions are always assumed to be C++ code.");
332 puts ("-d, --defines\n\
333 Create tag entries for C #defines, too.");
335 puts ("-D, --no-defines\n\
336 Don't create tag entries for C #defines. This makes the tags\n\
340 puts ("-F, --forward-search\n\
341 Write the search commands for the tag entries using '/', the\n\
342 forward-search command.");
345 puts ("-i FILE, --include=FILE\n\
346 Include a note in tag file indicating that, when searching for\n\
347 a tag, one should also consult the tags file FILE after\n\
348 checking the current file.");
350 puts ("-o FILE, --output=FILE\n\
351 Write the tags to FILE.");
352 puts ("-S, --ignore-indentation\n\
353 Don't rely on indentation quite as much as normal. Currently,\n\
354 this means not to assume that a closing brace in the first\n\
355 column is the final brace of a function or structure\n\
356 definition in C and C++.");
360 puts ("-t, --typedefs\n\
361 Generate tag entries for C typedefs.");
362 puts ("-T, --typedefs-and-c++\n\
363 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
364 and C++ member functions.");
365 puts ("-u, --update\n\
366 Update the tag entries for the given files, leaving tag\n\
367 entries for other files in place. Currently, this is\n\
368 implemented by deleting the existing entries for the given\n\
369 files and then rewriting the new entries at the end of the\n\
370 tags file. It is often faster to simply rebuild the entire\n\
371 tag file than to use this.");
372 puts ("-v, --vgrind\n\
373 Generates an index of items intended for human consumption,\n\
374 similar to the output of vgrind. The index is sorted, and\n\
375 gives the page number of each item.");
376 puts ("-x, --cxref\n\
377 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
378 The output uses line numbers instead of page numbers, but\n\
379 beyond that the differences are cosmetic; try both to see\n\
381 puts ("-w, --no-warn\n\
382 Suppress warning messages about entries defined in multiple\n\
386 puts ("-V, --version\n\
387 Print the version of the program.\n\
389 Print this help message.");
402 unsigned int nincluded_files
= 0;
403 char **included_files
= xnew (argc
, char *);
408 extern char *gfnames ();
409 extern char *massage_name ();
413 _fmode
= O_BINARY
; /* all of files are treated as binary files */
419 * If etags, always find typedefs and structure tags. Why not?
420 * Also default is to find macro constants.
423 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
428 opt
= getopt_long (argc
, argv
, "aCdDf:o:StTi:BFuvxwVH", longopts
, 0);
436 /* If getopt returns 0, then it has already processed a
437 long-named option. We should do nothing. */
440 /* Common options. */
453 case 'f': /* for compatibility with old makefiles */
458 "%s: -%c flag may only be given once\n", progname
, opt
);
477 included_files
[nincluded_files
++] = optarg
;
494 typedefs_and_cplusplus
++;
516 if (optind
== argc
&& nincluded_files
== 0)
518 fprintf (stderr
, "%s: No input files specified.\n", progname
);
521 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
528 tagfile
= CTAGS
? "tags" : "TAGS";
530 cwd
= etags_getcwd (); /* the current working directory */
532 if (streq (tagfile
, "-"))
538 tagfiledir
= absolute_dirname (tagfile
, cwd
);
541 init (); /* set up boolean "functions" */
544 initbuffer (&lbs
[0].lb
);
545 initbuffer (&lbs
[1].lb
);
546 initbuffer (&filename_lb
);
548 * loop through files finding functions
552 if (streq (tagfile
, "-"))
555 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
566 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
570 error ("Can't find file %s\n", this_file
);
575 this_file
= massage_name (this_file
);
578 } /* solely to balance out the ifdef'd parens above */
581 for (; optind
< argc
; optind
++)
583 this_file
= argv
[optind
];
585 /* Input file named "-" means read file names from stdin and use them. */
586 if (streq (this_file
, "-"))
588 while (!feof (stdin
))
590 (void) readline (&filename_lb
, stdin
);
591 if (strlen (filename_lb
.buffer
) > 0)
592 process_file (filename_lb
.buffer
);
596 process_file (this_file
);
601 while (nincluded_files
-- > 0)
602 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
604 (void) fclose (tagf
);
615 /* update cannot be set under VMS, so we may assume that argc
616 and argv have not been munged. */
617 for (i
= optind
; i
< argc
; i
++)
620 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
621 tagfile
, argv
[i
], tagfile
);
626 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
633 (void) fclose (tagf
);
636 sprintf (cmd
, "sort %s -o %s", tagfile
, tagfile
);
644 * This routine is called on each file argument.
650 struct stat stat_buf
;
652 if (stat (file
, &stat_buf
) == 0 && !S_ISREG (stat_buf
.st_mode
))
654 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
657 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
659 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
662 if (!find_entries (file
))
672 /* file is an absolute filename. Canonicalise it. */
673 filename
= absolute_filename (file
, cwd
);
677 /* file is a filename relative to cwd. Make it relative
678 to the directory of the tags file. */
679 filename
= relative_filename (file
, tagfiledir
);
681 fprintf (tagf
, "\f\n%s,%d\n", filename
, total_size_of_entries (head
));
689 * This routine sets up the boolean pseudo-functions which work
690 * by setting boolean flags dependent upon the corresponding character
691 * Every char which is NOT in that string is not a white char. Therefore,
692 * all of the array "_wht" is set to FALSE, and then the elements
693 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
694 * of a char is TRUE if it is the string "white", else FALSE.
702 for (i
= 0; i
< 0177; i
++)
703 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
704 for (sp
= white
; *sp
; sp
++)
706 for (sp
= endtk
; *sp
; sp
++)
708 for (sp
= intk
; *sp
; sp
++)
710 for (sp
= begtk
; *sp
; sp
++)
712 _wht
[0] = _wht
['\n'];
713 _etk
[0] = _etk
['\n'];
714 _btk
[0] = _btk
['\n'];
715 _itk
[0] = _itk
['\n'];
719 * This routine opens the specified file and calls the function
720 * which finds the function and type definitions.
729 inf
= fopen (file
, "r");
735 curfile
= savestr (file
);
736 cp
= etags_strrchr (file
, '.');
739 header_file
= (cp
&& (streq (cp1
, "h")));
741 /* .tex, .aux or .bbl implies LaTeX source code */
742 if (cp
&& (streq (cp1
, "tex") || streq (cp1
, "aux")
743 || streq (cp1
, "bbl")))
746 goto close_and_return
;
748 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
749 if (cp
&& (streq (cp1
, "l")
751 || streq (cp1
, "lsp")
752 || streq (cp1
, "lisp")
754 || streq (cp1
, "clisp")))
756 Lisp_functions (inf
);
757 goto close_and_return
;
759 /* .scm or .sm or .scheme or ... implies scheme source code */
760 if (cp
&& (streq (cp1
, "sm")
761 || streq (cp1
, "scm")
762 || streq (cp1
, "scheme")
764 || streq (cp1
, "sch")
767 || streq (cp1
, "SCM")
768 /* The `SCM' or `scm' prefix with a version number */
769 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
770 && string_numeric_p (cp1
))
771 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
772 && string_numeric_p (cp1
))))
774 Scheme_functions (inf
);
775 goto close_and_return
;
778 if (cp
&& (streq (cp1
, "s")
779 || streq (cp1
, "a") /* Unix assembler */
780 || streq (cp1
, "sa") /* Unix assembler */
781 || streq (cp1
, "asm") /* Microcontroller assembly */
782 || streq (cp1
, "src") /* BSO/Tasking C compiler output */
783 || streq (cp1
, "def") /* BSO/Tasking definition includes */
784 || streq (cp1
, "ins") /* Microcontroller include files */
785 || streq (cp1
, "inc")))/* Microcontroller include files */
788 goto close_and_return
;
790 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
791 if (cp
&& (streq (cp1
, "C")
793 || streq (cp1
, "cxx")
794 || streq (cp1
, "hxx")
795 || streq (cp1
, "cc")))
797 C_entries (C_PLPL
, inf
); /* C++ */
798 goto close_and_return
;
800 /* .cs or .hs: a C* file */
801 if (cp
&& (streq (cp1
, "cs")
802 || streq (cp1
, "hs")))
804 C_entries (C_STAR
, inf
);
805 goto close_and_return
;
807 /* .y: a yacc file */
808 if (cp
&& (streq (cp1
, "y")))
810 C_entries (YACC
, inf
);
811 goto close_and_return
;
813 /* .pl implies prolog source code */
814 if (cp
&& streq (cp1
, "pl"))
816 Prolog_functions (inf
);
817 goto close_and_return
;
819 /* .p or .pas: a Pascal file */
820 if (cp
&& (streq (cp1
, "p")
821 || streq (cp1
, "pas")))
823 Pascal_functions (inf
);
824 goto close_and_return
;
826 /* If .f or .for, assume it is fortran or nothing. */
827 if (cp
&& (streq (cp1
, "f")
828 || streq (cp1
, "for")))
830 (void) Fortran_functions (inf
);
831 goto close_and_return
;
833 /* if not a .c or .h or .y file, try fortran */
834 if (cp
&& ((cp
[1] != 'c'
837 || (cp
[1] != 0 && cp
[2] != 0)))
839 if (Fortran_functions (inf
) != 0)
840 goto close_and_return
;
841 rewind (inf
); /* no fortran tags found, try C */
843 C_entries (cplusplus
? C_PLPL
: 0, inf
);
850 /* Nonzero if string STR is composed of digits. */
853 string_numeric_p (str
)
858 if (*str
< '0' || *str
> '9')
865 /* Should take a TOKEN* instead!! */
867 pfnote (name
, is_func
, named
, linestart
, linelen
, lno
, cno
)
868 char *name
; /* tag name */
869 logical is_func
; /* function or type name? */
870 logical named
; /* tag different from text of definition? */
886 /* It's okay to output early in etags -- it only disrupts the
887 * character count of the tag entries, which is no longer used
890 error ("too many entries to sort", 0);
897 /* If ctags mode, change name "main" to M<thisfilename>. */
898 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
900 fp
= etags_strrchr (curfile
, '/');
901 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
902 fp
= etags_strrchr (name
, '.');
903 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
907 np
->name
= savestr (name
);
909 np
->is_func
= is_func
;
912 /* UNCOMMENT THE +1 HERE: */
913 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
914 np
->left
= np
->right
= 0;
917 c
= linestart
[linelen
];
918 linestart
[linelen
] = 0;
920 else if (cxref_style
== 0)
922 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
925 np
->pat
= savestr (linestart
);
928 linestart
[linelen
] = c
;
931 add_node (np
, &head
);
936 * recurse on left children, iterate on right children.
944 register NODE
*node_right
= node
->right
;
945 free_tree (node
->left
);
948 free ((char *) node
);
955 * Adds a node to the tree of nodes. In etags mode, we don't keep
956 * it sorted; we just keep a linear list. In ctags mode, maintain
957 * an ordered tree, with no attempt at balancing.
959 * add_node is the only function allowed to add nodes, so it can
962 /* Must avoid static vars within functions since some systems
963 #define static as nothing. */
964 NODE
*last_node
= NULL
;
967 add_node (node
, cur_node_p
)
968 NODE
*node
, **cur_node_p
;
971 register NODE
*cur_node
= *cur_node_p
;
973 if (cur_node
== NULL
)
983 if (last_node
== NULL
)
984 fatal ("internal error in add_node", 0);
985 last_node
->right
= node
;
991 dif
= strcmp (node
->name
, cur_node
->name
);
994 * If this tag name matches an existing one, then
995 * do not add the node, but maybe print a warning.
999 if (node
->file
== cur_node
->file
)
1003 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1004 node
->file
, lineno
, node
->name
);
1005 fprintf (stderr
, "Second entry ignored\n");
1009 if (!cur_node
->been_warned
&& !no_warnings
)
1012 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1013 node
->file
, cur_node
->file
, node
->name
);
1015 cur_node
->been_warned
= TRUE
;
1019 /* Maybe refuse to add duplicate nodes. */
1020 if (!permit_duplicates
)
1022 if (streq (node
->name
, cur_node
->name
)
1023 && streq (node
->file
, cur_node
->file
))
1027 /* Actually add the node */
1028 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1034 register NODE
*node
;
1041 /* Output subentries that precede this one */
1042 put_entries (node
->left
);
1044 /* Output this entry */
1050 fprintf (tagf
, "%s\177%s\001%d,%d\n",
1051 node
->pat
, node
->name
,
1052 node
->lno
, node
->cno
);
1056 fprintf (tagf
, "%s\177%d,%d\n",
1058 node
->lno
, node
->cno
);
1061 else if (!cxref_style
)
1063 fprintf (tagf
, "%s\t%s\t",
1064 node
->name
, node
->file
);
1068 putc (searchar
, tagf
);
1071 for (sp
= node
->pat
; *sp
; sp
++)
1073 if (*sp
== '\\' || *sp
== searchar
)
1077 putc (searchar
, tagf
);
1080 { /* a typedef; text pattern inadequate */
1081 fprintf (tagf
, "%d", node
->lno
);
1085 else if (vgrind_style
)
1086 fprintf (stdout
, "%s %s %d\n",
1087 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1089 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1090 node
->name
, node
->lno
, node
->file
, node
->pat
);
1092 /* Output subentries that follow this one */
1093 put_entries (node
->right
);
1096 /* Length of a number's decimal representation. */
1104 for (; num
; num
/= 10)
1110 * Return total number of characters that put_entries will output for
1111 * the nodes in the subtree of the specified node. Works only if
1112 * we are not ctags, but called only in that case. This count
1113 * is irrelevant with the new tags.el, but is still supplied for
1114 * backward compatibility.
1117 total_size_of_entries (node
)
1118 register NODE
*node
;
1126 for (; node
; node
= node
->right
)
1128 /* Count left subentries. */
1129 total
+= total_size_of_entries (node
->left
);
1131 /* Count this entry */
1132 total
+= strlen (node
->pat
) + 1;
1133 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1135 total
+= 1 + strlen (node
->name
); /* \001name */
1142 * The C symbol tables.
1145 /* Feed stuff between (but not including) %[ and %] lines to:
1146 gperf -c -k1,3 -o -p -r -t
1148 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1150 class, C_PLPL, st_C_struct
1151 domain, C_STAR, st_C_struct
1152 union, 0, st_C_struct
1153 struct, 0, st_C_struct
1155 typedef, 0, st_C_typedef
1156 define, 0, st_C_define
1157 long, 0, st_C_typespec
1158 short, 0, st_C_typespec
1159 int, 0, st_C_typespec
1160 char, 0, st_C_typespec
1161 float, 0, st_C_typespec
1162 double, 0, st_C_typespec
1163 signed, 0, st_C_typespec
1164 unsigned, 0, st_C_typespec
1165 auto, 0, st_C_typespec
1166 void, 0, st_C_typespec
1167 extern, 0, st_C_typespec
1168 static, 0, st_C_typespec
1169 const, 0, st_C_typespec
1170 volatile, 0, st_C_typespec
1172 and replace lines between %< and %> with its output. */
1174 /* C code produced by gperf version 1.8.1 (K&R C version) */
1175 /* Command-line: gperf -c -k1,3 -o -p -r -t */
1178 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
1180 #define MIN_WORD_LENGTH 3
1181 #define MAX_WORD_LENGTH 8
1182 #define MIN_HASH_VALUE 10
1183 #define MAX_HASH_VALUE 62
1186 53 is the maximum key range
1194 static unsigned char hash_table
[] =
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, 62, 62, 62,
1203 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1204 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1205 62, 62, 62, 62, 62, 62, 62, 2, 62, 7,
1206 6, 9, 15, 30, 62, 24, 62, 62, 1, 24,
1207 7, 27, 13, 62, 19, 26, 18, 27, 1, 62,
1208 62, 62, 62, 62, 62, 62, 62, 62,
1210 return len
+ hash_table
[str
[2]] + hash_table
[str
[0]];
1213 struct C_stab_entry
*
1214 in_word_set (str
, len
)
1219 static struct C_stab_entry wordlist
[] =
1221 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1223 {"volatile", 0, st_C_typespec
},
1225 {"long", 0, st_C_typespec
},
1226 {"char", 0, st_C_typespec
},
1227 {"class", C_PLPL
, st_C_struct
},
1228 {"",}, {"",}, {"",}, {"",},
1229 {"const", 0, st_C_typespec
},
1230 {"",}, {"",}, {"",}, {"",},
1231 {"auto", 0, st_C_typespec
},
1233 {"define", 0, st_C_define
},
1235 {"void", 0, st_C_typespec
},
1236 {"",}, {"",}, {"",},
1237 {"extern", 0, st_C_typespec
},
1238 {"static", 0, st_C_typespec
},
1240 {"domain", C_STAR
, st_C_struct
},
1242 {"typedef", 0, st_C_typedef
},
1243 {"double", 0, st_C_typespec
},
1244 {"enum", 0, st_C_enum
},
1245 {"",}, {"",}, {"",}, {"",},
1246 {"int", 0, st_C_typespec
},
1248 {"float", 0, st_C_typespec
},
1249 {"",}, {"",}, {"",},
1250 {"struct", 0, st_C_struct
},
1251 {"",}, {"",}, {"",}, {"",},
1252 {"union", 0, st_C_struct
},
1254 {"short", 0, st_C_typespec
},
1256 {"unsigned", 0, st_C_typespec
},
1257 {"signed", 0, st_C_typespec
},
1260 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
1262 register int key
= hash (str
, len
);
1264 if (key
<= MAX_HASH_VALUE
&& key
>= MIN_HASH_VALUE
)
1266 register char *s
= wordlist
[key
].name
;
1268 if (*s
== *str
&& strneq (str
+ 1, s
+ 1, len
- 1))
1269 return &wordlist
[key
];
1277 C_symtype(str
, len
, c_ext
)
1282 register struct C_stab_entry
*se
= in_word_set(str
, len
);
1284 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
1290 * C functions are recognized using a simple finite automaton.
1291 * funcdef is its state variable.
1295 fnone
, /* nothing seen */
1296 ftagseen
, /* function-like tag seen */
1297 fstartlist
, /* just after open parenthesis */
1298 finlist
, /* in parameter list */
1299 flistseen
, /* after parameter list */
1300 fignore
/* before open brace */
1306 * typedefs are recognized using a simple finite automaton.
1307 * typeddef is its state variable.
1311 tnone
, /* nothing seen */
1312 ttypedseen
, /* typedef keyword seen */
1313 tinbody
, /* inside typedef body */
1314 tend
, /* just before typedef tag */
1315 tignore
/* junk after typedef tag */
1321 * struct-like structures (enum, struct and union) are recognized
1322 * using another simple finite automaton. `structdef' is its state
1327 snone
, /* nothing seen yet */
1328 skeyseen
, /* struct-like keyword seen */
1329 stagseen
, /* struct-like tag seen */
1330 scolonseen
, /* colon seen after struct-like tag */
1331 sinbody
/* in struct body: recognize member func defs*/
1336 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1337 * struct tag, and structtype is the type of the preceding struct-like
1340 char structtag
[BUFSIZ
];
1341 enum sym_type structtype
;
1344 * Yet another little state machine to deal with preprocessor lines.
1348 dnone
, /* nothing seen */
1349 dsharpseen
, /* '#' seen as first char on line */
1350 ddefineseen
, /* '#' and 'define' seen */
1351 dignorerest
/* ignore rest of line */
1356 * Set this to TRUE, and the next token considered is called a function.
1357 * Used only for GNUmacs's function-defining macros.
1359 logical next_token_is_func
;
1362 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1368 * checks to see if the current token is at the start of a
1369 * function, or corresponds to a typedef, or is a struct/union/enum
1372 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1373 * C_EXT is which language we are looking at.
1375 * In the future we will need some way to adjust where the end of
1376 * the token is; for instance, implementing the C++ keyword
1377 * `operator' properly will adjust the end of the token to be after
1378 * whatever follows `operator'.
1385 * next_token_is_func IN OUT
1389 consider_token (c
, tokp
, c_ext
, cblev
, is_func
)
1390 register char c
; /* IN: first char after the token */
1391 register TOKEN
*tokp
; /* IN: token pointer */
1392 int c_ext
; /* IN: C extensions mask */
1393 int cblev
; /* IN: curly brace level */
1394 logical
*is_func
; /* OUT */
1396 enum sym_type toktype
= C_symtype(tokp
->p
, tokp
->len
, c_ext
);
1399 * Advance the definedef state machine.
1404 /* We're not on a preprocessor line. */
1407 if (toktype
== st_C_define
)
1409 definedef
= ddefineseen
;
1413 definedef
= dignorerest
;
1418 * Make a tag for any macro.
1420 definedef
= dignorerest
;
1421 *is_func
= (c
== '(');
1422 if (!*is_func
&& !constantypedefs
)
1429 error ("internal error: definedef value.", 0);
1438 if (toktype
== st_C_typedef
)
1441 typdef
= ttypedseen
;
1457 /* Do not return here, so the structdef stuff has a chance. */
1471 * This structdef business is currently only invoked when cblev==0.
1472 * It should be recursively invoked whatever the curly brace level,
1473 * and a stack of states kept, to allow for definitions of structs
1476 * This structdef business is NOT invoked when we are ctags and the
1477 * file is plain C. This is because a struct tag may have the same
1478 * name as another tag, and this loses with ctags.
1480 * This if statement deals with the typdef state machine as
1481 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1482 * return (FALSE). All the other code here is for the structdef
1489 if (typdef
== ttypedseen
1490 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1492 structdef
= skeyseen
;
1493 structtype
= toktype
;
1497 if (structdef
== skeyseen
)
1499 if (structtype
== st_C_struct
)
1501 strncpy (structtag
, tokp
->p
, tokp
->len
);
1502 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1506 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1508 structdef
= stagseen
;
1512 /* Avoid entering funcdef stuff if typdef is going on. */
1513 if (typdef
!= tnone
)
1519 /* Detect GNUmacs's function-defining macros. */
1520 if (definedef
== dnone
)
1522 if (strneq (tokp
->p
, "DEF", 3)
1523 || strneq (tokp
->p
, "ENTRY", 5)
1524 || strneq (tokp
->p
, "SYSCALL", 7)
1525 || strneq (tokp
->p
, "PSEUDO", 6))
1527 next_token_is_func
= TRUE
;
1530 if (strneq (tokp
->p
, "EXFUN", 5))
1532 next_token_is_func
= FALSE
;
1536 if (next_token_is_func
)
1538 next_token_is_func
= FALSE
;
1540 *is_func
= TRUE
; /* to force search string in ctags */
1548 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1549 funcdef
= fnone
; /* should be useless */
1552 if (funcdef
== fnone
)
1565 * This routine finds functions, typedefs, #define's and
1566 * struct/union/enum definitions in C syntax and adds them
1570 #define curlb (lbs[curndx].lb)
1571 #define othlb (lbs[1-curndx].lb)
1572 #define newlb (lbs[newndx].lb)
1573 #define curlinepos (lbs[curndx].linepos)
1574 #define othlinepos (lbs[1-curndx].linepos)
1575 #define newlinepos (lbs[newndx].linepos)
1577 /* Save and restore token state. This is used when preprocessor defines
1578 are handled, to avoid disturbing active function/typedef/struct states. */
1579 #define TOKEN_SAVED_P (savetok.lineno > 0)
1580 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1581 savetok.len = toklen, strcpy(savenameb, nameb))
1582 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1583 toklen = tok.len, strcpy(nameb, savenameb), \
1586 #define CNL_SAVE_DEFINEDEF \
1588 SET_FILEPOS (curlinepos, inf, charno); \
1590 charno += readline (&curlb, inf); \
1591 lp = curlb.buffer; \
1598 CNL_SAVE_DEFINEDEF; \
1599 if (TOKEN_SAVED_P) \
1601 definedef = dnone; \
1604 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1605 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1606 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1607 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1610 C_entries (c_ext
, inf
)
1611 int c_ext
; /* extension of C? */
1614 register char c
; /* latest char read; '\0' for end of line */
1615 register char *lp
; /* pointer one beyond the character `c' */
1616 int curndx
, newndx
; /* indices for current and new lb */
1617 TOKEN tok
; /* latest token read for funcdef & structdef */
1618 char nameb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1619 register int tokoff
; /* offset in line of start of latest token */
1620 register int toklen
; /* length of latest token */
1621 int cblev
; /* current curly brace level */
1622 int parlev
; /* current parenthesis level */
1623 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1625 TOKEN savetok
; /* saved token during preprocessor handling */
1626 char savenameb
[BUFSIZ
]; /* ouch! */
1629 curndx
= newndx
= 0;
1635 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1636 next_token_is_func
= yacc_rules
= FALSE
;
1637 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1640 cplpl
= c_ext
& C_PLPL
;
1647 /* If we're at the end of the line, the next character is a
1648 '\0'; don't skip it, because it's the thing that tells us
1649 to read the next line. */
1670 /* Newlines inside comments do not end macro definitions in
1685 /* Newlines inside strings do not end macro definitions
1686 in traditional cpp, even though compilers don't
1687 usually accept them. */
1698 /* Hmmm, something went wrong. */
1712 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1717 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1727 else if (cplpl
&& *lp
== '/')
1735 if ((c_ext
& YACC
) && *lp
== '%')
1737 /* entering or exiting rules section in yacc file */
1739 definedef
= dnone
; funcdef
= fnone
;
1740 typdef
= tnone
; structdef
= snone
;
1741 next_token_is_func
= FALSE
;
1742 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1744 yacc_rules
= !yacc_rules
;
1750 if (lp
== newlb
.buffer
+ 1 && definedef
== dnone
)
1751 definedef
= dsharpseen
;
1756 /* Consider token only if some complicated conditions are satisfied. */
1757 if (((cblev
== 0 && structdef
!= scolonseen
)
1758 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
1759 && typdef
!= tignore
1760 && definedef
!= dignorerest
1761 && (funcdef
!= finlist
1762 || definedef
!= dnone
))
1768 if (cplpl
&& c
== ':' && *lp
== ':' && begtoken(*(lp
+ 1)))
1771 * This handles :: in the middle, but not at beginning
1779 logical is_func
= FALSE
;
1781 tok
.lineno
= lineno
;
1782 tok
.p
= newlb
.buffer
+ tokoff
;
1786 || consider_token (c
, &tok
, c_ext
, cblev
, &is_func
))
1788 if (structdef
== sinbody
1789 && definedef
== dnone
1791 /* function defined in C++ class body */
1794 sprintf (nameb
, "%s::%.*s",
1795 ((structtag
[0] == '\0')
1796 ? "_anonymous_" : structtag
),
1801 sprintf (nameb
, "%.*s", tok
.len
, tok
.p
);
1804 if (structdef
== stagseen
1808 if (definedef
== dnone
1809 && (funcdef
== ftagseen
1810 || structdef
== stagseen
1813 if (newndx
== curndx
)
1814 curndx
= 1 - curndx
; /* switch line buffers */
1817 MAKE_TAG_FROM_NEW_LB (is_func
);
1821 } /* if (endtoken (c)) */
1822 else if (intoken (c
))
1827 } /* if (midtoken) */
1828 else if (begtoken (c
))
1839 MAKE_TAG_FROM_OTH_LB (TRUE
);
1846 if (structdef
== stagseen
)
1850 /* Take a quick peek ahead for define directive,
1851 so we can avoid saving the token when not absolutely
1852 necessary. [This is a speed hack.] */
1853 if (c
== 'd' && strneq(lp
, "efine", 5)
1854 && iswhite(*(lp
+ 5)))
1857 definedef
= ddefineseen
;
1861 definedef
= dignorerest
;
1864 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1866 tokoff
= lp
- 1 - newlb
.buffer
;
1872 } /* if must look at token */
1875 /* Detect end of line, colon, comma, semicolon and various braces
1876 after having handled a token.*/
1880 if (definedef
!= dnone
)
1882 if (structdef
== stagseen
)
1883 structdef
= scolonseen
;
1890 MAKE_TAG_FROM_OTH_LB (FALSE
);
1900 if (definedef
!= dnone
)
1906 MAKE_TAG_FROM_OTH_LB (FALSE
);
1911 if (funcdef
!= fignore
)
1913 if (structdef
== stagseen
)
1917 if (definedef
!= dnone
)
1919 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1921 if (structdef
== stagseen
)
1925 if (definedef
!= dnone
)
1927 if (cblev
== 0 && typdef
== tend
)
1930 MAKE_TAG_FROM_OTH_LB (FALSE
);
1933 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1935 if (structdef
== stagseen
)
1939 if (definedef
!= dnone
)
1944 funcdef
= fstartlist
;
1953 if (definedef
!= dnone
)
1961 funcdef
= flistseen
;
1964 if (cblev
== 0 && typdef
== tend
)
1967 MAKE_TAG_FROM_OTH_LB (FALSE
);
1970 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
1974 if (definedef
!= dnone
)
1976 if (typdef
== ttypedseen
)
1980 case skeyseen
: /* unnamed struct */
1981 structtag
[0] = '\0';
1982 structdef
= sinbody
;
1985 case scolonseen
: /* named struct */
1986 structdef
= sinbody
;
1987 MAKE_TAG_FROM_OTH_LB (FALSE
);
1993 MAKE_TAG_FROM_OTH_LB (TRUE
);
1999 /* Neutralize `extern "C" {' grot.
2000 if (cblev == 0 && structdef == snone && typdef == tnone)
2006 if (definedef
!= dnone
)
2008 if (funcdef
== fstartlist
)
2009 funcdef
= fnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
2012 if (definedef
!= dnone
)
2014 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
2016 cblev
= 0; /* reset curly brace level if first column */
2017 parlev
= 0; /* also reset paren level, just in case... */
2023 if (typdef
== tinbody
)
2026 strcpy (structtag
, "<error 2>");
2030 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
2031 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
2032 if (definedef
!= dnone
)
2034 /* These surely cannot follow a function tag. */
2035 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2039 /* If a macro spans multiple lines don't reset its state. */
2047 } /* while not eof */
2050 /* Fortran parsing */
2059 register int len
= 0;
2061 while (*cp
&& (*cp
| ' ') == (dbp
[len
] | ' '))
2074 while (isspace (*dbp
))
2079 while (isspace (*dbp
))
2081 if (!isdigit (*dbp
))
2083 --dbp
; /* force failure */
2088 while (isdigit (*dbp
));
2097 char nambuf
[BUFSIZ
];
2099 while (isspace (*dbp
))
2104 linecharno
= charno
;
2105 charno
+= readline (&lb
, inf
);
2110 while (isspace (*dbp
))
2119 && (isalpha (*cp
) || isdigit (*cp
) || (*cp
== '_') || (*cp
== '$')));
2124 strcpy (nambuf
, dbp
);
2126 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2127 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2132 Fortran_functions (inf
)
2142 linecharno
= charno
;
2143 charno
+= readline (&lb
, inf
);
2146 dbp
++; /* Ratfor escape to fortran */
2147 while (isspace (*dbp
))
2154 if (tail ("integer"))
2162 if (tail ("logical"))
2166 if (tail ("complex") || tail ("character"))
2170 if (tail ("double"))
2172 while (isspace (*dbp
))
2176 if (tail ("precision"))
2182 while (isspace (*dbp
))
2189 if (tail ("function"))
2193 if (tail ("subroutine"))
2201 if (tail ("program"))
2206 if (tail ("procedure"))
2215 * Bob Weiner, Motorola Inc., 4/3/94
2216 * Unix and microcontroller assembly tag handling
2217 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
2223 char nambuf
[BUFSIZ
];
2234 linecharno
= charno
;
2235 charno
+= readline (&lb
, inf
);
2238 /* If first char is alphabetic or one of [_.$], test for colon
2239 following identifier. */
2240 if (isalpha (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2242 /* Read past label. */
2244 while (isalnum (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2246 if (*cp
== ':' || isspace (*cp
))
2248 /* Found end of label, so copy it and add it to the table. */
2251 strcpy (nambuf
, lb
.buffer
);
2253 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2254 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2261 /* Added by Mosur Mohan, 4/22/88 */
2262 /* Pascal parsing */
2264 #define GET_NEW_LINE \
2266 linecharno = charno; lineno++; \
2267 charno += 1 + readline (&lb, inf); \
2271 /* Locates tags for procedures & functions.
2272 * Doesn't do any type- or var-definitions.
2273 * It does look for the keyword "extern" or "forward"
2274 * immediately following the procedure statement;
2275 * if found, the tag is skipped.
2279 Pascal_functions (inf
)
2282 struct linebuffer tline
; /* mostly copied from C_entries */
2286 char nambuf
[BUFSIZ
];
2288 logical
/* each of these flags is TRUE iff: */
2289 incomm1
, /* point is inside {..} comment */
2290 incomm2
, /* point is inside (*..*) comment */
2291 inquote
, /* point is inside '..' string */
2292 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2293 /* keyword, so next item = potential tag */
2294 found_tag
, /* point is after a potential tag */
2295 inparms
, /* point is within parameter-list */
2296 verify_tag
; /* point has passed the parm-list, so the */
2297 /* next token will determine whether */
2298 /* this is a FORWARD/EXTERN to be */
2299 /* ignored, or whether it is a real tag */
2305 initbuffer (&tline
);
2307 incomm1
= incomm2
= inquote
= FALSE
;
2308 found_tag
= FALSE
; /* have a proc name; check if extern */
2309 get_tagname
= FALSE
; /* have found "procedure" keyword */
2310 inparms
= FALSE
; /* found '(' after "proc" */
2311 verify_tag
= FALSE
; /* check if "extern" is ahead */
2313 /* long main loop to get next char */
2317 if (c
== 0) /* if end of line */
2322 if (!((found_tag
&& verify_tag
) ||
2324 c
= *dbp
++; /* only if don't need *dbp pointing */
2325 /* to the beginning of the name of */
2326 /* the procedure or function */
2328 if (incomm1
) /* within { - } comments */
2334 else if (incomm2
) /* within (* - *) comments */
2338 while ((c
= *dbp
++) == '*')
2357 inquote
= TRUE
; /* found first quote */
2359 case '{': /* found open-{-comment */
2363 if (*dbp
== '*') /* found open-(*-comment */
2368 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2371 case ')': /* end of parms list */
2376 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2383 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2385 /* check if this is an "extern" declaration */
2388 if ((*dbp
== 'e') || (*dbp
== 'E'))
2390 if (tail ("extern")) /* superfluous, really! */
2396 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2398 if (tail ("forward")) /* check for forward reference */
2404 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2408 pfnote (nambuf
, TRUE
, FALSE
,
2409 tline
.buffer
, cp
- tline
.buffer
+ 1,
2410 save_lineno
, save_lcno
);
2414 if (get_tagname
) /* grab name of proc or fn */
2419 /* save all values for later tagging */
2420 tline
.size
= lb
.size
;
2421 strcpy (tline
.buffer
, lb
.buffer
);
2422 save_lineno
= lineno
;
2423 save_lcno
= linecharno
;
2425 /* grab block name */
2426 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2430 strcpy (nambuf
, dbp
);
2432 dbp
= cp
; /* restore dbp to e-o-token */
2433 get_tagname
= FALSE
;
2437 /* and proceed to check for "extern" */
2439 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2440 (!found_tag
) && (!get_tagname
))
2442 /* check for proc/fn keywords */
2446 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2450 if (tail ("unction"))
2455 } /* while not eof */
2459 * lisp tag functions
2460 * just look for (def or (DEF
2467 return ((dbp
[1] == 'd' || dbp
[1] == 'D')
2468 && (dbp
[2] == 'e' || dbp
[2] == 'E')
2469 && (dbp
[3] == 'f' || dbp
[3] == 'F'));
2476 return ((*(++dbp
) == 'q' || *dbp
== 'Q')
2477 && (*(++dbp
) == 'u' || *dbp
== 'U')
2478 && (*(++dbp
) == 'o' || *dbp
== 'O')
2479 && (*(++dbp
) == 't' || *dbp
== 'T')
2480 && (*(++dbp
) == 'e' || *dbp
== 'E')
2481 && isspace(*(++dbp
)));
2489 char nambuf
[BUFSIZ
];
2491 if (*dbp
== '\'') /* Skip prefix quote */
2493 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2496 while (isspace(*dbp
))
2499 for (cp
= dbp
/*+1*/; *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')'; cp
++)
2506 strcpy (nambuf
, dbp
);
2508 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2509 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2514 Lisp_functions (inf
)
2524 linecharno
= charno
;
2525 charno
+= readline (&lb
, inf
);
2531 while (!isspace (*dbp
))
2533 while (isspace (*dbp
))
2539 /* Check for (foo::defmumble name-defined ... */
2542 while (*dbp
&& !isspace (*dbp
)
2543 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2548 while (*dbp
== ':');
2550 if (L_isdef (dbp
- 1))
2552 while (!isspace (*dbp
))
2554 while (isspace (*dbp
))
2565 * Scheme tag functions
2566 * look for (def... xyzzy
2567 * look for (def... (xyzzy
2568 * look for (def ... ((...(xyzzy ....
2569 * look for (set! xyzzy
2575 Scheme_functions (inf
)
2585 linecharno
= charno
;
2586 charno
+= readline (&lb
, inf
);
2588 if (dbp
[0] == '(' &&
2589 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2590 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2591 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2593 while (!isspace (*dbp
))
2595 /* Skip over open parens and white space */
2596 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2600 if (dbp
[0] == '(' &&
2601 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2602 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2603 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2604 (dbp
[4] == '!' || dbp
[4] == '!') &&
2607 while (!isspace (*dbp
))
2609 /* Skip over white space */
2610 while (isspace (*dbp
))
2622 char nambuf
[BUFSIZ
];
2626 /* Go till you get to white space or a syntactic break */
2627 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2629 /* Null terminate the string there. */
2632 /* Copy the string */
2633 strcpy (nambuf
, dbp
);
2634 /* Unterminate the string */
2636 /* Announce the change */
2637 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2641 /* Find tags in TeX and LaTeX input files. */
2643 /* TEX_toktab is a table of TeX control sequences that define tags.
2644 Each TEX_tabent records one such control sequence.
2645 CONVERT THIS TO USE THE Stab TYPE!! */
2653 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2655 /* Default set of control sequences to put into TEX_toktab.
2656 The value of environment var TEXTAGS is prepended to this. */
2658 char *TEX_defenv
= "\
2659 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2662 struct TEX_tabent
*TEX_decode_env ();
2666 char TEX_esc
= '\\';
2667 char TEX_opgrp
= '{';
2668 char TEX_clgrp
= '}';
2671 * TeX/LaTeX scanning loop.
2684 /* Select either \ or ! as escape character. */
2687 /* Initialize token table once from environment. */
2689 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2692 { /* Scan each line in file */
2694 linecharno
= charno
;
2695 charno
+= readline (&lb
, inf
);
2698 while (dbp
= etags_strchr (dbp
, TEX_esc
)) /* Look at each esc in line */
2704 linecharno
+= dbp
- lasthit
;
2706 i
= TEX_Token (lasthit
);
2709 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2710 break; /* We only save a line once */
2716 #define TEX_LESC '\\'
2717 #define TEX_SESC '!'
2720 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2721 /* chars accordingly. */
2729 while ((c
= getc (inf
)) != EOF
)
2731 /* Skip to next line if we hit the TeX comment char. */
2735 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2754 /* Read environment and prepend it to the default string. */
2755 /* Build token table. */
2758 TEX_decode_env (evarname
, defenv
)
2762 register char *env
, *p
;
2764 struct TEX_tabent
*tab
;
2767 /* Append default string to environment. */
2768 env
= getenv (evarname
);
2772 env
= concat (env
, defenv
, "");
2774 /* Allocate a token table */
2775 for (size
= 1, p
= env
; p
;)
2776 if ((p
= etags_strchr (p
, ':')) && *(++p
))
2778 /* Add 1 to leave room for null terminator. */
2779 tab
= xnew (size
+ 1, struct TEX_tabent
);
2781 /* Unpack environment string into token table. Be careful about */
2782 /* zero-length strings (leading ':', "::" and trailing ':') */
2785 p
= etags_strchr (env
, ':');
2786 if (!p
) /* End of environment string. */
2787 p
= env
+ strlen (env
);
2789 { /* Only non-zero strings. */
2790 tab
[i
].name
= savenstr (env
, p
- env
);
2791 tab
[i
].len
= strlen (tab
[i
].name
);
2798 tab
[i
].name
= NULL
; /* Mark end of table. */
2806 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2807 The name being defined actually starts at (NAME + LEN + 1).
2808 But we seem to include the TeX command in the tag name. */
2811 TEX_getit (name
, len
)
2815 char *p
= name
+ len
;
2816 char nambuf
[BUFSIZ
];
2821 /* Let tag name extend to next group close (or end of line) */
2822 while (*p
&& *p
!= TEX_clgrp
)
2824 strncpy (nambuf
, name
, p
- name
);
2825 nambuf
[p
- name
] = 0;
2827 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2831 /* If the text at CP matches one of the tag-defining TeX command names,
2832 return the pointer to the first occurrence of that command in TEX_toktab.
2833 Otherwise return -1. */
2835 /* Keep the capital `T' in `Token' for dumb truncating compilers
2836 (this distinguishes it from `TEX_toktab' */
2843 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2844 if (strneq (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
))
2849 /* Support for Prolog. */
2851 /* whole head (not only functor, but also arguments)
2852 is gotten in compound term. */
2855 prolog_getit (s
, lineno
, linecharno
)
2860 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2868 if (*s
== '\0') /* syntax error. */
2870 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2872 else if (*s
== '\'')
2874 insquote
= !insquote
;
2877 else if (!insquote
&& *s
== '(')
2882 else if (!insquote
&& *s
== ')')
2888 else if (npar
< 0) /* syntax error. */
2891 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2893 if (npar
!= 0) /* syntax error. */
2903 strcpy (nambuf
, save_s
);
2905 pfnote (nambuf
, TRUE
, FALSE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2908 /* It is assumed that prolog predicate starts from column 0. */
2911 Prolog_functions (inf
)
2914 void skip_comment (), prolog_getit ();
2916 lineno
= linecharno
= charno
= 0;
2920 linecharno
+= charno
;
2921 charno
= readline (&lb
, inf
) + 1; /* 1 for newline. */
2923 if (isspace (dbp
[0])) /* not predicate header. */
2925 else if (dbp
[0] == '%') /* comment. */
2927 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2928 skip_comment (&lb
, inf
, &lineno
, &linecharno
);
2930 prolog_getit (dbp
, lineno
, linecharno
);
2935 skip_comment (plb
, inf
, plineno
, plinecharno
)
2936 struct linebuffer
*plb
;
2938 int *plineno
; /* result */
2939 long *plinecharno
; /* result */
2941 while (!substr ("*/", plb
->buffer
))
2944 *plinecharno
+= readline (plb
, inf
) + 1;
2945 } /* 1 for newline. */
2948 /* Return TRUE if 'sub' exists somewhere in 's'. */
2955 while (*s
&& (s
= etags_strchr (s
, *sub
)))
2956 if (prestr (sub
, s
))
2963 /* Return TRUE if 'pre' is prefix of string 's'. */
2972 else if (*pre
== *s
)
2973 return (prestr (pre
+ 1, s
+ 1));
2978 /* Initialize a linebuffer for use */
2981 initbuffer (linebuffer
)
2982 struct linebuffer
*linebuffer
;
2984 linebuffer
->size
= 200;
2985 linebuffer
->buffer
= xnew (200, char);
2989 * Read a line of text from `stream' into `linebuffer'.
2990 * Return the number of characters read from `stream',
2991 * which is the length of the line including the newline, if any.
2994 readline (linebuffer
, stream
)
2995 struct linebuffer
*linebuffer
;
2996 register FILE *stream
;
2998 char *buffer
= linebuffer
->buffer
;
2999 register char *p
= linebuffer
->buffer
;
3000 register char *pend
;
3001 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
3003 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
3007 register int c
= getc (stream
);
3010 linebuffer
->size
*= 2;
3011 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
3012 p
+= buffer
- linebuffer
->buffer
;
3013 pend
= buffer
+ linebuffer
->size
;
3014 linebuffer
->buffer
= buffer
;
3016 if (c
== EOF
|| c
== '\n')
3019 newline
= (c
== '\n') ? 1 : 0;
3025 return p
- buffer
+ newline
;
3032 return savenstr (cp
, strlen (cp
));
3042 dp
= xnew (len
+ 1, char);
3043 strncpy (dp
, cp
, len
);
3049 * Return the ptr in sp at which the character c last
3050 * appears; NULL if not found
3052 * Identical to System V strrchr, included for portability.
3056 etags_strrchr (sp
, c
)
3057 register char *sp
, c
;
3072 * Return the ptr in sp at which the character c first
3073 * appears; NULL if not found
3075 * Identical to System V strchr, included for portability.
3079 etags_strchr (sp
, c
)
3080 register char *sp
, c
;
3090 /* Print error message and exit. */
3101 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3108 fprintf (stderr
, "%s: ", progname
);
3109 fprintf (stderr
, s1
, s2
);
3110 fprintf (stderr
, "\n");
3113 /* Return a newly-allocated string whose contents
3114 concatenate those of s1, s2, s3. */
3120 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3121 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3123 strcpy (result
, s1
);
3124 strcpy (result
+ len1
, s2
);
3125 strcpy (result
+ len1
+ len2
, s3
);
3126 result
[len1
+ len2
+ len3
] = '\0';
3131 /* Does the same work as the system V getcwd, but does not need to
3132 guess buffer size in advance. Included mostly for compatibility. */
3142 buf
= xnew (bufsize
, char);
3144 pipe
= popen ("pwd 2>/dev/null", "r");
3150 if (fgets (buf
, bufsize
, pipe
) == NULL
)
3159 } while (buf
[strlen (buf
) - 1] != '\n');
3164 /* Return a newly allocated string containing the filename
3165 of FILE relative to the absolute directory DIR (which
3166 should end with a slash). */
3169 relative_filename (file
, dir
)
3172 char *fp
, *dp
, *res
;
3174 /* Find the common root of file and dir. */
3175 fp
= absolute_filename (file
, cwd
);
3177 while (*fp
++ == *dp
++)
3186 /* Build a sequence of "../" strings for the resulting relative filename. */
3187 for (dp
= etags_strchr (dp
+ 1, '/'), res
= "";
3189 dp
= etags_strchr (dp
+ 1, '/'))
3191 res
= concat (res
, "../", "");
3194 /* Add the filename relative to the common root of file and dir. */
3195 res
= concat (res
, fp
+ 1, "");
3197 return res
; /* temporary stub */
3200 /* Return a newly allocated string containing the
3201 absolute filename of FILE given CWD (which should
3202 end with a slash). */
3205 absolute_filename (file
, cwd
)
3208 char *slashp
, *cp
, *res
;
3211 res
= concat (file
, "", "");
3213 res
= concat (cwd
, file
, "");
3215 /* Delete the "/dirname/.." and "/." substrings. */
3216 slashp
= etags_strchr (res
, '/');
3217 while (slashp
!= NULL
&& slashp
[0] != '\0')
3219 if (slashp
[1] == '.')
3221 if (slashp
[2] == '.'
3222 && (slashp
[3] == '/' || slashp
[3] == '\0'))
3227 while (cp
>= res
&& *cp
!= '/');
3230 strcpy (cp
, slashp
+ 3);
3232 else /* else (cp == res) */
3234 if (slashp
[3] != NULL
)
3235 strcpy (cp
, slashp
+ 4);
3241 else if (slashp
[2] == '/' || slashp
[2] == '\0')
3243 strcpy (slashp
, slashp
+ 2);
3248 slashp
= etags_strchr (slashp
+ 1, '/');
3255 /* Return a newly allocated string containing the absolute
3256 filename of dir where FILE resides given CWD (which should
3257 end with a slash). */
3260 absolute_dirname (file
, cwd
)
3266 slashp
= etags_strrchr (file
, '/');
3271 res
= absolute_filename (file
, cwd
);
3277 /* Like malloc but get fatal error if memory is exhausted. */
3283 char *result
= (char *) malloc (size
);
3285 fatal ("virtual memory exhausted", 0);
3290 xrealloc (ptr
, size
)
3294 char *result
= (char *) realloc (ptr
, size
);
3296 fatal ("virtual memory exhausted");