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++.
31 #include <sys/types.h>
34 #include "../src/config.h"
38 /* AIX requires this to be the first thing in the file. */
41 #define alloca __builtin_alloca
43 #else /* not __GNUC__ */
46 #else /* not HAVE_ALLOCA_H */
52 #endif /* not HAVE_ALLOCA_H */
53 #endif /* not __GNUC__ */
55 extern char *malloc (), *realloc ();
56 extern char *getenv ();
57 extern char *strcpy (), *strncpy ();
60 char *etags_index (), *etags_rindex ();
63 /* Define the symbol ETAGS to make the program "etags",
64 which makes emacs-style tag tables by default.
65 Define CTAGS to make the program "ctags" compatible with the usual one.
66 Define neither one to get behavior that depends
67 on the name with which the program is invoked
68 (but we don't normally compile it that way). */
70 #if !defined(ETAGS) && !defined(CTAGS)
71 /* If neither is defined, program can be run as either. */
76 /* On VMS, CTAGS is not useful, so always do ETAGS. */
83 /* Exit codes for success and failure. */
93 * The FILEPOS abstract type, which represents a position in a file,
94 * plus the following accessor functions:
96 * long GET_CHARNO (pos)
97 * returns absolute char number.
98 * void SET_FILEPOS (pos, fp, charno)
99 * FILE *fp; long charno;
100 * sets `pos' from the current file
101 * position of `fp' and from `charno',
102 * which must be the absolute character
103 * number corresponding to the current
106 * The `pos' parameter is an lvalue expression of type FILEPOS.
107 * Parameters to the accessor functions are evaluated 0 or more times,
108 * and so must have no side effects.
110 * FILEPOS objects can also be assigned and passed to and from
111 * functions in the normal C manner.
113 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
117 /* real implementation */
118 typedef long FILEPOS
;
119 #define GET_CHARNO(pos) ((pos) + 0)
120 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
122 /* debugging implementation */
128 #define GET_CHARNO(pos) ((pos).charno + 0)
129 #define SET_FILEPOS(pos, fp, cno) \
130 ((void) ((pos).charno = (cno), \
131 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
135 #define streq(s, t) (strcmp (s, t) == 0)
136 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
142 #define iswhite(arg) (_wht[arg]) /* T if char is white */
143 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
144 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
145 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
147 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
150 { /* sorting structure */
151 char *name
; /* function or type name */
152 char *file
; /* file name */
153 logical is_func
; /* use pattern or line no */
154 logical rewritten
; /* list name separately */
155 logical been_warned
; /* set if noticed dup */
156 int lno
; /* line number tag is on */
157 long cno
; /* character number line starts on */
158 char *pat
; /* search pattern */
159 struct nd_st
*left
, *right
; /* left and right sons */
163 typedef struct nd_st NODE
;
165 logical header_file
; /* TRUE if .h file, FALSE o.w. */
166 /* boolean "functions" (see init) */
167 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
177 int total_size_of_entries ();
178 logical
consider_token ();
186 void Scheme_funcs ();
191 void find_entries ();
199 void process_file ();
205 * xnew -- allocate storage
208 * Type *xnew (int n, Type);
210 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
215 * Symbol table stuff.
217 * Should probably be implemented with hash table; linked list for now.
222 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
230 struct stab_entry
*next
;
233 typedef struct stab_entry Stab_entry
;
234 typedef Stab_entry
*Stab
;
238 * Stab, Stab_entry, stab_create, stab_search, stab_find -- symbol table
241 * Types: Stab, Stab_entry, enum sym_type
243 * Stab * stab_create ()
245 * Stab_entry * stab_find (stab, sym)
249 * Stab_entry * stab_search (stab, sym)
254 * stab_create creates a Stab, a symbol table object, and returns a
255 * pointer to it. stab_find finds a symbol in a Stab; it returns a
256 * pointer to the Stab_entry if found, otherwise NULL. stab_search
257 * is like stab_find, except that it creates a new Stab_entry,
258 * initialized with type = st_none, if one did not exist already
259 * (it never returns NULL).
261 * A Stab_entry is a structure that contains at least the following
264 * char *name; // must not be modified
265 * enum sym_type type; // should be set
267 * The type field is initially set to st_none; it should be set to
268 * something else by the caller of stab_search. Other possible values
269 * of an enum sym_type can be added.
277 *sp
= NULL
; /* a Stab starts out as a null Stab_entry* */
282 stab_find (stab
, sym
, symlen
)
287 register Stab_entry
*se
;
288 for (se
= *stab
; se
!= NULL
; se
= se
->next
)
290 if (se
->symlen
== symlen
&& strneq (se
->sym
, sym
, symlen
))
298 stab_search (stab
, sym
, symlen
)
303 register Stab_entry
*se
;
304 se
= stab_find (stab
, sym
, symlen
);
309 se
= xnew (1, Stab_entry
);
310 se
->sym
= savenstr (sym
, symlen
);
322 * stab_type -- type of a symbol table entry
325 * enum sym_type stab_type (Stab_entry *se);
328 * May evaluate its argument more than once.
331 #define stab_type(se) ((se)==NULL ? st_none : (se)->type)
347 #define C_PLPL 0x00001 /* C++ */
348 #define C_STAR 0x00003 /* C* */
349 #define YACC 0x10000 /* yacc file */
351 char searchar
= '/'; /* use /.../ searches */
353 LINENO lineno
; /* line number of current line */
354 long charno
; /* current character number */
356 long linecharno
; /* charno of start of line; not used by C, but
357 * by every other language.
360 char *curfile
, /* current input file name */
361 *outfile
, /* output file */
362 *white
= " \f\t\n", /* white chars */
363 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
364 /* token starting chars */
365 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$",
366 /* valid in-token chars */
367 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
369 int append_to_tagfile
; /* -a: append to tags */
370 int emacs_tags_format
; /* emacs style output (no -e option any more) */
371 /* The following three default to 1 for etags, but to 0 for ctags. */
372 int typedefs
; /* -t: create tags for typedefs */
373 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
374 /* 0 struct/enum/union decls, and C++ */
375 /* member functions */
376 int constantypedefs
; /* -d: create tags for C #define and enum */
377 /* constants. Default under etags. Enum */
378 /* constants not implemented. */
379 /* -D: opposite of -d. Default under ctags. */
380 int update
; /* -u: update tags */
381 int vgrind_style
; /* -v: create vgrind style index output */
382 int no_warnings
; /* -w: suppress warnings */
383 int cxref_style
; /* -x: create cxref style output */
384 int cplusplus
; /* .[hc] means C++, not C */
385 int noindentypedefs
; /* -S: ignore indentation in C */
387 /* Name this program was invoked with. */
390 struct option longopts
[] = {
391 { "append", no_argument
, NULL
, 'a' },
392 { "backward-search", no_argument
, NULL
, 'B' },
393 { "c++", no_argument
, NULL
, 'C' },
394 { "cxref", no_argument
, NULL
, 'x' },
395 { "defines", no_argument
, NULL
, 'd' },
396 { "forward-search", no_argument
, NULL
, 'F' },
397 { "help", no_argument
, NULL
, 'H' },
398 { "ignore-indentation", no_argument
, NULL
, 'S' },
399 { "include", required_argument
, NULL
, 'i' },
400 { "no-defines", no_argument
, NULL
, 'D' },
401 { "no-warn", no_argument
, NULL
, 'w' },
402 { "output", required_argument
, NULL
, 'o' },
403 { "typedefs", no_argument
, NULL
, 't' },
404 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
405 { "update", no_argument
, NULL
, 'u' },
406 { "version", no_argument
, NULL
, 'V' },
407 { "vgrind", no_argument
, NULL
, 'v' },
411 FILE *inf
, /* ioptr for current input file */
412 *outf
; /* ioptr for tags file */
414 NODE
*head
; /* the head of the binary tree of tags */
416 int permit_duplicates
= 1; /* Nonzero means allow duplicate tags. */
418 /* A `struct linebuffer' is a structure which holds a line of text.
419 `readline' reads a line from a stream into a linebuffer
420 and works regardless of the length of the line. */
428 struct linebuffer lb
; /* the current line */
429 struct linebuffer filename_lb
; /* used to read in filenames */
433 struct linebuffer lb
; /* used by C_entries instead of lb */
448 printf ("for Emacs version 19.0.\n");
456 printf ("These are the options accepted by %s. You may use unambiguous\n\
457 abbreviations for the long option names.\n\n", progname
);
461 Append tag entries to existing tags file.\n\
463 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
464 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
465 extensions are always assumed to be C++ code.\n\
467 Create tag entries for #defines, too.", stdout
);
470 fputs (" This is the default\n\
476 Don't create tag entries for #defines.", stdout
);
479 fputs (" This is the default\n\
484 -o FILE, --output=FILE\n\
485 Write the tags to FILE.\n\
486 -S, --ignore-indentation\n\
487 Don't rely on indentation quite as much as normal. Currently,\n\
488 this means not to assume that a closing brace in the first\n\
489 column is the final brace of a function or structure\n\
492 Generate tag entries for typedefs. This is the default\n\
494 -T, --typedefs-and-c++\n\
495 Generate tag entries for typedefs, struct/enum/union tags, and\n\
496 C++ member functions.");
499 puts ("-i FILE, --include=FILE\n\
500 Include a note in tag file indicating that, when searching for\n\
501 a tag, one should also consult the tags file FILE after\n\
502 checking the current file.");
506 puts ("-B, --backward-search\n\
507 Write the search commands for the tag entries using '?', the\n\
508 backward-search command.\n\
509 -F, --forward-search\n\
510 Write the search commands for the tag entries using '/', the\n\
511 forward-search command.\n\
513 Update the tag entries for the given files, leaving tag\n\
514 entries for other files in place. Currently, this is\n\
515 implemented by deleting the existing entries for the given\n\
516 files and then rewriting the new entries at the end of the\n\
517 tags file. It is often faster to simply rebuild the entire\n\
518 tag file than to use this.\n\
520 Generates an index of items intended for human consumption,\n\
521 similar to the output of vgrind. The index is sorted, and\n\
522 gives the page number of each item.\n\
524 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
525 The output uses line numbers instead of page numbers, but\n\
526 beyond that the differences are cosmetic; try both to see\n\
529 Suppress warning messages about entries defined in multiple\n\
533 puts ("-V, --version\n\
534 Print the version of the program.\n\
536 Print this help message.");
549 unsigned int nincluded_files
= 0;
550 char **included_files
= (char **) alloca (argc
* sizeof (char *));
555 extern char *gfnames ();
556 extern char *massage_name ();
562 emacs_tags_format
= 1;
564 emacs_tags_format
= 0;
568 * If etags, always find typedefs and structure tags. Why not?
569 * Also default is to find macro constants.
571 if (emacs_tags_format
)
572 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
577 opt
= getopt_long (argc
, argv
, "aCdDo:StTi:BFuvxwVH", longopts
, 0);
585 /* If getopt returns '\0', then it has already processed a
586 long-named option. We should do nothing. */
589 /* Common options. */
606 "%s: -o flag may only be given once\n", progname
);
619 typedefs_and_cplusplus
++;
630 if (!emacs_tags_format
)
632 included_files
[nincluded_files
++] = optarg
;
638 if (emacs_tags_format
)
643 if (emacs_tags_format
)
648 if (emacs_tags_format
)
656 if (emacs_tags_format
)
661 if (emacs_tags_format
)
670 if (optind
== argc
&& nincluded_files
== 0)
672 fprintf (stderr
, "%s: No input files specified.\n", progname
);
675 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
682 outfile
= emacs_tags_format
? "TAGS" : "tags";
685 init (); /* set up boolean "functions" */
688 initbuffer (&lbs
[0].lb
);
689 initbuffer (&lbs
[1].lb
);
690 initbuffer (&filename_lb
);
692 * loop through files finding functions
694 if (emacs_tags_format
)
696 if (streq (outfile
, "-"))
699 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
710 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
714 error ("Can't find file %s\n", this_file
);
719 this_file
= massage_name (this_file
);
722 } /* solely to balance out the ifdef'd parens above */
725 for (; optind
< argc
; optind
++)
727 this_file
= argv
[optind
];
731 /* Input file named "-" means read file names from stdin
733 if (streq (this_file
, "-"))
735 while (!feof (stdin
))
737 (void) readline (&filename_lb
, stdin
);
738 if (strlen (filename_lb
.buffer
) > 0)
739 process_file (filename_lb
.buffer
);
743 process_file (this_file
);
747 if (emacs_tags_format
)
749 while (nincluded_files
-- > 0)
750 fprintf (outf
, "\f\n%s,include\n", *included_files
++);
752 (void) fclose (outf
);
763 /* update cannot be set under VMS, so we may assume that argc
764 and argv have not been munged. */
765 for (i
= optind
; i
< argc
; i
++)
768 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
769 outfile
, argv
[i
], outfile
);
774 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
781 (void) fclose (outf
);
784 sprintf (cmd
, "sort %s -o %s", outfile
, outfile
);
792 * This routine is called on each file argument.
798 struct stat stat_buf
;
800 stat (file
, &stat_buf
);
801 if (!(stat_buf
.st_mode
& S_IFREG
)
803 || !(stat_buf
.st_mode
& S_IFLNK
)
807 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
811 if (streq (file
, outfile
) && !streq (outfile
, "-"))
813 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
816 if (emacs_tags_format
)
818 char *cp
= etags_rindex (file
, '/');
825 if (emacs_tags_format
)
827 fprintf (outf
, "\f\n%s,%d\n",
828 file
, total_size_of_entries (head
));
836 * This routine sets up the boolean psuedo-functions which work
837 * by setting boolean flags dependent upon the corresponding character
838 * Every char which is NOT in that string is not a white char. Therefore,
839 * all of the array "_wht" is set to FALSE, and then the elements
840 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
841 * of a char is TRUE if it is the string "white", else FALSE.
849 for (i
= 0; i
< 0177; i
++)
850 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
851 for (sp
= white
; *sp
; sp
++)
853 for (sp
= endtk
; *sp
; sp
++)
855 for (sp
= intk
; *sp
; sp
++)
857 for (sp
= begtk
; *sp
; sp
++)
859 _wht
[0] = _wht
['\n'];
860 _etk
[0] = _etk
['\n'];
861 _btk
[0] = _btk
['\n'];
862 _itk
[0] = _itk
['\n'];
866 * This routine opens the specified file and calls the function
867 * which finds the function and type definitions.
874 void prolog_funcs ();
876 inf
= fopen (file
, "r");
882 curfile
= savestr (file
);
883 cp
= etags_rindex (file
, '.');
885 header_file
= (cp
&& (streq (cp
+ 1, "h")));
887 /* .tex, .aux or .bbl implies LaTeX source code */
888 if (cp
&& (streq (cp
+ 1, "tex") || streq (cp
+ 1, "aux")
889 || streq (cp
+ 1, "bbl")))
892 goto close_and_return
;
894 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
895 if (cp
&& (streq (cp
+ 1, "l")
896 || streq (cp
+ 1, "el")
897 || streq (cp
+ 1, "lsp")
898 || streq (cp
+ 1, "lisp")
899 || streq (cp
+ 1, "cl")
900 || streq (cp
+ 1, "clisp")))
903 goto close_and_return
;
905 /* .scm or .sm or .scheme or ... implies scheme source code */
906 if (cp
&& (streq (cp
+ 1, "sm")
907 || streq (cp
+ 1, "scm")
908 || streq (cp
+ 1, "scheme")
909 || streq (cp
+ 1, "t")
910 || streq (cp
+ 1, "sch")
911 || streq (cp
+ 1, "SM")
912 || streq (cp
+ 1, "SCM")
913 /* The `SCM' or `scm' prefix with a version number */
914 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
915 && string_numeric_p (cp
+ 1))
916 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
917 && string_numeric_p (cp
+ 1))))
923 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
925 if (cp
&& (streq (cp
+ 1, "s")
926 || streq (cp
+ 1, "a")
927 || streq (cp
+ 1, "sa")))
933 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
934 if (cp
&& (streq (cp
+ 1, "C")
935 || streq (cp
+ 1, "H")
936 || streq (cp
+ 1, "cxx")
937 || streq (cp
+ 1, "hxx")
938 || streq (cp
+ 1, "cc")))
940 C_entries (C_PLPL
); /* C++ */
941 goto close_and_return
;
943 /* .cs or .hs: a C* file */
944 if (cp
&& (streq (cp
+ 1, "cs")
945 || streq (cp
+ 1, "hs")))
948 goto close_and_return
;
950 /* .y: a yacc file */
951 if (cp
&& (streq (cp
+ 1, "y")))
954 goto close_and_return
;
956 /* .pl implies prolog source code */
957 if (cp
&& streq (cp
+ 1, "pl"))
960 goto close_and_return
;
962 /* .p or .pas: a Pascal file */
963 if (cp
&& (streq (cp
+ 1, "p")
964 || streq (cp
+ 1, "pas")))
967 goto close_and_return
;
969 /* If .f or .for, assume it is fortran or nothing. */
970 if (cp
&& (streq (cp
+ 1, "f")
971 || streq (cp
+ 1, "for")))
974 goto close_and_return
;
976 /* if not a .c or .h or .y file, try fortran */
977 if (cp
&& ((cp
[1] != 'c'
980 || (cp
[1] != 0 && cp
[2] != 0)))
982 if (PF_funcs (inf
) != 0)
983 goto close_and_return
;
984 rewind (inf
); /* no fortran tags found, try C */
986 C_entries (cplusplus
? C_PLPL
: 0);
992 /* Nonzero if string STR is composed of digits. */
995 string_numeric_p (str
)
1000 if (*str
< '0' || *str
> '9')
1007 /* Should take a TOKEN* instead!! */
1009 pfnote (name
, is_func
, rewritten
, linestart
, linelen
, lno
, cno
)
1010 char *name
; /* tag name */
1011 logical is_func
; /* function or type name? */
1012 logical rewritten
; /* tag different from text of definition? */
1023 np
= (NODE
*) malloc (sizeof (NODE
));
1026 if (!emacs_tags_format
)
1028 /* It's okay to output early in etags -- it only disrupts the
1029 * character count of the tag entries, which is no longer used
1030 * by tags.el anyway.
1032 error ("too many entries to sort");
1037 np
= xnew (1, NODE
);
1039 /* If ctags mode, change name "main" to M<thisfilename>. */
1040 if (!emacs_tags_format
&& !cxref_style
&& streq (name
, "main"))
1042 fp
= etags_rindex (curfile
, '/');
1043 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
1044 fp
= etags_rindex (name
, '.');
1045 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
1049 np
->name
= savestr (name
);
1051 np
->is_func
= is_func
;
1052 np
->rewritten
= rewritten
;
1054 /* UNCOMMENT THE +1 HERE: */
1055 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
1056 np
->left
= np
->right
= 0;
1057 if (emacs_tags_format
)
1059 c
= linestart
[linelen
];
1060 linestart
[linelen
] = 0;
1062 else if (cxref_style
== 0)
1064 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
1067 np
->pat
= savestr (linestart
);
1068 if (emacs_tags_format
)
1070 linestart
[linelen
] = c
;
1073 add_node (np
, &head
);
1078 * recurse on left children, iterate on right children.
1082 register NODE
*node
;
1086 register NODE
*node_right
= node
->right
;
1087 free_tree (node
->left
);
1090 free ((char *) node
);
1097 * Adds a node to the tree of nodes. In etags mode, we don't keep
1098 * it sorted; we just keep a linear list. In ctags mode, maintain
1099 * an ordered tree, with no attempt at balancing.
1101 * add_node is the only function allowed to add nodes, so it can
1105 add_node (node
, cur_node_p
)
1106 NODE
*node
, **cur_node_p
;
1109 register NODE
*cur_node
= *cur_node_p
;
1110 static NODE
*last_node
= NULL
;/* careful */
1112 if (cur_node
== NULL
)
1119 if (emacs_tags_format
)
1123 fatal ("internal error in add_node");
1124 last_node
->right
= node
;
1130 dif
= strcmp (node
->name
, cur_node
->name
);
1133 * If this tag name matches an existing one, then
1134 * do not add the node, but maybe print a warning.
1138 if (node
->file
== cur_node
->file
)
1142 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1143 node
->file
, lineno
, node
->name
);
1144 fprintf (stderr
, "Second entry ignored\n");
1148 if (!cur_node
->been_warned
&& !no_warnings
)
1151 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1152 node
->file
, cur_node
->file
, node
->name
);
1154 cur_node
->been_warned
= TRUE
;
1158 /* Maybe refuse to add duplicate nodes. */
1159 if (!permit_duplicates
)
1161 if (!strcmp (node
->name
, cur_node
->name
)
1162 && !strcmp (node
->file
, cur_node
->file
))
1166 /* Actually add the node */
1167 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1173 register NODE
*node
;
1180 /* Output subentries that precede this one */
1181 put_entries (node
->left
);
1183 /* Output this entry */
1185 if (emacs_tags_format
)
1187 if (node
->rewritten
)
1189 fprintf (outf
, "%s\177%s\001%d,%d\n",
1190 node
->name
, node
->pat
, node
->lno
, node
->cno
);
1194 fprintf (outf
, "%s\177%d,%d\n",
1195 node
->pat
, node
->lno
, node
->cno
);
1198 else if (!cxref_style
)
1200 fprintf (outf
, "%s\t%s\t",
1201 node
->name
, node
->file
);
1205 putc (searchar
, outf
);
1208 for (sp
= node
->pat
; *sp
; sp
++)
1210 if (*sp
== '\\' || *sp
== searchar
)
1214 putc (searchar
, outf
);
1217 { /* a typedef; text pattern inadequate */
1218 fprintf (outf
, "%d", node
->lno
);
1222 else if (vgrind_style
)
1223 fprintf (stdout
, "%s %s %d\n",
1224 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1226 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1227 node
->name
, node
->lno
, node
->file
, node
->pat
);
1229 /* Output subentries that follow this one */
1230 put_entries (node
->right
);
1233 /* Length of a number's decimal representation. */
1241 for (; num
; num
/= 10)
1247 * Return total number of characters that put_entries will output for
1248 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1249 * is set, but called only in that case. This count is irrelevant with
1250 * the new tags.el, but is still supplied for backward compatibility.
1253 total_size_of_entries (node
)
1254 register NODE
*node
;
1262 for (; node
; node
= node
->right
)
1264 /* Count left subentries. */
1265 total
+= total_size_of_entries (node
->left
);
1267 /* Count this entry */
1268 total
+= strlen (node
->pat
) + 1;
1269 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1270 if (node
->rewritten
)
1271 total
+= 1 + strlen (node
->name
); /* \001name */
1278 * The C symbol tables.
1281 Stab
*C_stab
, *C_PLPL_stab
, *C_STAR_stab
;
1285 * Stab *get_C_stab (int c_ext);
1287 #define get_C_stab(c_ext) ((c_ext & C_STAR) ? C_STAR_stab : \
1288 (c_ext & C_PLPL) ? C_PLPL_stab : \
1292 add_keyword (stab
, sym
, type
)
1297 stab_search (stab
, sym
, strlen (sym
))->type
= type
;
1301 C_create_stab (c_ext
)
1306 stab
= stab_create ();
1310 add_keyword (stab
, "class", st_C_struct
);
1312 add_keyword (stab
, "domain", st_C_struct
);
1313 add_keyword (stab
, "union", st_C_struct
);
1314 add_keyword (stab
, "struct", st_C_struct
);
1315 add_keyword (stab
, "enum", st_C_enum
);
1316 add_keyword (stab
, "typedef", st_C_typedef
);
1317 add_keyword (stab
, "define", st_C_define
);
1318 add_keyword (stab
, "long", st_C_typespec
);
1319 add_keyword (stab
, "short", st_C_typespec
);
1320 add_keyword (stab
, "int", st_C_typespec
);
1321 add_keyword (stab
, "char", st_C_typespec
);
1322 add_keyword (stab
, "float", st_C_typespec
);
1323 add_keyword (stab
, "double", st_C_typespec
);
1324 add_keyword (stab
, "signed", st_C_typespec
);
1325 add_keyword (stab
, "unsigned", st_C_typespec
);
1326 add_keyword (stab
, "auto", st_C_typespec
);
1327 add_keyword (stab
, "void", st_C_typespec
);
1328 add_keyword (stab
, "extern", st_C_typespec
);
1329 add_keyword (stab
, "static", st_C_typespec
);
1330 add_keyword (stab
, "const", st_C_typespec
);
1331 add_keyword (stab
, "volatile", st_C_typespec
);
1339 C_stab
= C_create_stab (0);
1340 C_PLPL_stab
= C_create_stab (C_PLPL
);
1341 C_STAR_stab
= C_create_stab (C_STAR
| C_PLPL
);
1345 * etags.c 4.2 1993/03/22 12:13:40 pot Exp
1346 * C functions are recognized using a simple finite automaton.
1347 * funcdef is its state variable.
1351 fnone
, ftagseen
, finlist
, flistseen
1356 /* typedefs are recognized using a simple finite automaton.
1357 * typeddef is its state variable.
1361 tnone
, ttypedseen
, tinbody
, tend
1366 /* struct tags for C++ are recognized using another simple
1367 * finite automaton. `structdef' is its state variable.
1368 * This machinery is only invoked for C++; otherwise structdef
1369 * should remain snone. However, this machinery can easily be
1370 * adapted to find structure tags in normal C code.
1374 snone
, /* nothing seen yet */
1375 skeyseen
, /* struct-like keyword seen */
1376 stagseen
, /* struct-like tag seen */
1377 scolonseen
, /* colon seen after struct-like tag */
1378 sinbody
/* in class body: recognize member func defs */
1382 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1383 * struct tag, and structkey is the preceding struct-like keyword.
1385 char structtag
[BUFSIZ
];
1386 Stab_entry
*structkey
;
1389 * Yet another little state machine to deal with preprocessor lines.
1393 dnone
, /* nothing seen */
1394 dsharpseen
, /* '#' seen as first char on line */
1395 ddefineseen
, /* '#' and 'define' seen */
1396 dignorerest
/* ignore rest of line */
1401 * Set this to TRUE, and the next token considered is called a function.
1402 * Used only for GNUmacs's function-defining macros.
1404 logical next_token_is_func
;
1407 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1413 * This routine finds functions, typedefs, #define's and
1414 * struct/union/enum definitions in C syntax and adds them
1419 * LEVEL_OK_FOR_FUNCDEF allows C++ function definition within class body.
1420 * Currently typdef and structdef stuff (typedefs and struct
1421 * definitions) are only noticed when level==0, but that may change.
1423 #define LEVEL_OK_FOR_FUNCDEF() \
1424 (level==0 || (cplpl && level==1 && structdef==sinbody))
1426 #define curlb (lbs[curndx].lb)
1427 #define othlb (lbs[1-curndx].lb)
1428 #define newlb (lbs[newndx].lb)
1429 #define curlinepos (lbs[curndx].linepos)
1430 #define othlinepos (lbs[1-curndx].linepos)
1431 #define newlinepos (lbs[newndx].linepos)
1433 #define CNL_SAVE_DEFINEDEF \
1435 SET_FILEPOS (curlinepos, inf, charno); \
1437 charno += readline (&curlb, inf); \
1438 lp = curlb.buffer; \
1445 CNL_SAVE_DEFINEDEF; \
1446 definedef = dnone; \
1449 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1450 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1451 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1452 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1456 int c_ext
; /* extension of C? */
1458 register char c
; /* latest char read; '\0' for end of line */
1459 register char *lp
; /* pointer one beyond the character `c' */
1460 int curndx
, newndx
; /* indices for current and new lb */
1461 TOKEN tok
; /* latest token read for funcdef & structdef */
1462 char tokb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1463 register int tokoff
; /* offset in line of start of latest token */
1464 register int toklen
; /* length of latest token */
1465 int level
; /* current curly brace level */
1466 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1469 curndx
= newndx
= 0;
1475 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1476 next_token_is_func
= yacc_rules
= FALSE
;
1477 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1479 cplpl
= c_ext
& C_PLPL
;
1488 /* If we're at the end of the line, the next character is a
1489 '\0'; don't skip it, because it's the thing that tells us
1490 to read the next line. */
1511 /* Newlines inside comments do not end macro definitions in
1526 /* Newlines inside strings, do not end macro definitions
1527 in traditional cpp, even though compilers don't
1528 usually accept them. */
1556 else if (cplpl
&& *lp
== '/')
1563 if ((c_ext
& YACC
) && *lp
== '%')
1565 /* entering or exiting rules section in yacc file */
1567 definedef
= dnone
; funcdef
= fnone
;
1568 typdef
= tnone
; structdef
= snone
;
1569 next_token_is_func
= FALSE
;
1570 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1572 yacc_rules
= !yacc_rules
;
1576 if (lp
== newlb
.buffer
+ 1 && definedef
== dnone
)
1577 definedef
= dsharpseen
;
1582 if (LEVEL_OK_FOR_FUNCDEF ()
1583 && definedef
!= dignorerest
1584 && structdef
!= scolonseen
1585 && funcdef
!= finlist
)
1591 if (cplpl
&& c
== ':' && *lp
== ':' && intoken (*(lp
+ 1)))
1594 * This handles :: in the middle, but not at beginning
1604 tok
.lineno
= lineno
;
1605 tok
.p
= newlb
.buffer
+ tokoff
;
1607 tok
.rewritten
= FALSE
;
1609 || consider_token (c
, lp
, &tok
,
1610 c_ext
, level
, &is_func
))
1612 if (structdef
== sinbody
1613 && definedef
== dnone
&& is_func
)
1614 { /* function defined in C++ class body */
1615 sprintf (tokb
, "%s::%.*s",
1616 ((structtag
[0] == '\0')
1617 ? "_anonymous_" : structtag
),
1619 tok
.rewritten
= TRUE
;
1623 sprintf (tokb
, "%.*s", tok
.len
, tok
.p
);
1626 if (funcdef
== ftagseen
|| structdef
== stagseen
)
1628 if (newndx
== curndx
)
1629 curndx
= 1 - curndx
; /* switch line buffers */
1632 MAKE_TAG_FROM_NEW_LB (is_func
);
1636 } /* if (endtoken (c)) */
1637 else if (intoken (c
))
1642 } /* if (midtoken) */
1643 else if (begtoken (c
))
1648 MAKE_TAG_FROM_OTH_LB (TRUE
);
1654 if (structdef
== stagseen
)
1656 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1658 tokoff
= lp
- 1 - newlb
.buffer
;
1664 } /* if must look at token */
1667 /* Detect end of line, colon, comma, semicolon and various braces
1668 after having handled the last token on the line.*/
1672 if (structdef
== stagseen
)
1673 structdef
= scolonseen
;
1674 else if (yacc_rules
&& funcdef
== ftagseen
)
1676 MAKE_TAG_FROM_OTH_LB (FALSE
);
1684 if (funcdef
!= finlist
)
1686 if (level
== 0 && typdef
== tend
)
1690 if (funcdef
!= finlist
)
1692 if (structdef
== stagseen
)
1708 if (funcdef
== finlist
)
1709 funcdef
= flistseen
;
1712 if (typdef
== ttypedseen
)
1716 case skeyseen
: /* unnamed struct */
1717 structtag
[0] = '\0';
1718 structdef
= sinbody
;
1721 case scolonseen
: /* named struct */
1722 structdef
= sinbody
;
1723 MAKE_TAG_FROM_OTH_LB (FALSE
);
1729 if (funcdef
== flistseen
)
1731 MAKE_TAG_FROM_OTH_LB (TRUE
);
1736 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
1737 level
= 0; /* reset level if first column */
1742 if (typdef
== tinbody
)
1745 (void) strcpy (structtag
, "<error 2>");
1749 /* If a macro spans multiple lines don't reset its state. */
1757 } /* while not eof */
1762 * checks to see if the current token is at the start of a
1763 * function, or corresponds to a typedef, or is a struct/union/enum
1766 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1767 * C_EXT is which language we are looking at.
1769 * In the future we will need some way to adjust where the end of
1770 * the token is; for instance, implementing the C++ keyword
1771 * `operator' properly will adjust the end of the token to be after
1772 * whatever follows `operator'.
1779 * next_token_is_func IN OUT
1783 consider_token (c
, lp
, tokp
, c_ext
, level
, is_func
)
1784 register char c
; /* IN: first char after the token */
1785 register char *lp
; /* IN: lp points to 2nd char after the token */
1786 register TOKEN
*tokp
; /* IN */
1789 logical
*is_func
; /* OUT */
1791 logical firsttok
; /* TRUE if have seen first token in ()'s */
1792 Stab_entry
*tokse
= stab_find (get_C_stab (c_ext
), tokp
->p
, tokp
->len
);
1793 enum sym_type toktype
= stab_type (tokse
);
1795 *is_func
= FALSE
; /* not a function */
1798 * Advance the definedef state machine.
1803 /* We're not on a preprocessor line. */
1806 if (toktype
== st_C_define
)
1808 definedef
= ddefineseen
;
1812 definedef
= dignorerest
;
1817 * Make a tag for any macro.
1819 definedef
= dignorerest
;
1820 *is_func
= (c
== '(');
1821 if (!*is_func
&& !constantypedefs
)
1828 error ("internal error: definedef value");
1837 if (toktype
== st_C_typedef
)
1840 typdef
= ttypedseen
;
1855 /* Do not return here, so the structdef stuff has a chance. */
1869 * This structdef business is currently only invoked when level==0.
1870 * It should be recursively invoked whatever the level, and a stack of
1871 * states kept, to allow for definitions of structs within structs.
1873 * This structdef business is NOT invoked when we are ctags and the
1874 * file is plain C. This is because a struct tag may have the same
1875 * name as another tag, and this loses with ctags.
1877 * This if statement deals with the typdef state machine as
1878 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1879 * return (FALSE). All the other code here is for the structdef
1886 if (typdef
== ttypedseen
1887 || (typedefs_and_cplusplus
&& level
== 0 && structdef
== snone
))
1889 structdef
= skeyseen
;
1894 if (structdef
== skeyseen
)
1896 if (stab_type (structkey
) == st_C_struct
)
1898 (void) strncpy (structtag
, tokp
->p
, tokp
->len
);
1899 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1903 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1905 structdef
= stagseen
;
1909 /* Avoid entering funcdef stuff if typdef is going on. */
1910 if (typdef
!= tnone
)
1916 /* Detect GNUmacs's function-defining macros. */
1917 if (definedef
== dnone
)
1919 if (strneq (tokp
->p
, "DEF", 3)
1920 || strneq (tokp
->p
, "ENTRY", 5)
1921 || strneq (tokp
->p
, "SYSCALL", 7)
1922 || strneq (tokp
->p
, "PSEUDO", 6))
1924 next_token_is_func
= TRUE
;
1927 if (strneq (tokp
->p
, "EXFUN", 5))
1929 next_token_is_func
= FALSE
;
1933 if (next_token_is_func
)
1935 next_token_is_func
= FALSE
;
1943 funcdef
== fnone
; /* should be useless */
1952 /* Fortran parsing */
1968 linecharno
= charno
;
1969 charno
+= readline (&lb
, fi
);
1972 dbp
++; /* Ratfor escape to fortran */
1973 while (isspace (*dbp
))
1980 if (tail ("integer"))
1988 if (tail ("logical"))
1992 if (tail ("complex") || tail ("character"))
1996 if (tail ("double"))
1998 while (isspace (*dbp
))
2002 if (tail ("precision"))
2008 while (isspace (*dbp
))
2015 if (tail ("function"))
2019 if (tail ("subroutine"))
2027 if (tail ("program"))
2032 if (tail ("procedure"))
2044 register int len
= 0;
2046 while (*cp
&& (*cp
& ~' ') == ((*(dbp
+ len
)) & ~' '))
2059 while (isspace (*dbp
))
2064 while (isspace (*dbp
))
2066 if (!isdigit (*dbp
))
2068 --dbp
; /* force failure */
2073 while (isdigit (*dbp
));
2081 char nambuf
[BUFSIZ
];
2083 while (isspace (*dbp
))
2090 for (cp
= dbp
+ 1; *cp
&& (isalpha (*cp
) || isdigit (*cp
)
2091 || (*cp
== '_') || (*cp
== '$')); cp
++)
2095 (void) strcpy (nambuf
, dbp
);
2097 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2101 /* Handle a file of assembler code. */
2117 linecharno
= charno
;
2118 charno
+= readline (&lb
, fi
);
2121 for (i
= 0; ((c
= dbp
[i
]) && !isspace (c
)) && (c
!= ':'); i
++)
2124 if ((i
> 0) && (c
== ':'))
2129 /* Added by Mosur Mohan, 4/22/88 */
2130 /* Pascal parsing */
2132 #define GET_NEW_LINE \
2134 linecharno = charno; lineno++; \
2135 charno += 1 + readline (&lb, inf); \
2139 /* Locates tags for procedures & functions.
2140 * Doesn't do any type- or var-definitions.
2141 * It does look for the keyword "extern" or "forward"
2142 * immediately following the procedure statement;
2143 * if found, the tag is skipped.
2150 struct linebuffer tline
; /* mostly copied from C_entries */
2154 char nambuf
[BUFSIZ
];
2156 logical
/* each of these flags is TRUE iff: */
2157 incomm1
, /* point is inside {..} comment */
2158 incomm2
, /* point is inside (*..*) comment */
2159 inquote
, /* point is inside '..' string */
2160 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2161 /* keyword, so next item = potential tag */
2162 found_tag
, /* point is after a potential tag */
2163 inparms
, /* point is within parameter-list */
2164 verify_tag
; /* point has passed the parm-list, so the */
2165 /* next token will determine whether */
2166 /* this is a FORWARD/EXTERN to be */
2167 /* ignored, or whether it is a real tag */
2173 initbuffer (&tline
);
2175 incomm1
= incomm2
= inquote
= FALSE
;
2176 found_tag
= FALSE
; /* have a proc name; check if extern */
2177 get_tagname
= FALSE
; /* have found "procedure" keyword */
2178 inparms
= FALSE
; /* found '(' after "proc" */
2179 verify_tag
= FALSE
; /* check if "extern" is ahead */
2181 /* long main loop to get next char */
2185 if (c
== 0) /* if end of line */
2190 if (!((found_tag
&& verify_tag
) ||
2192 c
= *dbp
++; /* only if don't need *dbp pointing */
2193 /* to the beginning of the name of */
2194 /* the procedure or function */
2196 if (incomm1
) /* within { - } comments */
2202 else if (incomm2
) /* within (* - *) comments */
2206 while ((c
= *dbp
++) == '*')
2225 inquote
= TRUE
; /* found first quote */
2227 case '{': /* found open-{-comment */
2231 if (*dbp
== '*') /* found open-(*-comment */
2236 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2239 case ')': /* end of parms list */
2244 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2251 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2253 /* check if this is an "extern" declaration */
2256 if ((*dbp
== 'e') || (*dbp
== 'E'))
2258 if (tail ("extern")) /* superfluous, really! */
2264 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2266 if (tail ("forward")) /* check for forward reference */
2272 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2276 pfnote (nambuf
, TRUE
, FALSE
,
2277 tline
.buffer
, cp
- tline
.buffer
+ 1,
2278 save_lineno
, save_lcno
);
2282 if (get_tagname
) /* grab name of proc or fn */
2287 /* save all values for later tagging */
2288 tline
.size
= lb
.size
;
2289 strcpy (tline
.buffer
, lb
.buffer
);
2290 save_lineno
= lineno
;
2291 save_lcno
= linecharno
;
2293 /* grab block name */
2294 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2298 strcpy (nambuf
, dbp
);
2300 dbp
= cp
; /* restore dbp to e-o-token */
2301 get_tagname
= FALSE
;
2305 /* and proceed to check for "extern" */
2307 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2308 (!found_tag
) && (!get_tagname
))
2310 /* check for proc/fn keywords */
2314 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2318 if (tail ("unction"))
2323 } /* while not e-o-f */
2327 * lisp tag functions
2328 * just look for (def or (DEF
2342 linecharno
= charno
;
2343 charno
+= readline (&lb
, fi
);
2349 while (!isspace (*dbp
))
2351 while (isspace (*dbp
))
2357 /* Check for (foo::defmumble name-defined ... */
2358 while (*dbp
&& *dbp
!= ':' && !isspace (*dbp
)
2359 && *dbp
!= '(' && *dbp
!= ')')
2368 while (!isspace (*dbp
))
2370 while (isspace (*dbp
))
2384 return ((dbp
[1] == 'D' || dbp
[1] == 'd') &&
2385 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2386 (dbp
[3] == 'F' || dbp
[3] == 'f'));
2394 char nambuf
[BUFSIZ
];
2398 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ' '; cp
++)
2402 (void) strcpy (nambuf
, dbp
);
2404 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2409 * Scheme tag functions
2410 * look for (def... xyzzy
2411 * look for (def... (xyzzy
2412 * look for (def ... ((...(xyzzy ....
2413 * look for (set! xyzzy
2416 static void get_scheme ();
2429 linecharno
= charno
;
2430 charno
+= readline (&lb
, fi
);
2432 if (dbp
[0] == '(' &&
2433 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2434 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2435 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2437 while (!isspace (*dbp
))
2439 /* Skip over open parens and white space */
2440 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2444 if (dbp
[0] == '(' &&
2445 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2446 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2447 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2448 (dbp
[4] == '!' || dbp
[4] == '!') &&
2451 while (!isspace (*dbp
))
2453 /* Skip over white space */
2454 while (isspace (*dbp
))
2466 char nambuf
[BUFSIZ
];
2470 /* Go till you get to white space or a syntactic break */
2471 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2473 /* Null terminate the string there. */
2476 /* Copy the string */
2477 strcpy (nambuf
, dbp
);
2478 /* Unterminate the string */
2480 /* Announce the change */
2481 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2485 /* Find tags in TeX and LaTeX input files. */
2487 /* TEX_toktab is a table of TeX control sequences that define tags.
2488 Each TEX_tabent records one such control sequence.
2489 CONVERT THIS TO USE THE Stab TYPE!! */
2497 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2499 /* Default set of control sequences to put into TEX_toktab.
2500 The value of environment var TEXTAGS is prepended to this. */
2502 static char *TEX_defenv
=
2503 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2506 struct TEX_tabent
*TEX_decode_env ();
2510 static char TEX_esc
= '\\';
2511 static char TEX_opgrp
= '{';
2512 static char TEX_clgrp
= '}';
2515 * TeX/LaTeX scanning loop.
2528 /* Select either \ or ! as escape character. */
2531 /* Initialize token table once from environment. */
2533 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2536 { /* Scan each line in file */
2538 linecharno
= charno
;
2539 charno
+= readline (&lb
, fi
);
2542 while (dbp
= etags_index (dbp
, TEX_esc
)) /* Look at each escape in line */
2548 linecharno
+= dbp
- lasthit
;
2550 i
= TEX_Token (lasthit
);
2553 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2554 break; /* We only save a line once */
2560 #define TEX_LESC '\\'
2561 #define TEX_SESC '!'
2564 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2565 /* chars accordingly. */
2573 while ((c
= getc (f
)) != EOF
)
2575 /* Skip to next line if we hit the TeX comment char. */
2579 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2598 /* Read environment and prepend it to the default string. */
2599 /* Build token table. */
2602 TEX_decode_env (evarname
, defenv
)
2606 register char *env
, *p
;
2608 struct TEX_tabent
*tab
;
2611 /* Append default string to environment. */
2612 env
= getenv (evarname
);
2616 env
= concat (env
, defenv
, "");
2618 /* Allocate a token table */
2619 for (size
= 1, p
= env
; p
;)
2620 if ((p
= etags_index (p
, ':')) && *(++p
))
2622 /* Add 1 to leave room for null terminator. */
2623 tab
= xnew (size
+ 1, struct TEX_tabent
);
2625 /* Unpack environment string into token table. Be careful about */
2626 /* zero-length strings (leading ':', "::" and trailing ':') */
2629 p
= etags_index (env
, ':');
2630 if (!p
) /* End of environment string. */
2631 p
= env
+ strlen (env
);
2633 { /* Only non-zero strings. */
2634 tab
[i
].name
= savenstr (env
, p
- env
);
2635 tab
[i
].len
= strlen (tab
[i
].name
);
2642 tab
[i
].name
= NULL
; /* Mark end of table. */
2650 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2651 The name being defined actually starts at (NAME + LEN + 1).
2652 But we seem to include the TeX command in the tag name. */
2655 TEX_getit (name
, len
)
2659 char *p
= name
+ len
;
2660 char nambuf
[BUFSIZ
];
2665 /* Let tag name extend to next group close (or end of line) */
2666 while (*p
&& *p
!= TEX_clgrp
)
2668 (void) strncpy (nambuf
, name
, p
- name
);
2669 nambuf
[p
- name
] = 0;
2671 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2675 /* If the text at CP matches one of the tag-defining TeX command names,
2676 return the etags_index of that command in TEX_toktab.
2677 Otherwise return -1. */
2679 /* Keep the capital `T' in `Token' for dumb truncating compilers
2680 (this distinguishes it from `TEX_toktab' */
2687 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2688 if (strncmp (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
) == 0)
2693 /* Support for Prolog. */
2695 /* whole head (not only functor, but also arguments)
2696 is gotten in compound term. */
2699 prolog_getit (s
, lineno
, linecharno
)
2704 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2712 if (*s
== '\0') /* syntax error. */
2714 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2716 else if (*s
== '\'')
2718 insquote
= !insquote
;
2721 else if (!insquote
&& *s
== '(')
2726 else if (!insquote
&& *s
== ')')
2732 else if (npar
< 0) /* syntax error. */
2735 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2737 if (npar
!= 0) /* syntax error. */
2747 strcpy (nambuf
, save_s
);
2749 pfnote (nambuf
, TRUE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2752 /* It is assumed that prolog predicate starts from column 0. */
2758 void skip_comment (), prolog_getit ();
2760 lineno
= linecharno
= charno
= 0;
2764 linecharno
+= charno
;
2765 charno
= readline (&lb
, fi
) + 1; /* 1 for newline. */
2767 if (isspace (dbp
[0])) /* not predicate header. */
2769 else if (dbp
[0] == '%') /* comment. */
2771 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2772 skip_comment (&lb
, fi
, &lineno
, &linecharno
);
2774 prolog_getit (dbp
, lineno
, linecharno
);
2779 skip_comment (plb
, fi
, plineno
, plinecharno
)
2780 struct linebuffer
*plb
;
2782 int *plineno
; /* result */
2783 long *plinecharno
; /* result */
2785 while (!substr ("*/", plb
->buffer
))
2788 *plinecharno
+= readline (plb
, fi
) + 1;
2789 } /* 1 for newline. */
2792 /* Return TRUE if 'sub' exists somewhere in 's'. */
2799 while (*s
&& (s
= etags_index (s
, *sub
)))
2800 if (prestr (sub
, s
))
2807 /* Return TRUE if 'pre' is prefix of string 's'. */
2816 else if (*pre
== *s
)
2817 return (prestr (pre
+ 1, s
+ 1));
2822 /* Initialize a linebuffer for use */
2825 initbuffer (linebuffer
)
2826 struct linebuffer
*linebuffer
;
2828 linebuffer
->size
= 200;
2829 linebuffer
->buffer
= xnew (200, char);
2833 * Read a line of text from `stream' into `linebuffer'.
2834 * Return the number of characters read from `stream',
2835 * which is the length of the line including the newline, if any.
2838 readline (linebuffer
, stream
)
2839 struct linebuffer
*linebuffer
;
2840 register FILE *stream
;
2842 char *buffer
= linebuffer
->buffer
;
2843 register char *p
= linebuffer
->buffer
;
2844 register char *pend
;
2845 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2847 pend
= p
+ linebuffer
->size
; /* Separate to avoind 386/IX compiler bug. */
2851 register int c
= getc (stream
);
2854 linebuffer
->size
*= 2;
2855 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
2856 p
+= buffer
- linebuffer
->buffer
;
2857 pend
= buffer
+ linebuffer
->size
;
2858 linebuffer
->buffer
= buffer
;
2860 if (c
< 0 || c
== '\n')
2863 newline
= (c
== '\n' ? 1 : 0);
2869 return p
- buffer
+ newline
;
2876 return savenstr (cp
, strlen (cp
));
2886 dp
= xnew (len
+ 1, char);
2887 (void) strncpy (dp
, cp
, len
);
2893 * Return the ptr in sp at which the character c last
2894 * appears; NULL if not found
2896 * Identical to v7 rindex, included for portability.
2900 etags_rindex (sp
, c
)
2901 register char *sp
, c
;
2916 * Return the ptr in sp at which the character c first
2917 * appears; NULL if not found
2919 * Identical to v7 index, included for portability.
2924 register char *sp
, c
;
2934 /* Print error message and exit. */
2945 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
2952 fprintf (stderr
, "%s: ", progname
);
2953 fprintf (stderr
, s1
, s2
);
2954 fprintf (stderr
, "\n");
2957 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
2963 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
2964 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
2966 (void) strcpy (result
, s1
);
2967 (void) strcpy (result
+ len1
, s2
);
2968 (void) strcpy (result
+ len1
+ len2
, s3
);
2969 *(result
+ len1
+ len2
+ len3
) = 0;
2974 /* Like malloc but get fatal error if memory is exhausted. */
2980 char *result
= malloc (size
);
2982 fatal ("virtual memory exhausted", 0);
2987 xrealloc (ptr
, size
)
2991 char *result
= realloc (ptr
, size
);
2993 fatal ("virtual memory exhausted");