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 ();
58 char *malloc (), *realloc ();
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 ();
165 int string_numeric_p ();
172 int Fortran_functions ();
173 void Lisp_functions ();
174 void Pascal_functions ();
175 void Prolog_functions ();
176 void Scheme_functions ();
177 void TeX_functions ();
181 logical
find_entries ();
188 void process_file ();
194 * xnew -- allocate storage
197 * Type *xnew (int n, Type);
199 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
202 * Symbol table types.
206 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
223 #define C_PLPL 0x00001 /* C++ */
224 #define C_STAR 0x00003 /* C* */
225 #define YACC 0x10000 /* yacc file */
227 char searchar
= '/'; /* use /.../ searches */
229 LINENO lineno
; /* line number of current line */
230 long charno
; /* current character number */
232 long linecharno
; /* charno of start of line; not used by C, but
233 * by every other language.
236 char *curfile
, /* current input file name */
237 *tagfile
, /* output file */
238 *white
= " \f\t\n\013", /* white chars */
239 *endtk
= " \t\n\013\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
240 /* token starting chars */
241 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
242 /* valid in-token chars */
243 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
245 int append_to_tagfile
; /* -a: append to tags */
246 /* The following three default to 1 for etags, but to 0 for ctags. */
247 int typedefs
; /* -t: create tags for typedefs */
248 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
249 /* 0 struct/enum/union decls, and C++ */
250 /* member functions. */
251 int constantypedefs
; /* -d: create tags for C #define and enum */
252 /* constants. Enum consts not implemented. */
253 /* -D: opposite of -d. Default under ctags. */
254 int update
; /* -u: update tags */
255 int vgrind_style
; /* -v: create vgrind style index output */
256 int no_warnings
; /* -w: suppress warnings */
257 int cxref_style
; /* -x: create cxref style output */
258 int cplusplus
; /* .[hc] means C++, not C */
259 int noindentypedefs
; /* -S: ignore indentation in C */
261 /* Name this program was invoked with. */
264 struct option longopts
[] = {
265 { "append", no_argument
, NULL
, 'a' },
266 { "backward-search", no_argument
, NULL
, 'B' },
267 { "c++", no_argument
, NULL
, 'C' },
268 { "cxref", no_argument
, NULL
, 'x' },
269 { "defines", no_argument
, NULL
, 'd' },
270 { "help", no_argument
, NULL
, 'H' },
271 { "ignore-indentation", no_argument
, NULL
, 'S' },
272 { "include", required_argument
, NULL
, 'i' },
273 { "no-defines", no_argument
, NULL
, 'D' },
274 { "no-warn", no_argument
, NULL
, 'w' },
275 { "output", required_argument
, NULL
, 'o' },
276 { "typedefs", no_argument
, NULL
, 't' },
277 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
278 { "update", no_argument
, NULL
, 'u' },
279 { "version", no_argument
, NULL
, 'V' },
280 { "vgrind", no_argument
, NULL
, 'v' },
284 FILE *tagf
; /* ioptr for tags file */
285 NODE
*head
; /* the head of the binary tree of tags */
286 logical permit_duplicates
= TRUE
; /* allow duplicate tags */
288 /* A `struct linebuffer' is a structure which holds a line of text.
289 `readline' reads a line from a stream into a linebuffer
290 and works regardless of the length of the line. */
298 struct linebuffer lb
; /* the current line */
299 struct linebuffer filename_lb
; /* used to read in filenames */
303 struct linebuffer lb
; /* used by C_entries instead of lb */
310 printf ("%s for Emacs version %s.\n", (CTAGS
) ? "CTAGS" : "ETAGS", VERSION
);
312 printf ("%s for Emacs version 19.\n", (CTAGS
) ? "CTAGS" : "ETAGS");
321 printf ("These are the options accepted by %s. You may use unambiguous\n\
322 abbreviations for the long option names. A - as file name means read file\n\
323 names from stdin.\n\n", progname
);
325 puts ("-a, --append\n\
326 Append tag entries to existing tags file.");
329 puts ("-B, --backward-search\n\
330 Write the search commands for the tag entries using '?', the\n\
331 backward-search command instead of '/', the forward-search command.");
334 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
335 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
336 extensions are always assumed to be C++ code.");
339 puts ("-d, --defines\n\
340 Create tag entries for constant C #defines, too.");
342 puts ("-D, --no-defines\n\
343 Don't create tag entries for constant C #defines. This makes\n\
344 the tags file smaller.");
347 puts ("-i FILE, --include=FILE\n\
348 Include a note in tag file indicating that, when searching for\n\
349 a tag, one should also consult the tags file FILE after\n\
350 checking the current file.");
352 puts ("-o FILE, --output=FILE\n\
353 Write the tags to FILE.");
354 puts ("-S, --ignore-indentation\n\
355 Don't rely on indentation quite as much as normal. Currently,\n\
356 this means not to assume that a closing brace in the first\n\
357 column is the final brace of a function or structure\n\
358 definition in C and C++.");
362 puts ("-t, --typedefs\n\
363 Generate tag entries for C typedefs.");
364 puts ("-T, --typedefs-and-c++\n\
365 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
366 and C++ member functions.");
367 puts ("-u, --update\n\
368 Update the tag entries for the given files, leaving tag\n\
369 entries for other files in place. Currently, this is\n\
370 implemented by deleting the existing entries for the given\n\
371 files and then rewriting the new entries at the end of the\n\
372 tags file. It is often faster to simply rebuild the entire\n\
373 tag file than to use this.");
374 puts ("-v, --vgrind\n\
375 Generates an index of items intended for human consumption,\n\
376 similar to the output of vgrind. The index is sorted, and\n\
377 gives the page number of each item.");
378 puts ("-x, --cxref\n\
379 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
380 The output uses line numbers instead of page numbers, but\n\
381 beyond that the differences are cosmetic; try both to see\n\
383 puts ("-w, --no-warn\n\
384 Suppress warning messages about entries defined in multiple\n\
388 puts ("-V, --version\n\
389 Print the version of the program.\n\
391 Print this help message.");
404 unsigned int nincluded_files
= 0;
405 char **included_files
= xnew (argc
, char *);
410 extern char *gfnames ();
411 extern char *massage_name ();
415 _fmode
= O_BINARY
; /* all of files are treated as binary files */
421 * If etags, always find typedefs and structure tags. Why not?
422 * Also default is to find macro constants.
425 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
430 opt
= getopt_long (argc
, argv
, "aCdDf:o:StTi:BuvxwVH", longopts
, 0);
438 /* If getopt returns 0, then it has already processed a
439 long-named option. We should do nothing. */
442 /* Common options. */
455 case 'f': /* for compatibility with old makefiles */
460 "%s: -%c flag may only be given once.\n", progname
, opt
);
479 typedefs_and_cplusplus
++;
486 included_files
[nincluded_files
++] = optarg
;
512 "%s: -%c flag not recognised.\n", progname
, opt
);
517 if (optind
== argc
&& nincluded_files
== 0)
519 fprintf (stderr
, "%s: No input files specified.\n", progname
);
522 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
529 tagfile
= CTAGS
? "tags" : "TAGS";
531 cwd
= etags_getcwd (); /* the current working directory */
533 if (streq (tagfile
, "-"))
539 tagfiledir
= absolute_dirname (tagfile
, cwd
);
542 init (); /* set up boolean "functions" */
545 initbuffer (&lbs
[0].lb
);
546 initbuffer (&lbs
[1].lb
);
547 initbuffer (&filename_lb
);
549 * loop through files finding functions
553 if (streq (tagfile
, "-"))
556 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
567 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
571 error ("Can't find file %s\n", this_file
);
576 this_file
= massage_name (this_file
);
579 } /* solely to balance out the ifdef'd parens above */
582 for (; optind
< argc
; optind
++)
584 this_file
= argv
[optind
];
586 /* Input file named "-" means read file names from stdin and use them. */
587 if (streq (this_file
, "-"))
589 while (!feof (stdin
))
591 (void) readline (&filename_lb
, stdin
);
592 if (strlen (filename_lb
.buffer
) > 0)
593 process_file (filename_lb
.buffer
);
597 process_file (this_file
);
602 while (nincluded_files
-- > 0)
603 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
605 (void) fclose (tagf
);
616 /* update cannot be set under VMS, so we may assume that argc
617 and argv have not been munged. */
618 for (i
= optind
; i
< argc
; i
++)
621 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
622 tagfile
, argv
[i
], tagfile
);
627 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
634 (void) fclose (tagf
);
637 sprintf (cmd
, "sort %s -o %s", tagfile
, tagfile
);
645 * This routine is called on each file argument.
651 struct stat stat_buf
;
653 if (stat (file
, &stat_buf
) == 0 && !S_ISREG (stat_buf
.st_mode
))
655 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
658 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
660 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
663 if (!find_entries (file
))
673 /* file is an absolute filename. Canonicalise it. */
674 filename
= absolute_filename (file
, cwd
);
678 /* file is a filename relative to cwd. Make it relative
679 to the directory of the tags file. */
680 filename
= relative_filename (file
, tagfiledir
);
682 fprintf (tagf
, "\f\n%s,%d\n", filename
, total_size_of_entries (head
));
690 * This routine sets up the boolean pseudo-functions which work
691 * by setting boolean flags dependent upon the corresponding character
692 * Every char which is NOT in that string is not a white char. Therefore,
693 * all of the array "_wht" is set to FALSE, and then the elements
694 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
695 * of a char is TRUE if it is the string "white", else FALSE.
703 for (i
= 0; i
< 0177; i
++)
704 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
705 for (sp
= white
; *sp
; sp
++)
707 for (sp
= endtk
; *sp
; sp
++)
709 for (sp
= intk
; *sp
; sp
++)
711 for (sp
= begtk
; *sp
; sp
++)
713 _wht
[0] = _wht
['\n'];
714 _etk
[0] = _etk
['\n'];
715 _btk
[0] = _btk
['\n'];
716 _itk
[0] = _itk
['\n'];
720 * This routine opens the specified file and calls the function
721 * which finds the function and type definitions.
730 inf
= fopen (file
, "r");
736 curfile
= savestr (file
);
737 cp
= etags_strrchr (file
, '.');
740 header_file
= (cp
&& (streq (cp1
, "h")));
742 /* .tex, .aux or .bbl implies LaTeX source code */
743 if (cp
&& (streq (cp1
, "tex") || streq (cp1
, "aux")
744 || streq (cp1
, "bbl")))
747 goto close_and_return
;
749 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
750 if (cp
&& (streq (cp1
, "l")
752 || streq (cp1
, "lsp")
753 || streq (cp1
, "lisp")
755 || streq (cp1
, "clisp")))
757 Lisp_functions (inf
);
758 goto close_and_return
;
760 /* .scm or .sm or .scheme or ... implies scheme source code */
761 if (cp
&& (streq (cp1
, "sm")
762 || streq (cp1
, "scm")
763 || streq (cp1
, "scheme")
765 || streq (cp1
, "sch")
768 || streq (cp1
, "SCM")
769 /* The `SCM' or `scm' prefix with a version number */
770 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
771 && string_numeric_p (cp1
))
772 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
773 && string_numeric_p (cp1
))))
775 Scheme_functions (inf
);
776 goto close_and_return
;
779 if (cp
&& (streq (cp1
, "s")
780 || streq (cp1
, "a") /* Unix assembler */
781 || streq (cp1
, "sa") /* Unix assembler */
782 || streq (cp1
, "asm") /* Microcontroller assembly */
783 || streq (cp1
, "src") /* BSO/Tasking C compiler output */
784 || streq (cp1
, "def") /* BSO/Tasking definition includes */
785 || streq (cp1
, "ins") /* Microcontroller include files */
786 || streq (cp1
, "inc")))/* Microcontroller include files */
789 goto close_and_return
;
791 /* .C or .H or .cxx or .hxx or .cc or .cpp: a C++ file */
792 if (cp
&& (streq (cp1
, "C")
794 || streq (cp1
, "cpp")
795 || streq (cp1
, "cxx")
796 || streq (cp1
, "hxx")
797 || streq (cp1
, "cc")))
799 C_entries (C_PLPL
, inf
); /* C++ */
800 goto close_and_return
;
802 /* .cs or .hs: a C* file */
803 if (cp
&& (streq (cp1
, "cs")
804 || streq (cp1
, "hs")))
806 C_entries (C_STAR
, inf
);
807 goto close_and_return
;
809 /* .y: a yacc file */
810 if (cp
&& (streq (cp1
, "y")))
812 C_entries (YACC
, inf
);
813 goto close_and_return
;
815 /* .pl implies prolog source code */
816 if (cp
&& streq (cp1
, "pl"))
818 Prolog_functions (inf
);
819 goto close_and_return
;
821 /* .p or .pas: a Pascal file */
822 if (cp
&& (streq (cp1
, "p")
823 || streq (cp1
, "pas")))
825 Pascal_functions (inf
);
826 goto close_and_return
;
828 /* If .f or .for, assume it is fortran or nothing. */
829 if (cp
&& (streq (cp1
, "f")
830 || streq (cp1
, "for")))
832 (void) Fortran_functions (inf
);
833 goto close_and_return
;
835 /* if not a .c or .h or .y file, try fortran */
836 if (cp
&& ((cp
[1] != 'c'
839 || (cp
[1] != 0 && cp
[2] != 0)))
841 if (Fortran_functions (inf
) != 0)
842 goto close_and_return
;
843 rewind (inf
); /* no fortran tags found, try C */
845 C_entries (cplusplus
? C_PLPL
: 0, inf
);
852 /* Nonzero if string STR is composed of digits. */
855 string_numeric_p (str
)
860 if (*str
< '0' || *str
> '9')
867 /* Should take a TOKEN* instead!! */
869 pfnote (name
, is_func
, named
, linestart
, linelen
, lno
, cno
)
870 char *name
; /* tag name */
871 logical is_func
; /* function or type name? */
872 logical named
; /* tag different from text of definition? */
888 /* It's okay to output early in etags -- it only disrupts the
889 * character count of the tag entries, which is no longer used
892 error ("too many entries to sort", 0);
899 /* If ctags mode, change name "main" to M<thisfilename>. */
900 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
902 fp
= etags_strrchr (curfile
, '/');
903 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
904 fp
= etags_strrchr (name
, '.');
905 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
909 np
->name
= savestr (name
);
911 np
->is_func
= is_func
;
914 /* UNCOMMENT THE +1 HERE: */
915 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
916 np
->left
= np
->right
= 0;
919 c
= linestart
[linelen
];
920 linestart
[linelen
] = 0;
922 else if (cxref_style
== 0)
924 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
927 np
->pat
= savestr (linestart
);
930 linestart
[linelen
] = c
;
933 add_node (np
, &head
);
938 * recurse on left children, iterate on right children.
946 register NODE
*node_right
= node
->right
;
947 free_tree (node
->left
);
950 free ((char *) node
);
957 * Adds a node to the tree of nodes. In etags mode, we don't keep
958 * it sorted; we just keep a linear list. In ctags mode, maintain
959 * an ordered tree, with no attempt at balancing.
961 * add_node is the only function allowed to add nodes, so it can
964 /* Must avoid static vars within functions since some systems
965 #define static as nothing. */
966 NODE
*last_node
= NULL
;
969 add_node (node
, cur_node_p
)
970 NODE
*node
, **cur_node_p
;
973 register NODE
*cur_node
= *cur_node_p
;
975 if (cur_node
== NULL
)
985 if (last_node
== NULL
)
986 fatal ("internal error in add_node", 0);
987 last_node
->right
= node
;
993 dif
= strcmp (node
->name
, cur_node
->name
);
996 * If this tag name matches an existing one, then
997 * do not add the node, but maybe print a warning.
1001 if (node
->file
== cur_node
->file
)
1005 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1006 node
->file
, lineno
, node
->name
);
1007 fprintf (stderr
, "Second entry ignored\n");
1011 if (!cur_node
->been_warned
&& !no_warnings
)
1014 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1015 node
->file
, cur_node
->file
, node
->name
);
1017 cur_node
->been_warned
= TRUE
;
1021 /* Maybe refuse to add duplicate nodes. */
1022 if (!permit_duplicates
)
1024 if (streq (node
->name
, cur_node
->name
)
1025 && streq (node
->file
, cur_node
->file
))
1029 /* Actually add the node */
1030 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1036 register NODE
*node
;
1043 /* Output subentries that precede this one */
1044 put_entries (node
->left
);
1046 /* Output this entry */
1052 fprintf (tagf
, "%s\177%s\001%d,%d\n",
1053 node
->pat
, node
->name
,
1054 node
->lno
, node
->cno
);
1058 fprintf (tagf
, "%s\177%d,%d\n",
1060 node
->lno
, node
->cno
);
1063 else if (!cxref_style
)
1065 fprintf (tagf
, "%s\t%s\t",
1066 node
->name
, node
->file
);
1070 putc (searchar
, tagf
);
1073 for (sp
= node
->pat
; *sp
; sp
++)
1075 if (*sp
== '\\' || *sp
== searchar
)
1079 putc (searchar
, tagf
);
1082 { /* a typedef; text pattern inadequate */
1083 fprintf (tagf
, "%d", node
->lno
);
1087 else if (vgrind_style
)
1088 fprintf (stdout
, "%s %s %d\n",
1089 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1091 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1092 node
->name
, node
->lno
, node
->file
, node
->pat
);
1094 /* Output subentries that follow this one */
1095 put_entries (node
->right
);
1098 /* Length of a number's decimal representation. */
1106 for (; num
; num
/= 10)
1112 * Return total number of characters that put_entries will output for
1113 * the nodes in the subtree of the specified node. Works only if
1114 * we are not ctags, but called only in that case. This count
1115 * is irrelevant with the new tags.el, but is still supplied for
1116 * backward compatibility.
1119 total_size_of_entries (node
)
1120 register NODE
*node
;
1128 for (; node
; node
= node
->right
)
1130 /* Count left subentries. */
1131 total
+= total_size_of_entries (node
->left
);
1133 /* Count this entry */
1134 total
+= strlen (node
->pat
) + 1;
1135 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1137 total
+= 1 + strlen (node
->name
); /* \001name */
1144 * The C symbol tables.
1147 /* Feed stuff between (but not including) %[ and %] lines to:
1148 gperf -c -k1,3 -o -p -r -t
1150 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1152 class, C_PLPL, st_C_struct
1153 domain, C_STAR, st_C_struct
1154 union, 0, st_C_struct
1155 struct, 0, st_C_struct
1157 typedef, 0, st_C_typedef
1158 define, 0, st_C_define
1159 long, 0, st_C_typespec
1160 short, 0, st_C_typespec
1161 int, 0, st_C_typespec
1162 char, 0, st_C_typespec
1163 float, 0, st_C_typespec
1164 double, 0, st_C_typespec
1165 signed, 0, st_C_typespec
1166 unsigned, 0, st_C_typespec
1167 auto, 0, st_C_typespec
1168 void, 0, st_C_typespec
1169 extern, 0, st_C_typespec
1170 static, 0, st_C_typespec
1171 const, 0, st_C_typespec
1172 volatile, 0, st_C_typespec
1174 and replace lines between %< and %> with its output. */
1176 /* C code produced by gperf version 1.8.1 (K&R C version) */
1177 /* Command-line: gperf -c -k1,3 -o -p -r -t */
1180 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
1182 #define MIN_WORD_LENGTH 3
1183 #define MAX_WORD_LENGTH 8
1184 #define MIN_HASH_VALUE 10
1185 #define MAX_HASH_VALUE 62
1188 53 is the maximum key range
1196 static unsigned char hash_table
[] =
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, 62, 62, 62,
1206 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1207 62, 62, 62, 62, 62, 62, 62, 2, 62, 7,
1208 6, 9, 15, 30, 62, 24, 62, 62, 1, 24,
1209 7, 27, 13, 62, 19, 26, 18, 27, 1, 62,
1210 62, 62, 62, 62, 62, 62, 62, 62,
1212 return len
+ hash_table
[str
[2]] + hash_table
[str
[0]];
1215 struct C_stab_entry
*
1216 in_word_set (str
, len
)
1221 static struct C_stab_entry wordlist
[] =
1223 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1225 {"volatile", 0, st_C_typespec
},
1227 {"long", 0, st_C_typespec
},
1228 {"char", 0, st_C_typespec
},
1229 {"class", C_PLPL
, st_C_struct
},
1230 {"",}, {"",}, {"",}, {"",},
1231 {"const", 0, st_C_typespec
},
1232 {"",}, {"",}, {"",}, {"",},
1233 {"auto", 0, st_C_typespec
},
1235 {"define", 0, st_C_define
},
1237 {"void", 0, st_C_typespec
},
1238 {"",}, {"",}, {"",},
1239 {"extern", 0, st_C_typespec
},
1240 {"static", 0, st_C_typespec
},
1242 {"domain", C_STAR
, st_C_struct
},
1244 {"typedef", 0, st_C_typedef
},
1245 {"double", 0, st_C_typespec
},
1246 {"enum", 0, st_C_enum
},
1247 {"",}, {"",}, {"",}, {"",},
1248 {"int", 0, st_C_typespec
},
1250 {"float", 0, st_C_typespec
},
1251 {"",}, {"",}, {"",},
1252 {"struct", 0, st_C_struct
},
1253 {"",}, {"",}, {"",}, {"",},
1254 {"union", 0, st_C_struct
},
1256 {"short", 0, st_C_typespec
},
1258 {"unsigned", 0, st_C_typespec
},
1259 {"signed", 0, st_C_typespec
},
1262 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
1264 register int key
= hash (str
, len
);
1266 if (key
<= MAX_HASH_VALUE
&& key
>= MIN_HASH_VALUE
)
1268 register char *s
= wordlist
[key
].name
;
1270 if (*s
== *str
&& strneq (str
+ 1, s
+ 1, len
- 1))
1271 return &wordlist
[key
];
1279 C_symtype(str
, len
, c_ext
)
1284 register struct C_stab_entry
*se
= in_word_set(str
, len
);
1286 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
1292 * C functions are recognized using a simple finite automaton.
1293 * funcdef is its state variable.
1297 fnone
, /* nothing seen */
1298 ftagseen
, /* function-like tag seen */
1299 fstartlist
, /* just after open parenthesis */
1300 finlist
, /* in parameter list */
1301 flistseen
, /* after parameter list */
1302 fignore
/* before open brace */
1308 * typedefs are recognized using a simple finite automaton.
1309 * typeddef is its state variable.
1313 tnone
, /* nothing seen */
1314 ttypedseen
, /* typedef keyword seen */
1315 tinbody
, /* inside typedef body */
1316 tend
, /* just before typedef tag */
1317 tignore
/* junk after typedef tag */
1323 * struct-like structures (enum, struct and union) are recognized
1324 * using another simple finite automaton. `structdef' is its state
1329 snone
, /* nothing seen yet */
1330 skeyseen
, /* struct-like keyword seen */
1331 stagseen
, /* struct-like tag seen */
1332 scolonseen
, /* colon seen after struct-like tag */
1333 sinbody
/* in struct body: recognize member func defs*/
1338 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1339 * struct tag, and structtype is the type of the preceding struct-like
1342 char structtag
[BUFSIZ
];
1343 enum sym_type structtype
;
1346 * Yet another little state machine to deal with preprocessor lines.
1350 dnone
, /* nothing seen */
1351 dsharpseen
, /* '#' seen as first char on line */
1352 ddefineseen
, /* '#' and 'define' seen */
1353 dignorerest
/* ignore rest of line */
1358 * Set this to TRUE, and the next token considered is called a function.
1359 * Used only for GNUmacs's function-defining macros.
1361 logical next_token_is_func
;
1364 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1370 * checks to see if the current token is at the start of a
1371 * function, or corresponds to a typedef, or is a struct/union/enum
1374 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1375 * C_EXT is which language we are looking at.
1377 * In the future we will need some way to adjust where the end of
1378 * the token is; for instance, implementing the C++ keyword
1379 * `operator' properly will adjust the end of the token to be after
1380 * whatever follows `operator'.
1387 * next_token_is_func IN OUT
1391 consider_token (c
, tokp
, c_ext
, cblev
, is_func
)
1392 register char c
; /* IN: first char after the token */
1393 register TOKEN
*tokp
; /* IN: token pointer */
1394 int c_ext
; /* IN: C extensions mask */
1395 int cblev
; /* IN: curly brace level */
1396 logical
*is_func
; /* OUT */
1398 enum sym_type toktype
= C_symtype(tokp
->p
, tokp
->len
, c_ext
);
1401 * Advance the definedef state machine.
1406 /* We're not on a preprocessor line. */
1409 if (toktype
== st_C_define
)
1411 definedef
= ddefineseen
;
1415 definedef
= dignorerest
;
1420 * Make a tag for any macro, unless it is a constant
1421 * and constantypedefs is FALSE.
1423 definedef
= dignorerest
;
1424 *is_func
= (c
== '(');
1425 if (!*is_func
&& !constantypedefs
)
1432 error ("internal error: definedef value.", 0);
1441 if (toktype
== st_C_typedef
)
1444 typdef
= ttypedseen
;
1460 /* Do not return here, so the structdef stuff has a chance. */
1474 * This structdef business is currently only invoked when cblev==0.
1475 * It should be recursively invoked whatever the curly brace level,
1476 * and a stack of states kept, to allow for definitions of structs
1479 * This structdef business is NOT invoked when we are ctags and the
1480 * file is plain C. This is because a struct tag may have the same
1481 * name as another tag, and this loses with ctags.
1483 * This if statement deals with the typdef state machine as
1484 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1485 * return (FALSE). All the other code here is for the structdef
1492 if (typdef
== ttypedseen
1493 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1495 structdef
= skeyseen
;
1496 structtype
= toktype
;
1500 if (structdef
== skeyseen
)
1502 if (structtype
== st_C_struct
)
1504 strncpy (structtag
, tokp
->p
, tokp
->len
);
1505 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1509 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1511 structdef
= stagseen
;
1515 /* Avoid entering funcdef stuff if typdef is going on. */
1516 if (typdef
!= tnone
)
1522 /* Detect GNUmacs's function-defining macros. */
1523 if (definedef
== dnone
)
1525 if (strneq (tokp
->p
, "DEF", 3)
1526 || strneq (tokp
->p
, "ENTRY", 5)
1527 || strneq (tokp
->p
, "SYSCALL", 7)
1528 || strneq (tokp
->p
, "PSEUDO", 6))
1530 next_token_is_func
= TRUE
;
1533 if (strneq (tokp
->p
, "EXFUN", 5))
1535 next_token_is_func
= FALSE
;
1539 if (next_token_is_func
)
1541 next_token_is_func
= FALSE
;
1543 *is_func
= TRUE
; /* to force search string in ctags */
1551 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1552 funcdef
= fnone
; /* should be useless */
1555 if (funcdef
== fnone
)
1568 * This routine finds functions, typedefs, #define's and
1569 * struct/union/enum definitions in C syntax and adds them
1573 #define curlb (lbs[curndx].lb)
1574 #define othlb (lbs[1-curndx].lb)
1575 #define newlb (lbs[newndx].lb)
1576 #define curlinepos (lbs[curndx].linepos)
1577 #define othlinepos (lbs[1-curndx].linepos)
1578 #define newlinepos (lbs[newndx].linepos)
1580 /* Save and restore token state. This is used when preprocessor defines
1581 are handled, to avoid disturbing active function/typedef/struct states. */
1582 #define TOKEN_SAVED_P (savetok.lineno > 0)
1583 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1584 savetok.len = toklen, strcpy(savenameb, nameb))
1585 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1586 toklen = tok.len, strcpy(nameb, savenameb), \
1589 #define CNL_SAVE_DEFINEDEF \
1591 SET_FILEPOS (curlinepos, inf, charno); \
1593 charno += readline (&curlb, inf); \
1594 lp = curlb.buffer; \
1601 CNL_SAVE_DEFINEDEF; \
1602 if (TOKEN_SAVED_P) \
1604 definedef = dnone; \
1607 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1608 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1609 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1610 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1613 C_entries (c_ext
, inf
)
1614 int c_ext
; /* extension of C? */
1617 register char c
; /* latest char read; '\0' for end of line */
1618 register char *lp
; /* pointer one beyond the character `c' */
1619 int curndx
, newndx
; /* indices for current and new lb */
1620 TOKEN tok
; /* latest token read for funcdef & structdef */
1621 char nameb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1622 register int tokoff
; /* offset in line of start of latest token */
1623 register int toklen
; /* length of latest token */
1624 int cblev
; /* current curly brace level */
1625 int parlev
; /* current parenthesis level */
1626 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1628 TOKEN savetok
; /* saved token during preprocessor handling */
1629 char savenameb
[BUFSIZ
]; /* ouch! */
1632 curndx
= newndx
= 0;
1638 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1639 next_token_is_func
= yacc_rules
= FALSE
;
1640 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1643 cplpl
= c_ext
& C_PLPL
;
1650 /* If we're at the end of the line, the next character is a
1651 '\0'; don't skip it, because it's the thing that tells us
1652 to read the next line. */
1673 /* Newlines inside comments do not end macro definitions in
1688 /* Newlines inside strings do not end macro definitions
1689 in traditional cpp, even though compilers don't
1690 usually accept them. */
1701 /* Hmmm, something went wrong. */
1715 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1720 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1730 else if (cplpl
&& *lp
== '/')
1738 if ((c_ext
& YACC
) && *lp
== '%')
1740 /* entering or exiting rules section in yacc file */
1742 definedef
= dnone
; funcdef
= fnone
;
1743 typdef
= tnone
; structdef
= snone
;
1744 next_token_is_func
= FALSE
;
1745 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1747 yacc_rules
= !yacc_rules
;
1753 if (definedef
== dnone
)
1756 logical cpptoken
= TRUE
;
1758 /* Look back on this line. If all blanks, or nonblanks
1759 followed by an end of comment, this is a preprocessor
1761 for (cp
= newlb
.buffer
; cp
< lp
-1; cp
++)
1764 if (*cp
== '*' && *(cp
+1) == '/')
1773 definedef
= dsharpseen
;
1774 } /* if (definedef == dnone) */
1780 /* Consider token only if some complicated conditions are satisfied. */
1781 if ((definedef
!= dnone
1782 || (cblev
== 0 && structdef
!= scolonseen
)
1783 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
1784 && typdef
!= tignore
1785 && definedef
!= dignorerest
1786 && funcdef
!= finlist
)
1792 if (cplpl
&& c
== ':' && *lp
== ':' && begtoken(*(lp
+ 1)))
1795 * This handles :: in the middle, but not at the
1796 * beginning of an identifier.
1803 logical is_func
= FALSE
;
1805 tok
.lineno
= lineno
;
1806 tok
.p
= newlb
.buffer
+ tokoff
;
1810 || consider_token (c
, &tok
, c_ext
, cblev
, &is_func
))
1812 if (structdef
== sinbody
1813 && definedef
== dnone
1815 /* function defined in C++ class body */
1817 sprintf (nameb
, "%s::%.*s",
1818 ((structtag
[0] == '\0')
1819 ? "_anonymous_" : structtag
),
1825 sprintf (nameb
, "%.*s", tok
.len
, tok
.p
);
1828 if (structdef
== stagseen
1830 || (definedef
== dignorerest
&& is_func
))
1833 if (definedef
== dnone
1834 && (funcdef
== ftagseen
1835 || structdef
== stagseen
1838 if (newndx
== curndx
)
1839 curndx
= 1 - curndx
; /* switch line buffers */
1842 MAKE_TAG_FROM_NEW_LB (is_func
);
1846 } /* if (endtoken (c)) */
1847 else if (intoken (c
))
1852 } /* if (midtoken) */
1853 else if (begtoken (c
))
1864 MAKE_TAG_FROM_OTH_LB (TRUE
);
1871 if (structdef
== stagseen
)
1875 /* Take a quick peek ahead for a define directive,
1876 so we can avoid saving the token when not absolutely
1877 necessary. [This is a speed hack.] */
1878 if (c
== 'd' && strneq(lp
, "efine", 5)
1879 && iswhite(*(lp
+ 5)))
1882 definedef
= ddefineseen
;
1886 definedef
= dignorerest
;
1889 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1891 tokoff
= lp
- 1 - newlb
.buffer
;
1897 } /* if must look at token */
1900 /* Detect end of line, colon, comma, semicolon and various braces
1901 after having handled a token.*/
1905 if (definedef
!= dnone
)
1907 if (structdef
== stagseen
)
1908 structdef
= scolonseen
;
1915 MAKE_TAG_FROM_OTH_LB (FALSE
);
1925 if (definedef
!= dnone
)
1931 MAKE_TAG_FROM_OTH_LB (FALSE
);
1936 if (funcdef
!= fignore
)
1938 if (structdef
== stagseen
)
1942 if (definedef
!= dnone
)
1944 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1946 if (structdef
== stagseen
)
1950 if (definedef
!= dnone
)
1952 if (cblev
== 0 && typdef
== tend
)
1955 MAKE_TAG_FROM_OTH_LB (FALSE
);
1958 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1960 if (structdef
== stagseen
)
1964 if (definedef
!= dnone
)
1973 /* Make sure that the next char is not a '*'.
1974 This handles constructs like:
1975 typedef void OperatorFun (int fun); */
1979 MAKE_TAG_FROM_OTH_LB (FALSE
);
1982 } /* switch (typdef) */
1985 funcdef
= fstartlist
;
1994 if (definedef
!= dnone
)
2002 funcdef
= flistseen
;
2005 if (cblev
== 0 && typdef
== tend
)
2008 MAKE_TAG_FROM_OTH_LB (FALSE
);
2011 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
2015 if (definedef
!= dnone
)
2017 if (typdef
== ttypedseen
)
2021 case skeyseen
: /* unnamed struct */
2022 structtag
[0] = '\0';
2023 structdef
= sinbody
;
2026 case scolonseen
: /* named struct */
2027 structdef
= sinbody
;
2028 MAKE_TAG_FROM_OTH_LB (FALSE
);
2034 MAKE_TAG_FROM_OTH_LB (TRUE
);
2040 /* Neutralize `extern "C" {' grot.
2041 if (cblev == 0 && structdef == snone && typdef == tnone)
2047 if (definedef
!= dnone
)
2049 if (funcdef
== fstartlist
)
2050 funcdef
= fnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
2053 if (definedef
!= dnone
)
2055 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
2057 cblev
= 0; /* reset curly brace level if first column */
2058 parlev
= 0; /* also reset paren level, just in case... */
2064 if (typdef
== tinbody
)
2067 strcpy (structtag
, "<error 2>");
2071 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
2072 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
2073 if (definedef
!= dnone
)
2075 /* These surely cannot follow a function tag. */
2076 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2080 /* If a macro spans multiple lines don't reset its state. */
2088 } /* while not eof */
2091 /* Fortran parsing */
2100 register int len
= 0;
2102 while (*cp
&& (*cp
| ' ') == (dbp
[len
] | ' '))
2115 while (isspace (*dbp
))
2120 while (isspace (*dbp
))
2124 if (!isdigit (*dbp
))
2126 --dbp
; /* force failure */
2131 while (isdigit (*dbp
));
2140 char nambuf
[BUFSIZ
];
2142 while (isspace (*dbp
))
2147 linecharno
= charno
;
2148 charno
+= readline (&lb
, inf
);
2153 while (isspace (*dbp
))
2162 && (isalpha (*cp
) || isdigit (*cp
) || (*cp
== '_') || (*cp
== '$')));
2167 strcpy (nambuf
, dbp
);
2169 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2170 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2175 Fortran_functions (inf
)
2185 linecharno
= charno
;
2186 charno
+= readline (&lb
, inf
);
2189 dbp
++; /* Ratfor escape to fortran */
2190 while (isspace (*dbp
))
2197 if (tail ("integer"))
2205 if (tail ("logical"))
2209 if (tail ("complex") || tail ("character"))
2213 if (tail ("double"))
2215 while (isspace (*dbp
))
2219 if (tail ("precision"))
2225 while (isspace (*dbp
))
2232 if (tail ("function"))
2236 if (tail ("subroutine"))
2244 if (tail ("program"))
2249 if (tail ("procedure"))
2258 * Bob Weiner, Motorola Inc., 4/3/94
2259 * Unix and microcontroller assembly tag handling
2260 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
2266 char nambuf
[BUFSIZ
];
2277 linecharno
= charno
;
2278 charno
+= readline (&lb
, inf
);
2281 /* If first char is alphabetic or one of [_.$], test for colon
2282 following identifier. */
2283 if (isalpha (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2285 /* Read past label. */
2287 while (isalnum (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2289 if (*cp
== ':' || isspace (*cp
))
2291 /* Found end of label, so copy it and add it to the table. */
2294 strcpy (nambuf
, lb
.buffer
);
2296 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2297 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2304 /* Added by Mosur Mohan, 4/22/88 */
2305 /* Pascal parsing */
2307 #define GET_NEW_LINE \
2309 linecharno = charno; lineno++; \
2310 charno += 1 + readline (&lb, inf); \
2314 /* Locates tags for procedures & functions.
2315 * Doesn't do any type- or var-definitions.
2316 * It does look for the keyword "extern" or "forward"
2317 * immediately following the procedure statement;
2318 * if found, the tag is skipped.
2322 Pascal_functions (inf
)
2325 struct linebuffer tline
; /* mostly copied from C_entries */
2329 char nambuf
[BUFSIZ
];
2331 logical
/* each of these flags is TRUE iff: */
2332 incomm1
, /* point is inside {..} comment */
2333 incomm2
, /* point is inside (*..*) comment */
2334 inquote
, /* point is inside '..' string */
2335 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2336 /* keyword, so next item = potential tag */
2337 found_tag
, /* point is after a potential tag */
2338 inparms
, /* point is within parameter-list */
2339 verify_tag
; /* point has passed the parm-list, so the */
2340 /* next token will determine whether */
2341 /* this is a FORWARD/EXTERN to be */
2342 /* ignored, or whether it is a real tag */
2348 initbuffer (&tline
);
2350 incomm1
= incomm2
= inquote
= FALSE
;
2351 found_tag
= FALSE
; /* have a proc name; check if extern */
2352 get_tagname
= FALSE
; /* have found "procedure" keyword */
2353 inparms
= FALSE
; /* found '(' after "proc" */
2354 verify_tag
= FALSE
; /* check if "extern" is ahead */
2356 /* long main loop to get next char */
2360 if (c
== 0) /* if end of line */
2365 if (!((found_tag
&& verify_tag
) ||
2367 c
= *dbp
++; /* only if don't need *dbp pointing */
2368 /* to the beginning of the name of */
2369 /* the procedure or function */
2371 if (incomm1
) /* within { - } comments */
2377 else if (incomm2
) /* within (* - *) comments */
2381 while ((c
= *dbp
++) == '*')
2400 inquote
= TRUE
; /* found first quote */
2402 case '{': /* found open-{-comment */
2406 if (*dbp
== '*') /* found open-(*-comment */
2411 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2414 case ')': /* end of parms list */
2419 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2426 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2428 /* check if this is an "extern" declaration */
2431 if ((*dbp
== 'e') || (*dbp
== 'E'))
2433 if (tail ("extern")) /* superfluous, really! */
2439 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2441 if (tail ("forward")) /* check for forward reference */
2447 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2451 pfnote (nambuf
, TRUE
, FALSE
,
2452 tline
.buffer
, cp
- tline
.buffer
+ 1,
2453 save_lineno
, save_lcno
);
2457 if (get_tagname
) /* grab name of proc or fn */
2462 /* save all values for later tagging */
2463 tline
.size
= lb
.size
;
2464 strcpy (tline
.buffer
, lb
.buffer
);
2465 save_lineno
= lineno
;
2466 save_lcno
= linecharno
;
2468 /* grab block name */
2469 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2473 strcpy (nambuf
, dbp
);
2475 dbp
= cp
; /* restore dbp to e-o-token */
2476 get_tagname
= FALSE
;
2480 /* and proceed to check for "extern" */
2482 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2483 (!found_tag
) && (!get_tagname
))
2485 /* check for proc/fn keywords */
2489 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2493 if (tail ("unction"))
2498 } /* while not eof */
2502 * lisp tag functions
2503 * just look for (def or (DEF
2510 return ((dbp
[1] == 'd' || dbp
[1] == 'D')
2511 && (dbp
[2] == 'e' || dbp
[2] == 'E')
2512 && (dbp
[3] == 'f' || dbp
[3] == 'F'));
2519 return ((*(++dbp
) == 'q' || *dbp
== 'Q')
2520 && (*(++dbp
) == 'u' || *dbp
== 'U')
2521 && (*(++dbp
) == 'o' || *dbp
== 'O')
2522 && (*(++dbp
) == 't' || *dbp
== 'T')
2523 && (*(++dbp
) == 'e' || *dbp
== 'E')
2524 && isspace(*(++dbp
)));
2532 char nambuf
[BUFSIZ
];
2534 if (*dbp
== '\'') /* Skip prefix quote */
2536 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2539 while (isspace(*dbp
))
2542 for (cp
= dbp
/*+1*/; *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')'; cp
++)
2549 strcpy (nambuf
, dbp
);
2551 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2552 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2557 Lisp_functions (inf
)
2567 linecharno
= charno
;
2568 charno
+= readline (&lb
, inf
);
2574 while (!isspace (*dbp
))
2576 while (isspace (*dbp
))
2582 /* Check for (foo::defmumble name-defined ... */
2585 while (*dbp
&& !isspace (*dbp
)
2586 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2591 while (*dbp
== ':');
2593 if (L_isdef (dbp
- 1))
2595 while (!isspace (*dbp
))
2597 while (isspace (*dbp
))
2608 * Scheme tag functions
2609 * look for (def... xyzzy
2610 * look for (def... (xyzzy
2611 * look for (def ... ((...(xyzzy ....
2612 * look for (set! xyzzy
2618 Scheme_functions (inf
)
2628 linecharno
= charno
;
2629 charno
+= readline (&lb
, inf
);
2631 if (dbp
[0] == '(' &&
2632 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2633 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2634 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2636 while (!isspace (*dbp
))
2638 /* Skip over open parens and white space */
2639 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2643 if (dbp
[0] == '(' &&
2644 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2645 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2646 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2647 (dbp
[4] == '!' || dbp
[4] == '!') &&
2650 while (!isspace (*dbp
))
2652 /* Skip over white space */
2653 while (isspace (*dbp
))
2665 char nambuf
[BUFSIZ
];
2669 /* Go till you get to white space or a syntactic break */
2670 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2672 /* Null terminate the string there. */
2675 /* Copy the string */
2676 strcpy (nambuf
, dbp
);
2677 /* Unterminate the string */
2679 /* Announce the change */
2680 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2684 /* Find tags in TeX and LaTeX input files. */
2686 /* TEX_toktab is a table of TeX control sequences that define tags.
2687 Each TEX_tabent records one such control sequence.
2688 CONVERT THIS TO USE THE Stab TYPE!! */
2696 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2698 /* Default set of control sequences to put into TEX_toktab.
2699 The value of environment var TEXTAGS is prepended to this. */
2701 char *TEX_defenv
= "\
2702 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2705 struct TEX_tabent
*TEX_decode_env ();
2709 char TEX_esc
= '\\';
2710 char TEX_opgrp
= '{';
2711 char TEX_clgrp
= '}';
2714 * TeX/LaTeX scanning loop.
2727 /* Select either \ or ! as escape character. */
2730 /* Initialize token table once from environment. */
2732 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2735 { /* Scan each line in file */
2737 linecharno
= charno
;
2738 charno
+= readline (&lb
, inf
);
2741 while (dbp
= etags_strchr (dbp
, TEX_esc
)) /* Look at each esc in line */
2747 linecharno
+= dbp
- lasthit
;
2749 i
= TEX_Token (lasthit
);
2752 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2753 break; /* We only save a line once */
2759 #define TEX_LESC '\\'
2760 #define TEX_SESC '!'
2763 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2764 /* chars accordingly. */
2772 while ((c
= getc (inf
)) != EOF
)
2774 /* Skip to next line if we hit the TeX comment char. */
2778 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2797 /* Read environment and prepend it to the default string. */
2798 /* Build token table. */
2801 TEX_decode_env (evarname
, defenv
)
2805 register char *env
, *p
;
2807 struct TEX_tabent
*tab
;
2810 /* Append default string to environment. */
2811 env
= getenv (evarname
);
2815 env
= concat (env
, defenv
, "");
2817 /* Allocate a token table */
2818 for (size
= 1, p
= env
; p
;)
2819 if ((p
= etags_strchr (p
, ':')) && *(++p
))
2821 /* Add 1 to leave room for null terminator. */
2822 tab
= xnew (size
+ 1, struct TEX_tabent
);
2824 /* Unpack environment string into token table. Be careful about */
2825 /* zero-length strings (leading ':', "::" and trailing ':') */
2828 p
= etags_strchr (env
, ':');
2829 if (!p
) /* End of environment string. */
2830 p
= env
+ strlen (env
);
2832 { /* Only non-zero strings. */
2833 tab
[i
].name
= savenstr (env
, p
- env
);
2834 tab
[i
].len
= strlen (tab
[i
].name
);
2841 tab
[i
].name
= NULL
; /* Mark end of table. */
2849 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2850 The name being defined actually starts at (NAME + LEN + 1).
2851 But we seem to include the TeX command in the tag name. */
2854 TEX_getit (name
, len
)
2858 char *p
= name
+ len
;
2859 char nambuf
[BUFSIZ
];
2864 /* Let tag name extend to next group close (or end of line) */
2865 while (*p
&& *p
!= TEX_clgrp
)
2867 strncpy (nambuf
, name
, p
- name
);
2868 nambuf
[p
- name
] = 0;
2870 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2874 /* If the text at CP matches one of the tag-defining TeX command names,
2875 return the pointer to the first occurrence of that command in TEX_toktab.
2876 Otherwise return -1. */
2878 /* Keep the capital `T' in `Token' for dumb truncating compilers
2879 (this distinguishes it from `TEX_toktab' */
2886 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2887 if (strneq (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
))
2892 /* Support for Prolog. */
2894 /* whole head (not only functor, but also arguments)
2895 is gotten in compound term. */
2898 prolog_getit (s
, lineno
, linecharno
)
2903 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2911 if (*s
== '\0') /* syntax error. */
2913 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2915 else if (*s
== '\'')
2917 insquote
= !insquote
;
2920 else if (!insquote
&& *s
== '(')
2925 else if (!insquote
&& *s
== ')')
2931 else if (npar
< 0) /* syntax error. */
2934 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2936 if (npar
!= 0) /* syntax error. */
2946 strcpy (nambuf
, save_s
);
2948 pfnote (nambuf
, TRUE
, FALSE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2951 /* It is assumed that prolog predicate starts from column 0. */
2954 Prolog_functions (inf
)
2957 void skip_comment (), prolog_getit ();
2959 lineno
= linecharno
= charno
= 0;
2963 linecharno
+= charno
;
2964 charno
= readline (&lb
, inf
) + 1; /* 1 for newline. */
2966 if (isspace (dbp
[0])) /* not predicate header. */
2968 else if (dbp
[0] == '%') /* comment. */
2970 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2971 skip_comment (&lb
, inf
, &lineno
, &linecharno
);
2973 prolog_getit (dbp
, lineno
, linecharno
);
2978 skip_comment (plb
, inf
, plineno
, plinecharno
)
2979 struct linebuffer
*plb
;
2981 int *plineno
; /* result */
2982 long *plinecharno
; /* result */
2984 while (!substr ("*/", plb
->buffer
))
2987 *plinecharno
+= readline (plb
, inf
) + 1;
2988 } /* 1 for newline. */
2991 /* Return TRUE if 'sub' exists somewhere in 's'. */
2998 while (*s
&& (s
= etags_strchr (s
, *sub
)))
2999 if (prestr (sub
, s
))
3006 /* Return TRUE if 'pre' is prefix of string 's'. */
3015 else if (*pre
== *s
)
3016 return (prestr (pre
+ 1, s
+ 1));
3021 /* Initialize a linebuffer for use */
3024 initbuffer (linebuffer
)
3025 struct linebuffer
*linebuffer
;
3027 linebuffer
->size
= 200;
3028 linebuffer
->buffer
= xnew (200, char);
3032 * Read a line of text from `stream' into `linebuffer'.
3033 * Return the number of characters read from `stream',
3034 * which is the length of the line including the newline, if any.
3037 readline (linebuffer
, stream
)
3038 struct linebuffer
*linebuffer
;
3039 register FILE *stream
;
3041 char *buffer
= linebuffer
->buffer
;
3042 register char *p
= linebuffer
->buffer
;
3043 register char *pend
;
3044 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
3046 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
3050 register int c
= getc (stream
);
3053 linebuffer
->size
*= 2;
3054 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
3055 p
+= buffer
- linebuffer
->buffer
;
3056 pend
= buffer
+ linebuffer
->size
;
3057 linebuffer
->buffer
= buffer
;
3059 if (c
== EOF
|| c
== '\n')
3062 newline
= (c
== '\n') ? 1 : 0;
3068 return p
- buffer
+ newline
;
3075 return savenstr (cp
, strlen (cp
));
3085 dp
= xnew (len
+ 1, char);
3086 strncpy (dp
, cp
, len
);
3092 * Return the ptr in sp at which the character c last
3093 * appears; NULL if not found
3095 * Identical to System V strrchr, included for portability.
3099 etags_strrchr (sp
, c
)
3100 register char *sp
, c
;
3115 * Return the ptr in sp at which the character c first
3116 * appears; NULL if not found
3118 * Identical to System V strchr, included for portability.
3122 etags_strchr (sp
, c
)
3123 register char *sp
, c
;
3133 /* Print error message and exit. */
3144 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3151 fprintf (stderr
, "%s: ", progname
);
3152 fprintf (stderr
, s1
, s2
);
3153 fprintf (stderr
, "\n");
3156 /* Return a newly-allocated string whose contents
3157 concatenate those of s1, s2, s3. */
3163 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3164 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3166 strcpy (result
, s1
);
3167 strcpy (result
+ len1
, s2
);
3168 strcpy (result
+ len1
+ len2
, s3
);
3169 result
[len1
+ len2
+ len3
] = '\0';
3178 char *p
, cwd
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
3185 *p
++ = tolower (*p
);
3186 return strdup (cwd
);
3188 #else /* not MSDOS */
3189 /* Does the same work as the system V getcwd, but does not need to
3190 guess buffer size in advance. Included mostly for compatibility. */
3200 buf
= xnew (bufsize
, char);
3203 while (getcwd (buf
, bufsize
/ 2) == NULL
);
3208 buf
= xnew (bufsize
, char);
3210 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
3216 if (fgets (buf
, bufsize
, pipe
) == NULL
)
3225 } while (buf
[strlen (buf
) - 1] != '\n');
3228 buf
[strlen (buf
) - 1] = '\0';
3231 #endif /* not MSDOS */
3233 /* Return a newly allocated string containing the filename
3234 of FILE relative to the absolute directory DIR (which
3235 should end with a slash). */
3238 relative_filename (file
, dir
)
3241 char *fp
, *dp
, *res
;
3243 /* Find the common root of file and dir. */
3244 fp
= absolute_filename (file
, cwd
);
3246 while (*fp
++ == *dp
++)
3255 /* Build a sequence of "../" strings for the resulting relative filename. */
3256 for (dp
= etags_strchr (dp
+ 1, '/'), res
= "";
3258 dp
= etags_strchr (dp
+ 1, '/'))
3260 res
= concat (res
, "../", "");
3263 /* Add the filename relative to the common root of file and dir. */
3264 res
= concat (res
, fp
+ 1, "");
3266 return res
; /* temporary stub */
3269 /* Return a newly allocated string containing the
3270 absolute filename of FILE given CWD (which should
3271 end with a slash). */
3274 absolute_filename (file
, cwd
)
3277 char *slashp
, *cp
, *res
;
3280 res
= concat (file
, "", "");
3282 res
= concat (cwd
, file
, "");
3284 /* Delete the "/dirname/.." and "/." substrings. */
3285 slashp
= etags_strchr (res
, '/');
3286 while (slashp
!= NULL
&& slashp
[0] != '\0')
3288 if (slashp
[1] == '.')
3290 if (slashp
[2] == '.'
3291 && (slashp
[3] == '/' || slashp
[3] == '\0'))
3296 while (cp
>= res
&& *cp
!= '/');
3299 strcpy (cp
, slashp
+ 3);
3301 else /* else (cp == res) */
3303 if (slashp
[3] != '\0')
3304 strcpy (cp
, slashp
+ 4);
3311 else if (slashp
[2] == '/' || slashp
[2] == '\0')
3313 strcpy (slashp
, slashp
+ 2);
3318 slashp
= etags_strchr (slashp
+ 1, '/');
3324 /* Return a newly allocated string containing the absolute
3325 filename of dir where FILE resides given CWD (which should
3326 end with a slash). */
3329 absolute_dirname (file
, cwd
)
3335 slashp
= etags_strrchr (file
, '/');
3340 res
= absolute_filename (file
, cwd
);
3346 /* Like malloc but get fatal error if memory is exhausted. */
3352 char *result
= (char *) malloc (size
);
3354 fatal ("virtual memory exhausted", 0);
3359 xrealloc (ptr
, size
)
3363 char *result
= (char *) realloc (ptr
, size
);
3365 fatal ("virtual memory exhausted");