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++.
30 #include "../src/config.h"
35 #include <sys/types.h>
40 extern char *malloc (), *realloc ();
41 extern char *getenv ();
42 extern char *strcpy (), *strncpy ();
45 char *etags_index (), *etags_rindex ();
48 /* Define the symbol ETAGS to make the program "etags",
49 which makes emacs-style tag tables by default.
50 Define CTAGS to make the program "ctags" compatible with the usual one.
51 Define neither one to get behavior that depends
52 on the name with which the program is invoked
53 (but we don't normally compile it that way). */
55 #if !defined(ETAGS) && !defined(CTAGS)
56 /* If neither is defined, program can be run as either. */
61 /* On VMS, CTAGS is not useful, so always do ETAGS. */
68 /* Exit codes for success and failure. */
78 * The FILEPOS abstract type, which represents a position in a file,
79 * plus the following accessor functions:
81 * long GET_CHARNO (pos)
82 * returns absolute char number.
83 * void SET_FILEPOS (pos, fp, charno)
84 * FILE *fp; long charno;
85 * sets `pos' from the current file
86 * position of `fp' and from `charno',
87 * which must be the absolute character
88 * number corresponding to the current
91 * The `pos' parameter is an lvalue expression of type FILEPOS.
92 * Parameters to the accessor functions are evaluated 0 or more times,
93 * and so must have no side effects.
95 * FILEPOS objects can also be assigned and passed to and from
96 * functions in the normal C manner.
98 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
102 /* real implementation */
103 typedef long FILEPOS
;
104 #define GET_CHARNO(pos) ((pos) + 0)
105 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
107 /* debugging implementation */
113 #define GET_CHARNO(pos) ((pos).charno + 0)
114 #define SET_FILEPOS(pos, fp, cno) \
115 ((void) ((pos).charno = (cno), \
116 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
120 #define streq(s, t) (strcmp (s, t) == 0)
121 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
127 #define iswhite(arg) (_wht[arg]) /* T if char is white */
128 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
129 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
130 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
132 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
135 { /* sorting structure */
136 char *name
; /* function or type name */
137 char *file
; /* file name */
138 logical is_func
; /* use pattern or line no */
139 logical rewritten
; /* list name separately */
140 logical been_warned
; /* set if noticed dup */
141 int lno
; /* line number tag is on */
142 long cno
; /* character number line starts on */
143 char *pat
; /* search pattern */
144 struct nd_st
*left
, *right
; /* left and right sons */
148 typedef struct nd_st NODE
;
150 logical header_file
; /* TRUE if .h file, FALSE o.w. */
151 /* boolean "functions" (see init) */
152 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
162 int total_size_of_entries ();
163 logical
consider_token ();
171 void Scheme_funcs ();
176 void find_entries ();
184 void process_file ();
190 * xnew -- allocate storage
193 * Type *xnew (int n, Type);
195 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
200 * Symbol table stuff.
202 * Should probably be implemented with hash table; linked list for now.
207 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
215 struct stab_entry
*next
;
218 typedef struct stab_entry Stab_entry
;
219 typedef Stab_entry
*Stab
;
223 * Stab, Stab_entry, stab_create, stab_search, stab_find -- symbol table
226 * Types: Stab, Stab_entry, enum sym_type
228 * Stab * stab_create ()
230 * Stab_entry * stab_find (stab, sym)
234 * Stab_entry * stab_search (stab, sym)
239 * stab_create creates a Stab, a symbol table object, and returns a
240 * pointer to it. stab_find finds a symbol in a Stab; it returns a
241 * pointer to the Stab_entry if found, otherwise NULL. stab_search
242 * is like stab_find, except that it creates a new Stab_entry,
243 * initialized with type = st_none, if one did not exist already
244 * (it never returns NULL).
246 * A Stab_entry is a structure that contains at least the following
249 * char *name; // must not be modified
250 * enum sym_type type; // should be set
252 * The type field is initially set to st_none; it should be set to
253 * something else by the caller of stab_search. Other possible values
254 * of an enum sym_type can be added.
262 *sp
= NULL
; /* a Stab starts out as a null Stab_entry* */
267 stab_find (stab
, sym
, symlen
)
272 register Stab_entry
*se
;
273 for (se
= *stab
; se
!= NULL
; se
= se
->next
)
275 if (se
->symlen
== symlen
&& strneq (se
->sym
, sym
, symlen
))
283 stab_search (stab
, sym
, symlen
)
288 register Stab_entry
*se
;
289 se
= stab_find (stab
, sym
, symlen
);
294 se
= xnew (1, Stab_entry
);
295 se
->sym
= savenstr (sym
, symlen
);
307 * stab_type -- type of a symbol table entry
310 * enum sym_type stab_type (Stab_entry *se);
313 * May evaluate its argument more than once.
316 #define stab_type(se) ((se)==NULL ? st_none : (se)->type)
332 #define C_PLPL 0x00001 /* C++ */
333 #define C_STAR 0x00003 /* C* */
334 #define YACC 0x10000 /* yacc file */
336 char searchar
= '/'; /* use /.../ searches */
338 LINENO lineno
; /* line number of current line */
339 long charno
; /* current character number */
341 long linecharno
; /* charno of start of line; not used by C, but
342 * by every other language.
345 char *curfile
, /* current input file name */
346 *outfile
, /* output file */
347 *white
= " \f\t\n", /* white chars */
348 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
349 /* token starting chars */
350 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$",
351 /* valid in-token chars */
352 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
354 int append_to_tagfile
; /* -a: append to tags */
355 int emacs_tags_format
; /* emacs style output (no -e option any more) */
356 /* The following three default to 1 for etags, but to 0 for ctags. */
357 int typedefs
; /* -t: create tags for typedefs */
358 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
359 /* 0 struct/enum/union decls, and C++ */
360 /* member functions */
361 int constantypedefs
; /* -d: create tags for C #define and enum */
362 /* constants. Default under etags. Enum */
363 /* constants not implemented. */
364 /* -D: opposite of -d. Default under ctags. */
365 int update
; /* -u: update tags */
366 int vgrind_style
; /* -v: create vgrind style index output */
367 int no_warnings
; /* -w: suppress warnings */
368 int cxref_style
; /* -x: create cxref style output */
369 int cplusplus
; /* .[hc] means C++, not C */
370 int noindentypedefs
; /* -S: ignore indentation in C */
372 /* Name this program was invoked with. */
375 struct option longopts
[] = {
376 { "append", no_argument
, NULL
, 'a' },
377 { "backward-search", no_argument
, NULL
, 'B' },
378 { "c++", no_argument
, NULL
, 'C' },
379 { "cxref", no_argument
, NULL
, 'x' },
380 { "defines", no_argument
, NULL
, 'd' },
381 { "forward-search", no_argument
, NULL
, 'F' },
382 { "help", no_argument
, NULL
, 'H' },
383 { "ignore-indentation", no_argument
, NULL
, 'S' },
384 { "include", required_argument
, NULL
, 'i' },
385 { "no-defines", no_argument
, NULL
, 'D' },
386 { "no-warn", no_argument
, NULL
, 'w' },
387 { "output", required_argument
, NULL
, 'o' },
388 { "typedefs", no_argument
, NULL
, 't' },
389 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
390 { "update", no_argument
, NULL
, 'u' },
391 { "version", no_argument
, NULL
, 'V' },
392 { "vgrind", no_argument
, NULL
, 'v' },
396 FILE *inf
, /* ioptr for current input file */
397 *outf
; /* ioptr for tags file */
399 NODE
*head
; /* the head of the binary tree of tags */
401 int permit_duplicates
= 1; /* Nonzero means allow duplicate tags. */
403 /* A `struct linebuffer' is a structure which holds a line of text.
404 `readline' reads a line from a stream into a linebuffer
405 and works regardless of the length of the line. */
413 struct linebuffer lb
; /* the current line */
414 struct linebuffer filename_lb
; /* used to read in filenames */
418 struct linebuffer lb
; /* used by C_entries instead of lb */
433 printf ("for Emacs version 19.0.\n");
441 printf ("These are the options accepted by %s. You may use unambiguous\n\
442 abbreviations for the long option names.\n\n", progname
);
444 puts ("-a, --append\n\
445 Append tag entries to existing tags file.");
447 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
448 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
449 extensions are always assumed to be C++ code.");
450 fputs ("-d, --defines\n\
451 Create tag entries for #defines, too.", stdout
);
454 fputs (" This is the default\n\
460 Don't create tag entries for #defines.", stdout
);
463 fputs (" This is the default\n\
468 -o FILE, --output=FILE\n\
469 Write the tags to FILE.\n\
470 -S, --ignore-indentation\n\
471 Don't rely on indentation quite as much as normal. Currently,\n\
472 this means not to assume that a closing brace in the first\n\
473 column is the final brace of a function or structure\n\
475 puts ("-t, --typedefs\n\
476 Generate tag entries for typedefs. This is the default\n\
478 puts ("-T, --typedefs-and-c++\n\
479 Generate tag entries for typedefs, struct/enum/union tags, and\n\
480 C++ member functions.");
483 puts ("-i FILE, --include=FILE\n\
484 Include a note in tag file indicating that, when searching for\n\
485 a tag, one should also consult the tags file FILE after\n\
486 checking the current file.");
490 puts ("-B, --backward-search\n\
491 Write the search commands for the tag entries using '?', the\n\
492 backward-search command.");
493 puts ("-F, --forward-search\n\
494 Write the search commands for the tag entries using '/', the\n\
495 forward-search command.");
496 puts ("-u, --update\n\
497 Update the tag entries for the given files, leaving tag\n\
498 entries for other files in place. Currently, this is\n\
499 implemented by deleting the existing entries for the given\n\
500 files and then rewriting the new entries at the end of the\n\
501 tags file. It is often faster to simply rebuild the entire\n\
502 tag file than to use this.");
503 puts ("-v, --vgrind\n\
504 Generates an index of items intended for human consumption,\n\
505 similar to the output of vgrind. The index is sorted, and\n\
506 gives the page number of each item.");
507 puts ("-x, --cxref\n\
508 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
509 The output uses line numbers instead of page numbers, but\n\
510 beyond that the differences are cosmetic; try both to see\n\
512 puts ("-w, --no-warn\n\
513 Suppress warning messages about entries defined in multiple\n\
517 puts ("-V, --version\n\
518 Print the version of the program.\n\
520 Print this help message.");
533 unsigned int nincluded_files
= 0;
534 char **included_files
= xnew (argc
, char *);
539 extern char *gfnames ();
540 extern char *massage_name ();
546 emacs_tags_format
= 1;
548 emacs_tags_format
= 0;
552 * If etags, always find typedefs and structure tags. Why not?
553 * Also default is to find macro constants.
555 if (emacs_tags_format
)
556 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
561 opt
= getopt_long (argc
, argv
, "aCdDo:f:StTi:BFuvxwVH", longopts
, 0);
569 /* If getopt returns '\0', then it has already processed a
570 long-named option. We should do nothing. */
573 /* Common options. */
591 "%s: -%c flag may only be given once\n", progname
, opt
);
604 typedefs_and_cplusplus
++;
615 if (!emacs_tags_format
)
617 included_files
[nincluded_files
++] = optarg
;
623 if (emacs_tags_format
)
628 if (emacs_tags_format
)
633 if (emacs_tags_format
)
641 if (emacs_tags_format
)
646 if (emacs_tags_format
)
655 if (optind
== argc
&& nincluded_files
== 0)
657 fprintf (stderr
, "%s: No input files specified.\n", progname
);
660 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
667 outfile
= emacs_tags_format
? "TAGS" : "tags";
670 init (); /* set up boolean "functions" */
673 initbuffer (&lbs
[0].lb
);
674 initbuffer (&lbs
[1].lb
);
675 initbuffer (&filename_lb
);
677 * loop through files finding functions
679 if (emacs_tags_format
)
681 if (streq (outfile
, "-"))
684 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
695 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
699 error ("Can't find file %s\n", this_file
);
704 this_file
= massage_name (this_file
);
707 } /* solely to balance out the ifdef'd parens above */
710 for (; optind
< argc
; optind
++)
712 this_file
= argv
[optind
];
716 /* Input file named "-" means read file names from stdin
718 if (streq (this_file
, "-"))
720 while (!feof (stdin
))
722 (void) readline (&filename_lb
, stdin
);
723 if (strlen (filename_lb
.buffer
) > 0)
724 process_file (filename_lb
.buffer
);
728 process_file (this_file
);
732 if (emacs_tags_format
)
734 while (nincluded_files
-- > 0)
735 fprintf (outf
, "\f\n%s,include\n", *included_files
++);
737 (void) fclose (outf
);
748 /* update cannot be set under VMS, so we may assume that argc
749 and argv have not been munged. */
750 for (i
= optind
; i
< argc
; i
++)
753 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
754 outfile
, argv
[i
], outfile
);
759 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
766 (void) fclose (outf
);
769 sprintf (cmd
, "sort %s -o %s", outfile
, outfile
);
777 * This routine is called on each file argument.
783 struct stat stat_buf
;
785 stat (file
, &stat_buf
);
786 if (!(stat_buf
.st_mode
& S_IFREG
)
788 || !(stat_buf
.st_mode
& S_IFLNK
)
792 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
796 if (streq (file
, outfile
) && !streq (outfile
, "-"))
798 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
801 if (emacs_tags_format
)
803 char *cp
= etags_rindex (file
, '/');
810 if (emacs_tags_format
)
812 fprintf (outf
, "\f\n%s,%d\n",
813 file
, total_size_of_entries (head
));
821 * This routine sets up the boolean pseudo-functions which work
822 * by setting boolean flags dependent upon the corresponding character
823 * Every char which is NOT in that string is not a white char. Therefore,
824 * all of the array "_wht" is set to FALSE, and then the elements
825 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
826 * of a char is TRUE if it is the string "white", else FALSE.
834 for (i
= 0; i
< 0177; i
++)
835 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
836 for (sp
= white
; *sp
; sp
++)
838 for (sp
= endtk
; *sp
; sp
++)
840 for (sp
= intk
; *sp
; sp
++)
842 for (sp
= begtk
; *sp
; sp
++)
844 _wht
[0] = _wht
['\n'];
845 _etk
[0] = _etk
['\n'];
846 _btk
[0] = _btk
['\n'];
847 _itk
[0] = _itk
['\n'];
851 * This routine opens the specified file and calls the function
852 * which finds the function and type definitions.
859 void prolog_funcs ();
861 inf
= fopen (file
, "r");
867 curfile
= savestr (file
);
868 cp
= etags_rindex (file
, '.');
870 header_file
= (cp
&& (streq (cp
+ 1, "h")));
872 /* .tex, .aux or .bbl implies LaTeX source code */
873 if (cp
&& (streq (cp
+ 1, "tex") || streq (cp
+ 1, "aux")
874 || streq (cp
+ 1, "bbl")))
877 goto close_and_return
;
879 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
880 if (cp
&& (streq (cp
+ 1, "l")
881 || streq (cp
+ 1, "el")
882 || streq (cp
+ 1, "lsp")
883 || streq (cp
+ 1, "lisp")
884 || streq (cp
+ 1, "cl")
885 || streq (cp
+ 1, "clisp")))
888 goto close_and_return
;
890 /* .scm or .sm or .scheme or ... implies scheme source code */
891 if (cp
&& (streq (cp
+ 1, "sm")
892 || streq (cp
+ 1, "scm")
893 || streq (cp
+ 1, "scheme")
894 || streq (cp
+ 1, "t")
895 || streq (cp
+ 1, "sch")
896 || streq (cp
+ 1, "SM")
897 || streq (cp
+ 1, "SCM")
898 /* The `SCM' or `scm' prefix with a version number */
899 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
900 && string_numeric_p (cp
+ 1))
901 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
902 && string_numeric_p (cp
+ 1))))
908 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
910 if (cp
&& (streq (cp
+ 1, "s")
911 || streq (cp
+ 1, "a")
912 || streq (cp
+ 1, "sa")))
918 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
919 if (cp
&& (streq (cp
+ 1, "C")
920 || streq (cp
+ 1, "H")
921 || streq (cp
+ 1, "cxx")
922 || streq (cp
+ 1, "hxx")
923 || streq (cp
+ 1, "cc")))
925 C_entries (C_PLPL
); /* C++ */
926 goto close_and_return
;
928 /* .cs or .hs: a C* file */
929 if (cp
&& (streq (cp
+ 1, "cs")
930 || streq (cp
+ 1, "hs")))
933 goto close_and_return
;
935 /* .y: a yacc file */
936 if (cp
&& (streq (cp
+ 1, "y")))
939 goto close_and_return
;
941 /* .pl implies prolog source code */
942 if (cp
&& streq (cp
+ 1, "pl"))
945 goto close_and_return
;
947 /* .p or .pas: a Pascal file */
948 if (cp
&& (streq (cp
+ 1, "p")
949 || streq (cp
+ 1, "pas")))
952 goto close_and_return
;
954 /* If .f or .for, assume it is fortran or nothing. */
955 if (cp
&& (streq (cp
+ 1, "f")
956 || streq (cp
+ 1, "for")))
959 goto close_and_return
;
961 /* if not a .c or .h or .y file, try fortran */
962 if (cp
&& ((cp
[1] != 'c'
965 || (cp
[1] != 0 && cp
[2] != 0)))
967 if (PF_funcs (inf
) != 0)
968 goto close_and_return
;
969 rewind (inf
); /* no fortran tags found, try C */
971 C_entries (cplusplus
? C_PLPL
: 0);
977 /* Nonzero if string STR is composed of digits. */
980 string_numeric_p (str
)
985 if (*str
< '0' || *str
> '9')
992 /* Should take a TOKEN* instead!! */
994 pfnote (name
, is_func
, rewritten
, linestart
, linelen
, lno
, cno
)
995 char *name
; /* tag name */
996 logical is_func
; /* function or type name? */
997 logical rewritten
; /* tag different from text of definition? */
1008 np
= (NODE
*) malloc (sizeof (NODE
));
1011 if (!emacs_tags_format
)
1013 /* It's okay to output early in etags -- it only disrupts the
1014 * character count of the tag entries, which is no longer used
1015 * by tags.el anyway.
1017 error ("too many entries to sort");
1022 np
= xnew (1, NODE
);
1024 /* If ctags mode, change name "main" to M<thisfilename>. */
1025 if (!emacs_tags_format
&& !cxref_style
&& streq (name
, "main"))
1027 fp
= etags_rindex (curfile
, '/');
1028 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
1029 fp
= etags_rindex (name
, '.');
1030 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
1034 np
->name
= savestr (name
);
1036 np
->is_func
= is_func
;
1037 np
->rewritten
= rewritten
;
1039 /* UNCOMMENT THE +1 HERE: */
1040 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
1041 np
->left
= np
->right
= 0;
1042 if (emacs_tags_format
)
1044 c
= linestart
[linelen
];
1045 linestart
[linelen
] = 0;
1047 else if (cxref_style
== 0)
1049 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
1052 np
->pat
= savestr (linestart
);
1053 if (emacs_tags_format
)
1055 linestart
[linelen
] = c
;
1058 add_node (np
, &head
);
1063 * recurse on left children, iterate on right children.
1067 register NODE
*node
;
1071 register NODE
*node_right
= node
->right
;
1072 free_tree (node
->left
);
1075 free ((char *) node
);
1082 * Adds a node to the tree of nodes. In etags mode, we don't keep
1083 * it sorted; we just keep a linear list. In ctags mode, maintain
1084 * an ordered tree, with no attempt at balancing.
1086 * add_node is the only function allowed to add nodes, so it can
1089 /* Must avoid static vars within functions since some systems
1090 #define static as nothing. */
1091 static NODE
*last_node
= NULL
;
1094 add_node (node
, cur_node_p
)
1095 NODE
*node
, **cur_node_p
;
1098 register NODE
*cur_node
= *cur_node_p
;
1100 if (cur_node
== NULL
)
1107 if (emacs_tags_format
)
1111 fatal ("internal error in add_node");
1112 last_node
->right
= node
;
1118 dif
= strcmp (node
->name
, cur_node
->name
);
1121 * If this tag name matches an existing one, then
1122 * do not add the node, but maybe print a warning.
1126 if (node
->file
== cur_node
->file
)
1130 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1131 node
->file
, lineno
, node
->name
);
1132 fprintf (stderr
, "Second entry ignored\n");
1136 if (!cur_node
->been_warned
&& !no_warnings
)
1139 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1140 node
->file
, cur_node
->file
, node
->name
);
1142 cur_node
->been_warned
= TRUE
;
1146 /* Maybe refuse to add duplicate nodes. */
1147 if (!permit_duplicates
)
1149 if (!strcmp (node
->name
, cur_node
->name
)
1150 && !strcmp (node
->file
, cur_node
->file
))
1154 /* Actually add the node */
1155 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1161 register NODE
*node
;
1168 /* Output subentries that precede this one */
1169 put_entries (node
->left
);
1171 /* Output this entry */
1173 if (emacs_tags_format
)
1175 if (node
->rewritten
)
1177 fprintf (outf
, "%s\177%s\001%d,%d\n",
1178 node
->name
, node
->pat
, node
->lno
, node
->cno
);
1182 fprintf (outf
, "%s\177%d,%d\n",
1183 node
->pat
, node
->lno
, node
->cno
);
1186 else if (!cxref_style
)
1188 fprintf (outf
, "%s\t%s\t",
1189 node
->name
, node
->file
);
1193 putc (searchar
, outf
);
1196 for (sp
= node
->pat
; *sp
; sp
++)
1198 if (*sp
== '\\' || *sp
== searchar
)
1202 putc (searchar
, outf
);
1205 { /* a typedef; text pattern inadequate */
1206 fprintf (outf
, "%d", node
->lno
);
1210 else if (vgrind_style
)
1211 fprintf (stdout
, "%s %s %d\n",
1212 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1214 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1215 node
->name
, node
->lno
, node
->file
, node
->pat
);
1217 /* Output subentries that follow this one */
1218 put_entries (node
->right
);
1221 /* Length of a number's decimal representation. */
1229 for (; num
; num
/= 10)
1235 * Return total number of characters that put_entries will output for
1236 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1237 * is set, but called only in that case. This count is irrelevant with
1238 * the new tags.el, but is still supplied for backward compatibility.
1241 total_size_of_entries (node
)
1242 register NODE
*node
;
1250 for (; node
; node
= node
->right
)
1252 /* Count left subentries. */
1253 total
+= total_size_of_entries (node
->left
);
1255 /* Count this entry */
1256 total
+= strlen (node
->pat
) + 1;
1257 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1258 if (node
->rewritten
)
1259 total
+= 1 + strlen (node
->name
); /* \001name */
1266 * The C symbol tables.
1269 Stab
*C_stab
, *C_PLPL_stab
, *C_STAR_stab
;
1273 * Stab *get_C_stab (int c_ext);
1275 #define get_C_stab(c_ext) ((c_ext & C_STAR) ? C_STAR_stab : \
1276 (c_ext & C_PLPL) ? C_PLPL_stab : \
1280 add_keyword (stab
, sym
, type
)
1285 stab_search (stab
, sym
, strlen (sym
))->type
= type
;
1289 C_create_stab (c_ext
)
1294 stab
= stab_create ();
1298 add_keyword (stab
, "class", st_C_struct
);
1300 add_keyword (stab
, "domain", st_C_struct
);
1301 add_keyword (stab
, "union", st_C_struct
);
1302 add_keyword (stab
, "struct", st_C_struct
);
1303 add_keyword (stab
, "enum", st_C_enum
);
1304 add_keyword (stab
, "typedef", st_C_typedef
);
1305 add_keyword (stab
, "define", st_C_define
);
1306 add_keyword (stab
, "long", st_C_typespec
);
1307 add_keyword (stab
, "short", st_C_typespec
);
1308 add_keyword (stab
, "int", st_C_typespec
);
1309 add_keyword (stab
, "char", st_C_typespec
);
1310 add_keyword (stab
, "float", st_C_typespec
);
1311 add_keyword (stab
, "double", st_C_typespec
);
1312 add_keyword (stab
, "signed", st_C_typespec
);
1313 add_keyword (stab
, "unsigned", st_C_typespec
);
1314 add_keyword (stab
, "auto", st_C_typespec
);
1315 add_keyword (stab
, "void", st_C_typespec
);
1316 add_keyword (stab
, "extern", st_C_typespec
);
1317 add_keyword (stab
, "static", st_C_typespec
);
1318 add_keyword (stab
, "const", st_C_typespec
);
1319 add_keyword (stab
, "volatile", st_C_typespec
);
1327 C_stab
= C_create_stab (0);
1328 C_PLPL_stab
= C_create_stab (C_PLPL
);
1329 C_STAR_stab
= C_create_stab (C_STAR
| C_PLPL
);
1333 * etags.c 4.2 1993/03/22 12:13:40 pot Exp
1334 * C functions are recognized using a simple finite automaton.
1335 * funcdef is its state variable.
1339 fnone
, ftagseen
, finlist
, flistseen
1344 /* typedefs are recognized using a simple finite automaton.
1345 * typeddef is its state variable.
1349 tnone
, ttypedseen
, tinbody
, tend
1354 /* struct tags for C++ are recognized using another simple
1355 * finite automaton. `structdef' is its state variable.
1356 * This machinery is only invoked for C++; otherwise structdef
1357 * should remain snone. However, this machinery can easily be
1358 * adapted to find structure tags in normal C code.
1362 snone
, /* nothing seen yet */
1363 skeyseen
, /* struct-like keyword seen */
1364 stagseen
, /* struct-like tag seen */
1365 scolonseen
, /* colon seen after struct-like tag */
1366 sinbody
/* in struct body: recognize member func defs*/
1370 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1371 * struct tag, and structkey is the preceding struct-like keyword.
1373 char structtag
[BUFSIZ
];
1374 Stab_entry
*structkey
;
1377 * Yet another little state machine to deal with preprocessor lines.
1381 dnone
, /* nothing seen */
1382 dsharpseen
, /* '#' seen as first char on line */
1383 ddefineseen
, /* '#' and 'define' seen */
1384 dignorerest
/* ignore rest of line */
1389 * Set this to TRUE, and the next token considered is called a function.
1390 * Used only for GNUmacs's function-defining macros.
1392 logical next_token_is_func
;
1395 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1401 * This routine finds functions, typedefs, #define's and
1402 * struct/union/enum definitions in C syntax and adds them
1406 #define curlb (lbs[curndx].lb)
1407 #define othlb (lbs[1-curndx].lb)
1408 #define newlb (lbs[newndx].lb)
1409 #define curlinepos (lbs[curndx].linepos)
1410 #define othlinepos (lbs[1-curndx].linepos)
1411 #define newlinepos (lbs[newndx].linepos)
1413 #define CNL_SAVE_DEFINEDEF \
1415 SET_FILEPOS (curlinepos, inf, charno); \
1417 charno += readline (&curlb, inf); \
1418 lp = curlb.buffer; \
1425 CNL_SAVE_DEFINEDEF; \
1426 definedef = dnone; \
1429 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1430 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1431 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1432 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1436 int c_ext
; /* extension of C? */
1438 register char c
; /* latest char read; '\0' for end of line */
1439 register char *lp
; /* pointer one beyond the character `c' */
1440 int curndx
, newndx
; /* indices for current and new lb */
1441 TOKEN tok
; /* latest token read for funcdef & structdef */
1442 char tokb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1443 register int tokoff
; /* offset in line of start of latest token */
1444 register int toklen
; /* length of latest token */
1445 int cblev
; /* current curly brace level */
1446 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1449 curndx
= newndx
= 0;
1455 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1456 next_token_is_func
= yacc_rules
= FALSE
;
1457 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1459 cplpl
= c_ext
& C_PLPL
;
1468 /* If we're at the end of the line, the next character is a
1469 '\0'; don't skip it, because it's the thing that tells us
1470 to read the next line. */
1491 /* Newlines inside comments do not end macro definitions in
1506 /* Newlines inside strings, do not end macro definitions
1507 in traditional cpp, even though compilers don't
1508 usually accept them. */
1536 else if (cplpl
&& *lp
== '/')
1543 if ((c_ext
& YACC
) && *lp
== '%')
1545 /* entering or exiting rules section in yacc file */
1547 definedef
= dnone
; funcdef
= fnone
;
1548 typdef
= tnone
; structdef
= snone
;
1549 next_token_is_func
= FALSE
;
1550 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1552 yacc_rules
= !yacc_rules
;
1556 if (lp
== newlb
.buffer
+ 1 && definedef
== dnone
)
1557 definedef
= dsharpseen
;
1562 /* Consider token only if some complicated conditions are satisfied. */
1563 if (((cblev
== 0 && structdef
!= scolonseen
)
1564 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
1565 && definedef
!= dignorerest
1566 && funcdef
!= finlist
)
1572 if (cplpl
&& c
== ':' && *lp
== ':' && intoken (*(lp
+ 1)))
1575 * This handles :: in the middle, but not at beginning
1585 tok
.lineno
= lineno
;
1586 tok
.p
= newlb
.buffer
+ tokoff
;
1588 tok
.rewritten
= FALSE
;
1590 || consider_token (c
, lp
, &tok
,
1591 c_ext
, cblev
, &is_func
))
1593 if (structdef
== sinbody
1594 && definedef
== dnone
&& is_func
)
1595 { /* function defined in C++ class body */
1596 sprintf (tokb
, "%s::%.*s",
1597 ((structtag
[0] == '\0')
1598 ? "_anonymous_" : structtag
),
1600 tok
.rewritten
= TRUE
;
1604 sprintf (tokb
, "%.*s", tok
.len
, tok
.p
);
1607 if (funcdef
== ftagseen
1608 || structdef
== stagseen
1611 if (newndx
== curndx
)
1612 curndx
= 1 - curndx
; /* switch line buffers */
1615 MAKE_TAG_FROM_NEW_LB (is_func
);
1619 } /* if (endtoken (c)) */
1620 else if (intoken (c
))
1625 } /* if (midtoken) */
1626 else if (begtoken (c
))
1631 MAKE_TAG_FROM_OTH_LB (TRUE
);
1637 if (structdef
== stagseen
)
1639 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1641 tokoff
= lp
- 1 - newlb
.buffer
;
1647 } /* if must look at token */
1650 /* Detect end of line, colon, comma, semicolon and various braces
1651 after having handled the last token on the line.*/
1655 if (structdef
== stagseen
)
1656 structdef
= scolonseen
;
1657 else if (yacc_rules
&& funcdef
== ftagseen
)
1659 MAKE_TAG_FROM_OTH_LB (FALSE
);
1664 if (cblev
== 0 && typdef
== tend
)
1667 MAKE_TAG_FROM_OTH_LB (FALSE
);
1674 if (funcdef
!= finlist
)
1676 if (structdef
== stagseen
)
1692 if (funcdef
== finlist
)
1693 funcdef
= flistseen
;
1696 if (typdef
== ttypedseen
)
1700 case skeyseen
: /* unnamed struct */
1701 structtag
[0] = '\0';
1702 structdef
= sinbody
;
1705 case scolonseen
: /* named struct */
1706 structdef
= sinbody
;
1707 MAKE_TAG_FROM_OTH_LB (FALSE
);
1713 if (funcdef
== flistseen
)
1715 MAKE_TAG_FROM_OTH_LB (TRUE
);
1720 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
1721 cblev
= 0; /* reset curly brace level if first column */
1726 if (typdef
== tinbody
)
1729 (void) strcpy (structtag
, "<error 2>");
1733 /* If a macro spans multiple lines don't reset its state. */
1741 } /* while not eof */
1746 * checks to see if the current token is at the start of a
1747 * function, or corresponds to a typedef, or is a struct/union/enum
1750 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1751 * C_EXT is which language we are looking at.
1753 * In the future we will need some way to adjust where the end of
1754 * the token is; for instance, implementing the C++ keyword
1755 * `operator' properly will adjust the end of the token to be after
1756 * whatever follows `operator'.
1763 * next_token_is_func IN OUT
1767 consider_token (c
, lp
, tokp
, c_ext
, cblev
, is_func
)
1768 register char c
; /* IN: first char after the token */
1769 register char *lp
; /* IN: lp points to 2nd char after the token */
1770 register TOKEN
*tokp
; /* IN: token pointer */
1771 int c_ext
; /* IN: C extensions mask */
1772 int cblev
; /* IN: curly brace level */
1773 logical
*is_func
; /* OUT */
1775 logical firsttok
; /* TRUE if have seen first token in ()'s */
1776 Stab_entry
*tokse
= stab_find (get_C_stab (c_ext
), tokp
->p
, tokp
->len
);
1777 enum sym_type toktype
= stab_type (tokse
);
1779 *is_func
= FALSE
; /* not a function */
1782 * Advance the definedef state machine.
1787 /* We're not on a preprocessor line. */
1790 if (toktype
== st_C_define
)
1792 definedef
= ddefineseen
;
1796 definedef
= dignorerest
;
1801 * Make a tag for any macro.
1803 definedef
= dignorerest
;
1804 *is_func
= (c
== '(');
1805 if (!*is_func
&& !constantypedefs
)
1812 error ("internal error: definedef value");
1821 if (toktype
== st_C_typedef
)
1824 typdef
= ttypedseen
;
1839 /* Do not return here, so the structdef stuff has a chance. */
1853 * This structdef business is currently only invoked when cblev==0.
1854 * It should be recursively invoked whatever the curly brace level,
1855 * and a stack of states kept, to allow for definitions of structs
1858 * This structdef business is NOT invoked when we are ctags and the
1859 * file is plain C. This is because a struct tag may have the same
1860 * name as another tag, and this loses with ctags.
1862 * This if statement deals with the typdef state machine as
1863 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1864 * return (FALSE). All the other code here is for the structdef
1871 if (typdef
== ttypedseen
1872 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1874 structdef
= skeyseen
;
1879 if (structdef
== skeyseen
)
1881 if (stab_type (structkey
) == st_C_struct
)
1883 (void) strncpy (structtag
, tokp
->p
, tokp
->len
);
1884 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1888 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1890 structdef
= stagseen
;
1894 /* Avoid entering funcdef stuff if typdef is going on. */
1895 if (typdef
!= tnone
)
1901 /* Detect GNUmacs's function-defining macros. */
1902 if (definedef
== dnone
)
1904 if (strneq (tokp
->p
, "DEF", 3)
1905 || strneq (tokp
->p
, "ENTRY", 5)
1906 || strneq (tokp
->p
, "SYSCALL", 7)
1907 || strneq (tokp
->p
, "PSEUDO", 6))
1909 next_token_is_func
= TRUE
;
1912 if (strneq (tokp
->p
, "EXFUN", 5))
1914 next_token_is_func
= FALSE
;
1918 if (next_token_is_func
)
1920 next_token_is_func
= FALSE
;
1929 funcdef
= fnone
; /* should be useless */
1938 /* Fortran parsing */
1954 linecharno
= charno
;
1955 charno
+= readline (&lb
, fi
);
1958 dbp
++; /* Ratfor escape to fortran */
1959 while (isspace (*dbp
))
1966 if (tail ("integer"))
1974 if (tail ("logical"))
1978 if (tail ("complex") || tail ("character"))
1982 if (tail ("double"))
1984 while (isspace (*dbp
))
1988 if (tail ("precision"))
1994 while (isspace (*dbp
))
2001 if (tail ("function"))
2005 if (tail ("subroutine"))
2013 if (tail ("program"))
2018 if (tail ("procedure"))
2030 register int len
= 0;
2032 while (*cp
&& (*cp
& ~' ') == ((*(dbp
+ len
)) & ~' '))
2045 while (isspace (*dbp
))
2050 while (isspace (*dbp
))
2052 if (!isdigit (*dbp
))
2054 --dbp
; /* force failure */
2059 while (isdigit (*dbp
));
2067 char nambuf
[BUFSIZ
];
2069 while (isspace (*dbp
))
2076 for (cp
= dbp
+ 1; *cp
&& (isalpha (*cp
) || isdigit (*cp
)
2077 || (*cp
== '_') || (*cp
== '$')); cp
++)
2081 (void) strcpy (nambuf
, dbp
);
2083 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2087 /* Handle a file of assembler code. */
2103 linecharno
= charno
;
2104 charno
+= readline (&lb
, fi
);
2107 for (i
= 0; ((c
= dbp
[i
]) && !isspace (c
)) && (c
!= ':'); i
++)
2110 if ((i
> 0) && (c
== ':'))
2115 /* Added by Mosur Mohan, 4/22/88 */
2116 /* Pascal parsing */
2118 #define GET_NEW_LINE \
2120 linecharno = charno; lineno++; \
2121 charno += 1 + readline (&lb, inf); \
2125 /* Locates tags for procedures & functions.
2126 * Doesn't do any type- or var-definitions.
2127 * It does look for the keyword "extern" or "forward"
2128 * immediately following the procedure statement;
2129 * if found, the tag is skipped.
2136 struct linebuffer tline
; /* mostly copied from C_entries */
2140 char nambuf
[BUFSIZ
];
2142 logical
/* each of these flags is TRUE iff: */
2143 incomm1
, /* point is inside {..} comment */
2144 incomm2
, /* point is inside (*..*) comment */
2145 inquote
, /* point is inside '..' string */
2146 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2147 /* keyword, so next item = potential tag */
2148 found_tag
, /* point is after a potential tag */
2149 inparms
, /* point is within parameter-list */
2150 verify_tag
; /* point has passed the parm-list, so the */
2151 /* next token will determine whether */
2152 /* this is a FORWARD/EXTERN to be */
2153 /* ignored, or whether it is a real tag */
2159 initbuffer (&tline
);
2161 incomm1
= incomm2
= inquote
= FALSE
;
2162 found_tag
= FALSE
; /* have a proc name; check if extern */
2163 get_tagname
= FALSE
; /* have found "procedure" keyword */
2164 inparms
= FALSE
; /* found '(' after "proc" */
2165 verify_tag
= FALSE
; /* check if "extern" is ahead */
2167 /* long main loop to get next char */
2171 if (c
== 0) /* if end of line */
2176 if (!((found_tag
&& verify_tag
) ||
2178 c
= *dbp
++; /* only if don't need *dbp pointing */
2179 /* to the beginning of the name of */
2180 /* the procedure or function */
2182 if (incomm1
) /* within { - } comments */
2188 else if (incomm2
) /* within (* - *) comments */
2192 while ((c
= *dbp
++) == '*')
2211 inquote
= TRUE
; /* found first quote */
2213 case '{': /* found open-{-comment */
2217 if (*dbp
== '*') /* found open-(*-comment */
2222 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2225 case ')': /* end of parms list */
2230 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2237 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2239 /* check if this is an "extern" declaration */
2242 if ((*dbp
== 'e') || (*dbp
== 'E'))
2244 if (tail ("extern")) /* superfluous, really! */
2250 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2252 if (tail ("forward")) /* check for forward reference */
2258 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2262 pfnote (nambuf
, TRUE
, FALSE
,
2263 tline
.buffer
, cp
- tline
.buffer
+ 1,
2264 save_lineno
, save_lcno
);
2268 if (get_tagname
) /* grab name of proc or fn */
2273 /* save all values for later tagging */
2274 tline
.size
= lb
.size
;
2275 strcpy (tline
.buffer
, lb
.buffer
);
2276 save_lineno
= lineno
;
2277 save_lcno
= linecharno
;
2279 /* grab block name */
2280 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2284 strcpy (nambuf
, dbp
);
2286 dbp
= cp
; /* restore dbp to e-o-token */
2287 get_tagname
= FALSE
;
2291 /* and proceed to check for "extern" */
2293 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2294 (!found_tag
) && (!get_tagname
))
2296 /* check for proc/fn keywords */
2300 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2304 if (tail ("unction"))
2309 } /* while not e-o-f */
2313 * lisp tag functions
2314 * just look for (def or (DEF
2328 linecharno
= charno
;
2329 charno
+= readline (&lb
, fi
);
2335 while (!isspace (*dbp
))
2337 while (isspace (*dbp
))
2343 /* Check for (foo::defmumble name-defined ... */
2344 while (*dbp
&& *dbp
!= ':' && !isspace (*dbp
)
2345 && *dbp
!= '(' && *dbp
!= ')')
2354 while (!isspace (*dbp
))
2356 while (isspace (*dbp
))
2370 return ((dbp
[1] == 'D' || dbp
[1] == 'd') &&
2371 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2372 (dbp
[3] == 'F' || dbp
[3] == 'f'));
2380 char nambuf
[BUFSIZ
];
2384 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ' '; cp
++)
2388 (void) strcpy (nambuf
, dbp
);
2390 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2391 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2396 * Scheme tag functions
2397 * look for (def... xyzzy
2398 * look for (def... (xyzzy
2399 * look for (def ... ((...(xyzzy ....
2400 * look for (set! xyzzy
2403 static void get_scheme ();
2416 linecharno
= charno
;
2417 charno
+= readline (&lb
, fi
);
2419 if (dbp
[0] == '(' &&
2420 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2421 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2422 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2424 while (!isspace (*dbp
))
2426 /* Skip over open parens and white space */
2427 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2431 if (dbp
[0] == '(' &&
2432 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2433 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2434 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2435 (dbp
[4] == '!' || dbp
[4] == '!') &&
2438 while (!isspace (*dbp
))
2440 /* Skip over white space */
2441 while (isspace (*dbp
))
2453 char nambuf
[BUFSIZ
];
2457 /* Go till you get to white space or a syntactic break */
2458 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2460 /* Null terminate the string there. */
2463 /* Copy the string */
2464 strcpy (nambuf
, dbp
);
2465 /* Unterminate the string */
2467 /* Announce the change */
2468 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2472 /* Find tags in TeX and LaTeX input files. */
2474 /* TEX_toktab is a table of TeX control sequences that define tags.
2475 Each TEX_tabent records one such control sequence.
2476 CONVERT THIS TO USE THE Stab TYPE!! */
2484 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2486 /* Default set of control sequences to put into TEX_toktab.
2487 The value of environment var TEXTAGS is prepended to this. */
2489 static char *TEX_defenv
=
2490 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2493 struct TEX_tabent
*TEX_decode_env ();
2497 static char TEX_esc
= '\\';
2498 static char TEX_opgrp
= '{';
2499 static char TEX_clgrp
= '}';
2502 * TeX/LaTeX scanning loop.
2515 /* Select either \ or ! as escape character. */
2518 /* Initialize token table once from environment. */
2520 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2523 { /* Scan each line in file */
2525 linecharno
= charno
;
2526 charno
+= readline (&lb
, fi
);
2529 while (dbp
= etags_index (dbp
, TEX_esc
)) /* Look at each escape in line */
2535 linecharno
+= dbp
- lasthit
;
2537 i
= TEX_Token (lasthit
);
2540 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2541 break; /* We only save a line once */
2547 #define TEX_LESC '\\'
2548 #define TEX_SESC '!'
2551 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2552 /* chars accordingly. */
2560 while ((c
= getc (f
)) != EOF
)
2562 /* Skip to next line if we hit the TeX comment char. */
2566 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2585 /* Read environment and prepend it to the default string. */
2586 /* Build token table. */
2589 TEX_decode_env (evarname
, defenv
)
2593 register char *env
, *p
;
2595 struct TEX_tabent
*tab
;
2598 /* Append default string to environment. */
2599 env
= getenv (evarname
);
2603 env
= concat (env
, defenv
, "");
2605 /* Allocate a token table */
2606 for (size
= 1, p
= env
; p
;)
2607 if ((p
= etags_index (p
, ':')) && *(++p
))
2609 /* Add 1 to leave room for null terminator. */
2610 tab
= xnew (size
+ 1, struct TEX_tabent
);
2612 /* Unpack environment string into token table. Be careful about */
2613 /* zero-length strings (leading ':', "::" and trailing ':') */
2616 p
= etags_index (env
, ':');
2617 if (!p
) /* End of environment string. */
2618 p
= env
+ strlen (env
);
2620 { /* Only non-zero strings. */
2621 tab
[i
].name
= savenstr (env
, p
- env
);
2622 tab
[i
].len
= strlen (tab
[i
].name
);
2629 tab
[i
].name
= NULL
; /* Mark end of table. */
2637 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2638 The name being defined actually starts at (NAME + LEN + 1).
2639 But we seem to include the TeX command in the tag name. */
2642 TEX_getit (name
, len
)
2646 char *p
= name
+ len
;
2647 char nambuf
[BUFSIZ
];
2652 /* Let tag name extend to next group close (or end of line) */
2653 while (*p
&& *p
!= TEX_clgrp
)
2655 (void) strncpy (nambuf
, name
, p
- name
);
2656 nambuf
[p
- name
] = 0;
2658 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2662 /* If the text at CP matches one of the tag-defining TeX command names,
2663 return the etags_index of that command in TEX_toktab.
2664 Otherwise return -1. */
2666 /* Keep the capital `T' in `Token' for dumb truncating compilers
2667 (this distinguishes it from `TEX_toktab' */
2674 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2675 if (strncmp (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
) == 0)
2680 /* Support for Prolog. */
2682 /* whole head (not only functor, but also arguments)
2683 is gotten in compound term. */
2686 prolog_getit (s
, lineno
, linecharno
)
2691 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2699 if (*s
== '\0') /* syntax error. */
2701 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2703 else if (*s
== '\'')
2705 insquote
= !insquote
;
2708 else if (!insquote
&& *s
== '(')
2713 else if (!insquote
&& *s
== ')')
2719 else if (npar
< 0) /* syntax error. */
2722 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2724 if (npar
!= 0) /* syntax error. */
2734 strcpy (nambuf
, save_s
);
2736 pfnote (nambuf
, TRUE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2739 /* It is assumed that prolog predicate starts from column 0. */
2745 void skip_comment (), prolog_getit ();
2747 lineno
= linecharno
= charno
= 0;
2751 linecharno
+= charno
;
2752 charno
= readline (&lb
, fi
) + 1; /* 1 for newline. */
2754 if (isspace (dbp
[0])) /* not predicate header. */
2756 else if (dbp
[0] == '%') /* comment. */
2758 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2759 skip_comment (&lb
, fi
, &lineno
, &linecharno
);
2761 prolog_getit (dbp
, lineno
, linecharno
);
2766 skip_comment (plb
, fi
, plineno
, plinecharno
)
2767 struct linebuffer
*plb
;
2769 int *plineno
; /* result */
2770 long *plinecharno
; /* result */
2772 while (!substr ("*/", plb
->buffer
))
2775 *plinecharno
+= readline (plb
, fi
) + 1;
2776 } /* 1 for newline. */
2779 /* Return TRUE if 'sub' exists somewhere in 's'. */
2786 while (*s
&& (s
= etags_index (s
, *sub
)))
2787 if (prestr (sub
, s
))
2794 /* Return TRUE if 'pre' is prefix of string 's'. */
2803 else if (*pre
== *s
)
2804 return (prestr (pre
+ 1, s
+ 1));
2809 /* Initialize a linebuffer for use */
2812 initbuffer (linebuffer
)
2813 struct linebuffer
*linebuffer
;
2815 linebuffer
->size
= 200;
2816 linebuffer
->buffer
= xnew (200, char);
2820 * Read a line of text from `stream' into `linebuffer'.
2821 * Return the number of characters read from `stream',
2822 * which is the length of the line including the newline, if any.
2825 readline (linebuffer
, stream
)
2826 struct linebuffer
*linebuffer
;
2827 register FILE *stream
;
2829 char *buffer
= linebuffer
->buffer
;
2830 register char *p
= linebuffer
->buffer
;
2831 register char *pend
;
2832 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2834 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
2838 register int c
= getc (stream
);
2841 linebuffer
->size
*= 2;
2842 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
2843 p
+= buffer
- linebuffer
->buffer
;
2844 pend
= buffer
+ linebuffer
->size
;
2845 linebuffer
->buffer
= buffer
;
2847 if (c
< 0 || c
== '\n')
2850 newline
= (c
== '\n' ? 1 : 0);
2856 return p
- buffer
+ newline
;
2863 return savenstr (cp
, strlen (cp
));
2873 dp
= xnew (len
+ 1, char);
2874 (void) strncpy (dp
, cp
, len
);
2880 * Return the ptr in sp at which the character c last
2881 * appears; NULL if not found
2883 * Identical to v7 rindex, included for portability.
2887 etags_rindex (sp
, c
)
2888 register char *sp
, c
;
2903 * Return the ptr in sp at which the character c first
2904 * appears; NULL if not found
2906 * Identical to v7 index, included for portability.
2911 register char *sp
, c
;
2921 /* Print error message and exit. */
2932 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
2939 fprintf (stderr
, "%s: ", progname
);
2940 fprintf (stderr
, s1
, s2
);
2941 fprintf (stderr
, "\n");
2944 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
2950 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
2951 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
2953 (void) strcpy (result
, s1
);
2954 (void) strcpy (result
+ len1
, s2
);
2955 (void) strcpy (result
+ len1
+ len2
, s3
);
2956 *(result
+ len1
+ len2
+ len3
) = 0;
2961 /* Like malloc but get fatal error if memory is exhausted. */
2967 char *result
= malloc (size
);
2969 fatal ("virtual memory exhausted", 0);
2974 xrealloc (ptr
, size
)
2978 char *result
= realloc (ptr
, size
);
2980 fatal ("virtual memory exhausted");