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 part of GNU Emacs.
6 GNU Emacs 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 1, or (at your option)
11 GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 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>
37 #define alloca __builtin_alloca
42 extern char *alloca ();
46 extern char *malloc (), *realloc ();
47 extern char *getenv ();
48 extern char *strcpy (), *strncpy ();
51 char *etags_index (), *etags_rindex ();
54 /* Define the symbol ETAGS to make the program "etags",
55 which makes emacs-style tag tables by default.
56 Define CTAGS to make the program "ctags" compatible with the usual one.
57 Define neither one to get behavior that depends
58 on the name with which the program is invoked
59 (but we don't normally compile it that way). */
61 #if !defined(ETAGS) && !defined(CTAGS)
62 /* If neither is defined, program can be run as either. */
67 /* On VMS, CTAGS is not useful, so always do ETAGS. */
74 /* Exit codes for success and failure. */
84 * The FILEPOS abstract type, which represents a position in a file,
85 * plus the following accessor functions:
87 * long GET_CHARNO (pos)
88 * returns absolute char number.
89 * void SET_FILEPOS (pos, fp, charno)
90 * FILE *fp; long charno;
91 * sets `pos' from the current file
92 * position of `fp' and from `charno',
93 * which must be the absolute character
94 * number corresponding to the current
97 * The `pos' parameter is an lvalue expression of type FILEPOS.
98 * Parameters to the accessor functions are evaluated 0 or more times,
99 * and so must have no side effects.
101 * FILEPOS objects can also be assigned and passed to and from
102 * functions in the normal C manner.
104 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
108 /* real implementation */
109 typedef long FILEPOS
;
110 #define GET_CHARNO(pos) ((pos) + 0)
111 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
113 /* debugging implementation */
119 #define GET_CHARNO(pos) ((pos).charno + 0)
120 #define SET_FILEPOS(pos, fp, cno) \
121 ((void) ((pos).charno = (cno), \
122 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
126 #define streq(s, t) (strcmp (s, t) == 0)
127 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
133 #define iswhite(arg) (_wht[arg]) /* T if char is white */
134 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
135 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
136 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
138 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
141 { /* sorting structure */
142 char *name
; /* function or type name */
143 char *file
; /* file name */
144 logical is_func
; /* use pattern or line no */
145 logical rewritten
; /* list name separately */
146 logical been_warned
; /* set if noticed dup */
147 int lno
; /* line number tag is on */
148 long cno
; /* character number line starts on */
149 char *pat
; /* search pattern */
150 struct nd_st
*left
, *right
; /* left and right sons */
154 typedef struct nd_st NODE
;
156 logical header_file
; /* TRUE if .h file, FALSE o.w. */
157 /* boolean "functions" (see init) */
158 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
168 int total_size_of_entries ();
169 logical
consider_token ();
177 void Scheme_funcs ();
182 void find_entries ();
190 void process_file ();
196 * xnew -- allocate storage
199 * Type *xnew (int n, Type);
201 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
206 * Symbol table stuff.
208 * Should probably be implemented with hash table; linked list for now.
213 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
221 struct stab_entry
*next
;
224 typedef struct stab_entry Stab_entry
;
225 typedef Stab_entry
*Stab
;
229 * Stab, Stab_entry, stab_create, stab_search, stab_find -- symbol table
232 * Types: Stab, Stab_entry, enum sym_type
234 * Stab * stab_create ()
236 * Stab_entry * stab_find (stab, sym)
240 * Stab_entry * stab_search (stab, sym)
245 * stab_create creates a Stab, a symbol table object, and returns a
246 * pointer to it. stab_find finds a symbol in a Stab; it returns a
247 * pointer to the Stab_entry if found, otherwise NULL. stab_search
248 * is like stab_find, except that it creates a new Stab_entry,
249 * initialized with type = st_none, if one did not exist already
250 * (it never returns NULL).
252 * A Stab_entry is a structure that contains at least the following
255 * char *name; // must not be modified
256 * enum sym_type type; // should be set
258 * The type field is initially set to st_none; it should be set to
259 * something else by the caller of stab_search. Other possible values
260 * of an enum sym_type can be added.
268 *sp
= NULL
; /* a Stab starts out as a null Stab_entry* */
273 stab_find (stab
, sym
, symlen
)
278 register Stab_entry
*se
;
279 for (se
= *stab
; se
!= NULL
; se
= se
->next
)
281 if (se
->symlen
== symlen
&& strneq (se
->sym
, sym
, symlen
))
289 stab_search (stab
, sym
, symlen
)
294 register Stab_entry
*se
;
295 se
= stab_find (stab
, sym
, symlen
);
300 se
= xnew (1, Stab_entry
);
301 se
->sym
= savenstr (sym
, symlen
);
313 * stab_type -- type of a symbol table entry
316 * enum sym_type stab_type (Stab_entry *se);
319 * May evaluate its argument more than once.
322 #define stab_type(se) ((se)==NULL ? st_none : (se)->type)
338 #define C_PLPL 0x00001 /* C++ */
339 #define C_STAR 0x00003 /* C* */
340 #define YACC 0x10000 /* yacc file */
342 char searchar
= '/'; /* use /.../ searches */
344 LINENO lineno
; /* line number of current line */
345 long charno
; /* current character number */
347 long linecharno
; /* charno of start of line; not used by C, but
348 * by every other language.
351 char *curfile
, /* current input file name */
352 *outfile
, /* output file */
353 *white
= " \f\t\n", /* white chars */
354 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
355 /* token starting chars */
356 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$",
357 /* valid in-token chars */
358 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
360 int append_to_tagfile
; /* -a: append to tags */
361 int emacs_tags_format
; /* emacs style output (no -e option any more) */
362 /* The following three default to 1 for etags, but to 0 for ctags. */
363 int typedefs
; /* -t: create tags for typedefs */
364 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
365 /* 0 struct/enum/union decls, and C++ */
366 /* member functions */
367 int constantypedefs
; /* -d: create tags for C #define and enum */
368 /* constants. Default under etags. Enum */
369 /* constants not implemented. */
370 /* -D: opposite of -d. Default under ctags. */
371 int update
; /* -u: update tags */
372 int vgrind_style
; /* -v: create vgrind style index output */
373 int no_warnings
; /* -w: suppress warnings */
374 int cxref_style
; /* -x: create cxref style output */
375 int cplusplus
; /* .[hc] means C++, not C */
376 int noindentypedefs
; /* -S: ignore indentation in C */
378 /* Name this program was invoked with. */
381 struct option longopts
[] = {
382 { "append", no_argument
, NULL
, 'a' },
383 { "backward-search", no_argument
, NULL
, 'B' },
384 { "c++", no_argument
, NULL
, 'C' },
385 { "cxref", no_argument
, NULL
, 'x' },
386 { "defines", no_argument
, NULL
, 'd' },
387 { "forward-search", no_argument
, NULL
, 'F' },
388 { "help", no_argument
, NULL
, 'H' },
389 { "ignore-indentation", no_argument
, NULL
, 'S' },
390 { "include", required_argument
, NULL
, 'i' },
391 { "no-defines", no_argument
, NULL
, 'D' },
392 { "no-warn", no_argument
, NULL
, 'w' },
393 { "output", required_argument
, NULL
, 'o' },
394 { "typedefs", no_argument
, NULL
, 't' },
395 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
396 { "update", no_argument
, NULL
, 'u' },
397 { "version", no_argument
, NULL
, 'V' },
398 { "vgrind", no_argument
, NULL
, 'v' },
402 FILE *inf
, /* ioptr for current input file */
403 *outf
; /* ioptr for tags file */
405 NODE
*head
; /* the head of the binary tree of tags */
407 int permit_duplicates
= 1; /* Nonzero means allow duplicate tags. */
409 /* A `struct linebuffer' is a structure which holds a line of text.
410 `readline' reads a line from a stream into a linebuffer
411 and works regardless of the length of the line. */
419 struct linebuffer lb
; /* the current line */
420 struct linebuffer filename_lb
; /* used to read in filenames */
424 struct linebuffer lb
; /* used by C_entries instead of lb */
439 printf ("for Emacs version 19.0.\n");
447 printf ("These are the options accepted by %s. You may use unambiguous\n\
448 abbreviations for the long option names.\n\n", progname
);
452 Append tag entries to existing tags file.\n\
454 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
455 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
456 extensions are always assumed to be C++ code.\n\
458 Create tag entries for #defines, too.", stdout
);
461 fputs (" This is the default\n\
467 Don't create tag entries for #defines.", stdout
);
470 fputs (" This is the default\n\
475 -o FILE, --output=FILE\n\
476 Write the tags to FILE.\n\
477 -S, --ignore-indentation\n\
478 Don't rely on indentation quite as much as normal. Currently,\n\
479 this means not to assume that a closing brace in the first\n\
480 column is the final brace of a function or structure\n\
483 Generate tag entries for typedefs. This is the default\n\
485 -T, --typedefs-and-c++\n\
486 Generate tag entries for typedefs, struct/enum/union tags, and\n\
487 C++ member functions.");
490 puts ("-i FILE, --include=FILE\n\
491 Include a note in tag file indicating that, when searching for\n\
492 a tag, one should also consult the tags file FILE after\n\
493 checking the current file.");
497 puts ("-B, --backward-search\n\
498 Write the search commands for the tag entries using '?', the\n\
499 backward-search command.\n\
500 -F, --forward-search\n\
501 Write the search commands for the tag entries using '/', the\n\
502 forward-search command.\n\
504 Update the tag entries for the given files, leaving tag\n\
505 entries for other files in place. Currently, this is\n\
506 implemented by deleting the existing entries for the given\n\
507 files and then rewriting the new entries at the end of the\n\
508 tags file. It is often faster to simply rebuild the entire\n\
509 tag file than to use this.\n\
511 Generates an index of items intended for human consumption,\n\
512 similar to the output of vgrind. The index is sorted, and\n\
513 gives the page number of each item.\n\
515 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
516 The output uses line numbers instead of page numbers, but\n\
517 beyond that the differences are cosmetic; try both to see\n\
520 Suppress warning messages about entries defined in multiple\n\
524 puts ("-V, --version\n\
525 Print the version of the program.\n\
527 Print this help message.");
540 unsigned int nincluded_files
= 0;
541 char **included_files
= (char **) alloca (argc
* sizeof (char *));
546 extern char *gfnames ();
547 extern char *massage_name ();
553 emacs_tags_format
= 1;
555 emacs_tags_format
= 0;
559 * If etags, always find typedefs and structure tags. Why not?
560 * Also default is to find macro constants.
562 if (emacs_tags_format
)
563 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
568 opt
= getopt_long (argc
, argv
, "aCdDo:StTi:BFuvxwVH", longopts
, 0);
576 /* If getopt returns '\0', then it has already processed a
577 long-named option. We should do nothing. */
580 /* Common options. */
597 "%s: -o flag may only be given once\n", progname
);
610 typedefs_and_cplusplus
++;
621 if (!emacs_tags_format
)
623 included_files
[nincluded_files
++] = optarg
;
629 if (emacs_tags_format
)
634 if (emacs_tags_format
)
639 if (emacs_tags_format
)
647 if (emacs_tags_format
)
652 if (emacs_tags_format
)
663 fprintf (stderr
, "%s: No input files specified.\n", progname
);
666 fprintf (stderr
, "%s: Try '%s --help' for a complete list of options.\n",
673 outfile
= emacs_tags_format
? "TAGS" : "tags";
676 init (); /* set up boolean "functions" */
679 initbuffer (&lbs
[0].lb
);
680 initbuffer (&lbs
[1].lb
);
681 initbuffer (&filename_lb
);
683 * loop through files finding functions
685 if (emacs_tags_format
)
687 if (streq (outfile
, "-"))
690 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
701 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
705 error ("Can't find file %s\n", this_file
);
710 this_file
= massage_name (this_file
);
713 } /* solely to balance out the ifdef'd parens above */
716 for (; optind
< argc
; optind
++)
718 this_file
= argv
[optind
];
722 /* Input file named "-" means read file names from stdin
724 if (streq (this_file
, "-"))
726 while (!feof (stdin
))
728 (void) readline (&filename_lb
, stdin
);
729 if (strlen (filename_lb
.buffer
) > 0)
730 process_file (filename_lb
.buffer
);
734 process_file (this_file
);
738 if (emacs_tags_format
)
740 while (nincluded_files
-- > 0)
741 fprintf (outf
, "\f\n%s,include\n", *included_files
++);
743 (void) fclose (outf
);
754 /* update cannot be set under VMS, so we may assume that argc
755 and argv have not been munged. */
756 for (i
= optind
; i
< argc
; i
++)
759 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
760 outfile
, argv
[i
], outfile
);
765 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
772 (void) fclose (outf
);
775 sprintf (cmd
, "sort %s -o %s", outfile
, outfile
);
783 * This routine is called on each file argument.
789 struct stat stat_buf
;
791 stat (file
, &stat_buf
);
792 if (!(stat_buf
.st_mode
& S_IFREG
)
794 || !(stat_buf
.st_mode
& S_IFLNK
)
798 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
802 if (streq (file
, outfile
) && !streq (outfile
, "-"))
804 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
807 if (emacs_tags_format
)
809 char *cp
= etags_rindex (file
, '/');
816 if (emacs_tags_format
)
818 fprintf (outf
, "\f\n%s,%d\n",
819 file
, total_size_of_entries (head
));
827 * This routine sets up the boolean psuedo-functions which work
828 * by setting boolean flags dependent upon the corresponding character
829 * Every char which is NOT in that string is not a white char. Therefore,
830 * all of the array "_wht" is set to FALSE, and then the elements
831 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
832 * of a char is TRUE if it is the string "white", else FALSE.
840 for (i
= 0; i
< 0177; i
++)
841 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
842 for (sp
= white
; *sp
; sp
++)
844 for (sp
= endtk
; *sp
; sp
++)
846 for (sp
= intk
; *sp
; sp
++)
848 for (sp
= begtk
; *sp
; sp
++)
850 _wht
[0] = _wht
['\n'];
851 _etk
[0] = _etk
['\n'];
852 _btk
[0] = _btk
['\n'];
853 _itk
[0] = _itk
['\n'];
857 * This routine opens the specified file and calls the function
858 * which finds the function and type definitions.
865 void prolog_funcs ();
867 inf
= fopen (file
, "r");
873 curfile
= savestr (file
);
874 cp
= etags_rindex (file
, '.');
876 header_file
= (cp
&& (streq (cp
+ 1, "h")));
878 /* .tex, .aux or .bbl implies LaTeX source code */
879 if (cp
&& (streq (cp
+ 1, "tex") || streq (cp
+ 1, "aux")
880 || streq (cp
+ 1, "bbl")))
883 goto close_and_return
;
885 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
886 if (cp
&& (streq (cp
+ 1, "l")
887 || streq (cp
+ 1, "el")
888 || streq (cp
+ 1, "lsp")
889 || streq (cp
+ 1, "lisp")
890 || streq (cp
+ 1, "cl")
891 || streq (cp
+ 1, "clisp")))
894 goto close_and_return
;
896 /* .scm or .sm or .scheme or ... implies scheme source code */
897 if (cp
&& (streq (cp
+ 1, "sm")
898 || streq (cp
+ 1, "scm")
899 || streq (cp
+ 1, "scheme")
900 || streq (cp
+ 1, "t")
901 || streq (cp
+ 1, "sch")
902 || streq (cp
+ 1, "SM")
903 || streq (cp
+ 1, "SCM")
904 /* The `SCM' or `scm' prefix with a version number */
905 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
906 && string_numeric_p (cp
+ 1))
907 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
908 && string_numeric_p (cp
+ 1))))
914 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
916 if (cp
&& (streq (cp
+ 1, "s")
917 || streq (cp
+ 1, "a")
918 || streq (cp
+ 1, "sa")))
924 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
925 if (cp
&& (streq (cp
+ 1, "C")
926 || streq (cp
+ 1, "H")
927 || streq (cp
+ 1, "cxx")
928 || streq (cp
+ 1, "hxx")
929 || streq (cp
+ 1, "cc")))
931 C_entries (C_PLPL
); /* C++ */
932 goto close_and_return
;
934 /* .cs or .hs: a C* file */
935 if (cp
&& (streq (cp
+ 1, "cs")
936 || streq (cp
+ 1, "hs")))
939 goto close_and_return
;
941 /* .y: a yacc file */
942 if (cp
&& (streq (cp
+ 1, "y")))
945 goto close_and_return
;
947 /* .pl implies prolog source code */
948 if (cp
&& streq (cp
+ 1, "pl"))
951 goto close_and_return
;
953 /* .p or .pas: a Pascal file */
954 if (cp
&& (streq (cp
+ 1, "p")
955 || streq (cp
+ 1, "pas")))
958 goto close_and_return
;
960 /* If .f or .for, assume it is fortran or nothing. */
961 if (cp
&& (streq (cp
+ 1, "f")
962 || streq (cp
+ 1, "for")))
965 goto close_and_return
;
967 /* if not a .c or .h or .y file, try fortran */
968 if (cp
&& ((cp
[1] != 'c'
971 || (cp
[1] != 0 && cp
[2] != 0)))
973 if (PF_funcs (inf
) != 0)
974 goto close_and_return
;
975 rewind (inf
); /* no fortran tags found, try C */
977 C_entries (cplusplus
? C_PLPL
: 0);
983 /* Nonzero if string STR is composed of digits. */
986 string_numeric_p (str
)
991 if (*str
< '0' || *str
> '9')
998 /* Should take a TOKEN* instead!! */
1000 pfnote (name
, is_func
, rewritten
, linestart
, linelen
, lno
, cno
)
1001 char *name
; /* tag name */
1002 logical is_func
; /* function or type name? */
1003 logical rewritten
; /* tag different from text of definition? */
1014 np
= (NODE
*) malloc (sizeof (NODE
));
1017 if (!emacs_tags_format
)
1019 /* It's okay to output early in etags -- it only disrupts the
1020 * character count of the tag entries, which is no longer used
1021 * by tags.el anyway.
1023 error ("too many entries to sort");
1028 np
= xnew (1, NODE
);
1030 /* If ctags mode, change name "main" to M<thisfilename>. */
1031 if (!emacs_tags_format
&& !cxref_style
&& streq (name
, "main"))
1033 fp
= etags_rindex (curfile
, '/');
1034 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
1035 fp
= etags_rindex (name
, '.');
1036 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
1040 np
->name
= savestr (name
);
1042 np
->is_func
= is_func
;
1043 np
->rewritten
= rewritten
;
1045 /* UNCOMMENT THE +1 HERE: */
1046 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
1047 np
->left
= np
->right
= 0;
1048 if (emacs_tags_format
)
1050 c
= linestart
[linelen
];
1051 linestart
[linelen
] = 0;
1053 else if (cxref_style
== 0)
1055 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
1058 np
->pat
= savestr (linestart
);
1059 if (emacs_tags_format
)
1061 linestart
[linelen
] = c
;
1064 add_node (np
, &head
);
1069 * recurse on left children, iterate on right children.
1073 register NODE
*node
;
1077 register NODE
*node_right
= node
->right
;
1078 free_tree (node
->left
);
1081 free ((char *) node
);
1088 * Adds a node to the tree of nodes. In etags mode, we don't keep
1089 * it sorted; we just keep a linear list. In ctags mode, maintain
1090 * an ordered tree, with no attempt at balancing.
1092 * add_node is the only function allowed to add nodes, so it can
1096 add_node (node
, cur_node_p
)
1097 NODE
*node
, **cur_node_p
;
1100 register NODE
*cur_node
= *cur_node_p
;
1101 static NODE
*last_node
= NULL
;/* careful */
1103 if (cur_node
== NULL
)
1110 if (emacs_tags_format
)
1114 fatal ("internal error in add_node");
1115 last_node
->right
= node
;
1121 dif
= strcmp (node
->name
, cur_node
->name
);
1124 * If this tag name matches an existing one, then
1125 * do not add the node, but maybe print a warning.
1129 if (node
->file
== cur_node
->file
)
1133 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1134 node
->file
, lineno
, node
->name
);
1135 fprintf (stderr
, "Second entry ignored\n");
1139 if (!cur_node
->been_warned
&& !no_warnings
)
1142 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1143 node
->file
, cur_node
->file
, node
->name
);
1145 cur_node
->been_warned
= TRUE
;
1149 /* Maybe refuse to add duplicate nodes. */
1150 if (!permit_duplicates
)
1152 if (!strcmp (node
->name
, cur_node
->name
)
1153 && !strcmp (node
->file
, cur_node
->file
))
1157 /* Actually add the node */
1158 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1164 register NODE
*node
;
1171 /* Output subentries that precede this one */
1172 put_entries (node
->left
);
1174 /* Output this entry */
1176 if (emacs_tags_format
)
1178 if (node
->rewritten
)
1180 fprintf (outf
, "%s\177%s\001%d,%d\n",
1181 node
->name
, node
->pat
, node
->lno
, node
->cno
);
1185 fprintf (outf
, "%s\177%d,%d\n",
1186 node
->pat
, node
->lno
, node
->cno
);
1189 else if (!cxref_style
)
1191 fprintf (outf
, "%s\t%s\t",
1192 node
->name
, node
->file
);
1196 putc (searchar
, outf
);
1199 for (sp
= node
->pat
; *sp
; sp
++)
1201 if (*sp
== '\\' || *sp
== searchar
)
1205 putc (searchar
, outf
);
1208 { /* a typedef; text pattern inadequate */
1209 fprintf (outf
, "%d", node
->lno
);
1213 else if (vgrind_style
)
1214 fprintf (stdout
, "%s %s %d\n",
1215 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1217 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1218 node
->name
, node
->lno
, node
->file
, node
->pat
);
1220 /* Output subentries that follow this one */
1221 put_entries (node
->right
);
1224 /* Length of a number's decimal representation. */
1232 for (; num
; num
/= 10)
1238 * Return total number of characters that put_entries will output for
1239 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1240 * is set, but called only in that case. This count is irrelevant with
1241 * the new tags.el, but is still supplied for backward compatibility.
1244 total_size_of_entries (node
)
1245 register NODE
*node
;
1253 for (; node
; node
= node
->right
)
1255 /* Count left subentries. */
1256 total
+= total_size_of_entries (node
->left
);
1258 /* Count this entry */
1259 total
+= strlen (node
->pat
) + 1;
1260 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1261 if (node
->rewritten
)
1262 total
+= 1 + strlen (node
->name
); /* \001name */
1269 * The C symbol tables.
1272 Stab
*C_stab
, *C_PLPL_stab
, *C_STAR_stab
;
1276 * Stab *get_C_stab (int c_ext);
1278 #define get_C_stab(c_ext) ((c_ext & C_STAR) ? C_STAR_stab : \
1279 (c_ext & C_PLPL) ? C_PLPL_stab : \
1283 add_keyword (stab
, sym
, type
)
1288 stab_search (stab
, sym
, strlen (sym
))->type
= type
;
1292 C_create_stab (c_ext
)
1297 stab
= stab_create ();
1301 add_keyword (stab
, "class", st_C_struct
);
1303 add_keyword (stab
, "domain", st_C_struct
);
1304 add_keyword (stab
, "union", st_C_struct
);
1305 add_keyword (stab
, "struct", st_C_struct
);
1306 add_keyword (stab
, "enum", st_C_enum
);
1307 add_keyword (stab
, "typedef", st_C_typedef
);
1308 add_keyword (stab
, "define", st_C_define
);
1309 add_keyword (stab
, "long", st_C_typespec
);
1310 add_keyword (stab
, "short", st_C_typespec
);
1311 add_keyword (stab
, "int", st_C_typespec
);
1312 add_keyword (stab
, "char", st_C_typespec
);
1313 add_keyword (stab
, "float", st_C_typespec
);
1314 add_keyword (stab
, "double", st_C_typespec
);
1315 add_keyword (stab
, "signed", st_C_typespec
);
1316 add_keyword (stab
, "unsigned", st_C_typespec
);
1317 add_keyword (stab
, "auto", st_C_typespec
);
1318 add_keyword (stab
, "void", st_C_typespec
);
1319 add_keyword (stab
, "extern", st_C_typespec
);
1320 add_keyword (stab
, "static", st_C_typespec
);
1321 add_keyword (stab
, "const", st_C_typespec
);
1322 add_keyword (stab
, "volatile", st_C_typespec
);
1330 C_stab
= C_create_stab (0);
1331 C_PLPL_stab
= C_create_stab (C_PLPL
);
1332 C_STAR_stab
= C_create_stab (C_STAR
| C_PLPL
);
1336 * etags.c 4.2 1993/03/22 12:13:40 pot Exp
1337 * C functions are recognized using a simple finite automaton.
1338 * funcdef is its state variable.
1342 fnone
, ftagseen
, finlist
, flistseen
1347 /* typedefs are recognized using a simple finite automaton.
1348 * typeddef is its state variable.
1352 tnone
, ttypedseen
, tinbody
, tend
1357 /* struct tags for C++ are recognized using another simple
1358 * finite automaton. `structdef' is its state variable.
1359 * This machinery is only invoked for C++; otherwise structdef
1360 * should remain snone. However, this machinery can easily be
1361 * adapted to find structure tags in normal C code.
1365 snone
, /* nothing seen yet */
1366 skeyseen
, /* struct-like keyword seen */
1367 stagseen
, /* struct-like tag seen */
1368 scolonseen
, /* colon seen after struct-like tag */
1369 sinbody
/* in class body: recognize member func defs */
1373 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1374 * struct tag, and structkey is the preceding struct-like keyword.
1376 char structtag
[BUFSIZ
];
1377 Stab_entry
*structkey
;
1380 * Yet another little state machine to deal with preprocessor lines.
1384 dnone
, /* nothing seen */
1385 dsharpseen
, /* '#' seen as first char on line */
1386 ddefineseen
, /* '#' and 'define' seen */
1387 dignorerest
/* ignore rest of line */
1392 * Set this to TRUE, and the next token considered is called a function.
1393 * Used only for GNUmacs's function-defining macros.
1395 logical next_token_is_func
;
1398 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1404 * This routine finds functions, typedefs, #define's and
1405 * struct/union/enum definitions in C syntax and adds them
1410 * LEVEL_OK_FOR_FUNCDEF allows C++ function definition within class body.
1411 * Currently typdef and structdef stuff (typedefs and struct
1412 * definitions) are only noticed when level==0, but that may change.
1414 #define LEVEL_OK_FOR_FUNCDEF() \
1415 (level==0 || (cplpl && level==1 && structdef==sinbody))
1417 #define curlb (lbs[curndx].lb)
1418 #define othlb (lbs[1-curndx].lb)
1419 #define newlb (lbs[newndx].lb)
1420 #define curlinepos (lbs[curndx].linepos)
1421 #define othlinepos (lbs[1-curndx].linepos)
1422 #define newlinepos (lbs[newndx].linepos)
1424 #define CNL_SAVE_DEFINEDEF \
1426 SET_FILEPOS (curlinepos, inf, charno); \
1428 charno += readline (&curlb, inf); \
1429 lp = curlb.buffer; \
1436 CNL_SAVE_DEFINEDEF; \
1437 definedef = dnone; \
1440 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1441 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1442 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1443 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1447 int c_ext
; /* extension of C? */
1449 register char c
; /* latest char read; '\0' for end of line */
1450 register char *lp
; /* pointer one beyond the character `c' */
1451 int curndx
, newndx
; /* indices for current and new lb */
1452 TOKEN tok
; /* latest token read for funcdef & structdef */
1453 char tokb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1454 register int tokoff
; /* offset in line of start of latest token */
1455 register int toklen
; /* length of latest token */
1456 int level
; /* current curly brace level */
1457 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1460 curndx
= newndx
= 0;
1466 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1467 next_token_is_func
= yacc_rules
= FALSE
;
1468 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1470 cplpl
= c_ext
& C_PLPL
;
1479 /* If we're at the end of the line, the next character is a
1480 '\0'; don't skip it, because it's the thing that tells us
1481 to read the next line. */
1502 /* Newlines inside comments do not end macro definitions in
1517 /* Newlines inside strings, do not end macro definitions
1518 in traditional cpp, even though compilers don't
1519 usually accept them. */
1547 else if (cplpl
&& *lp
== '/')
1554 if ((c_ext
& YACC
) && *lp
== '%')
1556 /* entering or exiting rules section in yacc file */
1558 definedef
= dnone
; funcdef
= fnone
;
1559 typdef
= tnone
; structdef
= snone
;
1560 next_token_is_func
= FALSE
;
1561 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1563 yacc_rules
= !yacc_rules
;
1567 if (lp
== newlb
.buffer
+ 1 && definedef
== dnone
)
1568 definedef
= dsharpseen
;
1573 if (LEVEL_OK_FOR_FUNCDEF ()
1574 && definedef
!= dignorerest
1575 && structdef
!= scolonseen
1576 && funcdef
!= finlist
)
1582 if (cplpl
&& c
== ':' && *lp
== ':' && intoken (*(lp
+ 1)))
1585 * This handles :: in the middle, but not at beginning
1595 tok
.lineno
= lineno
;
1596 tok
.p
= newlb
.buffer
+ tokoff
;
1598 tok
.rewritten
= FALSE
;
1600 || consider_token (c
, lp
, &tok
,
1601 c_ext
, level
, &is_func
))
1603 if (structdef
== sinbody
1604 && definedef
== dnone
&& is_func
)
1605 { /* function defined in C++ class body */
1606 sprintf (tokb
, "%s::%.*s",
1607 ((structtag
[0] == '\0')
1608 ? "_anonymous_" : structtag
),
1610 tok
.rewritten
= TRUE
;
1614 sprintf (tokb
, "%.*s", tok
.len
, tok
.p
);
1617 if (funcdef
== ftagseen
|| structdef
== stagseen
)
1619 if (newndx
== curndx
)
1620 curndx
= 1 - curndx
; /* switch line buffers */
1623 MAKE_TAG_FROM_NEW_LB (is_func
);
1627 } /* if (endtoken (c)) */
1628 else if (intoken (c
))
1633 } /* if (midtoken) */
1634 else if (begtoken (c
))
1639 MAKE_TAG_FROM_OTH_LB (TRUE
);
1645 if (structdef
== stagseen
)
1647 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
1649 tokoff
= lp
- 1 - newlb
.buffer
;
1655 } /* if must look at token */
1658 /* Detect end of line, colon, comma, semicolon and various braces
1659 after having handled the last token on the line.*/
1663 if (structdef
== stagseen
)
1664 structdef
= scolonseen
;
1665 else if (yacc_rules
&& funcdef
== ftagseen
)
1667 MAKE_TAG_FROM_OTH_LB (FALSE
);
1675 if (funcdef
!= finlist
)
1677 if (level
== 0 && typdef
== tend
)
1681 if (funcdef
!= finlist
)
1683 if (structdef
== stagseen
)
1699 if (funcdef
== finlist
)
1700 funcdef
= flistseen
;
1703 if (typdef
== ttypedseen
)
1707 case skeyseen
: /* unnamed struct */
1708 structtag
[0] = '\0';
1709 structdef
= sinbody
;
1712 case scolonseen
: /* named struct */
1713 structdef
= sinbody
;
1714 MAKE_TAG_FROM_OTH_LB (FALSE
);
1720 if (funcdef
== flistseen
)
1722 MAKE_TAG_FROM_OTH_LB (TRUE
);
1727 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
1728 level
= 0; /* reset level if first column */
1733 if (typdef
== tinbody
)
1736 (void) strcpy (structtag
, "<error 2>");
1740 /* If a macro spans multiple lines don't reset its state. */
1748 } /* while not eof */
1753 * checks to see if the current token is at the start of a
1754 * function, or corresponds to a typedef, or is a struct/union/enum
1757 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1758 * C_EXT is which language we are looking at.
1760 * In the future we will need some way to adjust where the end of
1761 * the token is; for instance, implementing the C++ keyword
1762 * `operator' properly will adjust the end of the token to be after
1763 * whatever follows `operator'.
1770 * next_token_is_func IN OUT
1774 consider_token (c
, lp
, tokp
, c_ext
, level
, is_func
)
1775 register char c
; /* IN: first char after the token */
1776 register char *lp
; /* IN: lp points to 2nd char after the token */
1777 register TOKEN
*tokp
; /* IN */
1780 logical
*is_func
; /* OUT */
1782 logical firsttok
; /* TRUE if have seen first token in ()'s */
1783 Stab_entry
*tokse
= stab_find (get_C_stab (c_ext
), tokp
->p
, tokp
->len
);
1784 enum sym_type toktype
= stab_type (tokse
);
1786 *is_func
= FALSE
; /* not a function */
1789 * Advance the definedef state machine.
1794 /* We're not on a preprocessor line. */
1797 if (toktype
== st_C_define
)
1799 definedef
= ddefineseen
;
1803 definedef
= dignorerest
;
1808 * Make a tag for any macro.
1810 definedef
= dignorerest
;
1811 *is_func
= (c
== '(');
1812 if (!*is_func
&& !constantypedefs
)
1819 error ("internal error: definedef value");
1828 if (toktype
== st_C_typedef
)
1831 typdef
= ttypedseen
;
1846 /* Do not return here, so the structdef stuff has a chance. */
1860 * This structdef business is currently only invoked when level==0.
1861 * It should be recursively invoked whatever the level, and a stack of
1862 * states kept, to allow for definitions of structs within structs.
1864 * This structdef business is NOT invoked when we are ctags and the
1865 * file is plain C. This is because a struct tag may have the same
1866 * name as another tag, and this loses with ctags.
1868 * This if statement deals with the typdef state machine as
1869 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1870 * return (FALSE). All the other code here is for the structdef
1877 if (typdef
== ttypedseen
1878 || (typedefs_and_cplusplus
&& level
== 0 && structdef
== snone
))
1880 structdef
= skeyseen
;
1885 if (structdef
== skeyseen
)
1887 if (stab_type (structkey
) == st_C_struct
)
1889 (void) strncpy (structtag
, tokp
->p
, tokp
->len
);
1890 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1894 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1896 structdef
= stagseen
;
1900 /* Avoid entering funcdef stuff if typdef is going on. */
1901 if (typdef
!= tnone
)
1907 /* Detect GNUmacs's function-defining macros. */
1908 if (definedef
== dnone
)
1910 if (strneq (tokp
->p
, "DEF", 3)
1911 || strneq (tokp
->p
, "ENTRY", 5)
1912 || strneq (tokp
->p
, "SYSCALL", 7)
1913 || strneq (tokp
->p
, "PSEUDO", 6))
1915 next_token_is_func
= TRUE
;
1918 if (strneq (tokp
->p
, "EXFUN", 5))
1920 next_token_is_func
= FALSE
;
1924 if (next_token_is_func
)
1926 next_token_is_func
= FALSE
;
1934 funcdef
== fnone
; /* should be useless */
1943 /* Fortran parsing */
1959 linecharno
= charno
;
1960 charno
+= readline (&lb
, fi
);
1963 dbp
++; /* Ratfor escape to fortran */
1964 while (isspace (*dbp
))
1971 if (tail ("integer"))
1979 if (tail ("logical"))
1983 if (tail ("complex") || tail ("character"))
1987 if (tail ("double"))
1989 while (isspace (*dbp
))
1993 if (tail ("precision"))
1999 while (isspace (*dbp
))
2006 if (tail ("function"))
2010 if (tail ("subroutine"))
2018 if (tail ("program"))
2023 if (tail ("procedure"))
2035 register int len
= 0;
2037 while (*cp
&& (*cp
& ~' ') == ((*(dbp
+ len
)) & ~' '))
2050 while (isspace (*dbp
))
2055 while (isspace (*dbp
))
2057 if (!isdigit (*dbp
))
2059 --dbp
; /* force failure */
2064 while (isdigit (*dbp
));
2072 char nambuf
[BUFSIZ
];
2074 while (isspace (*dbp
))
2081 for (cp
= dbp
+ 1; *cp
&& (isalpha (*cp
) || isdigit (*cp
)
2082 || (*cp
== '_') || (*cp
== '$')); cp
++)
2086 (void) strcpy (nambuf
, dbp
);
2088 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2092 /* Handle a file of assembler code. */
2108 linecharno
= charno
;
2109 charno
+= readline (&lb
, fi
);
2112 for (i
= 0; ((c
= dbp
[i
]) && !isspace (c
)) && (c
!= ':'); i
++)
2115 if ((i
> 0) && (c
== ':'))
2120 /* Added by Mosur Mohan, 4/22/88 */
2121 /* Pascal parsing */
2123 #define GET_NEW_LINE \
2125 linecharno = charno; lineno++; \
2126 charno += 1 + readline (&lb, inf); \
2130 /* Locates tags for procedures & functions.
2131 * Doesn't do any type- or var-definitions.
2132 * It does look for the keyword "extern" or "forward"
2133 * immediately following the procedure statement;
2134 * if found, the tag is skipped.
2141 struct linebuffer tline
; /* mostly copied from C_entries */
2145 char nambuf
[BUFSIZ
];
2147 logical
/* each of these flags is TRUE iff: */
2148 incomm1
, /* point is inside {..} comment */
2149 incomm2
, /* point is inside (*..*) comment */
2150 inquote
, /* point is inside '..' string */
2151 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2152 /* keyword, so next item = potential tag */
2153 found_tag
, /* point is after a potential tag */
2154 inparms
, /* point is within parameter-list */
2155 verify_tag
; /* point has passed the parm-list, so the */
2156 /* next token will determine whether */
2157 /* this is a FORWARD/EXTERN to be */
2158 /* ignored, or whether it is a real tag */
2164 initbuffer (&tline
);
2166 incomm1
= incomm2
= inquote
= FALSE
;
2167 found_tag
= FALSE
; /* have a proc name; check if extern */
2168 get_tagname
= FALSE
; /* have found "procedure" keyword */
2169 inparms
= FALSE
; /* found '(' after "proc" */
2170 verify_tag
= FALSE
; /* check if "extern" is ahead */
2172 /* long main loop to get next char */
2176 if (c
== 0) /* if end of line */
2181 if (!((found_tag
&& verify_tag
) ||
2183 c
= *dbp
++; /* only if don't need *dbp pointing */
2184 /* to the beginning of the name of */
2185 /* the procedure or function */
2187 if (incomm1
) /* within { - } comments */
2193 else if (incomm2
) /* within (* - *) comments */
2197 while ((c
= *dbp
++) == '*')
2216 inquote
= TRUE
; /* found first quote */
2218 case '{': /* found open-{-comment */
2222 if (*dbp
== '*') /* found open-(*-comment */
2227 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2230 case ')': /* end of parms list */
2235 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2242 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2244 /* check if this is an "extern" declaration */
2247 if ((*dbp
== 'e') || (*dbp
== 'E'))
2249 if (tail ("extern")) /* superfluous, really! */
2255 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2257 if (tail ("forward")) /* check for forward reference */
2263 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2267 pfnote (nambuf
, TRUE
, FALSE
,
2268 tline
.buffer
, cp
- tline
.buffer
+ 1,
2269 save_lineno
, save_lcno
);
2273 if (get_tagname
) /* grab name of proc or fn */
2278 /* save all values for later tagging */
2279 tline
.size
= lb
.size
;
2280 strcpy (tline
.buffer
, lb
.buffer
);
2281 save_lineno
= lineno
;
2282 save_lcno
= linecharno
;
2284 /* grab block name */
2285 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2289 strcpy (nambuf
, dbp
);
2291 dbp
= cp
; /* restore dbp to e-o-token */
2292 get_tagname
= FALSE
;
2296 /* and proceed to check for "extern" */
2298 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2299 (!found_tag
) && (!get_tagname
))
2301 /* check for proc/fn keywords */
2305 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2309 if (tail ("unction"))
2314 } /* while not e-o-f */
2318 * lisp tag functions
2319 * just look for (def or (DEF
2333 linecharno
= charno
;
2334 charno
+= readline (&lb
, fi
);
2340 while (!isspace (*dbp
))
2342 while (isspace (*dbp
))
2348 /* Check for (foo::defmumble name-defined ... */
2349 while (*dbp
&& *dbp
!= ':' && !isspace (*dbp
)
2350 && *dbp
!= '(' && *dbp
!= ')')
2359 while (!isspace (*dbp
))
2361 while (isspace (*dbp
))
2375 return ((dbp
[1] == 'D' || dbp
[1] == 'd') &&
2376 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2377 (dbp
[3] == 'F' || dbp
[3] == 'f'));
2385 char nambuf
[BUFSIZ
];
2389 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ' '; cp
++)
2393 (void) strcpy (nambuf
, dbp
);
2395 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2400 * Scheme tag functions
2401 * look for (def... xyzzy
2402 * look for (def... (xyzzy
2403 * look for (def ... ((...(xyzzy ....
2404 * look for (set! xyzzy
2407 static void get_scheme ();
2420 linecharno
= charno
;
2421 charno
+= readline (&lb
, fi
);
2423 if (dbp
[0] == '(' &&
2424 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2425 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2426 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2428 while (!isspace (*dbp
))
2430 /* Skip over open parens and white space */
2431 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2435 if (dbp
[0] == '(' &&
2436 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2437 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2438 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2439 (dbp
[4] == '!' || dbp
[4] == '!') &&
2442 while (!isspace (*dbp
))
2444 /* Skip over white space */
2445 while (isspace (*dbp
))
2457 char nambuf
[BUFSIZ
];
2461 /* Go till you get to white space or a syntactic break */
2462 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2464 /* Null terminate the string there. */
2467 /* Copy the string */
2468 strcpy (nambuf
, dbp
);
2469 /* Unterminate the string */
2471 /* Announce the change */
2472 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2476 /* Find tags in TeX and LaTeX input files. */
2478 /* TEX_toktab is a table of TeX control sequences that define tags.
2479 Each TEX_tabent records one such control sequence.
2480 CONVERT THIS TO USE THE Stab TYPE!! */
2488 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2490 /* Default set of control sequences to put into TEX_toktab.
2491 The value of environment var TEXTAGS is prepended to this. */
2493 static char *TEX_defenv
=
2494 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2497 struct TEX_tabent
*TEX_decode_env ();
2501 static char TEX_esc
= '\\';
2502 static char TEX_opgrp
= '{';
2503 static char TEX_clgrp
= '}';
2506 * TeX/LaTeX scanning loop.
2519 /* Select either \ or ! as escape character. */
2522 /* Initialize token table once from environment. */
2524 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2527 { /* Scan each line in file */
2529 linecharno
= charno
;
2530 charno
+= readline (&lb
, fi
);
2533 while (dbp
= etags_index (dbp
, TEX_esc
)) /* Look at each escape in line */
2539 linecharno
+= dbp
- lasthit
;
2541 i
= TEX_Token (lasthit
);
2544 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2545 break; /* We only save a line once */
2551 #define TEX_LESC '\\'
2552 #define TEX_SESC '!'
2555 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2556 /* chars accordingly. */
2564 while ((c
= getc (f
)) != EOF
)
2566 /* Skip to next line if we hit the TeX comment char. */
2570 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2589 /* Read environment and prepend it to the default string. */
2590 /* Build token table. */
2593 TEX_decode_env (evarname
, defenv
)
2597 register char *env
, *p
;
2599 struct TEX_tabent
*tab
;
2602 /* Append default string to environment. */
2603 env
= getenv (evarname
);
2607 env
= concat (env
, defenv
, "");
2609 /* Allocate a token table */
2610 for (size
= 1, p
= env
; p
;)
2611 if ((p
= etags_index (p
, ':')) && *(++p
))
2613 /* Add 1 to leave room for null terminator. */
2614 tab
= xnew (size
+ 1, struct TEX_tabent
);
2616 /* Unpack environment string into token table. Be careful about */
2617 /* zero-length strings (leading ':', "::" and trailing ':') */
2620 p
= etags_index (env
, ':');
2621 if (!p
) /* End of environment string. */
2622 p
= env
+ strlen (env
);
2624 { /* Only non-zero strings. */
2625 tab
[i
].name
= savenstr (env
, p
- env
);
2626 tab
[i
].len
= strlen (tab
[i
].name
);
2633 tab
[i
].name
= NULL
; /* Mark end of table. */
2641 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2642 The name being defined actually starts at (NAME + LEN + 1).
2643 But we seem to include the TeX command in the tag name. */
2646 TEX_getit (name
, len
)
2650 char *p
= name
+ len
;
2651 char nambuf
[BUFSIZ
];
2656 /* Let tag name extend to next group close (or end of line) */
2657 while (*p
&& *p
!= TEX_clgrp
)
2659 (void) strncpy (nambuf
, name
, p
- name
);
2660 nambuf
[p
- name
] = 0;
2662 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2666 /* If the text at CP matches one of the tag-defining TeX command names,
2667 return the etags_index of that command in TEX_toktab.
2668 Otherwise return -1. */
2670 /* Keep the capital `T' in `Token' for dumb truncating compilers
2671 (this distinguishes it from `TEX_toktab' */
2678 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2679 if (strncmp (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
) == 0)
2684 /* Support for Prolog. */
2686 /* whole head (not only functor, but also arguments)
2687 is gotten in compound term. */
2690 prolog_getit (s
, lineno
, linecharno
)
2695 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2703 if (*s
== '\0') /* syntax error. */
2705 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2707 else if (*s
== '\'')
2709 insquote
= !insquote
;
2712 else if (!insquote
&& *s
== '(')
2717 else if (!insquote
&& *s
== ')')
2723 else if (npar
< 0) /* syntax error. */
2726 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2728 if (npar
!= 0) /* syntax error. */
2738 strcpy (nambuf
, save_s
);
2740 pfnote (nambuf
, TRUE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2743 /* It is assumed that prolog predicate starts from column 0. */
2749 void skip_comment (), prolog_getit ();
2751 lineno
= linecharno
= charno
= 0;
2755 linecharno
+= charno
;
2756 charno
= readline (&lb
, fi
) + 1; /* 1 for newline. */
2758 if (isspace (dbp
[0])) /* not predicate header. */
2760 else if (dbp
[0] == '%') /* comment. */
2762 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2763 skip_comment (&lb
, fi
, &lineno
, &linecharno
);
2765 prolog_getit (dbp
, lineno
, linecharno
);
2770 skip_comment (plb
, fi
, plineno
, plinecharno
)
2771 struct linebuffer
*plb
;
2773 int *plineno
; /* result */
2774 long *plinecharno
; /* result */
2776 while (!substr ("*/", plb
->buffer
))
2779 *plinecharno
+= readline (plb
, fi
) + 1;
2780 } /* 1 for newline. */
2783 /* Return TRUE if 'sub' exists somewhere in 's'. */
2790 while (*s
&& (s
= etags_index (s
, *sub
)))
2791 if (prestr (sub
, s
))
2798 /* Return TRUE if 'pre' is prefix of string 's'. */
2807 else if (*pre
== *s
)
2808 return (prestr (pre
+ 1, s
+ 1));
2813 /* Initialize a linebuffer for use */
2816 initbuffer (linebuffer
)
2817 struct linebuffer
*linebuffer
;
2819 linebuffer
->size
= 200;
2820 linebuffer
->buffer
= xnew (200, char);
2824 * Read a line of text from `stream' into `linebuffer'.
2825 * Return the number of characters read from `stream',
2826 * which is the length of the line including the newline, if any.
2829 readline (linebuffer
, stream
)
2830 struct linebuffer
*linebuffer
;
2831 register FILE *stream
;
2833 char *buffer
= linebuffer
->buffer
;
2834 register char *p
= linebuffer
->buffer
;
2835 register char *pend
;
2836 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2838 pend
= p
+ linebuffer
->size
; /* Separate to avoind 386/IX compiler bug. */
2842 register int c
= getc (stream
);
2845 linebuffer
->size
*= 2;
2846 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
2847 p
+= buffer
- linebuffer
->buffer
;
2848 pend
= buffer
+ linebuffer
->size
;
2849 linebuffer
->buffer
= buffer
;
2851 if (c
< 0 || c
== '\n')
2854 newline
= (c
== '\n' ? 1 : 0);
2860 return p
- buffer
+ newline
;
2867 return savenstr (cp
, strlen (cp
));
2877 dp
= xnew (len
+ 1, char);
2878 (void) strncpy (dp
, cp
, len
);
2884 * Return the ptr in sp at which the character c last
2885 * appears; NULL if not found
2887 * Identical to v7 rindex, included for portability.
2891 etags_rindex (sp
, c
)
2892 register char *sp
, c
;
2907 * Return the ptr in sp at which the character c first
2908 * appears; NULL if not found
2910 * Identical to v7 index, included for portability.
2915 register char *sp
, c
;
2925 /* Print error message and exit. */
2936 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
2943 fprintf (stderr
, "%s: ", progname
);
2944 fprintf (stderr
, s1
, s2
);
2945 fprintf (stderr
, "\n");
2948 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
2954 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
2955 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
2957 (void) strcpy (result
, s1
);
2958 (void) strcpy (result
+ len1
, s2
);
2959 (void) strcpy (result
+ len1
+ len2
, s3
);
2960 *(result
+ len1
+ len2
+ len3
) = 0;
2965 /* Like malloc but get fatal error if memory is exhausted. */
2971 char *result
= malloc (size
);
2973 fatal ("virtual memory exhausted", 0);
2978 xrealloc (ptr
, size
)
2982 char *result
= realloc (ptr
, size
);
2984 fatal ("virtual memory exhausted");