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.21";
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 *outfiledir
; /* 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 L_isdef (), L_isquote ();
161 int total_size_of_entries ();
162 logical
consider_token ();
170 void Scheme_funcs ();
175 logical
find_entries ();
182 void process_file ();
188 * xnew -- allocate storage
191 * Type *xnew (int n, Type);
193 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
196 * Symbol table types.
200 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
217 #define C_PLPL 0x00001 /* C++ */
218 #define C_STAR 0x00003 /* C* */
219 #define YACC 0x10000 /* yacc file */
221 char searchar
= '/'; /* use /.../ searches */
223 LINENO lineno
; /* line number of current line */
224 long charno
; /* current character number */
226 long linecharno
; /* charno of start of line; not used by C, but
227 * by every other language.
230 char *curfile
, /* current input file name */
231 *outfile
, /* output file */
232 *white
= " \f\t\n", /* white chars */
233 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
234 /* token starting chars */
235 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
236 /* valid in-token chars */
237 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
239 int append_to_tagfile
; /* -a: append to tags */
240 /* The following three default to 1 for etags, but to 0 for ctags. */
241 int typedefs
; /* -t: create tags for typedefs */
242 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
243 /* 0 struct/enum/union decls, and C++ */
244 /* member functions. */
245 int constantypedefs
; /* -d: create tags for C #define and enum */
246 /* constants. Enum consts not implemented. */
247 /* -D: opposite of -d. Default under ctags. */
248 int update
; /* -u: update tags */
249 int vgrind_style
; /* -v: create vgrind style index output */
250 int no_warnings
; /* -w: suppress warnings */
251 int cxref_style
; /* -x: create cxref style output */
252 int cplusplus
; /* .[hc] means C++, not C */
253 int noindentypedefs
; /* -S: ignore indentation in C */
255 /* Name this program was invoked with. */
258 struct option longopts
[] = {
259 { "append", no_argument
, NULL
, 'a' },
260 { "backward-search", no_argument
, NULL
, 'B' },
261 { "c++", no_argument
, NULL
, 'C' },
262 { "cxref", no_argument
, NULL
, 'x' },
263 { "defines", no_argument
, NULL
, 'd' },
264 { "forward-search", no_argument
, NULL
, 'F' },
265 { "help", no_argument
, NULL
, 'H' },
266 { "ignore-indentation", no_argument
, NULL
, 'S' },
267 { "include", required_argument
, NULL
, 'i' },
268 { "no-defines", no_argument
, NULL
, 'D' },
269 { "no-warn", no_argument
, NULL
, 'w' },
270 { "output", required_argument
, NULL
, 'o' },
271 { "typedefs", no_argument
, NULL
, 't' },
272 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
273 { "update", no_argument
, NULL
, 'u' },
274 { "version", no_argument
, NULL
, 'V' },
275 { "vgrind", no_argument
, NULL
, 'v' },
279 FILE *inf
, /* ioptr for current input file */
280 *outf
; /* ioptr for tags file */
282 NODE
*head
; /* the head of the binary tree of tags */
284 int permit_duplicates
= 1; /* Nonzero means allow duplicate tags. */
286 /* A `struct linebuffer' is a structure which holds a line of text.
287 `readline' reads a line from a stream into a linebuffer
288 and works regardless of the length of the line. */
296 struct linebuffer lb
; /* the current line */
297 struct linebuffer filename_lb
; /* used to read in filenames */
301 struct linebuffer lb
; /* used by C_entries instead of lb */
308 printf ("%s for Emacs version %g.\n", (CTAGS
) ? "CTAGS" : "ETAGS", VERSION
);
310 printf ("%s for Emacs version 19.\n", (CTAGS
) ? "CTAGS" : "ETAGS");
319 printf ("These are the options accepted by %s. You may use unambiguous\n\
320 abbreviations for the long option names. A - as file name means read file\n\
321 names from stdin.\n\n", progname
);
323 puts ("-a, --append\n\
324 Append tag entries to existing tags file.");
327 puts ("-B, --backward-search\n\
328 Write the search commands for the tag entries using '?', the\n\
329 backward-search command.");
332 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
333 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
334 extensions are always assumed to be C++ code.");
337 puts ("-d, --defines\n\
338 Create tag entries for C #defines, too.");
340 puts ("-D, --no-defines\n\
341 Don't create tag entries for C #defines. This makes the tags\n\
345 puts ("-F, --forward-search\n\
346 Write the search commands for the tag entries using '/', the\n\
347 forward-search command.");
350 puts ("-i FILE, --include=FILE\n\
351 Include a note in tag file indicating that, when searching for\n\
352 a tag, one should also consult the tags file FILE after\n\
353 checking the current file.");
355 puts ("-o FILE, --output=FILE\n\
356 Write the tags to FILE.");
357 puts ("-S, --ignore-indentation\n\
358 Don't rely on indentation quite as much as normal. Currently,\n\
359 this means not to assume that a closing brace in the first\n\
360 column is the final brace of a function or structure\n\
361 definition in C and C++.");
365 puts ("-t, --typedefs\n\
366 Generate tag entries for C typedefs.");
367 puts ("-T, --typedefs-and-c++\n\
368 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
369 and C++ member functions.");
370 puts ("-u, --update\n\
371 Update the tag entries for the given files, leaving tag\n\
372 entries for other files in place. Currently, this is\n\
373 implemented by deleting the existing entries for the given\n\
374 files and then rewriting the new entries at the end of the\n\
375 tags file. It is often faster to simply rebuild the entire\n\
376 tag file than to use this.");
377 puts ("-v, --vgrind\n\
378 Generates an index of items intended for human consumption,\n\
379 similar to the output of vgrind. The index is sorted, and\n\
380 gives the page number of each item.");
381 puts ("-x, --cxref\n\
382 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
383 The output uses line numbers instead of page numbers, but\n\
384 beyond that the differences are cosmetic; try both to see\n\
386 puts ("-w, --no-warn\n\
387 Suppress warning messages about entries defined in multiple\n\
391 puts ("-V, --version\n\
392 Print the version of the program.\n\
394 Print this help message.");
407 unsigned int nincluded_files
= 0;
408 char **included_files
= xnew (argc
, char *);
413 extern char *gfnames ();
414 extern char *massage_name ();
418 _fmode
= O_BINARY
; /* all of files are treated as binary files */
424 * If etags, always find typedefs and structure tags. Why not?
425 * Also default is to find macro constants.
428 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
433 opt
= getopt_long (argc
, argv
, "aCdDf:o:StTi:BFuvxwVH", longopts
, 0);
441 /* If getopt returns 0, then it has already processed a
442 long-named option. We should do nothing. */
445 /* Common options. */
458 case 'f': /* for compatibility with old makefiles */
463 "%s: -%c flag may only be given once\n", progname
, opt
);
482 included_files
[nincluded_files
++] = optarg
;
499 typedefs_and_cplusplus
++;
521 if (optind
== argc
&& nincluded_files
== 0)
523 fprintf (stderr
, "%s: No input files specified.\n", progname
);
526 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
533 outfile
= CTAGS
? "tags" : "TAGS";
535 cwd
= etags_getcwd (); /* the current working directory */
537 if (streq (outfile
, "-"))
543 outfiledir
= absolute_dirname (outfile
, cwd
);
546 init (); /* set up boolean "functions" */
549 initbuffer (&lbs
[0].lb
);
550 initbuffer (&lbs
[1].lb
);
551 initbuffer (&filename_lb
);
553 * loop through files finding functions
557 if (streq (outfile
, "-"))
560 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
571 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
575 error ("Can't find file %s\n", this_file
);
580 this_file
= massage_name (this_file
);
583 } /* solely to balance out the ifdef'd parens above */
586 for (; optind
< argc
; optind
++)
588 this_file
= argv
[optind
];
590 /* Input file named "-" means read file names from stdin and use them. */
591 if (streq (this_file
, "-"))
593 while (!feof (stdin
))
595 (void) readline (&filename_lb
, stdin
);
596 if (strlen (filename_lb
.buffer
) > 0)
597 process_file (filename_lb
.buffer
);
601 process_file (this_file
);
606 while (nincluded_files
-- > 0)
607 fprintf (outf
, "\f\n%s,include\n", *included_files
++);
609 (void) fclose (outf
);
620 /* update cannot be set under VMS, so we may assume that argc
621 and argv have not been munged. */
622 for (i
= optind
; i
< argc
; i
++)
625 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
626 outfile
, argv
[i
], outfile
);
631 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
638 (void) fclose (outf
);
641 sprintf (cmd
, "sort %s -o %s", outfile
, outfile
);
649 * This routine is called on each file argument.
655 struct stat stat_buf
;
657 if (stat (file
, &stat_buf
) == 0 && !S_ISREG (stat_buf
.st_mode
))
659 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
662 if (streq (file
, outfile
) && !streq (outfile
, "-"))
664 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
667 if (!find_entries (file
))
677 /* file is an absolute filename. Canonicalise it. */
678 filename
= absolute_filename (file
, cwd
);
682 /* file is a filename relative to cwd. Make it relative
683 to the directory of the tags file. */
684 filename
= relative_filename (file
, outfiledir
);
686 fprintf (outf
, "\f\n%s,%d\n", filename
, total_size_of_entries (head
));
694 * This routine sets up the boolean pseudo-functions which work
695 * by setting boolean flags dependent upon the corresponding character
696 * Every char which is NOT in that string is not a white char. Therefore,
697 * all of the array "_wht" is set to FALSE, and then the elements
698 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
699 * of a char is TRUE if it is the string "white", else FALSE.
707 for (i
= 0; i
< 0177; i
++)
708 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
709 for (sp
= white
; *sp
; sp
++)
711 for (sp
= endtk
; *sp
; sp
++)
713 for (sp
= intk
; *sp
; sp
++)
715 for (sp
= begtk
; *sp
; sp
++)
717 _wht
[0] = _wht
['\n'];
718 _etk
[0] = _etk
['\n'];
719 _btk
[0] = _btk
['\n'];
720 _itk
[0] = _itk
['\n'];
724 * This routine opens the specified file and calls the function
725 * which finds the function and type definitions.
732 void prolog_funcs ();
734 inf
= fopen (file
, "r");
740 curfile
= savestr (file
);
741 cp
= etags_strrchr (file
, '.');
743 header_file
= (cp
&& (streq (cp
+ 1, "h")));
745 /* .tex, .aux or .bbl implies LaTeX source code */
746 if (cp
&& (streq (cp
+ 1, "tex") || streq (cp
+ 1, "aux")
747 || streq (cp
+ 1, "bbl")))
750 goto close_and_return
;
752 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
753 if (cp
&& (streq (cp
+ 1, "l")
754 || streq (cp
+ 1, "el")
755 || streq (cp
+ 1, "lsp")
756 || streq (cp
+ 1, "lisp")
757 || streq (cp
+ 1, "cl")
758 || streq (cp
+ 1, "clisp")))
761 goto close_and_return
;
763 /* .scm or .sm or .scheme or ... implies scheme source code */
764 if (cp
&& (streq (cp
+ 1, "sm")
765 || streq (cp
+ 1, "scm")
766 || streq (cp
+ 1, "scheme")
767 || streq (cp
+ 1, "t")
768 || streq (cp
+ 1, "sch")
769 || streq (cp
+ 1, "ss")
770 || streq (cp
+ 1, "SM")
771 || streq (cp
+ 1, "SCM")
772 /* The `SCM' or `scm' prefix with a version number */
773 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
774 && string_numeric_p (cp
+ 1))
775 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
776 && string_numeric_p (cp
+ 1))))
779 goto close_and_return
;
781 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
783 if (cp
&& (streq (cp
+ 1, "s")
784 || streq (cp
+ 1, "a")
785 || streq (cp
+ 1, "sa")))
788 goto close_and_return
;
790 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
791 if (cp
&& (streq (cp
+ 1, "C")
792 || streq (cp
+ 1, "H")
793 || streq (cp
+ 1, "cxx")
794 || streq (cp
+ 1, "hxx")
795 || streq (cp
+ 1, "cc")))
797 C_entries (C_PLPL
); /* C++ */
798 goto close_and_return
;
800 /* .cs or .hs: a C* file */
801 if (cp
&& (streq (cp
+ 1, "cs")
802 || streq (cp
+ 1, "hs")))
805 goto close_and_return
;
807 /* .y: a yacc file */
808 if (cp
&& (streq (cp
+ 1, "y")))
811 goto close_and_return
;
813 /* .pl implies prolog source code */
814 if (cp
&& streq (cp
+ 1, "pl"))
817 goto close_and_return
;
819 /* .p or .pas: a Pascal file */
820 if (cp
&& (streq (cp
+ 1, "p")
821 || streq (cp
+ 1, "pas")))
824 goto close_and_return
;
826 /* If .f or .for, assume it is fortran or nothing. */
827 if (cp
&& (streq (cp
+ 1, "f")
828 || streq (cp
+ 1, "for")))
830 (void) PF_funcs (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 (PF_funcs (inf
) != 0)
840 goto close_and_return
;
841 rewind (inf
); /* no fortran tags found, try C */
843 C_entries (cplusplus
? C_PLPL
: 0);
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 static 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 (outf
, "%s\177%s\001%d,%d\n",
1051 node
->pat
, node
->name
,
1052 node
->lno
, node
->cno
);
1056 fprintf (outf
, "%s\177%d,%d\n",
1058 node
->lno
, node
->cno
);
1061 else if (!cxref_style
)
1063 fprintf (outf
, "%s\t%s\t",
1064 node
->name
, node
->file
);
1068 putc (searchar
, outf
);
1071 for (sp
= node
->pat
; *sp
; sp
++)
1073 if (*sp
== '\\' || *sp
== searchar
)
1077 putc (searchar
, outf
);
1080 { /* a typedef; text pattern inadequate */
1081 fprintf (outf
, "%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 * This routine finds functions, typedefs, #define's and
1369 * struct/union/enum definitions in C syntax and adds them
1373 #define curlb (lbs[curndx].lb)
1374 #define othlb (lbs[1-curndx].lb)
1375 #define newlb (lbs[newndx].lb)
1376 #define curlinepos (lbs[curndx].linepos)
1377 #define othlinepos (lbs[1-curndx].linepos)
1378 #define newlinepos (lbs[newndx].linepos)
1380 /* Save and restore token state. This is used when preprocessor defines
1381 are handled, to avoid disturbing active function/typedef/struct states. */
1382 #define TOKEN_SAVED_P (savetok.lineno > 0)
1383 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1384 savetok.len = toklen, strcpy(savenameb, nameb))
1385 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1386 toklen = tok.len, strcpy(nameb, savenameb), \
1389 #define CNL_SAVE_DEFINEDEF \
1391 SET_FILEPOS (curlinepos, inf, charno); \
1393 charno += readline (&curlb, inf); \
1394 lp = curlb.buffer; \
1401 CNL_SAVE_DEFINEDEF; \
1402 if (TOKEN_SAVED_P) \
1404 definedef = dnone; \
1407 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1408 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1409 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1410 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1414 int c_ext
; /* extension of C? */
1416 register char c
; /* latest char read; '\0' for end of line */
1417 register char *lp
; /* pointer one beyond the character `c' */
1418 int curndx
, newndx
; /* indices for current and new lb */
1419 TOKEN tok
; /* latest token read for funcdef & structdef */
1420 char nameb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1421 register int tokoff
; /* offset in line of start of latest token */
1422 register int toklen
; /* length of latest token */
1423 int cblev
; /* current curly brace level */
1424 int parlev
; /* current parenthesis level */
1425 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1427 TOKEN savetok
; /* saved token during preprocessor handling */
1428 char savenameb
[BUFSIZ
]; /* ouch! */
1431 curndx
= newndx
= 0;
1437 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1438 next_token_is_func
= yacc_rules
= FALSE
;
1439 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1442 cplpl
= c_ext
& C_PLPL
;
1449 /* If we're at the end of the line, the next character is a
1450 '\0'; don't skip it, because it's the thing that tells us
1451 to read the next line. */
1472 /* Newlines inside comments do not end macro definitions in
1487 /* Newlines inside strings do not end macro definitions
1488 in traditional cpp, even though compilers don't
1489 usually accept them. */
1500 /* Hmmm, something went wrong. */
1514 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1519 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1529 else if (cplpl
&& *lp
== '/')
1537 if ((c_ext
& YACC
) && *lp
== '%')
1539 /* entering or exiting rules section in yacc file */
1541 definedef
= dnone
; funcdef
= fnone
;
1542 typdef
= tnone
; structdef
= snone
;
1543 next_token_is_func
= FALSE
;
1544 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1546 yacc_rules
= !yacc_rules
;
1552 if (lp
== newlb
.buffer
+ 1 && definedef
== dnone
)
1553 definedef
= dsharpseen
;
1558 /* Consider token only if some complicated conditions are satisfied. */
1559 if (((cblev
== 0 && structdef
!= scolonseen
)
1560 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
1561 && typdef
!= tignore
1562 && definedef
!= dignorerest
1563 && (funcdef
!= finlist
1564 || definedef
!= dnone
))
1570 if (cplpl
&& c
== ':' && *lp
== ':' && begtoken(*(lp
+ 1)))
1573 * This handles :: in the middle, but not at beginning
1581 logical is_func
= FALSE
;
1583 tok
.lineno
= lineno
;
1584 tok
.p
= newlb
.buffer
+ tokoff
;
1588 || consider_token (c
, &tok
, c_ext
, cblev
, &is_func
))
1590 if (structdef
== sinbody
1591 && definedef
== dnone
1593 /* function defined in C++ class body */
1596 sprintf (nameb
, "%s::%.*s",
1597 ((structtag
[0] == '\0')
1598 ? "_anonymous_" : structtag
),
1603 sprintf (nameb
, "%.*s", tok
.len
, tok
.p
);
1606 if (structdef
== stagseen
1610 if (definedef
== dnone
1611 && (funcdef
== ftagseen
1612 || structdef
== stagseen
1615 if (newndx
== curndx
)
1616 curndx
= 1 - curndx
; /* switch line buffers */
1619 MAKE_TAG_FROM_NEW_LB (is_func
);
1623 } /* if (endtoken (c)) */
1624 else if (intoken (c
))
1629 } /* if (midtoken) */
1630 else if (begtoken (c
))
1641 MAKE_TAG_FROM_OTH_LB (TRUE
);
1648 if (structdef
== stagseen
)
1652 /* Take a quick peek ahead for define directive,
1653 so we can avoid saving the token when not absolutely
1654 necessary. [This is a speed hack.] */
1655 if (c
== 'd' && strneq(lp
, "efine", 5)
1656 && iswhite(*(lp
+ 5)))
1659 definedef
= ddefineseen
;
1663 definedef
= dignorerest
;
1666 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1668 tokoff
= lp
- 1 - newlb
.buffer
;
1674 } /* if must look at token */
1677 /* Detect end of line, colon, comma, semicolon and various braces
1678 after having handled a token.*/
1682 if (definedef
!= dnone
)
1684 if (structdef
== stagseen
)
1685 structdef
= scolonseen
;
1692 MAKE_TAG_FROM_OTH_LB (FALSE
);
1702 if (definedef
!= dnone
)
1708 MAKE_TAG_FROM_OTH_LB (FALSE
);
1713 if (funcdef
!= fignore
)
1715 if (structdef
== stagseen
)
1719 if (definedef
!= dnone
)
1721 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1723 if (structdef
== stagseen
)
1727 if (definedef
!= dnone
)
1729 if (cblev
== 0 && typdef
== tend
)
1732 MAKE_TAG_FROM_OTH_LB (FALSE
);
1735 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1737 if (structdef
== stagseen
)
1741 if (definedef
!= dnone
)
1746 funcdef
= fstartlist
;
1755 if (definedef
!= dnone
)
1763 funcdef
= flistseen
;
1766 if (cblev
== 0 && typdef
== tend
)
1769 MAKE_TAG_FROM_OTH_LB (FALSE
);
1772 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
1776 if (definedef
!= dnone
)
1778 if (typdef
== ttypedseen
)
1782 case skeyseen
: /* unnamed struct */
1783 structtag
[0] = '\0';
1784 structdef
= sinbody
;
1787 case scolonseen
: /* named struct */
1788 structdef
= sinbody
;
1789 MAKE_TAG_FROM_OTH_LB (FALSE
);
1795 MAKE_TAG_FROM_OTH_LB (TRUE
);
1801 /* Neutralize `extern "C" {' grot.
1802 if (cblev == 0 && structdef == snone && typdef == tnone)
1808 if (definedef
!= dnone
)
1810 if (funcdef
== fstartlist
)
1811 funcdef
= fnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
1814 if (definedef
!= dnone
)
1816 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
1818 cblev
= 0; /* reset curly brace level if first column */
1819 parlev
= 0; /* also reset paren level, just in case... */
1825 if (typdef
== tinbody
)
1828 strcpy (structtag
, "<error 2>");
1832 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
1833 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
1834 if (definedef
!= dnone
)
1836 /* These surely cannot follow a function tag. */
1837 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1841 /* If a macro spans multiple lines don't reset its state. */
1849 } /* while not eof */
1854 * checks to see if the current token is at the start of a
1855 * function, or corresponds to a typedef, or is a struct/union/enum
1858 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1859 * C_EXT is which language we are looking at.
1861 * In the future we will need some way to adjust where the end of
1862 * the token is; for instance, implementing the C++ keyword
1863 * `operator' properly will adjust the end of the token to be after
1864 * whatever follows `operator'.
1871 * next_token_is_func IN OUT
1875 consider_token (c
, tokp
, c_ext
, cblev
, is_func
)
1876 register char c
; /* IN: first char after the token */
1877 register TOKEN
*tokp
; /* IN: token pointer */
1878 int c_ext
; /* IN: C extensions mask */
1879 int cblev
; /* IN: curly brace level */
1880 logical
*is_func
; /* OUT */
1882 enum sym_type toktype
= C_symtype(tokp
->p
, tokp
->len
, c_ext
);
1885 * Advance the definedef state machine.
1890 /* We're not on a preprocessor line. */
1893 if (toktype
== st_C_define
)
1895 definedef
= ddefineseen
;
1899 definedef
= dignorerest
;
1904 * Make a tag for any macro.
1906 definedef
= dignorerest
;
1907 *is_func
= (c
== '(');
1908 if (!*is_func
&& !constantypedefs
)
1915 error ("internal error: definedef value.", 0);
1924 if (toktype
== st_C_typedef
)
1927 typdef
= ttypedseen
;
1943 /* Do not return here, so the structdef stuff has a chance. */
1957 * This structdef business is currently only invoked when cblev==0.
1958 * It should be recursively invoked whatever the curly brace level,
1959 * and a stack of states kept, to allow for definitions of structs
1962 * This structdef business is NOT invoked when we are ctags and the
1963 * file is plain C. This is because a struct tag may have the same
1964 * name as another tag, and this loses with ctags.
1966 * This if statement deals with the typdef state machine as
1967 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1968 * return (FALSE). All the other code here is for the structdef
1975 if (typdef
== ttypedseen
1976 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1978 structdef
= skeyseen
;
1979 structtype
= toktype
;
1983 if (structdef
== skeyseen
)
1985 if (structtype
== st_C_struct
)
1987 strncpy (structtag
, tokp
->p
, tokp
->len
);
1988 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1992 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1994 structdef
= stagseen
;
1998 /* Avoid entering funcdef stuff if typdef is going on. */
1999 if (typdef
!= tnone
)
2005 /* Detect GNUmacs's function-defining macros. */
2006 if (definedef
== dnone
)
2008 if (strneq (tokp
->p
, "DEF", 3)
2009 || strneq (tokp
->p
, "ENTRY", 5)
2010 || strneq (tokp
->p
, "SYSCALL", 7)
2011 || strneq (tokp
->p
, "PSEUDO", 6))
2013 next_token_is_func
= TRUE
;
2016 if (strneq (tokp
->p
, "EXFUN", 5))
2018 next_token_is_func
= FALSE
;
2022 if (next_token_is_func
)
2024 next_token_is_func
= FALSE
;
2026 *is_func
= TRUE
; /* to force search string in ctags */
2034 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2035 funcdef
= fnone
; /* should be useless */
2038 if (funcdef
== fnone
)
2049 /* Fortran parsing */
2065 linecharno
= charno
;
2066 charno
+= readline (&lb
, fi
);
2069 dbp
++; /* Ratfor escape to fortran */
2070 while (isspace (*dbp
))
2077 if (tail ("integer"))
2085 if (tail ("logical"))
2089 if (tail ("complex") || tail ("character"))
2093 if (tail ("double"))
2095 while (isspace (*dbp
))
2099 if (tail ("precision"))
2105 while (isspace (*dbp
))
2112 if (tail ("function"))
2116 if (tail ("subroutine"))
2124 if (tail ("program"))
2129 if (tail ("procedure"))
2141 register int len
= 0;
2143 while (*cp
&& (*cp
| ' ') == (dbp
[len
] | ' '))
2156 while (isspace (*dbp
))
2161 while (isspace (*dbp
))
2163 if (!isdigit (*dbp
))
2165 --dbp
; /* force failure */
2170 while (isdigit (*dbp
));
2179 char nambuf
[BUFSIZ
];
2181 while (isspace (*dbp
))
2186 linecharno
= charno
;
2187 charno
+= readline (&lb
, fi
);
2192 while (isspace (*dbp
))
2201 && (isalpha (*cp
) || isdigit (*cp
) || (*cp
== '_') || (*cp
== '$')));
2206 strcpy (nambuf
, dbp
);
2208 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2209 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2213 /* Handle a file of assembler code. */
2229 linecharno
= charno
;
2230 charno
+= readline (&lb
, fi
);
2233 for (i
= 0; ((c
= dbp
[i
]) && !isspace (c
)) && (c
!= ':'); i
++)
2236 if ((i
> 0) && (c
== ':'))
2241 /* Added by Mosur Mohan, 4/22/88 */
2242 /* Pascal parsing */
2244 #define GET_NEW_LINE \
2246 linecharno = charno; lineno++; \
2247 charno += 1 + readline (&lb, inf); \
2251 /* Locates tags for procedures & functions.
2252 * Doesn't do any type- or var-definitions.
2253 * It does look for the keyword "extern" or "forward"
2254 * immediately following the procedure statement;
2255 * if found, the tag is skipped.
2262 struct linebuffer tline
; /* mostly copied from C_entries */
2266 char nambuf
[BUFSIZ
];
2268 logical
/* each of these flags is TRUE iff: */
2269 incomm1
, /* point is inside {..} comment */
2270 incomm2
, /* point is inside (*..*) comment */
2271 inquote
, /* point is inside '..' string */
2272 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2273 /* keyword, so next item = potential tag */
2274 found_tag
, /* point is after a potential tag */
2275 inparms
, /* point is within parameter-list */
2276 verify_tag
; /* point has passed the parm-list, so the */
2277 /* next token will determine whether */
2278 /* this is a FORWARD/EXTERN to be */
2279 /* ignored, or whether it is a real tag */
2285 initbuffer (&tline
);
2287 incomm1
= incomm2
= inquote
= FALSE
;
2288 found_tag
= FALSE
; /* have a proc name; check if extern */
2289 get_tagname
= FALSE
; /* have found "procedure" keyword */
2290 inparms
= FALSE
; /* found '(' after "proc" */
2291 verify_tag
= FALSE
; /* check if "extern" is ahead */
2293 /* long main loop to get next char */
2297 if (c
== 0) /* if end of line */
2302 if (!((found_tag
&& verify_tag
) ||
2304 c
= *dbp
++; /* only if don't need *dbp pointing */
2305 /* to the beginning of the name of */
2306 /* the procedure or function */
2308 if (incomm1
) /* within { - } comments */
2314 else if (incomm2
) /* within (* - *) comments */
2318 while ((c
= *dbp
++) == '*')
2337 inquote
= TRUE
; /* found first quote */
2339 case '{': /* found open-{-comment */
2343 if (*dbp
== '*') /* found open-(*-comment */
2348 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2351 case ')': /* end of parms list */
2356 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2363 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2365 /* check if this is an "extern" declaration */
2368 if ((*dbp
== 'e') || (*dbp
== 'E'))
2370 if (tail ("extern")) /* superfluous, really! */
2376 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2378 if (tail ("forward")) /* check for forward reference */
2384 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2388 pfnote (nambuf
, TRUE
, FALSE
,
2389 tline
.buffer
, cp
- tline
.buffer
+ 1,
2390 save_lineno
, save_lcno
);
2394 if (get_tagname
) /* grab name of proc or fn */
2399 /* save all values for later tagging */
2400 tline
.size
= lb
.size
;
2401 strcpy (tline
.buffer
, lb
.buffer
);
2402 save_lineno
= lineno
;
2403 save_lcno
= linecharno
;
2405 /* grab block name */
2406 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2410 strcpy (nambuf
, dbp
);
2412 dbp
= cp
; /* restore dbp to e-o-token */
2413 get_tagname
= FALSE
;
2417 /* and proceed to check for "extern" */
2419 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2420 (!found_tag
) && (!get_tagname
))
2422 /* check for proc/fn keywords */
2426 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2430 if (tail ("unction"))
2435 } /* while not e-o-f */
2439 * lisp tag functions
2440 * just look for (def or (DEF
2454 linecharno
= charno
;
2455 charno
+= readline (&lb
, fi
);
2461 while (!isspace (*dbp
))
2463 while (isspace (*dbp
))
2469 /* Check for (foo::defmumble name-defined ... */
2472 while (*dbp
&& !isspace (*dbp
)
2473 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2478 while (*dbp
== ':');
2480 if (L_isdef (dbp
- 1))
2482 while (!isspace (*dbp
))
2484 while (isspace (*dbp
))
2498 return ((dbp
[1] == 'd' || dbp
[1] == 'D')
2499 && (dbp
[2] == 'e' || dbp
[2] == 'E')
2500 && (dbp
[3] == 'f' || dbp
[3] == 'F'));
2507 return ((*(++dbp
) == 'q' || *dbp
== 'Q')
2508 && (*(++dbp
) == 'u' || *dbp
== 'U')
2509 && (*(++dbp
) == 'o' || *dbp
== 'O')
2510 && (*(++dbp
) == 't' || *dbp
== 'T')
2511 && (*(++dbp
) == 'e' || *dbp
== 'E')
2512 && isspace(*(++dbp
)));
2520 char nambuf
[BUFSIZ
];
2522 if (*dbp
== '\'') /* Skip prefix quote */
2524 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2527 while (isspace(*dbp
))
2530 for (cp
= dbp
/*+1*/; *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')'; cp
++)
2537 strcpy (nambuf
, dbp
);
2539 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2540 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2545 * Scheme tag functions
2546 * look for (def... xyzzy
2547 * look for (def... (xyzzy
2548 * look for (def ... ((...(xyzzy ....
2549 * look for (set! xyzzy
2552 static void get_scheme ();
2565 linecharno
= charno
;
2566 charno
+= readline (&lb
, fi
);
2568 if (dbp
[0] == '(' &&
2569 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2570 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2571 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2573 while (!isspace (*dbp
))
2575 /* Skip over open parens and white space */
2576 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2580 if (dbp
[0] == '(' &&
2581 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2582 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2583 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2584 (dbp
[4] == '!' || dbp
[4] == '!') &&
2587 while (!isspace (*dbp
))
2589 /* Skip over white space */
2590 while (isspace (*dbp
))
2602 char nambuf
[BUFSIZ
];
2606 /* Go till you get to white space or a syntactic break */
2607 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2609 /* Null terminate the string there. */
2612 /* Copy the string */
2613 strcpy (nambuf
, dbp
);
2614 /* Unterminate the string */
2616 /* Announce the change */
2617 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2621 /* Find tags in TeX and LaTeX input files. */
2623 /* TEX_toktab is a table of TeX control sequences that define tags.
2624 Each TEX_tabent records one such control sequence.
2625 CONVERT THIS TO USE THE Stab TYPE!! */
2633 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2635 /* Default set of control sequences to put into TEX_toktab.
2636 The value of environment var TEXTAGS is prepended to this. */
2638 static char *TEX_defenv
=
2639 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2642 struct TEX_tabent
*TEX_decode_env ();
2646 static char TEX_esc
= '\\';
2647 static char TEX_opgrp
= '{';
2648 static char TEX_clgrp
= '}';
2651 * TeX/LaTeX scanning loop.
2664 /* Select either \ or ! as escape character. */
2667 /* Initialize token table once from environment. */
2669 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2672 { /* Scan each line in file */
2674 linecharno
= charno
;
2675 charno
+= readline (&lb
, fi
);
2678 while (dbp
= etags_strchr (dbp
, TEX_esc
)) /* Look at each esc in line */
2684 linecharno
+= dbp
- lasthit
;
2686 i
= TEX_Token (lasthit
);
2689 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2690 break; /* We only save a line once */
2696 #define TEX_LESC '\\'
2697 #define TEX_SESC '!'
2700 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2701 /* chars accordingly. */
2709 while ((c
= getc (f
)) != EOF
)
2711 /* Skip to next line if we hit the TeX comment char. */
2715 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2734 /* Read environment and prepend it to the default string. */
2735 /* Build token table. */
2738 TEX_decode_env (evarname
, defenv
)
2742 register char *env
, *p
;
2744 struct TEX_tabent
*tab
;
2747 /* Append default string to environment. */
2748 env
= getenv (evarname
);
2752 env
= concat (env
, defenv
, "");
2754 /* Allocate a token table */
2755 for (size
= 1, p
= env
; p
;)
2756 if ((p
= etags_strchr (p
, ':')) && *(++p
))
2758 /* Add 1 to leave room for null terminator. */
2759 tab
= xnew (size
+ 1, struct TEX_tabent
);
2761 /* Unpack environment string into token table. Be careful about */
2762 /* zero-length strings (leading ':', "::" and trailing ':') */
2765 p
= etags_strchr (env
, ':');
2766 if (!p
) /* End of environment string. */
2767 p
= env
+ strlen (env
);
2769 { /* Only non-zero strings. */
2770 tab
[i
].name
= savenstr (env
, p
- env
);
2771 tab
[i
].len
= strlen (tab
[i
].name
);
2778 tab
[i
].name
= NULL
; /* Mark end of table. */
2786 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2787 The name being defined actually starts at (NAME + LEN + 1).
2788 But we seem to include the TeX command in the tag name. */
2791 TEX_getit (name
, len
)
2795 char *p
= name
+ len
;
2796 char nambuf
[BUFSIZ
];
2801 /* Let tag name extend to next group close (or end of line) */
2802 while (*p
&& *p
!= TEX_clgrp
)
2804 strncpy (nambuf
, name
, p
- name
);
2805 nambuf
[p
- name
] = 0;
2807 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2811 /* If the text at CP matches one of the tag-defining TeX command names,
2812 return the pointer to the first occurrence of that command in TEX_toktab.
2813 Otherwise return -1. */
2815 /* Keep the capital `T' in `Token' for dumb truncating compilers
2816 (this distinguishes it from `TEX_toktab' */
2823 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2824 if (strneq (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
))
2829 /* Support for Prolog. */
2831 /* whole head (not only functor, but also arguments)
2832 is gotten in compound term. */
2835 prolog_getit (s
, lineno
, linecharno
)
2840 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2848 if (*s
== '\0') /* syntax error. */
2850 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2852 else if (*s
== '\'')
2854 insquote
= !insquote
;
2857 else if (!insquote
&& *s
== '(')
2862 else if (!insquote
&& *s
== ')')
2868 else if (npar
< 0) /* syntax error. */
2871 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2873 if (npar
!= 0) /* syntax error. */
2883 strcpy (nambuf
, save_s
);
2885 pfnote (nambuf
, TRUE
, FALSE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2888 /* It is assumed that prolog predicate starts from column 0. */
2894 void skip_comment (), prolog_getit ();
2896 lineno
= linecharno
= charno
= 0;
2900 linecharno
+= charno
;
2901 charno
= readline (&lb
, fi
) + 1; /* 1 for newline. */
2903 if (isspace (dbp
[0])) /* not predicate header. */
2905 else if (dbp
[0] == '%') /* comment. */
2907 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2908 skip_comment (&lb
, fi
, &lineno
, &linecharno
);
2910 prolog_getit (dbp
, lineno
, linecharno
);
2915 skip_comment (plb
, fi
, plineno
, plinecharno
)
2916 struct linebuffer
*plb
;
2918 int *plineno
; /* result */
2919 long *plinecharno
; /* result */
2921 while (!substr ("*/", plb
->buffer
))
2924 *plinecharno
+= readline (plb
, fi
) + 1;
2925 } /* 1 for newline. */
2928 /* Return TRUE if 'sub' exists somewhere in 's'. */
2935 while (*s
&& (s
= etags_strchr (s
, *sub
)))
2936 if (prestr (sub
, s
))
2943 /* Return TRUE if 'pre' is prefix of string 's'. */
2952 else if (*pre
== *s
)
2953 return (prestr (pre
+ 1, s
+ 1));
2958 /* Initialize a linebuffer for use */
2961 initbuffer (linebuffer
)
2962 struct linebuffer
*linebuffer
;
2964 linebuffer
->size
= 200;
2965 linebuffer
->buffer
= xnew (200, char);
2969 * Read a line of text from `stream' into `linebuffer'.
2970 * Return the number of characters read from `stream',
2971 * which is the length of the line including the newline, if any.
2974 readline (linebuffer
, stream
)
2975 struct linebuffer
*linebuffer
;
2976 register FILE *stream
;
2978 char *buffer
= linebuffer
->buffer
;
2979 register char *p
= linebuffer
->buffer
;
2980 register char *pend
;
2981 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2983 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
2987 register int c
= getc (stream
);
2990 linebuffer
->size
*= 2;
2991 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
2992 p
+= buffer
- linebuffer
->buffer
;
2993 pend
= buffer
+ linebuffer
->size
;
2994 linebuffer
->buffer
= buffer
;
2996 if (c
== EOF
|| c
== '\n')
2999 newline
= (c
== '\n') ? 1 : 0;
3005 return p
- buffer
+ newline
;
3012 return savenstr (cp
, strlen (cp
));
3022 dp
= xnew (len
+ 1, char);
3023 strncpy (dp
, cp
, len
);
3029 * Return the ptr in sp at which the character c last
3030 * appears; NULL if not found
3032 * Identical to System V strrchr, included for portability.
3036 etags_strrchr (sp
, c
)
3037 register char *sp
, c
;
3052 * Return the ptr in sp at which the character c first
3053 * appears; NULL if not found
3055 * Identical to System V strchr, included for portability.
3059 etags_strchr (sp
, c
)
3060 register char *sp
, c
;
3070 /* Print error message and exit. */
3081 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3088 fprintf (stderr
, "%s: ", progname
);
3089 fprintf (stderr
, s1
, s2
);
3090 fprintf (stderr
, "\n");
3093 /* Return a newly-allocated string whose contents
3094 concatenate those of s1, s2, s3. */
3100 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3101 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3103 strcpy (result
, s1
);
3104 strcpy (result
+ len1
, s2
);
3105 strcpy (result
+ len1
+ len2
, s3
);
3106 result
[len1
+ len2
+ len3
] = '\0';
3111 /* Identical to system V getcwd, but does not need to guess
3112 buffer size in advance. Included mostly for compatibility. */
3122 buf
= xnew (bufsize
, char);
3124 pipe
= popen ("pwd 2>/dev/null", "r");
3130 if (fgets (buf
, bufsize
, pipe
) == NULL
)
3139 } while (buf
[strlen (buf
) - 1] != '\n');
3144 /* Return a newly allocated string containing the filename
3145 of FILE relative to the absolute directory DIR (which
3146 should end with a slash). */
3149 relative_filename (file
, dir
)
3152 char *fp
, *dp
, *res
;
3154 /* Find the common root of file and dir. */
3155 fp
= absolute_filename (file
, cwd
);
3157 while (*fp
++ == *dp
++)
3166 /* Build a sequence of "../" strings for the resulting relative filename. */
3167 for (dp
= etags_strchr (dp
+ 1, '/'), res
= "";
3169 dp
= etags_strchr (dp
+ 1, '/'))
3171 res
= concat (res
, "../", "");
3174 /* Add the filename relative to the common root of file and dir. */
3175 res
= concat (res
, fp
+ 1, "");
3177 return res
; /* temporary stub */
3180 /* Return a newly allocated string containing the
3181 absolute filename of FILE given CWD (which should
3182 end with a slash). */
3185 absolute_filename (file
, cwd
)
3188 char *slashp
, *cp
, *res
;
3191 res
= concat (file
, "", "");
3193 res
= concat (cwd
, file
, "");
3195 /* Delete the "/dirname/.." and "/." substrings. */
3196 slashp
= etags_strchr (res
, '/');
3197 while (slashp
!= NULL
&& slashp
[0] != '\0')
3199 if (slashp
[1] == '.')
3201 if (slashp
[2] == '.'
3202 && (slashp
[3] == '/' || slashp
[3] == '\0'))
3207 while (cp
>= res
&& *cp
!= '/');
3210 strcpy (cp
, slashp
+ 3);
3212 else /* else (cp == res) */
3214 if (slashp
[3] != NULL
)
3215 strcpy (cp
, slashp
+ 4);
3221 else if (slashp
[2] == '/' || slashp
[2] == '\0')
3223 strcpy (slashp
, slashp
+ 2);
3228 slashp
= etags_strchr (slashp
+ 1, '/');
3235 /* Return a newly allocated string containing the absolute
3236 filename of dir where FILE resides given CWD (which should
3237 end with a slash). */
3240 absolute_dirname (file
, cwd
)
3246 slashp
= etags_strrchr (file
, '/');
3251 res
= absolute_filename (file
, cwd
);
3257 /* Like malloc but get fatal error if memory is exhausted. */
3263 char *result
= (char *) malloc (size
);
3265 fatal ("virtual memory exhausted", 0);
3270 xrealloc (ptr
, size
)
3274 char *result
= (char *) realloc (ptr
, size
);
3276 fatal ("virtual memory exhausted");