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. 9.8
32 #include <../src/config.h>
37 #include <sys/types.h>
40 #if !defined (S_ISREG) && defined (S_IFREG)
41 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
46 extern char *malloc (), *realloc ();
47 extern char *getenv ();
48 extern char *strcpy (), *strncpy ();
51 char *etags_index (), *etags_rindex ();
54 /* Define the symbol ETAGS to make the program "etags",
55 which makes emacs-style tag tables by default.
56 Define CTAGS to make the program "ctags" compatible with the usual one.
57 Define neither one to get behavior that depends
58 on the name with which the program is invoked
59 (but we don't normally compile it that way). */
61 #if !defined(ETAGS) && !defined(CTAGS)
62 /* If neither is defined, program can be run as either. */
67 /* On VMS, CTAGS is not useful, so always do ETAGS. */
74 /* Exit codes for success and failure. */
84 * The FILEPOS abstract type, which represents a position in a file,
85 * plus the following accessor functions:
87 * long GET_CHARNO (pos)
88 * returns absolute char number.
89 * void SET_FILEPOS (pos, fp, charno)
90 * FILE *fp; long charno;
91 * sets `pos' from the current file
92 * position of `fp' and from `charno',
93 * which must be the absolute character
94 * number corresponding to the current
97 * The `pos' parameter is an lvalue expression of type FILEPOS.
98 * Parameters to the accessor functions are evaluated 0 or more times,
99 * and so must have no side effects.
101 * FILEPOS objects can also be assigned and passed to and from
102 * functions in the normal C manner.
104 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
108 /* real implementation */
109 typedef long FILEPOS
;
110 #define GET_CHARNO(pos) ((pos) + 0)
111 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
113 /* debugging implementation */
119 #define GET_CHARNO(pos) ((pos).charno + 0)
120 #define SET_FILEPOS(pos, fp, cno) \
121 ((void) ((pos).charno = (cno), \
122 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
126 #define streq(s, t) (strcmp (s, t) == 0)
127 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
133 #define iswhite(arg) (_wht[arg]) /* T if char is white */
134 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
135 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
136 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
138 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
141 { /* sorting structure */
142 char *name
; /* function or type name */
143 char *file
; /* file name */
144 logical is_func
; /* use pattern or line no */
145 logical named
; /* list name separately */
146 logical been_warned
; /* set if noticed dup */
147 int lno
; /* line number tag is on */
148 long cno
; /* character number line starts on */
149 char *pat
; /* search pattern */
150 struct nd_st
*left
, *right
; /* left and right sons */
154 typedef struct nd_st NODE
;
156 logical header_file
; /* TRUE if .h file, FALSE o.w. */
157 /* boolean "functions" (see init) */
158 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
166 int L_isdef (), L_isquote ();
168 int total_size_of_entries ();
169 logical
consider_token ();
177 void Scheme_funcs ();
182 void find_entries ();
190 void process_file ();
196 * xnew -- allocate storage
199 * Type *xnew (int n, Type);
201 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
206 * Symbol table stuff.
208 * Should probably be implemented with hash table; linked list for now.
213 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
221 struct stab_entry
*next
;
224 typedef struct stab_entry Stab_entry
;
225 typedef Stab_entry
*Stab
;
229 * Stab, Stab_entry, stab_create, stab_search, stab_find -- symbol table
232 * Types: Stab, Stab_entry, enum sym_type
234 * Stab * stab_create ()
236 * Stab_entry * stab_find (stab, sym)
240 * Stab_entry * stab_search (stab, sym)
245 * stab_create creates a Stab, a symbol table object, and returns a
246 * pointer to it. stab_find finds a symbol in a Stab; it returns a
247 * pointer to the Stab_entry if found, otherwise NULL. stab_search
248 * is like stab_find, except that it creates a new Stab_entry,
249 * initialized with type = st_none, if one did not exist already
250 * (it never returns NULL).
252 * A Stab_entry is a structure that contains at least the following
255 * char *name; // must not be modified
256 * enum sym_type type; // should be set
258 * The type field is initially set to st_none; it should be set to
259 * something else by the caller of stab_search. Other possible values
260 * of an enum sym_type can be added.
268 *sp
= NULL
; /* a Stab starts out as a null Stab_entry* */
273 stab_find (stab
, sym
, symlen
)
278 register Stab_entry
*se
;
279 for (se
= *stab
; se
!= NULL
; se
= se
->next
)
281 if (se
->symlen
== symlen
&& strneq (se
->sym
, sym
, symlen
))
289 stab_search (stab
, sym
, symlen
)
294 register Stab_entry
*se
;
295 se
= stab_find (stab
, sym
, symlen
);
300 se
= xnew (1, Stab_entry
);
301 se
->sym
= savenstr (sym
, symlen
);
313 * stab_type -- type of a symbol table entry
316 * enum sym_type stab_type (Stab_entry *se);
319 * May evaluate its argument more than once.
322 #define stab_type(se) ((se)==NULL ? st_none : (se)->type)
338 #define C_PLPL 0x00001 /* C++ */
339 #define C_STAR 0x00003 /* C* */
340 #define YACC 0x10000 /* yacc file */
342 char searchar
= '/'; /* use /.../ searches */
344 LINENO lineno
; /* line number of current line */
345 long charno
; /* current character number */
347 long linecharno
; /* charno of start of line; not used by C, but
348 * by every other language.
351 char *curfile
, /* current input file name */
352 *outfile
, /* output file */
353 *white
= " \f\t\n", /* white chars */
354 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
355 /* token starting chars */
356 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
357 /* valid in-token chars */
358 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
360 int append_to_tagfile
; /* -a: append to tags */
361 int emacs_tags_format
; /* emacs style output (no -e option any more) */
362 /* The following three default to 1 for etags, but to 0 for ctags. */
363 int typedefs
; /* -t: create tags for typedefs */
364 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
365 /* 0 struct/enum/union decls, and C++ */
366 /* member functions */
367 int constantypedefs
; /* -d: create tags for C #define and enum */
368 /* constants. Default under etags. Enum */
369 /* constants not implemented. */
370 /* -D: opposite of -d. Default under ctags. */
371 int update
; /* -u: update tags */
372 int vgrind_style
; /* -v: create vgrind style index output */
373 int no_warnings
; /* -w: suppress warnings */
374 int cxref_style
; /* -x: create cxref style output */
375 int cplusplus
; /* .[hc] means C++, not C */
376 int noindentypedefs
; /* -S: ignore indentation in C */
378 /* Name this program was invoked with. */
381 struct option longopts
[] = {
382 { "append", no_argument
, NULL
, 'a' },
383 { "backward-search", no_argument
, NULL
, 'B' },
384 { "c++", no_argument
, NULL
, 'C' },
385 { "cxref", no_argument
, NULL
, 'x' },
386 { "defines", no_argument
, NULL
, 'd' },
387 { "forward-search", no_argument
, NULL
, 'F' },
388 { "help", no_argument
, NULL
, 'H' },
389 { "ignore-indentation", no_argument
, NULL
, 'S' },
390 { "include", required_argument
, NULL
, 'i' },
391 { "no-defines", no_argument
, NULL
, 'D' },
392 { "no-warn", no_argument
, NULL
, 'w' },
393 { "output", required_argument
, NULL
, 'o' },
394 { "typedefs", no_argument
, NULL
, 't' },
395 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
396 { "update", no_argument
, NULL
, 'u' },
397 { "version", no_argument
, NULL
, 'V' },
398 { "vgrind", no_argument
, NULL
, 'v' },
402 FILE *inf
, /* ioptr for current input file */
403 *outf
; /* ioptr for tags file */
405 NODE
*head
; /* the head of the binary tree of tags */
407 int permit_duplicates
= 1; /* Nonzero means allow duplicate tags. */
409 /* A `struct linebuffer' is a structure which holds a line of text.
410 `readline' reads a line from a stream into a linebuffer
411 and works regardless of the length of the line. */
419 struct linebuffer lb
; /* the current line */
420 struct linebuffer filename_lb
; /* used to read in filenames */
424 struct linebuffer lb
; /* used by C_entries instead of lb */
439 printf ("for Emacs version 19.\n");
447 printf ("These are the options accepted by %s. You may use unambiguous\n\
448 abbreviations for the long option names.\n\n", progname
);
450 puts ("-a, --append\n\
451 Append tag entries to existing tags file.");
453 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
454 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
455 extensions are always assumed to be C++ code.");
456 fputs ("-d, --defines\n\
457 Create tag entries for #defines, too.", stdout
);
460 fputs (" This is the default\n\
466 Don't create tag entries for #defines.", stdout
);
469 fputs (" This is the default\n\
474 -o FILE, --output=FILE\n\
475 Write the tags to FILE.\n\
476 -S, --ignore-indentation\n\
477 Don't rely on indentation quite as much as normal. Currently,\n\
478 this means not to assume that a closing brace in the first\n\
479 column is the final brace of a function or structure\n\
481 puts ("-t, --typedefs\n\
482 Generate tag entries for typedefs. This is the default\n\
484 puts ("-T, --typedefs-and-c++\n\
485 Generate tag entries for typedefs, struct/enum/union tags, and\n\
486 C++ member functions.");
489 puts ("-i FILE, --include=FILE\n\
490 Include a note in tag file indicating that, when searching for\n\
491 a tag, one should also consult the tags file FILE after\n\
492 checking the current file.");
496 puts ("-B, --backward-search\n\
497 Write the search commands for the tag entries using '?', the\n\
498 backward-search command.");
499 puts ("-F, --forward-search\n\
500 Write the search commands for the tag entries using '/', the\n\
501 forward-search command.");
502 puts ("-u, --update\n\
503 Update the tag entries for the given files, leaving tag\n\
504 entries for other files in place. Currently, this is\n\
505 implemented by deleting the existing entries for the given\n\
506 files and then rewriting the new entries at the end of the\n\
507 tags file. It is often faster to simply rebuild the entire\n\
508 tag file than to use this.");
509 puts ("-v, --vgrind\n\
510 Generates an index of items intended for human consumption,\n\
511 similar to the output of vgrind. The index is sorted, and\n\
512 gives the page number of each item.");
513 puts ("-x, --cxref\n\
514 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
515 The output uses line numbers instead of page numbers, but\n\
516 beyond that the differences are cosmetic; try both to see\n\
518 puts ("-w, --no-warn\n\
519 Suppress warning messages about entries defined in multiple\n\
523 puts ("-V, --version\n\
524 Print the version of the program.\n\
526 Print this help message.");
539 unsigned int nincluded_files
= 0;
540 char **included_files
= xnew (argc
, char *);
545 extern char *gfnames ();
546 extern char *massage_name ();
552 emacs_tags_format
= 1;
554 emacs_tags_format
= 0;
558 * If etags, always find typedefs and structure tags. Why not?
559 * Also default is to find macro constants.
561 if (emacs_tags_format
)
562 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
567 opt
= getopt_long (argc
, argv
, "aCdDo:f:StTi:BFuvxwVH", longopts
, 0);
575 /* If getopt returns '\0', then it has already processed a
576 long-named option. We should do nothing. */
579 /* Common options. */
597 "%s: -%c flag may only be given once\n", progname
, opt
);
610 typedefs_and_cplusplus
++;
621 if (!emacs_tags_format
)
623 included_files
[nincluded_files
++] = optarg
;
629 if (emacs_tags_format
)
634 if (emacs_tags_format
)
639 if (emacs_tags_format
)
647 if (emacs_tags_format
)
652 if (emacs_tags_format
)
661 if (optind
== argc
&& nincluded_files
== 0)
663 fprintf (stderr
, "%s: No input files specified.\n", progname
);
666 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
673 outfile
= emacs_tags_format
? "TAGS" : "tags";
676 init (); /* set up boolean "functions" */
679 initbuffer (&lbs
[0].lb
);
680 initbuffer (&lbs
[1].lb
);
681 initbuffer (&filename_lb
);
683 * loop through files finding functions
685 if (emacs_tags_format
)
687 if (streq (outfile
, "-"))
690 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
701 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
705 error ("Can't find file %s\n", this_file
);
710 this_file
= massage_name (this_file
);
713 } /* solely to balance out the ifdef'd parens above */
716 for (; optind
< argc
; optind
++)
718 this_file
= argv
[optind
];
722 /* Input file named "-" means read file names from stdin
724 if (streq (this_file
, "-"))
726 while (!feof (stdin
))
728 (void) readline (&filename_lb
, stdin
);
729 if (strlen (filename_lb
.buffer
) > 0)
730 process_file (filename_lb
.buffer
);
734 process_file (this_file
);
738 if (emacs_tags_format
)
740 while (nincluded_files
-- > 0)
741 fprintf (outf
, "\f\n%s,include\n", *included_files
++);
743 (void) fclose (outf
);
754 /* update cannot be set under VMS, so we may assume that argc
755 and argv have not been munged. */
756 for (i
= optind
; i
< argc
; i
++)
759 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
760 outfile
, argv
[i
], outfile
);
765 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
772 (void) fclose (outf
);
775 sprintf (cmd
, "sort %s -o %s", outfile
, outfile
);
783 * This routine is called on each file argument.
789 struct stat stat_buf
;
791 if (stat (file
, &stat_buf
) || !S_ISREG (stat_buf
.st_mode
))
793 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
797 if (streq (file
, outfile
) && !streq (outfile
, "-"))
799 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
803 if (emacs_tags_format
)
805 fprintf (outf
, "\f\n%s,%d\n", file
, total_size_of_entries (head
));
813 * This routine sets up the boolean pseudo-functions which work
814 * by setting boolean flags dependent upon the corresponding character
815 * Every char which is NOT in that string is not a white char. Therefore,
816 * all of the array "_wht" is set to FALSE, and then the elements
817 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
818 * of a char is TRUE if it is the string "white", else FALSE.
826 for (i
= 0; i
< 0177; i
++)
827 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
828 for (sp
= white
; *sp
; sp
++)
830 for (sp
= endtk
; *sp
; sp
++)
832 for (sp
= intk
; *sp
; sp
++)
834 for (sp
= begtk
; *sp
; sp
++)
836 _wht
[0] = _wht
['\n'];
837 _etk
[0] = _etk
['\n'];
838 _btk
[0] = _btk
['\n'];
839 _itk
[0] = _itk
['\n'];
843 * This routine opens the specified file and calls the function
844 * which finds the function and type definitions.
851 void prolog_funcs ();
853 inf
= fopen (file
, "r");
859 curfile
= savestr (file
);
860 cp
= etags_rindex (file
, '.');
862 header_file
= (cp
&& (streq (cp
+ 1, "h")));
864 /* .tex, .aux or .bbl implies LaTeX source code */
865 if (cp
&& (streq (cp
+ 1, "tex") || streq (cp
+ 1, "aux")
866 || streq (cp
+ 1, "bbl")))
869 goto close_and_return
;
871 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
872 if (cp
&& (streq (cp
+ 1, "l")
873 || streq (cp
+ 1, "el")
874 || streq (cp
+ 1, "lsp")
875 || streq (cp
+ 1, "lisp")
876 || streq (cp
+ 1, "cl")
877 || streq (cp
+ 1, "clisp")))
880 goto close_and_return
;
882 /* .scm or .sm or .scheme or ... implies scheme source code */
883 if (cp
&& (streq (cp
+ 1, "sm")
884 || streq (cp
+ 1, "scm")
885 || streq (cp
+ 1, "scheme")
886 || streq (cp
+ 1, "t")
887 || streq (cp
+ 1, "sch")
888 || streq (cp
+ 1, "SM")
889 || streq (cp
+ 1, "SCM")
890 /* The `SCM' or `scm' prefix with a version number */
891 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
892 && string_numeric_p (cp
+ 1))
893 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
894 && string_numeric_p (cp
+ 1))))
900 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
902 if (cp
&& (streq (cp
+ 1, "s")
903 || streq (cp
+ 1, "a")
904 || streq (cp
+ 1, "sa")))
910 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
911 if (cp
&& (streq (cp
+ 1, "C")
912 || streq (cp
+ 1, "H")
913 || streq (cp
+ 1, "cxx")
914 || streq (cp
+ 1, "hxx")
915 || streq (cp
+ 1, "cc")))
917 C_entries (C_PLPL
); /* C++ */
918 goto close_and_return
;
920 /* .cs or .hs: a C* file */
921 if (cp
&& (streq (cp
+ 1, "cs")
922 || streq (cp
+ 1, "hs")))
925 goto close_and_return
;
927 /* .y: a yacc file */
928 if (cp
&& (streq (cp
+ 1, "y")))
931 goto close_and_return
;
933 /* .pl implies prolog source code */
934 if (cp
&& streq (cp
+ 1, "pl"))
937 goto close_and_return
;
939 /* .p or .pas: a Pascal file */
940 if (cp
&& (streq (cp
+ 1, "p")
941 || streq (cp
+ 1, "pas")))
944 goto close_and_return
;
946 /* If .f or .for, assume it is fortran or nothing. */
947 if (cp
&& (streq (cp
+ 1, "f")
948 || streq (cp
+ 1, "for")))
951 goto close_and_return
;
953 /* if not a .c or .h or .y file, try fortran */
954 if (cp
&& ((cp
[1] != 'c'
957 || (cp
[1] != 0 && cp
[2] != 0)))
959 if (PF_funcs (inf
) != 0)
960 goto close_and_return
;
961 rewind (inf
); /* no fortran tags found, try C */
963 C_entries (cplusplus
? C_PLPL
: 0);
969 /* Nonzero if string STR is composed of digits. */
972 string_numeric_p (str
)
977 if (*str
< '0' || *str
> '9')
984 /* Should take a TOKEN* instead!! */
986 pfnote (name
, is_func
, named
, linestart
, linelen
, lno
, cno
)
987 char *name
; /* tag name */
988 logical is_func
; /* function or type name? */
989 logical named
; /* tag different from text of definition? */
1000 np
= (NODE
*) malloc (sizeof (NODE
));
1003 if (!emacs_tags_format
)
1005 /* It's okay to output early in etags -- it only disrupts the
1006 * character count of the tag entries, which is no longer used
1007 * by tags.el anyway.
1009 error ("too many entries to sort");
1014 np
= xnew (1, NODE
);
1016 /* If ctags mode, change name "main" to M<thisfilename>. */
1017 if (!emacs_tags_format
&& !cxref_style
&& streq (name
, "main"))
1019 fp
= etags_rindex (curfile
, '/');
1020 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
1021 fp
= etags_rindex (name
, '.');
1022 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
1026 np
->name
= savestr (name
);
1028 np
->is_func
= is_func
;
1031 /* UNCOMMENT THE +1 HERE: */
1032 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
1033 np
->left
= np
->right
= 0;
1034 if (emacs_tags_format
)
1036 c
= linestart
[linelen
];
1037 linestart
[linelen
] = 0;
1039 else if (cxref_style
== 0)
1041 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
1044 np
->pat
= savestr (linestart
);
1045 if (emacs_tags_format
)
1047 linestart
[linelen
] = c
;
1050 add_node (np
, &head
);
1055 * recurse on left children, iterate on right children.
1059 register NODE
*node
;
1063 register NODE
*node_right
= node
->right
;
1064 free_tree (node
->left
);
1067 free ((char *) node
);
1074 * Adds a node to the tree of nodes. In etags mode, we don't keep
1075 * it sorted; we just keep a linear list. In ctags mode, maintain
1076 * an ordered tree, with no attempt at balancing.
1078 * add_node is the only function allowed to add nodes, so it can
1081 /* Must avoid static vars within functions since some systems
1082 #define static as nothing. */
1083 static NODE
*last_node
= NULL
;
1086 add_node (node
, cur_node_p
)
1087 NODE
*node
, **cur_node_p
;
1090 register NODE
*cur_node
= *cur_node_p
;
1092 if (cur_node
== NULL
)
1099 if (emacs_tags_format
)
1103 fatal ("internal error in add_node");
1104 last_node
->right
= node
;
1110 dif
= strcmp (node
->name
, cur_node
->name
);
1113 * If this tag name matches an existing one, then
1114 * do not add the node, but maybe print a warning.
1118 if (node
->file
== cur_node
->file
)
1122 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1123 node
->file
, lineno
, node
->name
);
1124 fprintf (stderr
, "Second entry ignored\n");
1128 if (!cur_node
->been_warned
&& !no_warnings
)
1131 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1132 node
->file
, cur_node
->file
, node
->name
);
1134 cur_node
->been_warned
= TRUE
;
1138 /* Maybe refuse to add duplicate nodes. */
1139 if (!permit_duplicates
)
1141 if (!strcmp (node
->name
, cur_node
->name
)
1142 && !strcmp (node
->file
, cur_node
->file
))
1146 /* Actually add the node */
1147 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1153 register NODE
*node
;
1160 /* Output subentries that precede this one */
1161 put_entries (node
->left
);
1163 /* Output this entry */
1165 if (emacs_tags_format
)
1169 fprintf (outf
, "%s\177%s\001%d,%d\n",
1170 node
->pat
, node
->name
,
1171 node
->lno
, node
->cno
);
1175 fprintf (outf
, "%s\177%d,%d\n",
1177 node
->lno
, node
->cno
);
1180 else if (!cxref_style
)
1182 fprintf (outf
, "%s\t%s\t",
1183 node
->name
, node
->file
);
1187 putc (searchar
, outf
);
1190 for (sp
= node
->pat
; *sp
; sp
++)
1192 if (*sp
== '\\' || *sp
== searchar
)
1196 putc (searchar
, outf
);
1199 { /* a typedef; text pattern inadequate */
1200 fprintf (outf
, "%d", node
->lno
);
1204 else if (vgrind_style
)
1205 fprintf (stdout
, "%s %s %d\n",
1206 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1208 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1209 node
->name
, node
->lno
, node
->file
, node
->pat
);
1211 /* Output subentries that follow this one */
1212 put_entries (node
->right
);
1215 /* Length of a number's decimal representation. */
1223 for (; num
; num
/= 10)
1229 * Return total number of characters that put_entries will output for
1230 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1231 * is set, but called only in that case. This count is irrelevant with
1232 * the new tags.el, but is still supplied for backward compatibility.
1235 total_size_of_entries (node
)
1236 register NODE
*node
;
1244 for (; node
; node
= node
->right
)
1246 /* Count left subentries. */
1247 total
+= total_size_of_entries (node
->left
);
1249 /* Count this entry */
1250 total
+= strlen (node
->pat
) + 1;
1251 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1253 total
+= 1 + strlen (node
->name
); /* \001name */
1260 * The C symbol tables.
1263 Stab
*C_stab
, *C_PLPL_stab
, *C_STAR_stab
;
1267 * Stab *get_C_stab (int c_ext);
1269 #define get_C_stab(c_ext) ((c_ext & C_STAR) ? C_STAR_stab : \
1270 (c_ext & C_PLPL) ? C_PLPL_stab : \
1274 add_keyword (stab
, sym
, type
)
1279 stab_search (stab
, sym
, strlen (sym
))->type
= type
;
1283 C_create_stab (c_ext
)
1288 stab
= stab_create ();
1292 add_keyword (stab
, "class", st_C_struct
);
1294 add_keyword (stab
, "domain", st_C_struct
);
1295 add_keyword (stab
, "union", st_C_struct
);
1296 add_keyword (stab
, "struct", st_C_struct
);
1297 add_keyword (stab
, "enum", st_C_enum
);
1298 add_keyword (stab
, "typedef", st_C_typedef
);
1299 add_keyword (stab
, "define", st_C_define
);
1300 add_keyword (stab
, "long", st_C_typespec
);
1301 add_keyword (stab
, "short", st_C_typespec
);
1302 add_keyword (stab
, "int", st_C_typespec
);
1303 add_keyword (stab
, "char", st_C_typespec
);
1304 add_keyword (stab
, "float", st_C_typespec
);
1305 add_keyword (stab
, "double", st_C_typespec
);
1306 add_keyword (stab
, "signed", st_C_typespec
);
1307 add_keyword (stab
, "unsigned", st_C_typespec
);
1308 add_keyword (stab
, "auto", st_C_typespec
);
1309 add_keyword (stab
, "void", st_C_typespec
);
1310 add_keyword (stab
, "extern", st_C_typespec
);
1311 add_keyword (stab
, "static", st_C_typespec
);
1312 add_keyword (stab
, "const", st_C_typespec
);
1313 add_keyword (stab
, "volatile", st_C_typespec
);
1321 C_stab
= C_create_stab (0);
1322 C_PLPL_stab
= C_create_stab (C_PLPL
);
1323 C_STAR_stab
= C_create_stab (C_STAR
| C_PLPL
);
1327 * C functions are recognized using a simple finite automaton.
1328 * funcdef is its state variable.
1332 fnone
, /* nothing seen */
1333 ftagseen
, /* function-like tag seen */
1334 fstartlist
, /* just after open parenthesis */
1335 finlist
, /* in parameter list */
1336 flistseen
, /* after parameter list */
1337 fignore
/* before open brace */
1342 /* typedefs are recognized using a simple finite automaton.
1343 * typeddef is its state variable.
1347 tnone
, /* nothing seen */
1348 ttypedseen
, /* typedef keyword seen */
1349 tinbody
, /* inside typedef body */
1350 tend
/* just before typedef tag */
1355 /* struct tags for C++ are recognized using another simple
1356 * finite automaton. `structdef' is its state variable.
1357 * This machinery is only invoked for C++; otherwise structdef
1358 * should remain snone. However, this machinery can easily be
1359 * adapted to find structure tags in normal C code.
1363 snone
, /* nothing seen yet */
1364 skeyseen
, /* struct-like keyword seen */
1365 stagseen
, /* struct-like tag seen */
1366 scolonseen
, /* colon seen after struct-like tag */
1367 sinbody
/* in struct body: recognize member func defs*/
1371 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1372 * struct tag, and structkey is the preceding struct-like keyword.
1374 char structtag
[BUFSIZ
];
1375 Stab_entry
*structkey
;
1378 * Yet another little state machine to deal with preprocessor lines.
1382 dnone
, /* nothing seen */
1383 dsharpseen
, /* '#' seen as first char on line */
1384 ddefineseen
, /* '#' and 'define' seen */
1385 dignorerest
/* ignore rest of line */
1390 * Set this to TRUE, and the next token considered is called a function.
1391 * Used only for GNUmacs's function-defining macros.
1393 logical next_token_is_func
;
1396 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1402 * This routine finds functions, typedefs, #define's and
1403 * struct/union/enum definitions in C syntax and adds them
1407 #define curlb (lbs[curndx].lb)
1408 #define othlb (lbs[1-curndx].lb)
1409 #define newlb (lbs[newndx].lb)
1410 #define curlinepos (lbs[curndx].linepos)
1411 #define othlinepos (lbs[1-curndx].linepos)
1412 #define newlinepos (lbs[newndx].linepos)
1414 /* Save and restore token state. This is used when preprocessor defines
1415 are handled, to avoid disturbing active function/typedef/struct states. */
1416 #define TOKEN_SAVED_P (savetok.lineno > 0)
1417 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1418 savetok.len = toklen, strcpy(savenameb, nameb))
1419 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1420 toklen = tok.len, strcpy(nameb, savenameb), \
1423 #define CNL_SAVE_DEFINEDEF \
1425 SET_FILEPOS (curlinepos, inf, charno); \
1427 charno += readline (&curlb, inf); \
1428 lp = curlb.buffer; \
1435 CNL_SAVE_DEFINEDEF; \
1436 if (TOKEN_SAVED_P) \
1438 definedef = dnone; \
1441 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1442 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1443 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1444 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1448 int c_ext
; /* extension of C? */
1450 register char c
; /* latest char read; '\0' for end of line */
1451 register char *lp
; /* pointer one beyond the character `c' */
1452 int curndx
, newndx
; /* indices for current and new lb */
1453 TOKEN tok
; /* latest token read for funcdef & structdef */
1454 char nameb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1455 register int tokoff
; /* offset in line of start of latest token */
1456 register int toklen
; /* length of latest token */
1457 int cblev
; /* current curly brace level */
1458 int parlev
; /* current parenthesis level */
1459 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1461 TOKEN savetok
; /* saved token during preprocessor handling */
1463 char savenameb
[BUFSIZ
]; /* ouch! */
1466 curndx
= newndx
= 0;
1472 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1473 next_token_is_func
= yacc_rules
= FALSE
;
1474 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1477 cplpl
= c_ext
& C_PLPL
;
1486 /* If we're at the end of the line, the next character is a
1487 '\0'; don't skip it, because it's the thing that tells us
1488 to read the next line. */
1509 /* Newlines inside comments do not end macro definitions in
1524 /* Newlines inside strings, do not end macro definitions
1525 in traditional cpp, even though compilers don't
1526 usually accept them. */
1543 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1548 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1558 else if (cplpl
&& *lp
== '/')
1566 if ((c_ext
& YACC
) && *lp
== '%')
1568 /* entering or exiting rules section in yacc file */
1570 definedef
= dnone
; funcdef
= fnone
;
1571 typdef
= tnone
; structdef
= snone
;
1572 next_token_is_func
= FALSE
;
1573 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1575 yacc_rules
= !yacc_rules
;
1581 if (lp
== newlb
.buffer
+ 1 && definedef
== dnone
)
1582 definedef
= dsharpseen
;
1587 /* Consider token only if some complicated conditions are satisfied. */
1588 if (((cblev
== 0 && structdef
!= scolonseen
)
1589 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
1590 && definedef
!= dignorerest
1591 && (funcdef
!= finlist
1592 || (definedef
!= dnone
&& definedef
!= dignorerest
)))
1598 if (cplpl
&& c
== ':' && *lp
== ':' && begtoken(*(lp
+ 1)))
1601 * This handles :: in the middle, but not at beginning
1609 logical is_func
= FALSE
;
1611 tok
.lineno
= lineno
;
1612 tok
.p
= newlb
.buffer
+ tokoff
;
1616 || consider_token (c
, lp
, &tok
,
1617 c_ext
, cblev
, &is_func
))
1619 if (structdef
== sinbody
1620 && definedef
== dnone
1622 /* function defined in C++ class body */
1625 sprintf (nameb
, "%s::%.*s",
1626 ((structtag
[0] == '\0')
1627 ? "_anonymous_" : structtag
),
1632 sprintf (nameb
, "%.*s", tok
.len
, tok
.p
);
1635 if (structdef
== stagseen
1639 if (definedef
== dnone
1640 && (funcdef
== ftagseen
1641 || structdef
== stagseen
1644 if (newndx
== curndx
)
1645 curndx
= 1 - curndx
; /* switch line buffers */
1648 MAKE_TAG_FROM_NEW_LB (is_func
);
1652 } /* if (endtoken (c)) */
1653 else if (intoken (c
))
1658 } /* if (midtoken) */
1659 else if (begtoken (c
))
1670 MAKE_TAG_FROM_OTH_LB (TRUE
);
1677 if (structdef
== stagseen
)
1681 /* Take a quick peek ahead for define directive,
1682 so we can avoid saving the token when not absolutely
1683 necessary. [This is a speed hack.] */
1684 if (c
== 'd' && strneq(lp
, "efine", 5)
1685 && iswhite(*(lp
+ 5)))
1688 definedef
= ddefineseen
;
1692 definedef
= dignorerest
;
1695 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1697 tokoff
= lp
- 1 - newlb
.buffer
;
1703 } /* if must look at token */
1706 /* Detect end of line, colon, comma, semicolon and various braces
1707 after having handled a token.*/
1711 if (definedef
!= dnone
)
1713 if (structdef
== stagseen
)
1714 structdef
= scolonseen
;
1721 MAKE_TAG_FROM_OTH_LB (FALSE
);
1731 if (definedef
!= dnone
)
1733 if (cblev
== 0 && typdef
== tend
)
1736 MAKE_TAG_FROM_OTH_LB (FALSE
);
1738 if (funcdef
!= fignore
)
1744 if (definedef
!= dnone
)
1746 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1748 if (structdef
== stagseen
)
1752 if (definedef
!= dnone
)
1757 funcdef
= fstartlist
;
1766 if (definedef
!= dnone
)
1774 funcdef
= flistseen
;
1778 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
1782 if (definedef
!= dnone
)
1784 if (typdef
== ttypedseen
)
1788 case skeyseen
: /* unnamed struct */
1789 structtag
[0] = '\0';
1790 structdef
= sinbody
;
1793 case scolonseen
: /* named struct */
1794 structdef
= sinbody
;
1795 MAKE_TAG_FROM_OTH_LB (FALSE
);
1801 MAKE_TAG_FROM_OTH_LB (TRUE
);
1809 if (definedef
!= dnone
)
1811 if (funcdef
== fstartlist
)
1812 funcdef
= fnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
1815 if (definedef
!= dnone
)
1817 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
1819 cblev
= 0; /* reset curly brace level if first column */
1820 parlev
= 0; /* also reset paren level, just in case... */
1826 if (typdef
== tinbody
)
1829 (void) strcpy (structtag
, "<error 2>");
1847 if (definedef
!= dnone
)
1849 /* These surely cannot follow a function tag. */
1850 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1854 /* If a macro spans multiple lines don't reset its state. */
1862 } /* while not eof */
1867 * checks to see if the current token is at the start of a
1868 * function, or corresponds to a typedef, or is a struct/union/enum
1871 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1872 * C_EXT is which language we are looking at.
1874 * In the future we will need some way to adjust where the end of
1875 * the token is; for instance, implementing the C++ keyword
1876 * `operator' properly will adjust the end of the token to be after
1877 * whatever follows `operator'.
1884 * next_token_is_func IN OUT
1888 consider_token (c
, lp
, tokp
, c_ext
, cblev
, is_func
)
1889 register char c
; /* IN: first char after the token */
1890 register char *lp
; /* IN: lp points to 2nd char after the token */
1891 register TOKEN
*tokp
; /* IN: token pointer */
1892 int c_ext
; /* IN: C extensions mask */
1893 int cblev
; /* IN: curly brace level */
1894 logical
*is_func
; /* OUT */
1896 Stab_entry
*tokse
= stab_find (get_C_stab (c_ext
), tokp
->p
, tokp
->len
);
1897 enum sym_type toktype
= stab_type (tokse
);
1900 * Advance the definedef state machine.
1905 /* We're not on a preprocessor line. */
1908 if (toktype
== st_C_define
)
1910 definedef
= ddefineseen
;
1914 definedef
= dignorerest
;
1919 * Make a tag for any macro.
1921 definedef
= dignorerest
;
1922 *is_func
= (c
== '(');
1923 if (!*is_func
&& !constantypedefs
)
1930 error ("internal error: definedef value");
1939 if (toktype
== st_C_typedef
)
1942 typdef
= ttypedseen
;
1957 /* Do not return here, so the structdef stuff has a chance. */
1971 * This structdef business is currently only invoked when cblev==0.
1972 * It should be recursively invoked whatever the curly brace level,
1973 * and a stack of states kept, to allow for definitions of structs
1976 * This structdef business is NOT invoked when we are ctags and the
1977 * file is plain C. This is because a struct tag may have the same
1978 * name as another tag, and this loses with ctags.
1980 * This if statement deals with the typdef state machine as
1981 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1982 * return (FALSE). All the other code here is for the structdef
1989 if (typdef
== ttypedseen
1990 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1992 structdef
= skeyseen
;
1997 if (structdef
== skeyseen
)
1999 if (stab_type (structkey
) == st_C_struct
)
2001 (void) strncpy (structtag
, tokp
->p
, tokp
->len
);
2002 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
2006 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
2008 structdef
= stagseen
;
2012 /* Avoid entering funcdef stuff if typdef is going on. */
2013 if (typdef
!= tnone
)
2019 /* Detect GNUmacs's function-defining macros. */
2020 if (definedef
== dnone
)
2022 if (strneq (tokp
->p
, "DEF", 3)
2023 || strneq (tokp
->p
, "ENTRY", 5)
2024 || strneq (tokp
->p
, "SYSCALL", 7)
2025 || strneq (tokp
->p
, "PSEUDO", 6))
2027 next_token_is_func
= TRUE
;
2030 if (strneq (tokp
->p
, "EXFUN", 5))
2032 next_token_is_func
= FALSE
;
2036 if (next_token_is_func
)
2038 next_token_is_func
= FALSE
;
2040 *is_func
= TRUE
; /* to force search string in ctags */
2048 funcdef
= fnone
; /* should be useless */
2051 if (funcdef
== fnone
)
2062 /* Fortran parsing */
2078 linecharno
= charno
;
2079 charno
+= readline (&lb
, fi
);
2082 dbp
++; /* Ratfor escape to fortran */
2083 while (isspace (*dbp
))
2090 if (tail ("integer"))
2098 if (tail ("logical"))
2102 if (tail ("complex") || tail ("character"))
2106 if (tail ("double"))
2108 while (isspace (*dbp
))
2112 if (tail ("precision"))
2118 while (isspace (*dbp
))
2125 if (tail ("function"))
2129 if (tail ("subroutine"))
2137 if (tail ("program"))
2142 if (tail ("procedure"))
2154 register int len
= 0;
2156 while (*cp
&& (*cp
& ~' ') == ((*(dbp
+ len
)) & ~' '))
2169 while (isspace (*dbp
))
2174 while (isspace (*dbp
))
2176 if (!isdigit (*dbp
))
2178 --dbp
; /* force failure */
2183 while (isdigit (*dbp
));
2191 char nambuf
[BUFSIZ
];
2193 while (isspace (*dbp
))
2200 for (cp
= dbp
+ 1; *cp
&& (isalpha (*cp
) || isdigit (*cp
)
2201 || (*cp
== '_') || (*cp
== '$')); cp
++)
2205 (void) strcpy (nambuf
, dbp
);
2207 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2211 /* Handle a file of assembler code. */
2227 linecharno
= charno
;
2228 charno
+= readline (&lb
, fi
);
2231 for (i
= 0; ((c
= dbp
[i
]) && !isspace (c
)) && (c
!= ':'); i
++)
2234 if ((i
> 0) && (c
== ':'))
2239 /* Added by Mosur Mohan, 4/22/88 */
2240 /* Pascal parsing */
2242 #define GET_NEW_LINE \
2244 linecharno = charno; lineno++; \
2245 charno += 1 + readline (&lb, inf); \
2249 /* Locates tags for procedures & functions.
2250 * Doesn't do any type- or var-definitions.
2251 * It does look for the keyword "extern" or "forward"
2252 * immediately following the procedure statement;
2253 * if found, the tag is skipped.
2260 struct linebuffer tline
; /* mostly copied from C_entries */
2264 char nambuf
[BUFSIZ
];
2266 logical
/* each of these flags is TRUE iff: */
2267 incomm1
, /* point is inside {..} comment */
2268 incomm2
, /* point is inside (*..*) comment */
2269 inquote
, /* point is inside '..' string */
2270 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2271 /* keyword, so next item = potential tag */
2272 found_tag
, /* point is after a potential tag */
2273 inparms
, /* point is within parameter-list */
2274 verify_tag
; /* point has passed the parm-list, so the */
2275 /* next token will determine whether */
2276 /* this is a FORWARD/EXTERN to be */
2277 /* ignored, or whether it is a real tag */
2283 initbuffer (&tline
);
2285 incomm1
= incomm2
= inquote
= FALSE
;
2286 found_tag
= FALSE
; /* have a proc name; check if extern */
2287 get_tagname
= FALSE
; /* have found "procedure" keyword */
2288 inparms
= FALSE
; /* found '(' after "proc" */
2289 verify_tag
= FALSE
; /* check if "extern" is ahead */
2291 /* long main loop to get next char */
2295 if (c
== 0) /* if end of line */
2300 if (!((found_tag
&& verify_tag
) ||
2302 c
= *dbp
++; /* only if don't need *dbp pointing */
2303 /* to the beginning of the name of */
2304 /* the procedure or function */
2306 if (incomm1
) /* within { - } comments */
2312 else if (incomm2
) /* within (* - *) comments */
2316 while ((c
= *dbp
++) == '*')
2335 inquote
= TRUE
; /* found first quote */
2337 case '{': /* found open-{-comment */
2341 if (*dbp
== '*') /* found open-(*-comment */
2346 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2349 case ')': /* end of parms list */
2354 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2361 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2363 /* check if this is an "extern" declaration */
2366 if ((*dbp
== 'e') || (*dbp
== 'E'))
2368 if (tail ("extern")) /* superfluous, really! */
2374 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2376 if (tail ("forward")) /* check for forward reference */
2382 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2386 pfnote (nambuf
, TRUE
, FALSE
,
2387 tline
.buffer
, cp
- tline
.buffer
+ 1,
2388 save_lineno
, save_lcno
);
2392 if (get_tagname
) /* grab name of proc or fn */
2397 /* save all values for later tagging */
2398 tline
.size
= lb
.size
;
2399 strcpy (tline
.buffer
, lb
.buffer
);
2400 save_lineno
= lineno
;
2401 save_lcno
= linecharno
;
2403 /* grab block name */
2404 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2408 strcpy (nambuf
, dbp
);
2410 dbp
= cp
; /* restore dbp to e-o-token */
2411 get_tagname
= FALSE
;
2415 /* and proceed to check for "extern" */
2417 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2418 (!found_tag
) && (!get_tagname
))
2420 /* check for proc/fn keywords */
2424 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2428 if (tail ("unction"))
2433 } /* while not e-o-f */
2437 * lisp tag functions
2438 * just look for (def or (DEF
2452 linecharno
= charno
;
2453 charno
+= readline (&lb
, fi
);
2459 while (!isspace (*dbp
))
2461 while (isspace (*dbp
))
2467 /* Check for (foo::defmumble name-defined ... */
2470 while (*dbp
&& !isspace (*dbp
)
2471 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2476 while (*dbp
== ':');
2478 if (L_isdef (dbp
- 1))
2480 while (!isspace (*dbp
))
2482 while (isspace (*dbp
))
2496 return ((dbp
[1] == 'd' || dbp
[1] == 'D')
2497 && (dbp
[2] == 'e' || dbp
[2] == 'E')
2498 && (dbp
[3] == 'f' || dbp
[3] == 'F'));
2505 return ((*(++dbp
) == 'q' || *dbp
== 'Q')
2506 && (*(++dbp
) == 'u' || *dbp
== 'U')
2507 && (*(++dbp
) == 'o' || *dbp
== 'O')
2508 && (*(++dbp
) == 't' || *dbp
== 'T')
2509 && (*(++dbp
) == 'e' || *dbp
== 'E')
2510 && isspace(*(++dbp
)));
2518 char nambuf
[BUFSIZ
];
2520 if (*dbp
== '\'') /* Skip prefix quote */
2522 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2525 while (isspace(*dbp
))
2528 for (cp
= dbp
/*+1*/; *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')'; cp
++)
2535 (void) strcpy (nambuf
, dbp
);
2537 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2538 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2543 * Scheme tag functions
2544 * look for (def... xyzzy
2545 * look for (def... (xyzzy
2546 * look for (def ... ((...(xyzzy ....
2547 * look for (set! xyzzy
2550 static void get_scheme ();
2563 linecharno
= charno
;
2564 charno
+= readline (&lb
, fi
);
2566 if (dbp
[0] == '(' &&
2567 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2568 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2569 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2571 while (!isspace (*dbp
))
2573 /* Skip over open parens and white space */
2574 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2578 if (dbp
[0] == '(' &&
2579 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2580 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2581 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2582 (dbp
[4] == '!' || dbp
[4] == '!') &&
2585 while (!isspace (*dbp
))
2587 /* Skip over white space */
2588 while (isspace (*dbp
))
2600 char nambuf
[BUFSIZ
];
2604 /* Go till you get to white space or a syntactic break */
2605 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2607 /* Null terminate the string there. */
2610 /* Copy the string */
2611 strcpy (nambuf
, dbp
);
2612 /* Unterminate the string */
2614 /* Announce the change */
2615 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2619 /* Find tags in TeX and LaTeX input files. */
2621 /* TEX_toktab is a table of TeX control sequences that define tags.
2622 Each TEX_tabent records one such control sequence.
2623 CONVERT THIS TO USE THE Stab TYPE!! */
2631 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2633 /* Default set of control sequences to put into TEX_toktab.
2634 The value of environment var TEXTAGS is prepended to this. */
2636 static char *TEX_defenv
=
2637 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2640 struct TEX_tabent
*TEX_decode_env ();
2644 static char TEX_esc
= '\\';
2645 static char TEX_opgrp
= '{';
2646 static char TEX_clgrp
= '}';
2649 * TeX/LaTeX scanning loop.
2662 /* Select either \ or ! as escape character. */
2665 /* Initialize token table once from environment. */
2667 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2670 { /* Scan each line in file */
2672 linecharno
= charno
;
2673 charno
+= readline (&lb
, fi
);
2676 while (dbp
= etags_index (dbp
, TEX_esc
)) /* Look at each escape in line */
2682 linecharno
+= dbp
- lasthit
;
2684 i
= TEX_Token (lasthit
);
2687 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2688 break; /* We only save a line once */
2694 #define TEX_LESC '\\'
2695 #define TEX_SESC '!'
2698 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2699 /* chars accordingly. */
2707 while ((c
= getc (f
)) != EOF
)
2709 /* Skip to next line if we hit the TeX comment char. */
2713 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2732 /* Read environment and prepend it to the default string. */
2733 /* Build token table. */
2736 TEX_decode_env (evarname
, defenv
)
2740 register char *env
, *p
;
2742 struct TEX_tabent
*tab
;
2745 /* Append default string to environment. */
2746 env
= getenv (evarname
);
2750 env
= concat (env
, defenv
, "");
2752 /* Allocate a token table */
2753 for (size
= 1, p
= env
; p
;)
2754 if ((p
= etags_index (p
, ':')) && *(++p
))
2756 /* Add 1 to leave room for null terminator. */
2757 tab
= xnew (size
+ 1, struct TEX_tabent
);
2759 /* Unpack environment string into token table. Be careful about */
2760 /* zero-length strings (leading ':', "::" and trailing ':') */
2763 p
= etags_index (env
, ':');
2764 if (!p
) /* End of environment string. */
2765 p
= env
+ strlen (env
);
2767 { /* Only non-zero strings. */
2768 tab
[i
].name
= savenstr (env
, p
- env
);
2769 tab
[i
].len
= strlen (tab
[i
].name
);
2776 tab
[i
].name
= NULL
; /* Mark end of table. */
2784 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2785 The name being defined actually starts at (NAME + LEN + 1).
2786 But we seem to include the TeX command in the tag name. */
2789 TEX_getit (name
, len
)
2793 char *p
= name
+ len
;
2794 char nambuf
[BUFSIZ
];
2799 /* Let tag name extend to next group close (or end of line) */
2800 while (*p
&& *p
!= TEX_clgrp
)
2802 (void) strncpy (nambuf
, name
, p
- name
);
2803 nambuf
[p
- name
] = 0;
2805 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2809 /* If the text at CP matches one of the tag-defining TeX command names,
2810 return the etags_index of that command in TEX_toktab.
2811 Otherwise return -1. */
2813 /* Keep the capital `T' in `Token' for dumb truncating compilers
2814 (this distinguishes it from `TEX_toktab' */
2821 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2822 if (strncmp (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
) == 0)
2827 /* Support for Prolog. */
2829 /* whole head (not only functor, but also arguments)
2830 is gotten in compound term. */
2833 prolog_getit (s
, lineno
, linecharno
)
2838 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2846 if (*s
== '\0') /* syntax error. */
2848 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2850 else if (*s
== '\'')
2852 insquote
= !insquote
;
2855 else if (!insquote
&& *s
== '(')
2860 else if (!insquote
&& *s
== ')')
2866 else if (npar
< 0) /* syntax error. */
2869 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2871 if (npar
!= 0) /* syntax error. */
2881 strcpy (nambuf
, save_s
);
2883 pfnote (nambuf
, TRUE
, FALSE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2886 /* It is assumed that prolog predicate starts from column 0. */
2892 void skip_comment (), prolog_getit ();
2894 lineno
= linecharno
= charno
= 0;
2898 linecharno
+= charno
;
2899 charno
= readline (&lb
, fi
) + 1; /* 1 for newline. */
2901 if (isspace (dbp
[0])) /* not predicate header. */
2903 else if (dbp
[0] == '%') /* comment. */
2905 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2906 skip_comment (&lb
, fi
, &lineno
, &linecharno
);
2908 prolog_getit (dbp
, lineno
, linecharno
);
2913 skip_comment (plb
, fi
, plineno
, plinecharno
)
2914 struct linebuffer
*plb
;
2916 int *plineno
; /* result */
2917 long *plinecharno
; /* result */
2919 while (!substr ("*/", plb
->buffer
))
2922 *plinecharno
+= readline (plb
, fi
) + 1;
2923 } /* 1 for newline. */
2926 /* Return TRUE if 'sub' exists somewhere in 's'. */
2933 while (*s
&& (s
= etags_index (s
, *sub
)))
2934 if (prestr (sub
, s
))
2941 /* Return TRUE if 'pre' is prefix of string 's'. */
2950 else if (*pre
== *s
)
2951 return (prestr (pre
+ 1, s
+ 1));
2956 /* Initialize a linebuffer for use */
2959 initbuffer (linebuffer
)
2960 struct linebuffer
*linebuffer
;
2962 linebuffer
->size
= 200;
2963 linebuffer
->buffer
= xnew (200, char);
2967 * Read a line of text from `stream' into `linebuffer'.
2968 * Return the number of characters read from `stream',
2969 * which is the length of the line including the newline, if any.
2972 readline (linebuffer
, stream
)
2973 struct linebuffer
*linebuffer
;
2974 register FILE *stream
;
2976 char *buffer
= linebuffer
->buffer
;
2977 register char *p
= linebuffer
->buffer
;
2978 register char *pend
;
2979 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2981 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
2985 register int c
= getc (stream
);
2988 linebuffer
->size
*= 2;
2989 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
2990 p
+= buffer
- linebuffer
->buffer
;
2991 pend
= buffer
+ linebuffer
->size
;
2992 linebuffer
->buffer
= buffer
;
2994 if (c
< 0 || c
== '\n')
2997 newline
= (c
== '\n' ? 1 : 0);
3003 return p
- buffer
+ newline
;
3010 return savenstr (cp
, strlen (cp
));
3020 dp
= xnew (len
+ 1, char);
3021 (void) strncpy (dp
, cp
, len
);
3027 * Return the ptr in sp at which the character c last
3028 * appears; NULL if not found
3030 * Identical to v7 rindex, included for portability.
3034 etags_rindex (sp
, c
)
3035 register char *sp
, c
;
3050 * Return the ptr in sp at which the character c first
3051 * appears; NULL if not found
3053 * Identical to v7 index, included for portability.
3058 register char *sp
, c
;
3068 /* Print error message and exit. */
3079 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3086 fprintf (stderr
, "%s: ", progname
);
3087 fprintf (stderr
, s1
, s2
);
3088 fprintf (stderr
, "\n");
3091 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
3097 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3098 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3100 (void) strcpy (result
, s1
);
3101 (void) strcpy (result
+ len1
, s2
);
3102 (void) strcpy (result
+ len1
+ len2
, s3
);
3103 *(result
+ len1
+ len2
+ len3
) = 0;
3108 /* Like malloc but get fatal error if memory is exhausted. */
3114 char *result
= malloc (size
);
3116 fatal ("virtual memory exhausted", 0);
3121 xrealloc (ptr
, size
)
3125 char *result
= realloc (ptr
, size
);
3127 fatal ("virtual memory exhausted");