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` is the current maintainer. 7.5
32 #include <../src/config.h>
37 #include <sys/types.h>
42 extern char *malloc (), *realloc ();
43 extern char *getenv ();
44 extern char *strcpy (), *strncpy ();
47 char *etags_index (), *etags_rindex ();
50 /* Define the symbol ETAGS to make the program "etags",
51 which makes emacs-style tag tables by default.
52 Define CTAGS to make the program "ctags" compatible with the usual one.
53 Define neither one to get behavior that depends
54 on the name with which the program is invoked
55 (but we don't normally compile it that way). */
57 #if !defined(ETAGS) && !defined(CTAGS)
58 /* If neither is defined, program can be run as either. */
63 /* On VMS, CTAGS is not useful, so always do ETAGS. */
70 /* Exit codes for success and failure. */
80 * The FILEPOS abstract type, which represents a position in a file,
81 * plus the following accessor functions:
83 * long GET_CHARNO (pos)
84 * returns absolute char number.
85 * void SET_FILEPOS (pos, fp, charno)
86 * FILE *fp; long charno;
87 * sets `pos' from the current file
88 * position of `fp' and from `charno',
89 * which must be the absolute character
90 * number corresponding to the current
93 * The `pos' parameter is an lvalue expression of type FILEPOS.
94 * Parameters to the accessor functions are evaluated 0 or more times,
95 * and so must have no side effects.
97 * FILEPOS objects can also be assigned and passed to and from
98 * functions in the normal C manner.
100 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
104 /* real implementation */
105 typedef long FILEPOS
;
106 #define GET_CHARNO(pos) ((pos) + 0)
107 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
109 /* debugging implementation */
115 #define GET_CHARNO(pos) ((pos).charno + 0)
116 #define SET_FILEPOS(pos, fp, cno) \
117 ((void) ((pos).charno = (cno), \
118 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
122 #define streq(s, t) (strcmp (s, t) == 0)
123 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
129 #define iswhite(arg) (_wht[arg]) /* T if char is white */
130 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
131 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
132 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
134 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
137 { /* sorting structure */
138 char *name
; /* function or type name */
139 char *file
; /* file name */
140 logical is_func
; /* use pattern or line no */
141 logical rewritten
; /* list name separately */
142 logical been_warned
; /* set if noticed dup */
143 int lno
; /* line number tag is on */
144 long cno
; /* character number line starts on */
145 char *pat
; /* search pattern */
146 struct nd_st
*left
, *right
; /* left and right sons */
150 typedef struct nd_st NODE
;
152 logical header_file
; /* TRUE if .h file, FALSE o.w. */
153 /* boolean "functions" (see init) */
154 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
162 int L_isdef (), L_isquote ();
164 int total_size_of_entries ();
165 logical
consider_token ();
173 void Scheme_funcs ();
178 void find_entries ();
186 void process_file ();
192 * xnew -- allocate storage
195 * Type *xnew (int n, Type);
197 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
202 * Symbol table stuff.
204 * Should probably be implemented with hash table; linked list for now.
209 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
217 struct stab_entry
*next
;
220 typedef struct stab_entry Stab_entry
;
221 typedef Stab_entry
*Stab
;
225 * Stab, Stab_entry, stab_create, stab_search, stab_find -- symbol table
228 * Types: Stab, Stab_entry, enum sym_type
230 * Stab * stab_create ()
232 * Stab_entry * stab_find (stab, sym)
236 * Stab_entry * stab_search (stab, sym)
241 * stab_create creates a Stab, a symbol table object, and returns a
242 * pointer to it. stab_find finds a symbol in a Stab; it returns a
243 * pointer to the Stab_entry if found, otherwise NULL. stab_search
244 * is like stab_find, except that it creates a new Stab_entry,
245 * initialized with type = st_none, if one did not exist already
246 * (it never returns NULL).
248 * A Stab_entry is a structure that contains at least the following
251 * char *name; // must not be modified
252 * enum sym_type type; // should be set
254 * The type field is initially set to st_none; it should be set to
255 * something else by the caller of stab_search. Other possible values
256 * of an enum sym_type can be added.
264 *sp
= NULL
; /* a Stab starts out as a null Stab_entry* */
269 stab_find (stab
, sym
, symlen
)
274 register Stab_entry
*se
;
275 for (se
= *stab
; se
!= NULL
; se
= se
->next
)
277 if (se
->symlen
== symlen
&& strneq (se
->sym
, sym
, symlen
))
285 stab_search (stab
, sym
, symlen
)
290 register Stab_entry
*se
;
291 se
= stab_find (stab
, sym
, symlen
);
296 se
= xnew (1, Stab_entry
);
297 se
->sym
= savenstr (sym
, symlen
);
309 * stab_type -- type of a symbol table entry
312 * enum sym_type stab_type (Stab_entry *se);
315 * May evaluate its argument more than once.
318 #define stab_type(se) ((se)==NULL ? st_none : (se)->type)
334 #define C_PLPL 0x00001 /* C++ */
335 #define C_STAR 0x00003 /* C* */
336 #define YACC 0x10000 /* yacc file */
338 char searchar
= '/'; /* use /.../ searches */
340 LINENO lineno
; /* line number of current line */
341 long charno
; /* current character number */
343 long linecharno
; /* charno of start of line; not used by C, but
344 * by every other language.
347 char *curfile
, /* current input file name */
348 *outfile
, /* output file */
349 *white
= " \f\t\n", /* white chars */
350 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
351 /* token starting chars */
352 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$",
353 /* valid in-token chars */
354 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
356 int append_to_tagfile
; /* -a: append to tags */
357 int emacs_tags_format
; /* emacs style output (no -e option any more) */
358 /* The following three default to 1 for etags, but to 0 for ctags. */
359 int typedefs
; /* -t: create tags for typedefs */
360 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
361 /* 0 struct/enum/union decls, and C++ */
362 /* member functions */
363 int constantypedefs
; /* -d: create tags for C #define and enum */
364 /* constants. Default under etags. Enum */
365 /* constants not implemented. */
366 /* -D: opposite of -d. Default under ctags. */
367 int update
; /* -u: update tags */
368 int vgrind_style
; /* -v: create vgrind style index output */
369 int no_warnings
; /* -w: suppress warnings */
370 int cxref_style
; /* -x: create cxref style output */
371 int cplusplus
; /* .[hc] means C++, not C */
372 int noindentypedefs
; /* -S: ignore indentation in C */
374 /* Name this program was invoked with. */
377 struct option longopts
[] = {
378 { "append", no_argument
, NULL
, 'a' },
379 { "backward-search", no_argument
, NULL
, 'B' },
380 { "c++", no_argument
, NULL
, 'C' },
381 { "cxref", no_argument
, NULL
, 'x' },
382 { "defines", no_argument
, NULL
, 'd' },
383 { "forward-search", no_argument
, NULL
, 'F' },
384 { "help", no_argument
, NULL
, 'H' },
385 { "ignore-indentation", no_argument
, NULL
, 'S' },
386 { "include", required_argument
, NULL
, 'i' },
387 { "no-defines", no_argument
, NULL
, 'D' },
388 { "no-warn", no_argument
, NULL
, 'w' },
389 { "output", required_argument
, NULL
, 'o' },
390 { "typedefs", no_argument
, NULL
, 't' },
391 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
392 { "update", no_argument
, NULL
, 'u' },
393 { "version", no_argument
, NULL
, 'V' },
394 { "vgrind", no_argument
, NULL
, 'v' },
398 FILE *inf
, /* ioptr for current input file */
399 *outf
; /* ioptr for tags file */
401 NODE
*head
; /* the head of the binary tree of tags */
403 int permit_duplicates
= 1; /* Nonzero means allow duplicate tags. */
405 /* A `struct linebuffer' is a structure which holds a line of text.
406 `readline' reads a line from a stream into a linebuffer
407 and works regardless of the length of the line. */
415 struct linebuffer lb
; /* the current line */
416 struct linebuffer filename_lb
; /* used to read in filenames */
420 struct linebuffer lb
; /* used by C_entries instead of lb */
435 printf ("for Emacs version 19.0.\n");
443 printf ("These are the options accepted by %s. You may use unambiguous\n\
444 abbreviations for the long option names.\n\n", progname
);
446 puts ("-a, --append\n\
447 Append tag entries to existing tags file.");
449 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
450 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
451 extensions are always assumed to be C++ code.");
452 fputs ("-d, --defines\n\
453 Create tag entries for #defines, too.", stdout
);
456 fputs (" This is the default\n\
462 Don't create tag entries for #defines.", stdout
);
465 fputs (" This is the default\n\
470 -o FILE, --output=FILE\n\
471 Write the tags to FILE.\n\
472 -S, --ignore-indentation\n\
473 Don't rely on indentation quite as much as normal. Currently,\n\
474 this means not to assume that a closing brace in the first\n\
475 column is the final brace of a function or structure\n\
477 puts ("-t, --typedefs\n\
478 Generate tag entries for typedefs. This is the default\n\
480 puts ("-T, --typedefs-and-c++\n\
481 Generate tag entries for typedefs, struct/enum/union tags, and\n\
482 C++ member functions.");
485 puts ("-i FILE, --include=FILE\n\
486 Include a note in tag file indicating that, when searching for\n\
487 a tag, one should also consult the tags file FILE after\n\
488 checking the current file.");
492 puts ("-B, --backward-search\n\
493 Write the search commands for the tag entries using '?', the\n\
494 backward-search command.");
495 puts ("-F, --forward-search\n\
496 Write the search commands for the tag entries using '/', the\n\
497 forward-search command.");
498 puts ("-u, --update\n\
499 Update the tag entries for the given files, leaving tag\n\
500 entries for other files in place. Currently, this is\n\
501 implemented by deleting the existing entries for the given\n\
502 files and then rewriting the new entries at the end of the\n\
503 tags file. It is often faster to simply rebuild the entire\n\
504 tag file than to use this.");
505 puts ("-v, --vgrind\n\
506 Generates an index of items intended for human consumption,\n\
507 similar to the output of vgrind. The index is sorted, and\n\
508 gives the page number of each item.");
509 puts ("-x, --cxref\n\
510 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
511 The output uses line numbers instead of page numbers, but\n\
512 beyond that the differences are cosmetic; try both to see\n\
514 puts ("-w, --no-warn\n\
515 Suppress warning messages about entries defined in multiple\n\
519 puts ("-V, --version\n\
520 Print the version of the program.\n\
522 Print this help message.");
535 unsigned int nincluded_files
= 0;
536 char **included_files
= xnew (argc
, char *);
541 extern char *gfnames ();
542 extern char *massage_name ();
548 emacs_tags_format
= 1;
550 emacs_tags_format
= 0;
554 * If etags, always find typedefs and structure tags. Why not?
555 * Also default is to find macro constants.
557 if (emacs_tags_format
)
558 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
563 opt
= getopt_long (argc
, argv
, "aCdDo:f:StTi:BFuvxwVH", longopts
, 0);
571 /* If getopt returns '\0', then it has already processed a
572 long-named option. We should do nothing. */
575 /* Common options. */
593 "%s: -%c flag may only be given once\n", progname
, opt
);
606 typedefs_and_cplusplus
++;
617 if (!emacs_tags_format
)
619 included_files
[nincluded_files
++] = optarg
;
625 if (emacs_tags_format
)
630 if (emacs_tags_format
)
635 if (emacs_tags_format
)
643 if (emacs_tags_format
)
648 if (emacs_tags_format
)
657 if (optind
== argc
&& nincluded_files
== 0)
659 fprintf (stderr
, "%s: No input files specified.\n", progname
);
662 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
669 outfile
= emacs_tags_format
? "TAGS" : "tags";
672 init (); /* set up boolean "functions" */
675 initbuffer (&lbs
[0].lb
);
676 initbuffer (&lbs
[1].lb
);
677 initbuffer (&filename_lb
);
679 * loop through files finding functions
681 if (emacs_tags_format
)
683 if (streq (outfile
, "-"))
686 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
697 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
701 error ("Can't find file %s\n", this_file
);
706 this_file
= massage_name (this_file
);
709 } /* solely to balance out the ifdef'd parens above */
712 for (; optind
< argc
; optind
++)
714 this_file
= argv
[optind
];
718 /* Input file named "-" means read file names from stdin
720 if (streq (this_file
, "-"))
722 while (!feof (stdin
))
724 (void) readline (&filename_lb
, stdin
);
725 if (strlen (filename_lb
.buffer
) > 0)
726 process_file (filename_lb
.buffer
);
730 process_file (this_file
);
734 if (emacs_tags_format
)
736 while (nincluded_files
-- > 0)
737 fprintf (outf
, "\f\n%s,include\n", *included_files
++);
739 (void) fclose (outf
);
750 /* update cannot be set under VMS, so we may assume that argc
751 and argv have not been munged. */
752 for (i
= optind
; i
< argc
; i
++)
755 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
756 outfile
, argv
[i
], outfile
);
761 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
768 (void) fclose (outf
);
771 sprintf (cmd
, "sort %s -o %s", outfile
, outfile
);
779 * This routine is called on each file argument.
785 struct stat stat_buf
;
787 stat (file
, &stat_buf
);
788 if (!(stat_buf
.st_mode
& S_IFREG
)
790 || !(stat_buf
.st_mode
& S_IFLNK
)
794 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
798 if (streq (file
, outfile
) && !streq (outfile
, "-"))
800 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
803 if (emacs_tags_format
)
805 char *cp
= etags_rindex (file
, '/');
812 if (emacs_tags_format
)
814 fprintf (outf
, "\f\n%s,%d\n",
815 file
, total_size_of_entries (head
));
823 * This routine sets up the boolean pseudo-functions which work
824 * by setting boolean flags dependent upon the corresponding character
825 * Every char which is NOT in that string is not a white char. Therefore,
826 * all of the array "_wht" is set to FALSE, and then the elements
827 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
828 * of a char is TRUE if it is the string "white", else FALSE.
836 for (i
= 0; i
< 0177; i
++)
837 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
838 for (sp
= white
; *sp
; sp
++)
840 for (sp
= endtk
; *sp
; sp
++)
842 for (sp
= intk
; *sp
; sp
++)
844 for (sp
= begtk
; *sp
; sp
++)
846 _wht
[0] = _wht
['\n'];
847 _etk
[0] = _etk
['\n'];
848 _btk
[0] = _btk
['\n'];
849 _itk
[0] = _itk
['\n'];
853 * This routine opens the specified file and calls the function
854 * which finds the function and type definitions.
861 void prolog_funcs ();
863 inf
= fopen (file
, "r");
869 curfile
= savestr (file
);
870 cp
= etags_rindex (file
, '.');
872 header_file
= (cp
&& (streq (cp
+ 1, "h")));
874 /* .tex, .aux or .bbl implies LaTeX source code */
875 if (cp
&& (streq (cp
+ 1, "tex") || streq (cp
+ 1, "aux")
876 || streq (cp
+ 1, "bbl")))
879 goto close_and_return
;
881 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
882 if (cp
&& (streq (cp
+ 1, "l")
883 || streq (cp
+ 1, "el")
884 || streq (cp
+ 1, "lsp")
885 || streq (cp
+ 1, "lisp")
886 || streq (cp
+ 1, "cl")
887 || streq (cp
+ 1, "clisp")))
890 goto close_and_return
;
892 /* .scm or .sm or .scheme or ... implies scheme source code */
893 if (cp
&& (streq (cp
+ 1, "sm")
894 || streq (cp
+ 1, "scm")
895 || streq (cp
+ 1, "scheme")
896 || streq (cp
+ 1, "t")
897 || streq (cp
+ 1, "sch")
898 || streq (cp
+ 1, "SM")
899 || streq (cp
+ 1, "SCM")
900 /* The `SCM' or `scm' prefix with a version number */
901 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
902 && string_numeric_p (cp
+ 1))
903 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
904 && string_numeric_p (cp
+ 1))))
910 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
912 if (cp
&& (streq (cp
+ 1, "s")
913 || streq (cp
+ 1, "a")
914 || streq (cp
+ 1, "sa")))
920 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
921 if (cp
&& (streq (cp
+ 1, "C")
922 || streq (cp
+ 1, "H")
923 || streq (cp
+ 1, "cxx")
924 || streq (cp
+ 1, "hxx")
925 || streq (cp
+ 1, "cc")))
927 C_entries (C_PLPL
); /* C++ */
928 goto close_and_return
;
930 /* .cs or .hs: a C* file */
931 if (cp
&& (streq (cp
+ 1, "cs")
932 || streq (cp
+ 1, "hs")))
935 goto close_and_return
;
937 /* .y: a yacc file */
938 if (cp
&& (streq (cp
+ 1, "y")))
941 goto close_and_return
;
943 /* .pl implies prolog source code */
944 if (cp
&& streq (cp
+ 1, "pl"))
947 goto close_and_return
;
949 /* .p or .pas: a Pascal file */
950 if (cp
&& (streq (cp
+ 1, "p")
951 || streq (cp
+ 1, "pas")))
954 goto close_and_return
;
956 /* If .f or .for, assume it is fortran or nothing. */
957 if (cp
&& (streq (cp
+ 1, "f")
958 || streq (cp
+ 1, "for")))
961 goto close_and_return
;
963 /* if not a .c or .h or .y file, try fortran */
964 if (cp
&& ((cp
[1] != 'c'
967 || (cp
[1] != 0 && cp
[2] != 0)))
969 if (PF_funcs (inf
) != 0)
970 goto close_and_return
;
971 rewind (inf
); /* no fortran tags found, try C */
973 C_entries (cplusplus
? C_PLPL
: 0);
979 /* Nonzero if string STR is composed of digits. */
982 string_numeric_p (str
)
987 if (*str
< '0' || *str
> '9')
994 /* Should take a TOKEN* instead!! */
996 pfnote (name
, is_func
, rewritten
, linestart
, linelen
, lno
, cno
)
997 char *name
; /* tag name */
998 logical is_func
; /* function or type name? */
999 logical rewritten
; /* tag different from text of definition? */
1010 np
= (NODE
*) malloc (sizeof (NODE
));
1013 if (!emacs_tags_format
)
1015 /* It's okay to output early in etags -- it only disrupts the
1016 * character count of the tag entries, which is no longer used
1017 * by tags.el anyway.
1019 error ("too many entries to sort");
1024 np
= xnew (1, NODE
);
1026 /* If ctags mode, change name "main" to M<thisfilename>. */
1027 if (!emacs_tags_format
&& !cxref_style
&& streq (name
, "main"))
1029 fp
= etags_rindex (curfile
, '/');
1030 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
1031 fp
= etags_rindex (name
, '.');
1032 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
1036 np
->name
= savestr (name
);
1038 np
->is_func
= is_func
;
1039 np
->rewritten
= rewritten
;
1041 /* UNCOMMENT THE +1 HERE: */
1042 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
1043 np
->left
= np
->right
= 0;
1044 if (emacs_tags_format
)
1046 c
= linestart
[linelen
];
1047 linestart
[linelen
] = 0;
1049 else if (cxref_style
== 0)
1051 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
1054 np
->pat
= savestr (linestart
);
1055 if (emacs_tags_format
)
1057 linestart
[linelen
] = c
;
1060 add_node (np
, &head
);
1065 * recurse on left children, iterate on right children.
1069 register NODE
*node
;
1073 register NODE
*node_right
= node
->right
;
1074 free_tree (node
->left
);
1077 free ((char *) node
);
1084 * Adds a node to the tree of nodes. In etags mode, we don't keep
1085 * it sorted; we just keep a linear list. In ctags mode, maintain
1086 * an ordered tree, with no attempt at balancing.
1088 * add_node is the only function allowed to add nodes, so it can
1091 /* Must avoid static vars within functions since some systems
1092 #define static as nothing. */
1093 static NODE
*last_node
= NULL
;
1096 add_node (node
, cur_node_p
)
1097 NODE
*node
, **cur_node_p
;
1100 register NODE
*cur_node
= *cur_node_p
;
1102 if (cur_node
== NULL
)
1109 if (emacs_tags_format
)
1113 fatal ("internal error in add_node");
1114 last_node
->right
= node
;
1120 dif
= strcmp (node
->name
, cur_node
->name
);
1123 * If this tag name matches an existing one, then
1124 * do not add the node, but maybe print a warning.
1128 if (node
->file
== cur_node
->file
)
1132 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1133 node
->file
, lineno
, node
->name
);
1134 fprintf (stderr
, "Second entry ignored\n");
1138 if (!cur_node
->been_warned
&& !no_warnings
)
1141 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1142 node
->file
, cur_node
->file
, node
->name
);
1144 cur_node
->been_warned
= TRUE
;
1148 /* Maybe refuse to add duplicate nodes. */
1149 if (!permit_duplicates
)
1151 if (!strcmp (node
->name
, cur_node
->name
)
1152 && !strcmp (node
->file
, cur_node
->file
))
1156 /* Actually add the node */
1157 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1163 register NODE
*node
;
1170 /* Output subentries that precede this one */
1171 put_entries (node
->left
);
1173 /* Output this entry */
1175 if (emacs_tags_format
)
1177 if (node
->rewritten
)
1179 fprintf (outf
, "%s\177%s\001%d,%d\n",
1180 node
->pat
, node
->name
,
1181 node
->lno
, node
->cno
);
1185 fprintf (outf
, "%s\177%d,%d\n",
1187 node
->lno
, node
->cno
);
1190 else if (!cxref_style
)
1192 fprintf (outf
, "%s\t%s\t",
1193 node
->name
, node
->file
);
1197 putc (searchar
, outf
);
1200 for (sp
= node
->pat
; *sp
; sp
++)
1202 if (*sp
== '\\' || *sp
== searchar
)
1206 putc (searchar
, outf
);
1209 { /* a typedef; text pattern inadequate */
1210 fprintf (outf
, "%d", node
->lno
);
1214 else if (vgrind_style
)
1215 fprintf (stdout
, "%s %s %d\n",
1216 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1218 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1219 node
->name
, node
->lno
, node
->file
, node
->pat
);
1221 /* Output subentries that follow this one */
1222 put_entries (node
->right
);
1225 /* Length of a number's decimal representation. */
1233 for (; num
; num
/= 10)
1239 * Return total number of characters that put_entries will output for
1240 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1241 * is set, but called only in that case. This count is irrelevant with
1242 * the new tags.el, but is still supplied for backward compatibility.
1245 total_size_of_entries (node
)
1246 register NODE
*node
;
1254 for (; node
; node
= node
->right
)
1256 /* Count left subentries. */
1257 total
+= total_size_of_entries (node
->left
);
1259 /* Count this entry */
1260 total
+= strlen (node
->pat
) + 1;
1261 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1262 if (node
->rewritten
)
1263 total
+= 1 + strlen (node
->name
); /* \001name */
1270 * The C symbol tables.
1273 Stab
*C_stab
, *C_PLPL_stab
, *C_STAR_stab
;
1277 * Stab *get_C_stab (int c_ext);
1279 #define get_C_stab(c_ext) ((c_ext & C_STAR) ? C_STAR_stab : \
1280 (c_ext & C_PLPL) ? C_PLPL_stab : \
1284 add_keyword (stab
, sym
, type
)
1289 stab_search (stab
, sym
, strlen (sym
))->type
= type
;
1293 C_create_stab (c_ext
)
1298 stab
= stab_create ();
1302 add_keyword (stab
, "class", st_C_struct
);
1304 add_keyword (stab
, "domain", st_C_struct
);
1305 add_keyword (stab
, "union", st_C_struct
);
1306 add_keyword (stab
, "struct", st_C_struct
);
1307 add_keyword (stab
, "enum", st_C_enum
);
1308 add_keyword (stab
, "typedef", st_C_typedef
);
1309 add_keyword (stab
, "define", st_C_define
);
1310 add_keyword (stab
, "long", st_C_typespec
);
1311 add_keyword (stab
, "short", st_C_typespec
);
1312 add_keyword (stab
, "int", st_C_typespec
);
1313 add_keyword (stab
, "char", st_C_typespec
);
1314 add_keyword (stab
, "float", st_C_typespec
);
1315 add_keyword (stab
, "double", st_C_typespec
);
1316 add_keyword (stab
, "signed", st_C_typespec
);
1317 add_keyword (stab
, "unsigned", st_C_typespec
);
1318 add_keyword (stab
, "auto", st_C_typespec
);
1319 add_keyword (stab
, "void", st_C_typespec
);
1320 add_keyword (stab
, "extern", st_C_typespec
);
1321 add_keyword (stab
, "static", st_C_typespec
);
1322 add_keyword (stab
, "const", st_C_typespec
);
1323 add_keyword (stab
, "volatile", st_C_typespec
);
1331 C_stab
= C_create_stab (0);
1332 C_PLPL_stab
= C_create_stab (C_PLPL
);
1333 C_STAR_stab
= C_create_stab (C_STAR
| C_PLPL
);
1337 * C functions are recognized using a simple finite automaton.
1338 * funcdef is its state variable.
1342 fnone
, /* nothing seen */
1343 ftagseen
, /* function-like tag seen */
1344 finlist
, /* in parameter list */
1345 flistseen
, /* after parameter list */
1346 fignore
, /* before open brace */
1351 /* typedefs are recognized using a simple finite automaton.
1352 * typeddef is its state variable.
1356 tnone
, /* nothing seen */
1357 ttypedseen
, /* typedef keyword seen */
1358 tinbody
, /* inside typedef body */
1359 tend
, /* just before typedef tag */
1364 /* struct tags for C++ are recognized using another simple
1365 * finite automaton. `structdef' is its state variable.
1366 * This machinery is only invoked for C++; otherwise structdef
1367 * should remain snone. However, this machinery can easily be
1368 * adapted to find structure tags in normal C code.
1372 snone
, /* nothing seen yet */
1373 skeyseen
, /* struct-like keyword seen */
1374 stagseen
, /* struct-like tag seen */
1375 scolonseen
, /* colon seen after struct-like tag */
1376 sinbody
, /* in struct body: recognize member func defs*/
1380 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1381 * struct tag, and structkey is the preceding struct-like keyword.
1383 char structtag
[BUFSIZ
];
1384 Stab_entry
*structkey
;
1387 * Yet another little state machine to deal with preprocessor lines.
1391 dnone
, /* nothing seen */
1392 dsharpseen
, /* '#' seen as first char on line */
1393 ddefineseen
, /* '#' and 'define' seen */
1394 dignorerest
, /* ignore rest of line */
1399 * Set this to TRUE, and the next token considered is called a function.
1400 * Used only for GNUmacs's function-defining macros.
1402 logical next_token_is_func
;
1405 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1411 * This routine finds functions, typedefs, #define's and
1412 * struct/union/enum definitions in C syntax and adds them
1416 #define curlb (lbs[curndx].lb)
1417 #define othlb (lbs[1-curndx].lb)
1418 #define newlb (lbs[newndx].lb)
1419 #define curlinepos (lbs[curndx].linepos)
1420 #define othlinepos (lbs[1-curndx].linepos)
1421 #define newlinepos (lbs[newndx].linepos)
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 definedef = dnone; \
1439 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1440 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1441 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1442 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1446 int c_ext
; /* extension of C? */
1448 register char c
; /* latest char read; '\0' for end of line */
1449 register char *lp
; /* pointer one beyond the character `c' */
1450 int curndx
, newndx
; /* indices for current and new lb */
1451 TOKEN tok
; /* latest token read for funcdef & structdef */
1452 char tokb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1453 register int tokoff
; /* offset in line of start of latest token */
1454 register int toklen
; /* length of latest token */
1455 int cblev
; /* current curly brace level */
1456 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1459 curndx
= newndx
= 0;
1465 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1466 next_token_is_func
= yacc_rules
= FALSE
;
1467 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1469 cplpl
= c_ext
& C_PLPL
;
1478 /* If we're at the end of the line, the next character is a
1479 '\0'; don't skip it, because it's the thing that tells us
1480 to read the next line. */
1501 /* Newlines inside comments do not end macro definitions in
1516 /* Newlines inside strings, do not end macro definitions
1517 in traditional cpp, even though compilers don't
1518 usually accept them. */
1546 else if (cplpl
&& *lp
== '/')
1553 if ((c_ext
& YACC
) && *lp
== '%')
1555 /* entering or exiting rules section in yacc file */
1557 definedef
= dnone
; funcdef
= fnone
;
1558 typdef
= tnone
; structdef
= snone
;
1559 next_token_is_func
= FALSE
;
1560 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1562 yacc_rules
= !yacc_rules
;
1566 if (lp
== newlb
.buffer
+ 1 && definedef
== dnone
)
1567 definedef
= dsharpseen
;
1572 /* Consider token only if some complicated conditions are satisfied. */
1573 if (((cblev
== 0 && structdef
!= scolonseen
)
1574 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
1575 && definedef
!= dignorerest
1576 && funcdef
!= finlist
)
1582 if (cplpl
&& c
== ':' && *lp
== ':' && intoken (*(lp
+ 1)))
1585 * This handles :: in the middle, but not at beginning
1595 tok
.lineno
= lineno
;
1596 tok
.p
= newlb
.buffer
+ tokoff
;
1598 tok
.rewritten
= FALSE
;
1600 || consider_token (c
, lp
, &tok
,
1601 c_ext
, cblev
, &is_func
))
1603 if (structdef
== sinbody
1604 && definedef
== dnone
&& is_func
)
1605 { /* function defined in C++ class body */
1606 sprintf (tokb
, "%s::%.*s",
1607 ((structtag
[0] == '\0')
1608 ? "_anonymous_" : structtag
),
1610 tok
.rewritten
= TRUE
;
1614 sprintf (tokb
, "%.*s", tok
.len
, tok
.p
);
1617 if (funcdef
== ftagseen
1618 || structdef
== stagseen
1621 if (newndx
== curndx
)
1622 curndx
= 1 - curndx
; /* switch line buffers */
1625 MAKE_TAG_FROM_NEW_LB (is_func
);
1629 } /* if (endtoken (c)) */
1630 else if (intoken (c
))
1635 } /* if (midtoken) */
1636 else if (begtoken (c
))
1641 MAKE_TAG_FROM_OTH_LB (TRUE
);
1648 if (structdef
== stagseen
)
1650 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1652 tokoff
= lp
- 1 - newlb
.buffer
;
1658 } /* if must look at token */
1661 /* Detect end of line, colon, comma, semicolon and various braces
1662 after having handled the last token on the line.*/
1666 if (structdef
== stagseen
)
1667 structdef
= scolonseen
;
1668 else if (yacc_rules
&& funcdef
== ftagseen
)
1670 MAKE_TAG_FROM_OTH_LB (FALSE
);
1675 if (cblev
== 0 && typdef
== tend
)
1678 MAKE_TAG_FROM_OTH_LB (FALSE
);
1680 if (funcdef
!= fignore
)
1686 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1688 if (structdef
== stagseen
)
1704 if (funcdef
== finlist
)
1705 funcdef
= flistseen
;
1708 if (typdef
== ttypedseen
)
1712 case skeyseen
: /* unnamed struct */
1713 structtag
[0] = '\0';
1714 structdef
= sinbody
;
1717 case scolonseen
: /* named struct */
1718 structdef
= sinbody
;
1719 MAKE_TAG_FROM_OTH_LB (FALSE
);
1725 MAKE_TAG_FROM_OTH_LB (TRUE
);
1733 if (funcdef
== flistseen
)
1735 MAKE_TAG_FROM_OTH_LB (TRUE
);
1740 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
1741 cblev
= 0; /* reset curly brace level if first column */
1746 if (typdef
== tinbody
)
1749 (void) strcpy (structtag
, "<error 2>");
1753 /* If a macro spans multiple lines don't reset its state. */
1761 } /* while not eof */
1766 * checks to see if the current token is at the start of a
1767 * function, or corresponds to a typedef, or is a struct/union/enum
1770 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1771 * C_EXT is which language we are looking at.
1773 * In the future we will need some way to adjust where the end of
1774 * the token is; for instance, implementing the C++ keyword
1775 * `operator' properly will adjust the end of the token to be after
1776 * whatever follows `operator'.
1783 * next_token_is_func IN OUT
1787 consider_token (c
, lp
, tokp
, c_ext
, cblev
, is_func
)
1788 register char c
; /* IN: first char after the token */
1789 register char *lp
; /* IN: lp points to 2nd char after the token */
1790 register TOKEN
*tokp
; /* IN: token pointer */
1791 int c_ext
; /* IN: C extensions mask */
1792 int cblev
; /* IN: curly brace level */
1793 logical
*is_func
; /* OUT */
1795 logical firsttok
; /* TRUE if have seen first token in ()'s */
1796 Stab_entry
*tokse
= stab_find (get_C_stab (c_ext
), tokp
->p
, tokp
->len
);
1797 enum sym_type toktype
= stab_type (tokse
);
1799 *is_func
= FALSE
; /* not a function */
1802 * Advance the definedef state machine.
1807 /* We're not on a preprocessor line. */
1810 if (toktype
== st_C_define
)
1812 definedef
= ddefineseen
;
1816 definedef
= dignorerest
;
1821 * Make a tag for any macro.
1823 definedef
= dignorerest
;
1824 *is_func
= (c
== '(');
1825 if (!*is_func
&& !constantypedefs
)
1832 error ("internal error: definedef value");
1841 if (toktype
== st_C_typedef
)
1844 typdef
= ttypedseen
;
1859 /* Do not return here, so the structdef stuff has a chance. */
1873 * This structdef business is currently only invoked when cblev==0.
1874 * It should be recursively invoked whatever the curly brace level,
1875 * and a stack of states kept, to allow for definitions of structs
1878 * This structdef business is NOT invoked when we are ctags and the
1879 * file is plain C. This is because a struct tag may have the same
1880 * name as another tag, and this loses with ctags.
1882 * This if statement deals with the typdef state machine as
1883 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1884 * return (FALSE). All the other code here is for the structdef
1891 if (typdef
== ttypedseen
1892 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1894 structdef
= skeyseen
;
1899 if (structdef
== skeyseen
)
1901 if (stab_type (structkey
) == st_C_struct
)
1903 (void) strncpy (structtag
, tokp
->p
, tokp
->len
);
1904 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1908 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1910 structdef
= stagseen
;
1914 /* Avoid entering funcdef stuff if typdef is going on. */
1915 if (typdef
!= tnone
)
1921 /* Detect GNUmacs's function-defining macros. */
1922 if (definedef
== dnone
)
1924 if (strneq (tokp
->p
, "DEF", 3)
1925 || strneq (tokp
->p
, "ENTRY", 5)
1926 || strneq (tokp
->p
, "SYSCALL", 7)
1927 || strneq (tokp
->p
, "PSEUDO", 6))
1929 next_token_is_func
= TRUE
;
1932 if (strneq (tokp
->p
, "EXFUN", 5))
1934 next_token_is_func
= FALSE
;
1938 if (next_token_is_func
)
1940 next_token_is_func
= FALSE
;
1942 *is_func
= TRUE
; /* to force search string in ctags */
1950 funcdef
= fnone
; /* should be useless */
1953 if (funcdef
== fnone
)
1964 /* Fortran parsing */
1980 linecharno
= charno
;
1981 charno
+= readline (&lb
, fi
);
1984 dbp
++; /* Ratfor escape to fortran */
1985 while (isspace (*dbp
))
1992 if (tail ("integer"))
2000 if (tail ("logical"))
2004 if (tail ("complex") || tail ("character"))
2008 if (tail ("double"))
2010 while (isspace (*dbp
))
2014 if (tail ("precision"))
2020 while (isspace (*dbp
))
2027 if (tail ("function"))
2031 if (tail ("subroutine"))
2039 if (tail ("program"))
2044 if (tail ("procedure"))
2056 register int len
= 0;
2058 while (*cp
&& (*cp
& ~' ') == ((*(dbp
+ len
)) & ~' '))
2071 while (isspace (*dbp
))
2076 while (isspace (*dbp
))
2078 if (!isdigit (*dbp
))
2080 --dbp
; /* force failure */
2085 while (isdigit (*dbp
));
2093 char nambuf
[BUFSIZ
];
2095 while (isspace (*dbp
))
2102 for (cp
= dbp
+ 1; *cp
&& (isalpha (*cp
) || isdigit (*cp
)
2103 || (*cp
== '_') || (*cp
== '$')); cp
++)
2107 (void) strcpy (nambuf
, dbp
);
2109 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2113 /* Handle a file of assembler code. */
2129 linecharno
= charno
;
2130 charno
+= readline (&lb
, fi
);
2133 for (i
= 0; ((c
= dbp
[i
]) && !isspace (c
)) && (c
!= ':'); i
++)
2136 if ((i
> 0) && (c
== ':'))
2141 /* Added by Mosur Mohan, 4/22/88 */
2142 /* Pascal parsing */
2144 #define GET_NEW_LINE \
2146 linecharno = charno; lineno++; \
2147 charno += 1 + readline (&lb, inf); \
2151 /* Locates tags for procedures & functions.
2152 * Doesn't do any type- or var-definitions.
2153 * It does look for the keyword "extern" or "forward"
2154 * immediately following the procedure statement;
2155 * if found, the tag is skipped.
2162 struct linebuffer tline
; /* mostly copied from C_entries */
2166 char nambuf
[BUFSIZ
];
2168 logical
/* each of these flags is TRUE iff: */
2169 incomm1
, /* point is inside {..} comment */
2170 incomm2
, /* point is inside (*..*) comment */
2171 inquote
, /* point is inside '..' string */
2172 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2173 /* keyword, so next item = potential tag */
2174 found_tag
, /* point is after a potential tag */
2175 inparms
, /* point is within parameter-list */
2176 verify_tag
; /* point has passed the parm-list, so the */
2177 /* next token will determine whether */
2178 /* this is a FORWARD/EXTERN to be */
2179 /* ignored, or whether it is a real tag */
2185 initbuffer (&tline
);
2187 incomm1
= incomm2
= inquote
= FALSE
;
2188 found_tag
= FALSE
; /* have a proc name; check if extern */
2189 get_tagname
= FALSE
; /* have found "procedure" keyword */
2190 inparms
= FALSE
; /* found '(' after "proc" */
2191 verify_tag
= FALSE
; /* check if "extern" is ahead */
2193 /* long main loop to get next char */
2197 if (c
== 0) /* if end of line */
2202 if (!((found_tag
&& verify_tag
) ||
2204 c
= *dbp
++; /* only if don't need *dbp pointing */
2205 /* to the beginning of the name of */
2206 /* the procedure or function */
2208 if (incomm1
) /* within { - } comments */
2214 else if (incomm2
) /* within (* - *) comments */
2218 while ((c
= *dbp
++) == '*')
2237 inquote
= TRUE
; /* found first quote */
2239 case '{': /* found open-{-comment */
2243 if (*dbp
== '*') /* found open-(*-comment */
2248 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2251 case ')': /* end of parms list */
2256 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2263 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2265 /* check if this is an "extern" declaration */
2268 if ((*dbp
== 'e') || (*dbp
== 'E'))
2270 if (tail ("extern")) /* superfluous, really! */
2276 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2278 if (tail ("forward")) /* check for forward reference */
2284 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2288 pfnote (nambuf
, TRUE
, FALSE
,
2289 tline
.buffer
, cp
- tline
.buffer
+ 1,
2290 save_lineno
, save_lcno
);
2294 if (get_tagname
) /* grab name of proc or fn */
2299 /* save all values for later tagging */
2300 tline
.size
= lb
.size
;
2301 strcpy (tline
.buffer
, lb
.buffer
);
2302 save_lineno
= lineno
;
2303 save_lcno
= linecharno
;
2305 /* grab block name */
2306 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2310 strcpy (nambuf
, dbp
);
2312 dbp
= cp
; /* restore dbp to e-o-token */
2313 get_tagname
= FALSE
;
2317 /* and proceed to check for "extern" */
2319 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2320 (!found_tag
) && (!get_tagname
))
2322 /* check for proc/fn keywords */
2326 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2330 if (tail ("unction"))
2335 } /* while not e-o-f */
2339 * lisp tag functions
2340 * just look for (def or (DEF
2354 linecharno
= charno
;
2355 charno
+= readline (&lb
, fi
);
2361 while (!isspace (*dbp
))
2363 while (isspace (*dbp
))
2369 /* Check for (foo::defmumble name-defined ... */
2372 while (*dbp
&& !isspace (*dbp
)
2373 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2378 while (*dbp
== ':');
2380 if (L_isdef (dbp
- 1))
2382 while (!isspace (*dbp
))
2384 while (isspace (*dbp
))
2398 return ((dbp
[1] == 'd' || dbp
[1] == 'D')
2399 && (dbp
[2] == 'e' || dbp
[2] == 'E')
2400 && (dbp
[3] == 'f' || dbp
[3] == 'F'));
2407 return ((*(++dbp
) == 'q' || *dbp
== 'Q')
2408 && (*(++dbp
) == 'u' || *dbp
== 'U')
2409 && (*(++dbp
) == 'o' || *dbp
== 'O')
2410 && (*(++dbp
) == 't' || *dbp
== 'T')
2411 && (*(++dbp
) == 'e' || *dbp
== 'E')
2412 && isspace(*(++dbp
)));
2420 char nambuf
[BUFSIZ
];
2422 if (*dbp
== '\'') /* Skip prefix quote */
2424 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2427 while (isspace(*dbp
))
2430 for (cp
= dbp
/*+1*/; *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')'; cp
++)
2437 (void) strcpy (nambuf
, dbp
);
2439 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2440 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2445 * Scheme tag functions
2446 * look for (def... xyzzy
2447 * look for (def... (xyzzy
2448 * look for (def ... ((...(xyzzy ....
2449 * look for (set! xyzzy
2452 static void get_scheme ();
2465 linecharno
= charno
;
2466 charno
+= readline (&lb
, fi
);
2468 if (dbp
[0] == '(' &&
2469 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2470 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2471 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2473 while (!isspace (*dbp
))
2475 /* Skip over open parens and white space */
2476 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2480 if (dbp
[0] == '(' &&
2481 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2482 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2483 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2484 (dbp
[4] == '!' || dbp
[4] == '!') &&
2487 while (!isspace (*dbp
))
2489 /* Skip over white space */
2490 while (isspace (*dbp
))
2502 char nambuf
[BUFSIZ
];
2506 /* Go till you get to white space or a syntactic break */
2507 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2509 /* Null terminate the string there. */
2512 /* Copy the string */
2513 strcpy (nambuf
, dbp
);
2514 /* Unterminate the string */
2516 /* Announce the change */
2517 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2521 /* Find tags in TeX and LaTeX input files. */
2523 /* TEX_toktab is a table of TeX control sequences that define tags.
2524 Each TEX_tabent records one such control sequence.
2525 CONVERT THIS TO USE THE Stab TYPE!! */
2533 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2535 /* Default set of control sequences to put into TEX_toktab.
2536 The value of environment var TEXTAGS is prepended to this. */
2538 static char *TEX_defenv
=
2539 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2542 struct TEX_tabent
*TEX_decode_env ();
2546 static char TEX_esc
= '\\';
2547 static char TEX_opgrp
= '{';
2548 static char TEX_clgrp
= '}';
2551 * TeX/LaTeX scanning loop.
2564 /* Select either \ or ! as escape character. */
2567 /* Initialize token table once from environment. */
2569 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2572 { /* Scan each line in file */
2574 linecharno
= charno
;
2575 charno
+= readline (&lb
, fi
);
2578 while (dbp
= etags_index (dbp
, TEX_esc
)) /* Look at each escape in line */
2584 linecharno
+= dbp
- lasthit
;
2586 i
= TEX_Token (lasthit
);
2589 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2590 break; /* We only save a line once */
2596 #define TEX_LESC '\\'
2597 #define TEX_SESC '!'
2600 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2601 /* chars accordingly. */
2609 while ((c
= getc (f
)) != EOF
)
2611 /* Skip to next line if we hit the TeX comment char. */
2615 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2634 /* Read environment and prepend it to the default string. */
2635 /* Build token table. */
2638 TEX_decode_env (evarname
, defenv
)
2642 register char *env
, *p
;
2644 struct TEX_tabent
*tab
;
2647 /* Append default string to environment. */
2648 env
= getenv (evarname
);
2652 env
= concat (env
, defenv
, "");
2654 /* Allocate a token table */
2655 for (size
= 1, p
= env
; p
;)
2656 if ((p
= etags_index (p
, ':')) && *(++p
))
2658 /* Add 1 to leave room for null terminator. */
2659 tab
= xnew (size
+ 1, struct TEX_tabent
);
2661 /* Unpack environment string into token table. Be careful about */
2662 /* zero-length strings (leading ':', "::" and trailing ':') */
2665 p
= etags_index (env
, ':');
2666 if (!p
) /* End of environment string. */
2667 p
= env
+ strlen (env
);
2669 { /* Only non-zero strings. */
2670 tab
[i
].name
= savenstr (env
, p
- env
);
2671 tab
[i
].len
= strlen (tab
[i
].name
);
2678 tab
[i
].name
= NULL
; /* Mark end of table. */
2686 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2687 The name being defined actually starts at (NAME + LEN + 1).
2688 But we seem to include the TeX command in the tag name. */
2691 TEX_getit (name
, len
)
2695 char *p
= name
+ len
;
2696 char nambuf
[BUFSIZ
];
2701 /* Let tag name extend to next group close (or end of line) */
2702 while (*p
&& *p
!= TEX_clgrp
)
2704 (void) strncpy (nambuf
, name
, p
- name
);
2705 nambuf
[p
- name
] = 0;
2707 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2711 /* If the text at CP matches one of the tag-defining TeX command names,
2712 return the etags_index of that command in TEX_toktab.
2713 Otherwise return -1. */
2715 /* Keep the capital `T' in `Token' for dumb truncating compilers
2716 (this distinguishes it from `TEX_toktab' */
2723 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2724 if (strncmp (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
) == 0)
2729 /* Support for Prolog. */
2731 /* whole head (not only functor, but also arguments)
2732 is gotten in compound term. */
2735 prolog_getit (s
, lineno
, linecharno
)
2740 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2748 if (*s
== '\0') /* syntax error. */
2750 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2752 else if (*s
== '\'')
2754 insquote
= !insquote
;
2757 else if (!insquote
&& *s
== '(')
2762 else if (!insquote
&& *s
== ')')
2768 else if (npar
< 0) /* syntax error. */
2771 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2773 if (npar
!= 0) /* syntax error. */
2783 strcpy (nambuf
, save_s
);
2785 pfnote (nambuf
, TRUE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2788 /* It is assumed that prolog predicate starts from column 0. */
2794 void skip_comment (), prolog_getit ();
2796 lineno
= linecharno
= charno
= 0;
2800 linecharno
+= charno
;
2801 charno
= readline (&lb
, fi
) + 1; /* 1 for newline. */
2803 if (isspace (dbp
[0])) /* not predicate header. */
2805 else if (dbp
[0] == '%') /* comment. */
2807 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2808 skip_comment (&lb
, fi
, &lineno
, &linecharno
);
2810 prolog_getit (dbp
, lineno
, linecharno
);
2815 skip_comment (plb
, fi
, plineno
, plinecharno
)
2816 struct linebuffer
*plb
;
2818 int *plineno
; /* result */
2819 long *plinecharno
; /* result */
2821 while (!substr ("*/", plb
->buffer
))
2824 *plinecharno
+= readline (plb
, fi
) + 1;
2825 } /* 1 for newline. */
2828 /* Return TRUE if 'sub' exists somewhere in 's'. */
2835 while (*s
&& (s
= etags_index (s
, *sub
)))
2836 if (prestr (sub
, s
))
2843 /* Return TRUE if 'pre' is prefix of string 's'. */
2852 else if (*pre
== *s
)
2853 return (prestr (pre
+ 1, s
+ 1));
2858 /* Initialize a linebuffer for use */
2861 initbuffer (linebuffer
)
2862 struct linebuffer
*linebuffer
;
2864 linebuffer
->size
= 200;
2865 linebuffer
->buffer
= xnew (200, char);
2869 * Read a line of text from `stream' into `linebuffer'.
2870 * Return the number of characters read from `stream',
2871 * which is the length of the line including the newline, if any.
2874 readline (linebuffer
, stream
)
2875 struct linebuffer
*linebuffer
;
2876 register FILE *stream
;
2878 char *buffer
= linebuffer
->buffer
;
2879 register char *p
= linebuffer
->buffer
;
2880 register char *pend
;
2881 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2883 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
2887 register int c
= getc (stream
);
2890 linebuffer
->size
*= 2;
2891 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
2892 p
+= buffer
- linebuffer
->buffer
;
2893 pend
= buffer
+ linebuffer
->size
;
2894 linebuffer
->buffer
= buffer
;
2896 if (c
< 0 || c
== '\n')
2899 newline
= (c
== '\n' ? 1 : 0);
2905 return p
- buffer
+ newline
;
2912 return savenstr (cp
, strlen (cp
));
2922 dp
= xnew (len
+ 1, char);
2923 (void) strncpy (dp
, cp
, len
);
2929 * Return the ptr in sp at which the character c last
2930 * appears; NULL if not found
2932 * Identical to v7 rindex, included for portability.
2936 etags_rindex (sp
, c
)
2937 register char *sp
, c
;
2952 * Return the ptr in sp at which the character c first
2953 * appears; NULL if not found
2955 * Identical to v7 index, included for portability.
2960 register char *sp
, c
;
2970 /* Print error message and exit. */
2981 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
2988 fprintf (stderr
, "%s: ", progname
);
2989 fprintf (stderr
, s1
, s2
);
2990 fprintf (stderr
, "\n");
2993 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
2999 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3000 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3002 (void) strcpy (result
, s1
);
3003 (void) strcpy (result
+ len1
, s2
);
3004 (void) strcpy (result
+ len1
+ len2
, s3
);
3005 *(result
+ len1
+ len2
+ len3
) = 0;
3010 /* Like malloc but get fatal error if memory is exhausted. */
3016 char *result
= malloc (size
);
3018 fatal ("virtual memory exhausted", 0);
3023 xrealloc (ptr
, size
)
3027 char *result
= realloc (ptr
, size
);
3029 fatal ("virtual memory exhausted");