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++.
29 #include "../src/config.h"
32 /* AIX requires this to be the first thing in the file. */
35 #define alloca __builtin_alloca
37 #else /* not __GNUC__ */
40 #else /* not HAVE_ALLOCA_H */
46 #endif /* not HAVE_ALLOCA_H */
47 #endif /* not __GNUC__ */
51 #include <sys/types.h>
56 extern char *malloc (), *realloc ();
57 extern char *getenv ();
58 extern char *strcpy (), *strncpy ();
61 char *etags_index (), *etags_rindex ();
64 /* Define the symbol ETAGS to make the program "etags",
65 which makes emacs-style tag tables by default.
66 Define CTAGS to make the program "ctags" compatible with the usual one.
67 Define neither one to get behavior that depends
68 on the name with which the program is invoked
69 (but we don't normally compile it that way). */
71 #if !defined(ETAGS) && !defined(CTAGS)
72 /* If neither is defined, program can be run as either. */
77 /* On VMS, CTAGS is not useful, so always do ETAGS. */
84 /* Exit codes for success and failure. */
94 * The FILEPOS abstract type, which represents a position in a file,
95 * plus the following accessor functions:
97 * long GET_CHARNO (pos)
98 * returns absolute char number.
99 * void SET_FILEPOS (pos, fp, charno)
100 * FILE *fp; long charno;
101 * sets `pos' from the current file
102 * position of `fp' and from `charno',
103 * which must be the absolute character
104 * number corresponding to the current
107 * The `pos' parameter is an lvalue expression of type FILEPOS.
108 * Parameters to the accessor functions are evaluated 0 or more times,
109 * and so must have no side effects.
111 * FILEPOS objects can also be assigned and passed to and from
112 * functions in the normal C manner.
114 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
118 /* real implementation */
119 typedef long FILEPOS
;
120 #define GET_CHARNO(pos) ((pos) + 0)
121 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
123 /* debugging implementation */
129 #define GET_CHARNO(pos) ((pos).charno + 0)
130 #define SET_FILEPOS(pos, fp, cno) \
131 ((void) ((pos).charno = (cno), \
132 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
136 #define streq(s, t) (strcmp (s, t) == 0)
137 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
143 #define iswhite(arg) (_wht[arg]) /* T if char is white */
144 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
145 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
146 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
148 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
151 { /* sorting structure */
152 char *name
; /* function or type name */
153 char *file
; /* file name */
154 logical is_func
; /* use pattern or line no */
155 logical rewritten
; /* list name separately */
156 logical been_warned
; /* set if noticed dup */
157 int lno
; /* line number tag is on */
158 long cno
; /* character number line starts on */
159 char *pat
; /* search pattern */
160 struct nd_st
*left
, *right
; /* left and right sons */
164 typedef struct nd_st NODE
;
166 logical header_file
; /* TRUE if .h file, FALSE o.w. */
167 /* boolean "functions" (see init) */
168 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
178 int total_size_of_entries ();
179 logical
consider_token ();
187 void Scheme_funcs ();
192 void find_entries ();
200 void process_file ();
206 * xnew -- allocate storage
209 * Type *xnew (int n, Type);
211 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
216 * Symbol table stuff.
218 * Should probably be implemented with hash table; linked list for now.
223 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
231 struct stab_entry
*next
;
234 typedef struct stab_entry Stab_entry
;
235 typedef Stab_entry
*Stab
;
239 * Stab, Stab_entry, stab_create, stab_search, stab_find -- symbol table
242 * Types: Stab, Stab_entry, enum sym_type
244 * Stab * stab_create ()
246 * Stab_entry * stab_find (stab, sym)
250 * Stab_entry * stab_search (stab, sym)
255 * stab_create creates a Stab, a symbol table object, and returns a
256 * pointer to it. stab_find finds a symbol in a Stab; it returns a
257 * pointer to the Stab_entry if found, otherwise NULL. stab_search
258 * is like stab_find, except that it creates a new Stab_entry,
259 * initialized with type = st_none, if one did not exist already
260 * (it never returns NULL).
262 * A Stab_entry is a structure that contains at least the following
265 * char *name; // must not be modified
266 * enum sym_type type; // should be set
268 * The type field is initially set to st_none; it should be set to
269 * something else by the caller of stab_search. Other possible values
270 * of an enum sym_type can be added.
278 *sp
= NULL
; /* a Stab starts out as a null Stab_entry* */
283 stab_find (stab
, sym
, symlen
)
288 register Stab_entry
*se
;
289 for (se
= *stab
; se
!= NULL
; se
= se
->next
)
291 if (se
->symlen
== symlen
&& strneq (se
->sym
, sym
, symlen
))
299 stab_search (stab
, sym
, symlen
)
304 register Stab_entry
*se
;
305 se
= stab_find (stab
, sym
, symlen
);
310 se
= xnew (1, Stab_entry
);
311 se
->sym
= savenstr (sym
, symlen
);
323 * stab_type -- type of a symbol table entry
326 * enum sym_type stab_type (Stab_entry *se);
329 * May evaluate its argument more than once.
332 #define stab_type(se) ((se)==NULL ? st_none : (se)->type)
348 #define C_PLPL 0x00001 /* C++ */
349 #define C_STAR 0x00003 /* C* */
350 #define YACC 0x10000 /* yacc file */
352 char searchar
= '/'; /* use /.../ searches */
354 LINENO lineno
; /* line number of current line */
355 long charno
; /* current character number */
357 long linecharno
; /* charno of start of line; not used by C, but
358 * by every other language.
361 char *curfile
, /* current input file name */
362 *outfile
, /* output file */
363 *white
= " \f\t\n", /* white chars */
364 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
365 /* token starting chars */
366 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$",
367 /* valid in-token chars */
368 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
370 int append_to_tagfile
; /* -a: append to tags */
371 int emacs_tags_format
; /* emacs style output (no -e option any more) */
372 /* The following three default to 1 for etags, but to 0 for ctags. */
373 int typedefs
; /* -t: create tags for typedefs */
374 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
375 /* 0 struct/enum/union decls, and C++ */
376 /* member functions */
377 int constantypedefs
; /* -d: create tags for C #define and enum */
378 /* constants. Default under etags. Enum */
379 /* constants not implemented. */
380 /* -D: opposite of -d. Default under ctags. */
381 int update
; /* -u: update tags */
382 int vgrind_style
; /* -v: create vgrind style index output */
383 int no_warnings
; /* -w: suppress warnings */
384 int cxref_style
; /* -x: create cxref style output */
385 int cplusplus
; /* .[hc] means C++, not C */
386 int noindentypedefs
; /* -S: ignore indentation in C */
388 /* Name this program was invoked with. */
391 struct option longopts
[] = {
392 { "append", no_argument
, NULL
, 'a' },
393 { "backward-search", no_argument
, NULL
, 'B' },
394 { "c++", no_argument
, NULL
, 'C' },
395 { "cxref", no_argument
, NULL
, 'x' },
396 { "defines", no_argument
, NULL
, 'd' },
397 { "forward-search", no_argument
, NULL
, 'F' },
398 { "help", no_argument
, NULL
, 'H' },
399 { "ignore-indentation", no_argument
, NULL
, 'S' },
400 { "include", required_argument
, NULL
, 'i' },
401 { "no-defines", no_argument
, NULL
, 'D' },
402 { "no-warn", no_argument
, NULL
, 'w' },
403 { "output", required_argument
, NULL
, 'o' },
404 { "typedefs", no_argument
, NULL
, 't' },
405 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
406 { "update", no_argument
, NULL
, 'u' },
407 { "version", no_argument
, NULL
, 'V' },
408 { "vgrind", no_argument
, NULL
, 'v' },
412 FILE *inf
, /* ioptr for current input file */
413 *outf
; /* ioptr for tags file */
415 NODE
*head
; /* the head of the binary tree of tags */
417 int permit_duplicates
= 1; /* Nonzero means allow duplicate tags. */
419 /* A `struct linebuffer' is a structure which holds a line of text.
420 `readline' reads a line from a stream into a linebuffer
421 and works regardless of the length of the line. */
429 struct linebuffer lb
; /* the current line */
430 struct linebuffer filename_lb
; /* used to read in filenames */
434 struct linebuffer lb
; /* used by C_entries instead of lb */
449 printf ("for Emacs version 19.0.\n");
457 printf ("These are the options accepted by %s. You may use unambiguous\n\
458 abbreviations for the long option names.\n\n", progname
);
462 Append tag entries to existing tags file.\n\
464 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
465 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
466 extensions are always assumed to be C++ code.\n\
468 Create tag entries for #defines, too.", stdout
);
471 fputs (" This is the default\n\
477 Don't create tag entries for #defines.", stdout
);
480 fputs (" This is the default\n\
485 -o FILE, --output=FILE\n\
486 Write the tags to FILE.\n\
487 -S, --ignore-indentation\n\
488 Don't rely on indentation quite as much as normal. Currently,\n\
489 this means not to assume that a closing brace in the first\n\
490 column is the final brace of a function or structure\n\
493 Generate tag entries for typedefs. This is the default\n\
495 -T, --typedefs-and-c++\n\
496 Generate tag entries for typedefs, struct/enum/union tags, and\n\
497 C++ member functions.");
500 puts ("-i FILE, --include=FILE\n\
501 Include a note in tag file indicating that, when searching for\n\
502 a tag, one should also consult the tags file FILE after\n\
503 checking the current file.");
507 puts ("-B, --backward-search\n\
508 Write the search commands for the tag entries using '?', the\n\
509 backward-search command.\n\
510 -F, --forward-search\n\
511 Write the search commands for the tag entries using '/', the\n\
512 forward-search command.\n\
514 Update the tag entries for the given files, leaving tag\n\
515 entries for other files in place. Currently, this is\n\
516 implemented by deleting the existing entries for the given\n\
517 files and then rewriting the new entries at the end of the\n\
518 tags file. It is often faster to simply rebuild the entire\n\
519 tag file than to use this.\n\
521 Generates an index of items intended for human consumption,\n\
522 similar to the output of vgrind. The index is sorted, and\n\
523 gives the page number of each item.\n\
525 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
526 The output uses line numbers instead of page numbers, but\n\
527 beyond that the differences are cosmetic; try both to see\n\
530 Suppress warning messages about entries defined in multiple\n\
534 puts ("-V, --version\n\
535 Print the version of the program.\n\
537 Print this help message.");
550 unsigned int nincluded_files
= 0;
551 char **included_files
= (char **) alloca (argc
* sizeof (char *));
556 extern char *gfnames ();
557 extern char *massage_name ();
563 emacs_tags_format
= 1;
565 emacs_tags_format
= 0;
569 * If etags, always find typedefs and structure tags. Why not?
570 * Also default is to find macro constants.
572 if (emacs_tags_format
)
573 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
578 opt
= getopt_long (argc
, argv
, "aCdDo:f:StTi:BFuvxwVH", longopts
, 0);
586 /* If getopt returns '\0', then it has already processed a
587 long-named option. We should do nothing. */
590 /* Common options. */
608 "%s: -%c flag may only be given once\n", progname
, opt
);
621 typedefs_and_cplusplus
++;
632 if (!emacs_tags_format
)
634 included_files
[nincluded_files
++] = optarg
;
640 if (emacs_tags_format
)
645 if (emacs_tags_format
)
650 if (emacs_tags_format
)
658 if (emacs_tags_format
)
663 if (emacs_tags_format
)
672 if (optind
== argc
&& nincluded_files
== 0)
674 fprintf (stderr
, "%s: No input files specified.\n", progname
);
677 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
684 outfile
= emacs_tags_format
? "TAGS" : "tags";
687 init (); /* set up boolean "functions" */
690 initbuffer (&lbs
[0].lb
);
691 initbuffer (&lbs
[1].lb
);
692 initbuffer (&filename_lb
);
694 * loop through files finding functions
696 if (emacs_tags_format
)
698 if (streq (outfile
, "-"))
701 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
712 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
716 error ("Can't find file %s\n", this_file
);
721 this_file
= massage_name (this_file
);
724 } /* solely to balance out the ifdef'd parens above */
727 for (; optind
< argc
; optind
++)
729 this_file
= argv
[optind
];
733 /* Input file named "-" means read file names from stdin
735 if (streq (this_file
, "-"))
737 while (!feof (stdin
))
739 (void) readline (&filename_lb
, stdin
);
740 if (strlen (filename_lb
.buffer
) > 0)
741 process_file (filename_lb
.buffer
);
745 process_file (this_file
);
749 if (emacs_tags_format
)
751 while (nincluded_files
-- > 0)
752 fprintf (outf
, "\f\n%s,include\n", *included_files
++);
754 (void) fclose (outf
);
765 /* update cannot be set under VMS, so we may assume that argc
766 and argv have not been munged. */
767 for (i
= optind
; i
< argc
; i
++)
770 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
771 outfile
, argv
[i
], outfile
);
776 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
783 (void) fclose (outf
);
786 sprintf (cmd
, "sort %s -o %s", outfile
, outfile
);
794 * This routine is called on each file argument.
800 struct stat stat_buf
;
802 stat (file
, &stat_buf
);
803 if (!(stat_buf
.st_mode
& S_IFREG
)
805 || !(stat_buf
.st_mode
& S_IFLNK
)
809 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
813 if (streq (file
, outfile
) && !streq (outfile
, "-"))
815 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
818 if (emacs_tags_format
)
820 char *cp
= etags_rindex (file
, '/');
827 if (emacs_tags_format
)
829 fprintf (outf
, "\f\n%s,%d\n",
830 file
, total_size_of_entries (head
));
838 * This routine sets up the boolean pseudo-functions which work
839 * by setting boolean flags dependent upon the corresponding character
840 * Every char which is NOT in that string is not a white char. Therefore,
841 * all of the array "_wht" is set to FALSE, and then the elements
842 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
843 * of a char is TRUE if it is the string "white", else FALSE.
851 for (i
= 0; i
< 0177; i
++)
852 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
853 for (sp
= white
; *sp
; sp
++)
855 for (sp
= endtk
; *sp
; sp
++)
857 for (sp
= intk
; *sp
; sp
++)
859 for (sp
= begtk
; *sp
; sp
++)
861 _wht
[0] = _wht
['\n'];
862 _etk
[0] = _etk
['\n'];
863 _btk
[0] = _btk
['\n'];
864 _itk
[0] = _itk
['\n'];
868 * This routine opens the specified file and calls the function
869 * which finds the function and type definitions.
876 void prolog_funcs ();
878 inf
= fopen (file
, "r");
884 curfile
= savestr (file
);
885 cp
= etags_rindex (file
, '.');
887 header_file
= (cp
&& (streq (cp
+ 1, "h")));
889 /* .tex, .aux or .bbl implies LaTeX source code */
890 if (cp
&& (streq (cp
+ 1, "tex") || streq (cp
+ 1, "aux")
891 || streq (cp
+ 1, "bbl")))
894 goto close_and_return
;
896 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
897 if (cp
&& (streq (cp
+ 1, "l")
898 || streq (cp
+ 1, "el")
899 || streq (cp
+ 1, "lsp")
900 || streq (cp
+ 1, "lisp")
901 || streq (cp
+ 1, "cl")
902 || streq (cp
+ 1, "clisp")))
905 goto close_and_return
;
907 /* .scm or .sm or .scheme or ... implies scheme source code */
908 if (cp
&& (streq (cp
+ 1, "sm")
909 || streq (cp
+ 1, "scm")
910 || streq (cp
+ 1, "scheme")
911 || streq (cp
+ 1, "t")
912 || streq (cp
+ 1, "sch")
913 || streq (cp
+ 1, "SM")
914 || streq (cp
+ 1, "SCM")
915 /* The `SCM' or `scm' prefix with a version number */
916 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
917 && string_numeric_p (cp
+ 1))
918 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
919 && string_numeric_p (cp
+ 1))))
925 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
927 if (cp
&& (streq (cp
+ 1, "s")
928 || streq (cp
+ 1, "a")
929 || streq (cp
+ 1, "sa")))
935 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
936 if (cp
&& (streq (cp
+ 1, "C")
937 || streq (cp
+ 1, "H")
938 || streq (cp
+ 1, "cxx")
939 || streq (cp
+ 1, "hxx")
940 || streq (cp
+ 1, "cc")))
942 C_entries (C_PLPL
); /* C++ */
943 goto close_and_return
;
945 /* .cs or .hs: a C* file */
946 if (cp
&& (streq (cp
+ 1, "cs")
947 || streq (cp
+ 1, "hs")))
950 goto close_and_return
;
952 /* .y: a yacc file */
953 if (cp
&& (streq (cp
+ 1, "y")))
956 goto close_and_return
;
958 /* .pl implies prolog source code */
959 if (cp
&& streq (cp
+ 1, "pl"))
962 goto close_and_return
;
964 /* .p or .pas: a Pascal file */
965 if (cp
&& (streq (cp
+ 1, "p")
966 || streq (cp
+ 1, "pas")))
969 goto close_and_return
;
971 /* If .f or .for, assume it is fortran or nothing. */
972 if (cp
&& (streq (cp
+ 1, "f")
973 || streq (cp
+ 1, "for")))
976 goto close_and_return
;
978 /* if not a .c or .h or .y file, try fortran */
979 if (cp
&& ((cp
[1] != 'c'
982 || (cp
[1] != 0 && cp
[2] != 0)))
984 if (PF_funcs (inf
) != 0)
985 goto close_and_return
;
986 rewind (inf
); /* no fortran tags found, try C */
988 C_entries (cplusplus
? C_PLPL
: 0);
994 /* Nonzero if string STR is composed of digits. */
997 string_numeric_p (str
)
1002 if (*str
< '0' || *str
> '9')
1009 /* Should take a TOKEN* instead!! */
1011 pfnote (name
, is_func
, rewritten
, linestart
, linelen
, lno
, cno
)
1012 char *name
; /* tag name */
1013 logical is_func
; /* function or type name? */
1014 logical rewritten
; /* tag different from text of definition? */
1025 np
= (NODE
*) malloc (sizeof (NODE
));
1028 if (!emacs_tags_format
)
1030 /* It's okay to output early in etags -- it only disrupts the
1031 * character count of the tag entries, which is no longer used
1032 * by tags.el anyway.
1034 error ("too many entries to sort");
1039 np
= xnew (1, NODE
);
1041 /* If ctags mode, change name "main" to M<thisfilename>. */
1042 if (!emacs_tags_format
&& !cxref_style
&& streq (name
, "main"))
1044 fp
= etags_rindex (curfile
, '/');
1045 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
1046 fp
= etags_rindex (name
, '.');
1047 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
1051 np
->name
= savestr (name
);
1053 np
->is_func
= is_func
;
1054 np
->rewritten
= rewritten
;
1056 /* UNCOMMENT THE +1 HERE: */
1057 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
1058 np
->left
= np
->right
= 0;
1059 if (emacs_tags_format
)
1061 c
= linestart
[linelen
];
1062 linestart
[linelen
] = 0;
1064 else if (cxref_style
== 0)
1066 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
1069 np
->pat
= savestr (linestart
);
1070 if (emacs_tags_format
)
1072 linestart
[linelen
] = c
;
1075 add_node (np
, &head
);
1080 * recurse on left children, iterate on right children.
1084 register NODE
*node
;
1088 register NODE
*node_right
= node
->right
;
1089 free_tree (node
->left
);
1092 free ((char *) node
);
1099 * Adds a node to the tree of nodes. In etags mode, we don't keep
1100 * it sorted; we just keep a linear list. In ctags mode, maintain
1101 * an ordered tree, with no attempt at balancing.
1103 * add_node is the only function allowed to add nodes, so it can
1106 /* Must avoid static vars within functions since some systems
1107 #define static as nothing. */
1108 static NODE
*last_node
= NULL
;
1111 add_node (node
, cur_node_p
)
1112 NODE
*node
, **cur_node_p
;
1115 register NODE
*cur_node
= *cur_node_p
;
1117 if (cur_node
== NULL
)
1124 if (emacs_tags_format
)
1128 fatal ("internal error in add_node");
1129 last_node
->right
= node
;
1135 dif
= strcmp (node
->name
, cur_node
->name
);
1138 * If this tag name matches an existing one, then
1139 * do not add the node, but maybe print a warning.
1143 if (node
->file
== cur_node
->file
)
1147 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1148 node
->file
, lineno
, node
->name
);
1149 fprintf (stderr
, "Second entry ignored\n");
1153 if (!cur_node
->been_warned
&& !no_warnings
)
1156 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1157 node
->file
, cur_node
->file
, node
->name
);
1159 cur_node
->been_warned
= TRUE
;
1163 /* Maybe refuse to add duplicate nodes. */
1164 if (!permit_duplicates
)
1166 if (!strcmp (node
->name
, cur_node
->name
)
1167 && !strcmp (node
->file
, cur_node
->file
))
1171 /* Actually add the node */
1172 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1178 register NODE
*node
;
1185 /* Output subentries that precede this one */
1186 put_entries (node
->left
);
1188 /* Output this entry */
1190 if (emacs_tags_format
)
1192 if (node
->rewritten
)
1194 fprintf (outf
, "%s\177%s\001%d,%d\n",
1195 node
->name
, node
->pat
, node
->lno
, node
->cno
);
1199 fprintf (outf
, "%s\177%d,%d\n",
1200 node
->pat
, node
->lno
, node
->cno
);
1203 else if (!cxref_style
)
1205 fprintf (outf
, "%s\t%s\t",
1206 node
->name
, node
->file
);
1210 putc (searchar
, outf
);
1213 for (sp
= node
->pat
; *sp
; sp
++)
1215 if (*sp
== '\\' || *sp
== searchar
)
1219 putc (searchar
, outf
);
1222 { /* a typedef; text pattern inadequate */
1223 fprintf (outf
, "%d", node
->lno
);
1227 else if (vgrind_style
)
1228 fprintf (stdout
, "%s %s %d\n",
1229 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1231 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1232 node
->name
, node
->lno
, node
->file
, node
->pat
);
1234 /* Output subentries that follow this one */
1235 put_entries (node
->right
);
1238 /* Length of a number's decimal representation. */
1246 for (; num
; num
/= 10)
1252 * Return total number of characters that put_entries will output for
1253 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1254 * is set, but called only in that case. This count is irrelevant with
1255 * the new tags.el, but is still supplied for backward compatibility.
1258 total_size_of_entries (node
)
1259 register NODE
*node
;
1267 for (; node
; node
= node
->right
)
1269 /* Count left subentries. */
1270 total
+= total_size_of_entries (node
->left
);
1272 /* Count this entry */
1273 total
+= strlen (node
->pat
) + 1;
1274 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1275 if (node
->rewritten
)
1276 total
+= 1 + strlen (node
->name
); /* \001name */
1283 * The C symbol tables.
1286 Stab
*C_stab
, *C_PLPL_stab
, *C_STAR_stab
;
1290 * Stab *get_C_stab (int c_ext);
1292 #define get_C_stab(c_ext) ((c_ext & C_STAR) ? C_STAR_stab : \
1293 (c_ext & C_PLPL) ? C_PLPL_stab : \
1297 add_keyword (stab
, sym
, type
)
1302 stab_search (stab
, sym
, strlen (sym
))->type
= type
;
1306 C_create_stab (c_ext
)
1311 stab
= stab_create ();
1315 add_keyword (stab
, "class", st_C_struct
);
1317 add_keyword (stab
, "domain", st_C_struct
);
1318 add_keyword (stab
, "union", st_C_struct
);
1319 add_keyword (stab
, "struct", st_C_struct
);
1320 add_keyword (stab
, "enum", st_C_enum
);
1321 add_keyword (stab
, "typedef", st_C_typedef
);
1322 add_keyword (stab
, "define", st_C_define
);
1323 add_keyword (stab
, "long", st_C_typespec
);
1324 add_keyword (stab
, "short", st_C_typespec
);
1325 add_keyword (stab
, "int", st_C_typespec
);
1326 add_keyword (stab
, "char", st_C_typespec
);
1327 add_keyword (stab
, "float", st_C_typespec
);
1328 add_keyword (stab
, "double", st_C_typespec
);
1329 add_keyword (stab
, "signed", st_C_typespec
);
1330 add_keyword (stab
, "unsigned", st_C_typespec
);
1331 add_keyword (stab
, "auto", st_C_typespec
);
1332 add_keyword (stab
, "void", st_C_typespec
);
1333 add_keyword (stab
, "extern", st_C_typespec
);
1334 add_keyword (stab
, "static", st_C_typespec
);
1335 add_keyword (stab
, "const", st_C_typespec
);
1336 add_keyword (stab
, "volatile", st_C_typespec
);
1344 C_stab
= C_create_stab (0);
1345 C_PLPL_stab
= C_create_stab (C_PLPL
);
1346 C_STAR_stab
= C_create_stab (C_STAR
| C_PLPL
);
1350 * etags.c 4.2 1993/03/22 12:13:40 pot Exp
1351 * C functions are recognized using a simple finite automaton.
1352 * funcdef is its state variable.
1356 fnone
, ftagseen
, finlist
, flistseen
1361 /* typedefs are recognized using a simple finite automaton.
1362 * typeddef is its state variable.
1366 tnone
, ttypedseen
, tinbody
, tend
1371 /* struct tags for C++ are recognized using another simple
1372 * finite automaton. `structdef' is its state variable.
1373 * This machinery is only invoked for C++; otherwise structdef
1374 * should remain snone. However, this machinery can easily be
1375 * adapted to find structure tags in normal C code.
1379 snone
, /* nothing seen yet */
1380 skeyseen
, /* struct-like keyword seen */
1381 stagseen
, /* struct-like tag seen */
1382 scolonseen
, /* colon seen after struct-like tag */
1383 sinbody
/* in class body: recognize member func defs */
1387 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1388 * struct tag, and structkey is the preceding struct-like keyword.
1390 char structtag
[BUFSIZ
];
1391 Stab_entry
*structkey
;
1394 * Yet another little state machine to deal with preprocessor lines.
1398 dnone
, /* nothing seen */
1399 dsharpseen
, /* '#' seen as first char on line */
1400 ddefineseen
, /* '#' and 'define' seen */
1401 dignorerest
/* ignore rest of line */
1406 * Set this to TRUE, and the next token considered is called a function.
1407 * Used only for GNUmacs's function-defining macros.
1409 logical next_token_is_func
;
1412 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1418 * This routine finds functions, typedefs, #define's and
1419 * struct/union/enum definitions in C syntax and adds them
1424 * LEVEL_OK_FOR_FUNCDEF allows C++ function definition within class body.
1425 * Currently typdef and structdef stuff (typedefs and struct
1426 * definitions) are only noticed when level==0, but that may change.
1428 #define LEVEL_OK_FOR_FUNCDEF() \
1429 (level==0 || (cplpl && level==1 && structdef==sinbody))
1431 #define curlb (lbs[curndx].lb)
1432 #define othlb (lbs[1-curndx].lb)
1433 #define newlb (lbs[newndx].lb)
1434 #define curlinepos (lbs[curndx].linepos)
1435 #define othlinepos (lbs[1-curndx].linepos)
1436 #define newlinepos (lbs[newndx].linepos)
1438 #define CNL_SAVE_DEFINEDEF \
1440 SET_FILEPOS (curlinepos, inf, charno); \
1442 charno += readline (&curlb, inf); \
1443 lp = curlb.buffer; \
1450 CNL_SAVE_DEFINEDEF; \
1451 definedef = dnone; \
1454 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1455 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1456 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1457 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1461 int c_ext
; /* extension of C? */
1463 register char c
; /* latest char read; '\0' for end of line */
1464 register char *lp
; /* pointer one beyond the character `c' */
1465 int curndx
, newndx
; /* indices for current and new lb */
1466 TOKEN tok
; /* latest token read for funcdef & structdef */
1467 char tokb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1468 register int tokoff
; /* offset in line of start of latest token */
1469 register int toklen
; /* length of latest token */
1470 int level
; /* current curly brace level */
1471 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1474 curndx
= newndx
= 0;
1480 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1481 next_token_is_func
= yacc_rules
= FALSE
;
1482 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1484 cplpl
= c_ext
& C_PLPL
;
1493 /* If we're at the end of the line, the next character is a
1494 '\0'; don't skip it, because it's the thing that tells us
1495 to read the next line. */
1516 /* Newlines inside comments do not end macro definitions in
1531 /* Newlines inside strings, do not end macro definitions
1532 in traditional cpp, even though compilers don't
1533 usually accept them. */
1561 else if (cplpl
&& *lp
== '/')
1568 if ((c_ext
& YACC
) && *lp
== '%')
1570 /* entering or exiting rules section in yacc file */
1572 definedef
= dnone
; funcdef
= fnone
;
1573 typdef
= tnone
; structdef
= snone
;
1574 next_token_is_func
= FALSE
;
1575 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1577 yacc_rules
= !yacc_rules
;
1581 if (lp
== newlb
.buffer
+ 1 && definedef
== dnone
)
1582 definedef
= dsharpseen
;
1587 if (LEVEL_OK_FOR_FUNCDEF ()
1588 && definedef
!= dignorerest
1589 && structdef
!= scolonseen
1590 && funcdef
!= finlist
)
1596 if (cplpl
&& c
== ':' && *lp
== ':' && intoken (*(lp
+ 1)))
1599 * This handles :: in the middle, but not at beginning
1609 tok
.lineno
= lineno
;
1610 tok
.p
= newlb
.buffer
+ tokoff
;
1612 tok
.rewritten
= FALSE
;
1614 || consider_token (c
, lp
, &tok
,
1615 c_ext
, level
, &is_func
))
1617 if (structdef
== sinbody
1618 && definedef
== dnone
&& is_func
)
1619 { /* function defined in C++ class body */
1620 sprintf (tokb
, "%s::%.*s",
1621 ((structtag
[0] == '\0')
1622 ? "_anonymous_" : structtag
),
1624 tok
.rewritten
= TRUE
;
1628 sprintf (tokb
, "%.*s", tok
.len
, tok
.p
);
1631 if (funcdef
== ftagseen
|| structdef
== stagseen
)
1633 if (newndx
== curndx
)
1634 curndx
= 1 - curndx
; /* switch line buffers */
1637 MAKE_TAG_FROM_NEW_LB (is_func
);
1641 } /* if (endtoken (c)) */
1642 else if (intoken (c
))
1647 } /* if (midtoken) */
1648 else if (begtoken (c
))
1653 MAKE_TAG_FROM_OTH_LB (TRUE
);
1659 if (structdef
== stagseen
)
1661 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1663 tokoff
= lp
- 1 - newlb
.buffer
;
1669 } /* if must look at token */
1672 /* Detect end of line, colon, comma, semicolon and various braces
1673 after having handled the last token on the line.*/
1677 if (structdef
== stagseen
)
1678 structdef
= scolonseen
;
1679 else if (yacc_rules
&& funcdef
== ftagseen
)
1681 MAKE_TAG_FROM_OTH_LB (FALSE
);
1689 if (funcdef
!= finlist
)
1691 if (level
== 0 && typdef
== tend
)
1695 if (funcdef
!= finlist
)
1697 if (structdef
== stagseen
)
1713 if (funcdef
== finlist
)
1714 funcdef
= flistseen
;
1717 if (typdef
== ttypedseen
)
1721 case skeyseen
: /* unnamed struct */
1722 structtag
[0] = '\0';
1723 structdef
= sinbody
;
1726 case scolonseen
: /* named struct */
1727 structdef
= sinbody
;
1728 MAKE_TAG_FROM_OTH_LB (FALSE
);
1734 if (funcdef
== flistseen
)
1736 MAKE_TAG_FROM_OTH_LB (TRUE
);
1741 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
1742 level
= 0; /* reset level if first column */
1747 if (typdef
== tinbody
)
1750 (void) strcpy (structtag
, "<error 2>");
1754 /* If a macro spans multiple lines don't reset its state. */
1762 } /* while not eof */
1767 * checks to see if the current token is at the start of a
1768 * function, or corresponds to a typedef, or is a struct/union/enum
1771 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1772 * C_EXT is which language we are looking at.
1774 * In the future we will need some way to adjust where the end of
1775 * the token is; for instance, implementing the C++ keyword
1776 * `operator' properly will adjust the end of the token to be after
1777 * whatever follows `operator'.
1784 * next_token_is_func IN OUT
1788 consider_token (c
, lp
, tokp
, c_ext
, level
, is_func
)
1789 register char c
; /* IN: first char after the token */
1790 register char *lp
; /* IN: lp points to 2nd char after the token */
1791 register TOKEN
*tokp
; /* IN */
1794 logical
*is_func
; /* OUT */
1796 logical firsttok
; /* TRUE if have seen first token in ()'s */
1797 Stab_entry
*tokse
= stab_find (get_C_stab (c_ext
), tokp
->p
, tokp
->len
);
1798 enum sym_type toktype
= stab_type (tokse
);
1800 *is_func
= FALSE
; /* not a function */
1803 * Advance the definedef state machine.
1808 /* We're not on a preprocessor line. */
1811 if (toktype
== st_C_define
)
1813 definedef
= ddefineseen
;
1817 definedef
= dignorerest
;
1822 * Make a tag for any macro.
1824 definedef
= dignorerest
;
1825 *is_func
= (c
== '(');
1826 if (!*is_func
&& !constantypedefs
)
1833 error ("internal error: definedef value");
1842 if (toktype
== st_C_typedef
)
1845 typdef
= ttypedseen
;
1860 /* Do not return here, so the structdef stuff has a chance. */
1874 * This structdef business is currently only invoked when level==0.
1875 * It should be recursively invoked whatever the level, and a stack of
1876 * states kept, to allow for definitions of structs within 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
&& level
== 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
;
1948 funcdef
== fnone
; /* should be useless */
1957 /* Fortran parsing */
1973 linecharno
= charno
;
1974 charno
+= readline (&lb
, fi
);
1977 dbp
++; /* Ratfor escape to fortran */
1978 while (isspace (*dbp
))
1985 if (tail ("integer"))
1993 if (tail ("logical"))
1997 if (tail ("complex") || tail ("character"))
2001 if (tail ("double"))
2003 while (isspace (*dbp
))
2007 if (tail ("precision"))
2013 while (isspace (*dbp
))
2020 if (tail ("function"))
2024 if (tail ("subroutine"))
2032 if (tail ("program"))
2037 if (tail ("procedure"))
2049 register int len
= 0;
2051 while (*cp
&& (*cp
& ~' ') == ((*(dbp
+ len
)) & ~' '))
2064 while (isspace (*dbp
))
2069 while (isspace (*dbp
))
2071 if (!isdigit (*dbp
))
2073 --dbp
; /* force failure */
2078 while (isdigit (*dbp
));
2086 char nambuf
[BUFSIZ
];
2088 while (isspace (*dbp
))
2095 for (cp
= dbp
+ 1; *cp
&& (isalpha (*cp
) || isdigit (*cp
)
2096 || (*cp
== '_') || (*cp
== '$')); cp
++)
2100 (void) strcpy (nambuf
, dbp
);
2102 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2106 /* Handle a file of assembler code. */
2122 linecharno
= charno
;
2123 charno
+= readline (&lb
, fi
);
2126 for (i
= 0; ((c
= dbp
[i
]) && !isspace (c
)) && (c
!= ':'); i
++)
2129 if ((i
> 0) && (c
== ':'))
2134 /* Added by Mosur Mohan, 4/22/88 */
2135 /* Pascal parsing */
2137 #define GET_NEW_LINE \
2139 linecharno = charno; lineno++; \
2140 charno += 1 + readline (&lb, inf); \
2144 /* Locates tags for procedures & functions.
2145 * Doesn't do any type- or var-definitions.
2146 * It does look for the keyword "extern" or "forward"
2147 * immediately following the procedure statement;
2148 * if found, the tag is skipped.
2155 struct linebuffer tline
; /* mostly copied from C_entries */
2159 char nambuf
[BUFSIZ
];
2161 logical
/* each of these flags is TRUE iff: */
2162 incomm1
, /* point is inside {..} comment */
2163 incomm2
, /* point is inside (*..*) comment */
2164 inquote
, /* point is inside '..' string */
2165 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2166 /* keyword, so next item = potential tag */
2167 found_tag
, /* point is after a potential tag */
2168 inparms
, /* point is within parameter-list */
2169 verify_tag
; /* point has passed the parm-list, so the */
2170 /* next token will determine whether */
2171 /* this is a FORWARD/EXTERN to be */
2172 /* ignored, or whether it is a real tag */
2178 initbuffer (&tline
);
2180 incomm1
= incomm2
= inquote
= FALSE
;
2181 found_tag
= FALSE
; /* have a proc name; check if extern */
2182 get_tagname
= FALSE
; /* have found "procedure" keyword */
2183 inparms
= FALSE
; /* found '(' after "proc" */
2184 verify_tag
= FALSE
; /* check if "extern" is ahead */
2186 /* long main loop to get next char */
2190 if (c
== 0) /* if end of line */
2195 if (!((found_tag
&& verify_tag
) ||
2197 c
= *dbp
++; /* only if don't need *dbp pointing */
2198 /* to the beginning of the name of */
2199 /* the procedure or function */
2201 if (incomm1
) /* within { - } comments */
2207 else if (incomm2
) /* within (* - *) comments */
2211 while ((c
= *dbp
++) == '*')
2230 inquote
= TRUE
; /* found first quote */
2232 case '{': /* found open-{-comment */
2236 if (*dbp
== '*') /* found open-(*-comment */
2241 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2244 case ')': /* end of parms list */
2249 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2256 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2258 /* check if this is an "extern" declaration */
2261 if ((*dbp
== 'e') || (*dbp
== 'E'))
2263 if (tail ("extern")) /* superfluous, really! */
2269 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2271 if (tail ("forward")) /* check for forward reference */
2277 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2281 pfnote (nambuf
, TRUE
, FALSE
,
2282 tline
.buffer
, cp
- tline
.buffer
+ 1,
2283 save_lineno
, save_lcno
);
2287 if (get_tagname
) /* grab name of proc or fn */
2292 /* save all values for later tagging */
2293 tline
.size
= lb
.size
;
2294 strcpy (tline
.buffer
, lb
.buffer
);
2295 save_lineno
= lineno
;
2296 save_lcno
= linecharno
;
2298 /* grab block name */
2299 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2303 strcpy (nambuf
, dbp
);
2305 dbp
= cp
; /* restore dbp to e-o-token */
2306 get_tagname
= FALSE
;
2310 /* and proceed to check for "extern" */
2312 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2313 (!found_tag
) && (!get_tagname
))
2315 /* check for proc/fn keywords */
2319 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2323 if (tail ("unction"))
2328 } /* while not e-o-f */
2332 * lisp tag functions
2333 * just look for (def or (DEF
2347 linecharno
= charno
;
2348 charno
+= readline (&lb
, fi
);
2354 while (!isspace (*dbp
))
2356 while (isspace (*dbp
))
2362 /* Check for (foo::defmumble name-defined ... */
2363 while (*dbp
&& *dbp
!= ':' && !isspace (*dbp
)
2364 && *dbp
!= '(' && *dbp
!= ')')
2373 while (!isspace (*dbp
))
2375 while (isspace (*dbp
))
2389 return ((dbp
[1] == 'D' || dbp
[1] == 'd') &&
2390 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2391 (dbp
[3] == 'F' || dbp
[3] == 'f'));
2399 char nambuf
[BUFSIZ
];
2403 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ' '; cp
++)
2407 (void) strcpy (nambuf
, dbp
);
2409 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2414 * Scheme tag functions
2415 * look for (def... xyzzy
2416 * look for (def... (xyzzy
2417 * look for (def ... ((...(xyzzy ....
2418 * look for (set! xyzzy
2421 static void get_scheme ();
2434 linecharno
= charno
;
2435 charno
+= readline (&lb
, fi
);
2437 if (dbp
[0] == '(' &&
2438 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2439 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2440 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2442 while (!isspace (*dbp
))
2444 /* Skip over open parens and white space */
2445 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2449 if (dbp
[0] == '(' &&
2450 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2451 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2452 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2453 (dbp
[4] == '!' || dbp
[4] == '!') &&
2456 while (!isspace (*dbp
))
2458 /* Skip over white space */
2459 while (isspace (*dbp
))
2471 char nambuf
[BUFSIZ
];
2475 /* Go till you get to white space or a syntactic break */
2476 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2478 /* Null terminate the string there. */
2481 /* Copy the string */
2482 strcpy (nambuf
, dbp
);
2483 /* Unterminate the string */
2485 /* Announce the change */
2486 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2490 /* Find tags in TeX and LaTeX input files. */
2492 /* TEX_toktab is a table of TeX control sequences that define tags.
2493 Each TEX_tabent records one such control sequence.
2494 CONVERT THIS TO USE THE Stab TYPE!! */
2502 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2504 /* Default set of control sequences to put into TEX_toktab.
2505 The value of environment var TEXTAGS is prepended to this. */
2507 static char *TEX_defenv
=
2508 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2511 struct TEX_tabent
*TEX_decode_env ();
2515 static char TEX_esc
= '\\';
2516 static char TEX_opgrp
= '{';
2517 static char TEX_clgrp
= '}';
2520 * TeX/LaTeX scanning loop.
2533 /* Select either \ or ! as escape character. */
2536 /* Initialize token table once from environment. */
2538 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2541 { /* Scan each line in file */
2543 linecharno
= charno
;
2544 charno
+= readline (&lb
, fi
);
2547 while (dbp
= etags_index (dbp
, TEX_esc
)) /* Look at each escape in line */
2553 linecharno
+= dbp
- lasthit
;
2555 i
= TEX_Token (lasthit
);
2558 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2559 break; /* We only save a line once */
2565 #define TEX_LESC '\\'
2566 #define TEX_SESC '!'
2569 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2570 /* chars accordingly. */
2578 while ((c
= getc (f
)) != EOF
)
2580 /* Skip to next line if we hit the TeX comment char. */
2584 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2603 /* Read environment and prepend it to the default string. */
2604 /* Build token table. */
2607 TEX_decode_env (evarname
, defenv
)
2611 register char *env
, *p
;
2613 struct TEX_tabent
*tab
;
2616 /* Append default string to environment. */
2617 env
= getenv (evarname
);
2621 env
= concat (env
, defenv
, "");
2623 /* Allocate a token table */
2624 for (size
= 1, p
= env
; p
;)
2625 if ((p
= etags_index (p
, ':')) && *(++p
))
2627 /* Add 1 to leave room for null terminator. */
2628 tab
= xnew (size
+ 1, struct TEX_tabent
);
2630 /* Unpack environment string into token table. Be careful about */
2631 /* zero-length strings (leading ':', "::" and trailing ':') */
2634 p
= etags_index (env
, ':');
2635 if (!p
) /* End of environment string. */
2636 p
= env
+ strlen (env
);
2638 { /* Only non-zero strings. */
2639 tab
[i
].name
= savenstr (env
, p
- env
);
2640 tab
[i
].len
= strlen (tab
[i
].name
);
2647 tab
[i
].name
= NULL
; /* Mark end of table. */
2655 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2656 The name being defined actually starts at (NAME + LEN + 1).
2657 But we seem to include the TeX command in the tag name. */
2660 TEX_getit (name
, len
)
2664 char *p
= name
+ len
;
2665 char nambuf
[BUFSIZ
];
2670 /* Let tag name extend to next group close (or end of line) */
2671 while (*p
&& *p
!= TEX_clgrp
)
2673 (void) strncpy (nambuf
, name
, p
- name
);
2674 nambuf
[p
- name
] = 0;
2676 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2680 /* If the text at CP matches one of the tag-defining TeX command names,
2681 return the etags_index of that command in TEX_toktab.
2682 Otherwise return -1. */
2684 /* Keep the capital `T' in `Token' for dumb truncating compilers
2685 (this distinguishes it from `TEX_toktab' */
2692 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2693 if (strncmp (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
) == 0)
2698 /* Support for Prolog. */
2700 /* whole head (not only functor, but also arguments)
2701 is gotten in compound term. */
2704 prolog_getit (s
, lineno
, linecharno
)
2709 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2717 if (*s
== '\0') /* syntax error. */
2719 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2721 else if (*s
== '\'')
2723 insquote
= !insquote
;
2726 else if (!insquote
&& *s
== '(')
2731 else if (!insquote
&& *s
== ')')
2737 else if (npar
< 0) /* syntax error. */
2740 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2742 if (npar
!= 0) /* syntax error. */
2752 strcpy (nambuf
, save_s
);
2754 pfnote (nambuf
, TRUE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2757 /* It is assumed that prolog predicate starts from column 0. */
2763 void skip_comment (), prolog_getit ();
2765 lineno
= linecharno
= charno
= 0;
2769 linecharno
+= charno
;
2770 charno
= readline (&lb
, fi
) + 1; /* 1 for newline. */
2772 if (isspace (dbp
[0])) /* not predicate header. */
2774 else if (dbp
[0] == '%') /* comment. */
2776 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2777 skip_comment (&lb
, fi
, &lineno
, &linecharno
);
2779 prolog_getit (dbp
, lineno
, linecharno
);
2784 skip_comment (plb
, fi
, plineno
, plinecharno
)
2785 struct linebuffer
*plb
;
2787 int *plineno
; /* result */
2788 long *plinecharno
; /* result */
2790 while (!substr ("*/", plb
->buffer
))
2793 *plinecharno
+= readline (plb
, fi
) + 1;
2794 } /* 1 for newline. */
2797 /* Return TRUE if 'sub' exists somewhere in 's'. */
2804 while (*s
&& (s
= etags_index (s
, *sub
)))
2805 if (prestr (sub
, s
))
2812 /* Return TRUE if 'pre' is prefix of string 's'. */
2821 else if (*pre
== *s
)
2822 return (prestr (pre
+ 1, s
+ 1));
2827 /* Initialize a linebuffer for use */
2830 initbuffer (linebuffer
)
2831 struct linebuffer
*linebuffer
;
2833 linebuffer
->size
= 200;
2834 linebuffer
->buffer
= xnew (200, char);
2838 * Read a line of text from `stream' into `linebuffer'.
2839 * Return the number of characters read from `stream',
2840 * which is the length of the line including the newline, if any.
2843 readline (linebuffer
, stream
)
2844 struct linebuffer
*linebuffer
;
2845 register FILE *stream
;
2847 char *buffer
= linebuffer
->buffer
;
2848 register char *p
= linebuffer
->buffer
;
2849 register char *pend
;
2850 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2852 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
2856 register int c
= getc (stream
);
2859 linebuffer
->size
*= 2;
2860 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
2861 p
+= buffer
- linebuffer
->buffer
;
2862 pend
= buffer
+ linebuffer
->size
;
2863 linebuffer
->buffer
= buffer
;
2865 if (c
< 0 || c
== '\n')
2868 newline
= (c
== '\n' ? 1 : 0);
2874 return p
- buffer
+ newline
;
2881 return savenstr (cp
, strlen (cp
));
2891 dp
= xnew (len
+ 1, char);
2892 (void) strncpy (dp
, cp
, len
);
2898 * Return the ptr in sp at which the character c last
2899 * appears; NULL if not found
2901 * Identical to v7 rindex, included for portability.
2905 etags_rindex (sp
, c
)
2906 register char *sp
, c
;
2921 * Return the ptr in sp at which the character c first
2922 * appears; NULL if not found
2924 * Identical to v7 index, included for portability.
2929 register char *sp
, c
;
2939 /* Print error message and exit. */
2950 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
2957 fprintf (stderr
, "%s: ", progname
);
2958 fprintf (stderr
, s1
, s2
);
2959 fprintf (stderr
, "\n");
2962 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
2968 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
2969 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
2971 (void) strcpy (result
, s1
);
2972 (void) strcpy (result
+ len1
, s2
);
2973 (void) strcpy (result
+ len1
+ len2
, s3
);
2974 *(result
+ len1
+ len2
+ len3
) = 0;
2979 /* Like malloc but get fatal error if memory is exhausted. */
2985 char *result
= malloc (size
);
2987 fatal ("virtual memory exhausted", 0);
2992 xrealloc (ptr
, size
)
2996 char *result
= realloc (ptr
, size
);
2998 fatal ("virtual memory exhausted");