1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 1987, 1988, 1989, 1992 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 * long GET_COOKIE (pos)
90 * returns ftell () cookie.
91 * void SET_FILEPOS (pos, fp, charno)
92 * FILE *fp; long charno;
93 * sets `pos' from the current file
94 * position of `fp' and from `charno',
95 * which must be the absolute character
96 * number corresponding to the current
99 * The `pos' parameter is an lvalue expression of type FILEPOS.
100 * Parameters to the accessor functions are evaluated 0 or more times,
101 * and so must have no side effects.
103 * FILEPOS objects can also be assigned and passed to and from
104 * functions in the normal C manner.
106 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
115 #define GET_CHARNO(pos) ((pos).charno + 0)
116 #define GET_COOKIE(pos) ((pos).cookie + 0)
117 #define SET_FILEPOS(pos, fp, cno) \
118 ((void) ((pos).cookie = ftell (fp), (pos).charno = (cno)))
121 /* UNIX real implementation */
122 typedef long FILEPOS
;
123 #define GET_CHARNO(pos) ((pos) + 0)
124 #define GET_COOKIE(pos) GET_CHARNO (pos)
125 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
127 /* UNIX debugging implementation */
133 #define GET_CHARNO(pos) ((pos).charno + 0)
134 #define GET_COOKIE(pos) GET_CHARNO (pos)
135 #define SET_FILEPOS(pos, fp, cno) \
136 ((void) ((pos).charno = (cno), \
137 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
142 #define streq(s, t) (strcmp (s, t) == 0)
143 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
150 #define iswhite(arg) (_wht[arg]) /* T if char is white */
151 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
152 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
153 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
154 #define isgood(arg) (_gd[arg]) /* T if char can be after ')' */
156 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
159 { /* sorting structure */
160 char *name
; /* function or type name */
161 char *file
; /* file name */
162 logical is_func
; /* use pattern or line no */
163 logical rewritten
; /* list name separately */
164 logical been_warned
; /* set if noticed dup */
165 int lno
; /* line number tag is on */
166 long cno
; /* character number line starts on */
167 char *pat
; /* search pattern */
168 struct nd_st
*left
, *right
; /* left and right sons */
172 typedef struct nd_st NODE
;
174 logical gotone
, /* found a func already on line */
175 /* boolean "func" (see init) */
176 header_file
, /* TRUE if .h file, FALSE o.w. */
177 _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177], _gd
[0177];
187 int total_size_of_entries ();
188 logical
consider_token ();
196 void Scheme_funcs ();
201 void find_entries ();
209 void process_file ();
215 * xnew -- allocate storage
218 * Type *xnew (int n, Type);
220 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
225 * Symbol table stuff.
227 * Should probably be implemented with hash table; linked list for now.
232 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
240 struct stab_entry
*next
;
243 typedef struct stab_entry Stab_entry
;
244 typedef Stab_entry
*Stab
;
248 * Stab, Stab_entry, stab_create, stab_search, stab_find -- symbol table
251 * Types: Stab, Stab_entry, enum sym_type
253 * Stab * stab_create ()
255 * Stab_entry * stab_find (stab, sym)
259 * Stab_entry * stab_search (stab, sym)
264 * stab_create creates a Stab, a symbol table object, and returns a
265 * pointer to it. stab_find finds a symbol in a Stab; it returns a
266 * pointer to the Stab_entry if found, otherwise NULL. stab_search
267 * is like stab_find, except that it creates a new Stab_entry,
268 * initialized with type = st_none, if one did not exist already
269 * (it never returns NULL).
271 * A Stab_entry is a structure that contains at least the following
274 * char *name; // must not be modified
275 * enum sym_type type; // should be set
277 * The type field is initially set to st_none; it should be set to
278 * something else by the caller of stab_search. Other possible values
279 * of an enum sym_type can be added.
287 *sp
= NULL
; /* a Stab starts out as a null Stab_entry* */
292 stab_find (stab
, sym
, symlen
)
297 register Stab_entry
*se
;
298 for (se
= *stab
; se
!= NULL
; se
= se
->next
)
300 if (se
->symlen
== symlen
&& strneq (se
->sym
, sym
, symlen
))
308 stab_search (stab
, sym
, symlen
)
313 register Stab_entry
*se
;
314 se
= stab_find (stab
, sym
, symlen
);
319 se
= xnew (1, Stab_entry
);
320 se
->sym
= savenstr (sym
, symlen
);
332 * stab_type -- type of a symbol table entry
335 * enum sym_type stab_type (Stab_entry *se);
338 * May evaluate its argument more than once.
341 #define stab_type(se) ((se)==NULL ? st_none : (se)->type)
357 /* typedefs are recognized using a simple finite automaton.
358 * tydef is its state variable.
362 none
, begin
, middle
, end
368 /* struct tags for C++ are recognized using another simple
369 * finite automaton. `structdef' is its state variable.
370 * This machinery is only invoked for C++; otherwise structdef
371 * should remain snone. However, this machinery can easily be
372 * adapted to find structure tags in normal C code.
376 snone
, /* nothing seen yet */
377 skeyseen
, /* struct-like keyword seen */
378 stagseen
, /* struct-like tag seen */
379 scolonseen
, /* colon seen after struct-like tag */
380 sinbody
/* in a class body: recognize member func defs */
382 STRUCTST structdef
= snone
;
384 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
385 * struct tag, and structkey is the preceding struct-like keyword.
388 Stab_entry
*structkey
;
391 * Yet another little state machine to deal with preprocessor lines.
395 dnone
, /* nothing seen */
396 dsharpseen
, /* '#' seen as first char on line */
397 ddefineseen
, /* '#' and 'define' seen */
398 dignorerest
/* ignore rest of line */
403 * LEVEL_OK_FOR_FUNCDEF allows C++ function definition within class body.
404 * Currently tydef and structdef stuff (typedefs and struct definitions) are
405 * only noticed when level==0, but that may change.
407 * Note that this macro may only be evaluated inside C_entries(). It is
408 * for self-documentation only.
410 #define LEVEL_OK_FOR_FUNCDEF() \
411 (level==0 || (c_ext && level==1 && structdef==sinbody))
415 * set this to TRUE, and the next token considered is called a function.
417 logical next_token_is_func
;
419 /* C extensions. Currently all listed extensions are C++ dialects, so
420 * `c_ext' is used as an abbreviation for `c_ext&C_PLPL'. If a non-C++
421 * dialect is added, this must change.
423 #define C_PLPL 0x1 /* C++ */
424 #define C_STAR 0x3 /* C* */
426 char searchar
= '/'; /* use /.../ searches */
428 LINENO lineno
; /* line number of current line */
429 long charno
; /* current character number */
430 FILEPOS linepos
; /* start of line (C only) */
431 FILEPOS prev_linepos
; /* start of previous line (C only) */
433 long linecharno
; /* charno of start of line; not used by C, but
434 * by every other language.
437 char *curfile
, /* current input file name */
438 *outfile
, /* output file */
439 *white
= " \f\t\n", /* white chars */
440 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
441 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$", /* token starting chars */
442 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789", /* valid in-token chars */
443 *notgd
= ",;"; /* non-valid after-function chars */
445 int append_to_tagfile
; /* -a: append to tags */
446 int emacs_tags_format
; /* emacs style output (no -e option any more) */
447 /* The following three default to 1 for etags, but to 0 for ctags. */
448 int typedefs
; /* -t: create tags for typedefs */
449 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
450 /* 0 struct/enum/union decls, and C++ */
451 /* member functions */
452 int constantypedefs
; /* -d: create tags for C #define and enum */
453 /* constants. Default under etags. Enum */
454 /* constants not implemented. */
455 /* -D: opposite of -d. Default under ctags. */
456 int update
; /* -u: update tags */
457 int vgrind_style
; /* -v: create vgrind style index output */
458 int no_warnings
; /* -w: suppress warnings */
459 int cxref_style
; /* -x: create cxref style output */
460 int cplusplus
; /* .[hc] means C++, not C */
461 int noindentypedefs
; /* -S: ignore indentation in C */
463 /* Name this program was invoked with. */
466 struct option longopts
[] = {
467 { "append", no_argument
, NULL
, 'a' },
468 { "backward-search", no_argument
, NULL
, 'B' },
469 { "c++", no_argument
, NULL
, 'C' },
470 { "cxref", no_argument
, NULL
, 'x' },
471 { "defines", no_argument
, NULL
, 'd' },
472 { "forward-search", no_argument
, NULL
, 'F' },
473 { "help", no_argument
, NULL
, 'H' },
474 { "ignore-indentation", no_argument
, NULL
, 'S' },
475 { "include", required_argument
, NULL
, 'i' },
476 { "no-defines", no_argument
, NULL
, 'D' },
477 { "no-warn", no_argument
, NULL
, 'w' },
478 { "output", required_argument
, NULL
, 'o' },
479 { "typedefs", no_argument
, NULL
, 't' },
480 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
481 { "update", no_argument
, NULL
, 'u' },
482 { "version", no_argument
, NULL
, 'V' },
483 { "vgrind", no_argument
, NULL
, 'v' },
487 FILE *inf
, /* ioptr for current input file */
488 *outf
; /* ioptr for tags file */
490 NODE
*head
; /* the head of the binary tree of tags */
492 int permit_duplicates
= 1; /* Nonzero means allow duplicate tags. */
494 /* A `struct linebuffer' is a structure which holds a line of text.
495 `readline' reads a line from a stream into a linebuffer
496 and works regardless of the length of the line. */
504 struct linebuffer lb
; /* the current line */
505 struct linebuffer lb1
; /* sometimes, a previous line in which a token lies */
506 struct linebuffer filename_lb
; /* used to read in filenames */
521 printf ("for Emacs version 19.0.\n");
529 printf ("These are the options accepted by %s. You may use unambiguous\n\
530 abbreviations for the long option names.\n\n", progname
);
534 Append tag entries to existing tags file.\n\
536 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
537 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
538 extensions are always assumed to be C++ code.\n\
540 Create tag entries for #defines, too.", stdout
);
543 fputs (" This is the default\n\
549 Don't create tag entries for #defines.", stdout
);
552 fputs (" This is the default\n\
557 -o FILE, --output=FILE\n\
558 Write the tags to FILE.\n\
559 -S, --ignore-indentation\n\
560 Don't rely on indentation quite as much as normal. Currently,\n\
561 this means not to assume that a closing brace in the first\n\
562 column is the final brace of a function or structure\n\
565 Generate tag entries for typedefs. This is the default\n\
567 -T, --typedefs-and-c++\n\
568 Generate tag entries for typedefs, struct/enum/union tags, and\n\
569 C++ member functions.");
572 puts ("-i FILE, --include=FILE\n\
573 Include a note in tag file indicating that, when searching for\n\
574 a tag, one should also consult the tags file FILE after\n\
575 checking the current file.");
579 puts ("-B, --backward-search\n\
580 Write the search commands for the tag entries using '?', the\n\
581 backward-search command.\n\
582 -F, --forward-search\n\
583 Write the search commands for the tag entries using '/', the\n\
584 forward-search command.\n\
586 Update the tag entries for the given files, leaving tag\n\
587 entries for other files in place. Currently, this is\n\
588 implemented by deleting the existing entries for the given\n\
589 files and then rewriting the new entries at the end of the\n\
590 tags file. It is often faster to simply rebuild the entire\n\
591 tag file than to use this.\n\
593 Generates an index of items intended for human consumption,\n\
594 similar to the output of vgrind. The index is sorted, and\n\
595 gives the page number of each item.\n\
597 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
598 The output uses line numbers instead of page numbers, but\n\
599 beyond that the differences are cosmetic; try both to see\n\
602 Suppress warning messages about entries defined in multiple\n\
606 puts ("-V, --version\n\
607 Print the version of the program.\n\
609 Print this help message.");
622 unsigned int nincluded_files
= 0;
623 char **included_files
= (char **) alloca (argc
* sizeof (char *));
628 extern char *gfnames ();
629 extern char *massage_name ();
635 emacs_tags_format
= 1;
637 emacs_tags_format
= 0;
641 * If etags, always find typedefs and structure tags. Why not?
642 * Also default is to find macro constants.
644 if (emacs_tags_format
)
645 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
650 opt
= getopt_long (argc
, argv
, "aCdDo:StTi:BFuvxwVH", longopts
, 0);
658 /* If getopt returns '\0', then it has already processed a
659 long-named option. We should do nothing. */
662 /* Common options. */
679 "%s: -o flag may only be given once\n", progname
);
692 typedefs_and_cplusplus
++;
703 if (!emacs_tags_format
)
705 included_files
[nincluded_files
++] = optarg
;
711 if (emacs_tags_format
)
716 if (emacs_tags_format
)
721 if (emacs_tags_format
)
729 if (emacs_tags_format
)
734 if (emacs_tags_format
)
745 fprintf (stderr
, "%s: No input files specified.\n", progname
);
748 fprintf (stderr
, "%s: Try '%s --help' for a complete list of options.\n",
755 outfile
= emacs_tags_format
? "TAGS" : "tags";
758 init (); /* set up boolean "functions" */
762 initbuffer (&filename_lb
);
764 * loop through files finding functions
766 if (emacs_tags_format
)
768 if (streq (outfile
, "-"))
771 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
782 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
786 error ("Can't find file %s\n", this_file
);
791 this_file
= massage_name (this_file
);
794 } /* solely to balance out the ifdef'd parens above */
797 for (; optind
< argc
; optind
++)
799 this_file
= argv
[optind
];
803 /* Input file named "-" means read file names from stdin
805 if (streq (this_file
, "-"))
807 while (!feof (stdin
))
809 (void) readline (&filename_lb
, stdin
);
810 if (strlen (filename_lb
.buffer
) > 0)
811 process_file (filename_lb
.buffer
);
815 process_file (this_file
);
819 if (emacs_tags_format
)
821 while (nincluded_files
-- > 0)
822 fprintf (outf
, "\f\n%s,include\n", *included_files
++);
824 (void) fclose (outf
);
835 /* update cannot be set under VMS, so we may assume that argc
836 and argv have not been munged. */
837 for (i
= optind
; i
< argc
; i
++)
840 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
841 outfile
, argv
[i
], outfile
);
846 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
853 (void) fclose (outf
);
856 sprintf (cmd
, "sort %s -o %s", outfile
, outfile
);
864 * This routine is called on each file argument.
870 struct stat stat_buf
;
872 stat (file
, &stat_buf
);
873 if (!(stat_buf
.st_mode
& S_IFREG
)
875 || !(stat_buf
.st_mode
& S_IFLNK
)
879 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
883 if (streq (file
, outfile
) && !streq (outfile
, "-"))
885 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
888 if (emacs_tags_format
)
890 char *cp
= etags_rindex (file
, '/');
897 if (emacs_tags_format
)
899 fprintf (outf
, "\f\n%s,%d\n",
900 file
, total_size_of_entries (head
));
908 * This routine sets up the boolean psuedo-functions which work
909 * by setting boolean flags dependent upon the corresponding character
910 * Every char which is NOT in that string is not a white char. Therefore,
911 * all of the array "_wht" is set to FALSE, and then the elements
912 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
913 * of a char is TRUE if it is the string "white", else FALSE.
921 for (i
= 0; i
< 0177; i
++)
923 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
926 for (sp
= white
; *sp
; sp
++)
928 for (sp
= endtk
; *sp
; sp
++)
930 for (sp
= intk
; *sp
; sp
++)
932 for (sp
= begtk
; *sp
; sp
++)
934 for (sp
= notgd
; *sp
; sp
++)
936 _wht
[0] = _wht
['\n'];
937 _etk
[0] = _etk
['\n'];
938 _btk
[0] = _btk
['\n'];
939 _itk
[0] = _itk
['\n'];
944 * This routine opens the specified file and calls the function
945 * which finds the function and type definitions.
952 void prolog_funcs ();
954 inf
= fopen (file
, "r");
960 curfile
= savestr (file
);
961 cp
= etags_rindex (file
, '.');
963 header_file
= (cp
&& (streq (cp
+ 1, "h")));
965 /* .tex, .aux or .bbl implies LaTeX source code */
966 if (cp
&& (streq (cp
+ 1, "tex") || streq (cp
+ 1, "aux")
967 || streq (cp
+ 1, "bbl")))
970 goto close_and_return
;
972 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
973 if (cp
&& (streq (cp
+ 1, "l")
974 || streq (cp
+ 1, "el")
975 || streq (cp
+ 1, "lsp")
976 || streq (cp
+ 1, "lisp")
977 || streq (cp
+ 1, "cl")
978 || streq (cp
+ 1, "clisp")))
981 goto close_and_return
;
983 /* .scm or .sm or .scheme or ... implies scheme source code */
984 if (cp
&& (streq (cp
+ 1, "sm")
985 || streq (cp
+ 1, "scm")
986 || streq (cp
+ 1, "scheme")
987 || streq (cp
+ 1, "t")
988 || streq (cp
+ 1, "sch")
989 || streq (cp
+ 1, "SM")
990 || streq (cp
+ 1, "SCM")
991 /* The `SCM' or `scm' prefix with a version number */
992 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
993 && string_numeric_p (cp
+ 1))
994 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
995 && string_numeric_p (cp
+ 1))))
1001 /* Assume that ".s" or ".a" is assembly code. -wolfgang. */
1002 if (cp
&& (cp
[1] == 's' || cp
[1] == 'a') && cp
[2] == '\0')
1008 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
1009 if (cp
&& (streq (cp
+ 1, "C")
1010 || streq (cp
+ 1, "H")
1011 || streq (cp
+ 1, "cxx")
1012 || streq (cp
+ 1, "hxx")
1013 || streq (cp
+ 1, "cc")))
1015 C_entries (C_PLPL
); /* C++ */
1016 goto close_and_return
;
1018 /* .cs or .hs: a C* file */
1019 if (cp
&& (cp
[1] == 'c' || cp
[1] == 'h') && cp
[2] == 's' && cp
[3] == '\0')
1022 goto close_and_return
;
1024 /* .pl implies prolog source code */
1025 if (cp
&& !strcmp (cp
+ 1, "pl"))
1028 goto close_and_return
;
1030 /* .p or .pas: a Pascal file */
1031 if (cp
&& (streq (cp
+ 1, "p")
1032 || streq (cp
+ 1, "pas")))
1035 goto close_and_return
;
1037 /* If .f or .for, assume it is fortran or nothing. */
1038 if (cp
&& (streq (cp
+ 1, "f") || streq (cp
+ 1, "for")))
1041 goto close_and_return
;
1043 /* if not a .c or .h or .y file, try fortran */
1044 if (cp
&& ((cp
[1] != 'c'
1047 || (cp
[1] != 0 && cp
[2] != 0)))
1049 if (PF_funcs (inf
) != 0)
1050 goto close_and_return
;
1051 rewind (inf
); /* no fortran tags found, try C */
1053 C_entries (cplusplus
? C_PLPL
: 0);
1056 (void) fclose (inf
);
1059 /* Nonzero if string STR is composed of digits. */
1062 string_numeric_p (str
)
1067 if (*str
< '0' || *str
> '9')
1074 /* Should take a TOKEN* instead!! */
1077 pfnote (name
, is_func
, rewritten
, linestart
, linelen
, lno
, cno
)
1078 char *name
; /* tag name */
1079 logical is_func
; /* function or type name? */
1080 logical rewritten
; /* tag different from text of definition? */
1091 np
= (NODE
*) malloc (sizeof (NODE
));
1094 if (!emacs_tags_format
)
1096 /* It's okay to output early in etags -- it only disrupts the
1097 * character count of the tag entries, which is no longer used
1098 * by tags.el anyway.
1100 error ("too many entries to sort");
1105 np
= xnew (1, NODE
);
1107 /* If ctags mode, change name "main" to M<thisfilename>. */
1108 if (!emacs_tags_format
&& !cxref_style
&& streq (name
, "main"))
1110 fp
= etags_rindex (curfile
, '/');
1111 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
1112 fp
= etags_rindex (name
, '.');
1113 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
1117 np
->name
= savestr (name
);
1119 np
->is_func
= is_func
;
1120 np
->rewritten
= rewritten
;
1122 /* UNCOMMENT THE +1 HERE: */
1123 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
1124 np
->left
= np
->right
= 0;
1125 if (emacs_tags_format
)
1127 c
= linestart
[linelen
];
1128 linestart
[linelen
] = 0;
1130 else if (cxref_style
== 0)
1132 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
1135 np
->pat
= savestr (linestart
);
1136 if (emacs_tags_format
)
1138 linestart
[linelen
] = c
;
1141 add_node (np
, &head
);
1146 * recurse on left children, iterate on right children.
1150 register NODE
*node
;
1154 register NODE
*node_right
= node
->right
;
1155 free_tree (node
->left
);
1158 free ((char *) node
);
1165 * Adds a node to the tree of nodes. In etags mode, we don't keep
1166 * it sorted; we just keep a linear list. In ctags mode, maintain
1167 * an ordered tree, with no attempt at balancing.
1169 * add_node is the only function allowed to add nodes, so it can
1173 add_node (node
, cur_node_p
)
1174 NODE
*node
, **cur_node_p
;
1177 register NODE
*cur_node
= *cur_node_p
;
1178 static NODE
*last_node
= NULL
;/* careful */
1180 if (cur_node
== NULL
)
1187 if (emacs_tags_format
)
1191 fatal ("internal error in add_node");
1192 last_node
->right
= node
;
1198 dif
= strcmp (node
->name
, cur_node
->name
);
1201 * If this tag name matches an existing one, then
1202 * do not add the node, but maybe print a warning.
1206 if (node
->file
== cur_node
->file
)
1210 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1211 node
->file
, lineno
, node
->name
);
1212 fprintf (stderr
, "Second entry ignored\n");
1216 if (!cur_node
->been_warned
&& !no_warnings
)
1219 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1220 node
->file
, cur_node
->file
, node
->name
);
1222 cur_node
->been_warned
= TRUE
;
1226 /* Maybe refuse to add duplicate nodes. */
1227 if (!permit_duplicates
)
1229 if (!strcmp (node
->name
, cur_node
->name
)
1230 && !strcmp (node
->file
, cur_node
->file
))
1234 /* Actually add the node */
1235 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1248 /* Output subentries that precede this one */
1249 put_entries (node
->left
);
1251 /* Output this entry */
1253 if (emacs_tags_format
)
1255 if (node
->rewritten
)
1257 fprintf (outf
, "%s\177%s\001%d,%d\n",
1258 node
->name
, node
->pat
, node
->lno
, node
->cno
);
1262 fprintf (outf
, "%s\177%d,%d\n",
1263 node
->pat
, node
->lno
, node
->cno
);
1266 else if (!cxref_style
)
1268 fprintf (outf
, "%s\t%s\t",
1269 node
->name
, node
->file
);
1273 putc (searchar
, outf
);
1276 for (sp
= node
->pat
; *sp
; sp
++)
1278 if (*sp
== '\\' || *sp
== searchar
)
1282 putc (searchar
, outf
);
1285 { /* a typedef; text pattern inadequate */
1286 fprintf (outf
, "%d", node
->lno
);
1290 else if (vgrind_style
)
1291 fprintf (stdout
, "%s %s %d\n",
1292 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1294 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1295 node
->name
, node
->lno
, node
->file
, node
->pat
);
1297 /* Output subentries that follow this one */
1298 put_entries (node
->right
);
1301 /* Length of a number's decimal representation. */
1309 for (; num
; num
/= 10)
1315 * Return total number of characters that put_entries will output for
1316 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1317 * is set, but called only in that case. This count is irrelevant with
1318 * the new tags.el, but is still supplied for backward compatibility.
1321 total_size_of_entries (node
)
1330 for (; node
; node
= node
->right
)
1332 /* Count left subentries. */
1333 total
+= total_size_of_entries (node
->left
);
1335 /* Count this entry */
1336 total
+= strlen (node
->pat
) + 1;
1337 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1338 if (node
->rewritten
)
1339 total
+= 1 + strlen (node
->name
); /* \001name */
1346 * The C symbol tables.
1349 Stab
*C_stab
, *C_PLPL_stab
, *C_STAR_stab
;
1353 * Stab *get_C_stab (int c_ext);
1355 #define get_C_stab(c_ext) ((c_ext&C_STAR) ? C_STAR_stab : \
1356 c_ext ? C_PLPL_stab : \
1360 add_keyword (stab
, sym
, type
)
1365 stab_search (stab
, sym
, strlen (sym
))->type
= type
;
1369 C_create_stab (c_ext
)
1374 stab
= stab_create ();
1378 add_keyword (stab
, "class", st_C_struct
);
1380 add_keyword (stab
, "domain", st_C_struct
);
1381 add_keyword (stab
, "union", st_C_struct
);
1382 add_keyword (stab
, "struct", st_C_struct
);
1383 add_keyword (stab
, "enum", st_C_enum
);
1384 add_keyword (stab
, "typedef", st_C_typedef
);
1385 add_keyword (stab
, "define", st_C_define
);
1386 add_keyword (stab
, "long", st_C_typespec
);
1387 add_keyword (stab
, "short", st_C_typespec
);
1388 add_keyword (stab
, "int", st_C_typespec
);
1389 add_keyword (stab
, "char", st_C_typespec
);
1390 add_keyword (stab
, "float", st_C_typespec
);
1391 add_keyword (stab
, "double", st_C_typespec
);
1392 add_keyword (stab
, "signed", st_C_typespec
);
1393 add_keyword (stab
, "unsigned", st_C_typespec
);
1394 add_keyword (stab
, "const", st_C_typespec
);
1395 add_keyword (stab
, "volatile", st_C_typespec
);
1403 C_stab
= C_create_stab (0);
1404 C_PLPL_stab
= C_create_stab (C_PLPL
);
1405 C_STAR_stab
= C_create_stab (C_STAR
| C_PLPL
);
1410 * This routine finds functions and typedefs in C syntax and adds them
1414 #define CNL_SAVE_DEFINEDEF \
1417 prev_linepos = linepos; \
1418 SET_FILEPOS (linepos, inf, charno); \
1420 charno += readline (&lb, inf); \
1426 CNL_SAVE_DEFINEDEF; \
1427 definedef = dnone; \
1432 int c_ext
; /* extension of C? */
1434 register int c
; /* latest char read; '\0' for end of line */
1435 register int tokoff
; /* offset in line of start of latest token*/
1436 register int toklen
; /* length of latest token */
1437 register char *lp
; /* pointer one beyond the character `c' */
1438 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1439 int level
; /* current curly brace level */
1448 gotone
= midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1451 next_token_is_func
= 0;
1460 /* If we're at the end of the line, the next character is a
1461 '\0'; don't skip it, because it's the thing that tells us
1462 to read the next line. */
1473 if (c
== '*' && *lp
== '/')
1507 else if (c_ext
&& *lp
== '/')
1514 if (lp
== lb
.buffer
+ 1 && definedef
== dnone
)
1515 definedef
= dsharpseen
;
1519 * The next two are to help the strucdef state machine.
1520 * They break when they are finished, so they don't interfere
1521 * with anything else that is going on.
1524 if (structdef
== stagseen
)
1525 structdef
= scolonseen
;
1527 /* Not a struct definition when semicolon seen
1528 in non-sinbody context. */
1530 if (structdef
!= snone
&& structdef
!= sinbody
)
1533 (void) strcpy (structtag
, "<error 1>");
1544 case skeyseen
: /* unnamed struct */
1545 structtag
[0] = '\0';
1548 case scolonseen
: /* named struct */
1549 structdef
= sinbody
;
1555 if (!noindentypedefs
&& lp
== lb
.buffer
+ 1)
1556 level
= 0; /* reset level if first column */
1559 if (level
== 0 && tydef
== middle
)
1566 (void) strcpy (structtag
, "<error 2>");
1570 if (LEVEL_OK_FOR_FUNCDEF () && !inquote
&& !incomm
&& gotone
== FALSE
)
1576 if (c_ext
&& c
== ':' && *lp
== ':' && intoken (*(lp
+ 1)))
1579 * This handles :: in the middle, but not at beginning
1587 /* The following is no longer true,
1588 now that we advance to the next line
1589 at the end of processing the character. */
1591 * We've just finished lexing an identifier.
1592 * Note that if `c' is '\0', `lb' is the NEXT
1593 * line, `lp' points to the beginning of it, and
1594 * old pointers into `lb.buffer' may no longer be
1595 * valid, since `lb.buffer' may have been
1596 * reallocated. In this case (which corresponds
1597 * to an identifier followed immediately by a
1598 * newline), we re-read the line into lb1.
1600 * This would be faster if the previous line's
1601 * buffer were always saved.
1606 logical bingo
, tok_at_end_of_line
;
1607 char *lp_tmp
; /* addressable */
1612 getline (GET_COOKIE (prev_linepos
));
1613 tok_linebuf
= lb1
.buffer
;
1614 tok_at_end_of_line
= TRUE
;
1615 tok
.linestart
= prev_linepos
;
1616 tok
.lineno
= lineno
- 1;
1621 tok_linebuf
= lb
.buffer
;
1622 tok_at_end_of_line
= FALSE
;
1623 tok
.linestart
= linepos
;
1624 tok
.lineno
= lineno
;
1626 tok
.p
= tok_linebuf
+ tokoff
;
1628 tok
.rewritten
= FALSE
;
1630 bingo
= consider_token (c
, &lp_tmp
, &tok
,
1631 &is_func
, c_ext
, level
);
1635 if (GET_CHARNO (tok
.linestart
) != GET_CHARNO(linepos
)
1636 && !tok_at_end_of_line
)
1639 * Resynchronize tok.p to point into the right
1642 getline (GET_COOKIE (tok
.linestart
));
1644 tok
.p
= lb1
.buffer
+ (tok
.p
- tok_linebuf
);
1645 tok_linebuf
= lb1
.buffer
;
1647 if (structdef
== sinbody
1648 && definedef
== dnone
&& is_func
)
1649 { /* function defined in C++ class body */
1650 sprintf (tokb
, "%s::%.*s",
1651 structtag
[0] == '\0' ? "_anonymous_"
1654 tok
.rewritten
= TRUE
;
1658 sprintf (tokb
, "%.*s", tok
.len
, tok
.p
);
1660 pfnote (tokb
, is_func
, tok
.rewritten
, tok_linebuf
,
1661 tokoff
+ toklen
+ (tok_at_end_of_line
? 0 : 1),
1662 tok
.lineno
, GET_CHARNO (tok
.linestart
));
1663 gotone
= is_func
; /* function */
1668 else if (intoken (c
))
1671 else if (begtoken (c
))
1673 tokoff
= lp
- 1 - lb
.buffer
;
1678 /* Detect end of line, having handled the last token on the line. */
1681 if (incomm
|| inquote
|| quotednl
)
1691 if (c
== ';' && tydef
== end
) /* clean with typedefs */
1698 * checks to see if the current token is at the start of a
1699 * function, or corresponds to a typedef. It updates the input
1700 * line pointer *LPP so that the '(' will be in it when it returns.
1702 * *IS_FUNC gets TRUE iff the token is a function.
1703 * C_EXT is which language we are looking at.
1705 * In the future we will need some way to adjust where the end of
1706 * the token is; for instance, implementing the C++ keyword
1707 * `operator' properly will adjust the end of the token to be after
1708 * whatever follows `operator'.
1717 consider_token (c
, lpp
, tokp
, is_func
, c_ext
, level
)
1718 reg
char c
; /* IN: first char after the token */
1719 char **lpp
; /* IN OUT: *lpp points
1720 to 2nd char after the token */
1721 reg TOKEN
*tokp
; /* IN */
1722 logical
*is_func
; /* OUT */
1726 reg
char *lp
= *lpp
;
1727 logical firsttok
; /* TRUE if have seen first token in ()'s */
1728 Stab_entry
*tokse
= stab_find (get_C_stab (c_ext
), tokp
->p
, tokp
->len
);
1729 enum sym_type toktype
= stab_type (tokse
);
1731 *is_func
= TRUE
; /* a function */
1734 * Advance the definedef state machine. We set `gotone' for good measure;
1740 /* We're not on a preprocessor line. */
1743 if (toktype
== st_C_define
)
1745 definedef
= ddefineseen
;
1750 definedef
= dignorerest
;
1756 * Make a tag for any macro.
1757 * This will flub up if there is a newline immediately following
1760 *is_func
= (c
== '(');
1761 definedef
= dignorerest
;
1763 if (!*is_func
&& !constantypedefs
)
1769 error ("internal error: definedef value");
1773 * Skip whitespace and comments after the token. This loop should
1774 * also skip C++ comments.
1778 /* At whitespace => skip it. */
1783 /* At a comment => skip to end of comment. */
1784 else if (c
== '/' && *lp
== '*')
1786 /* If we find a comment, skip it. */
1787 while (!(c
== '*' && *lp
== '/'))
1796 if (c
== '*' && *lp
== '/')
1798 lp
++; /* lp now points past the '/' */
1799 c
= *lp
++; /* c is now the --whatever-- after the '/' */
1805 /* If we arrived at eof or eol, decide which one it is.
1806 If it's eol, advance to the next line. */
1816 * If you have custom token types, or when configuration files can
1817 * define custom token types, this switch will be larger.
1829 if (tydef
== begin
|| tydef
== end
)
1838 * This structdef business is currently only invoked when level==0.
1839 * It should be recursively invoked whatever the level, and a stack of
1840 * states kept, to allow for definitions of structs within structs.
1842 * This structdef business is NOT invoked when we are ctags and the
1843 * file is plain C. This is because a struct tag may have the same
1844 * name as another tag, and this loses with ctags.
1846 * This if statement deals with the tydef state machine as follows: if
1847 * tydef==begin and token is struct/union/class/enum, goto badone.
1848 * All the other code here is for the structdef state machine.
1855 || (typedefs_and_cplusplus
&& level
== 0 && structdef
== snone
))
1857 structdef
= skeyseen
;
1863 if (structdef
== skeyseen
)
1865 /* If next char is '{' or (for C++) ':', found a structure tag. */
1866 if (c
== '{' || (c_ext
&& c
== ':'))
1869 * We should do this slightly differently for straight C:
1870 * instead of defining `tag', as we now do, we should define
1871 * `struct tag'. (Do this only if the find-tag defaulting is
1872 * done on a sophisticated per-mode basis, so that if the user
1873 * says meta-. anywhere in `struct foo', the default comes out
1874 * `struct foo', not `struct' or `foo'.) This will require
1875 * remembering which keyword (struct/union/class/enum) we saw, as a
1876 * Stab_entry* -- this will also make it possible to merge the
1877 * skeyseen and senumseen states, if we want.
1879 if (stab_type (structkey
) == st_C_struct
)
1881 (void) strncpy (structtag
, tokp
->p
, tokp
->len
);
1882 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1883 structdef
= stagseen
;
1887 structtag
[0] = '\0'; /* for enum */
1889 *is_func
= FALSE
; /* not a function */
1894 /* Not a definition: reset structdef */
1896 (void) strcpy (structtag
, "<error 3>");
1898 /* Now what? And how does/should this stuff interact with tydef?? */
1899 /* Also maybe reset lp to *lpp for sake of function-finding code. */
1911 /* Detect GNUmacs's function-defining macros. */
1912 if (definedef
== dnone
)
1914 if (strneq (tokp
->p
, "DEF", 3)
1915 || strneq (tokp
->p
, "ENTRY", 5)
1916 || strneq (tokp
->p
, "SYSCALL", 7)
1917 || strneq (tokp
->p
, "PSEUDO", 6))
1919 next_token_is_func
= TRUE
;
1922 else if (strneq (tokp
->p
, "EXFUN", 5))
1924 next_token_is_func
= FALSE
;
1928 if (next_token_is_func
)
1930 next_token_is_func
= FALSE
;
1936 while ((c
= *lp
++) != ')')
1944 * This line used to confuse ctags:
1946 * This fixes it. A nonwhite char before the first
1947 * token, other than a / (in case of a comment in there)
1948 * makes this not a declaration.
1950 if (begtoken (c
) || c
== '/')
1952 else if (!iswhite (c
) && !firsttok
)
1955 while (iswhite (c
= *lp
++))
1979 long saveftell
= ftell (inf
);
1981 (void) fseek (inf
, atcookie
, 0);
1982 (void) readline (&lb1
, inf
);
1983 (void) fseek (inf
, saveftell
, 0);
1986 /* Fortran parsing */
2002 linecharno
= charno
;
2003 charno
+= readline (&lb
, fi
);
2006 dbp
++; /* Ratfor escape to fortran */
2007 while (isspace (*dbp
))
2014 if (tail ("integer"))
2022 if (tail ("logical"))
2026 if (tail ("complex") || tail ("character"))
2030 if (tail ("double"))
2032 while (isspace (*dbp
))
2036 if (tail ("precision"))
2042 while (isspace (*dbp
))
2049 if (tail ("function"))
2053 if (tail ("subroutine"))
2061 if (tail ("program"))
2066 if (tail ("procedure"))
2078 register int len
= 0;
2080 while (*cp
&& (*cp
& ~' ') == ((*(dbp
+ len
)) & ~' '))
2093 while (isspace (*dbp
))
2098 while (isspace (*dbp
))
2100 if (!isdigit (*dbp
))
2102 --dbp
; /* force failure */
2107 while (isdigit (*dbp
));
2115 char nambuf
[BUFSIZ
];
2117 while (isspace (*dbp
))
2124 for (cp
= dbp
+ 1; *cp
&& (isalpha (*cp
) || isdigit (*cp
)
2125 || (*cp
== '_') || (*cp
== '$')); cp
++)
2129 (void) strcpy (nambuf
, dbp
);
2131 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2135 /* Handle a file of assembler code. */
2151 linecharno
= charno
;
2152 charno
+= readline (&lb
, fi
);
2155 for (i
= 0; ((c
= dbp
[i
]) && !isspace (c
)) && (c
!= ':'); i
++)
2158 if ((i
> 0) && (c
== ':'))
2163 /* Added by Mosur Mohan, 4/22/88 */
2164 /* Pascal parsing */
2166 #define GET_NEW_LINE \
2168 linecharno = charno; lineno++; \
2169 charno += 1 + readline (&lb, inf); \
2173 /* Locates tags for procedures & functions.
2174 * Doesn't do any type- or var-definitions.
2175 * It does look for the keyword "extern" or "forward"
2176 * immediately following the procedure statement;
2177 * if found, the tag is skipped.
2184 struct linebuffer tline
; /* mostly copied from C_entries */
2188 char nambuf
[BUFSIZ
];
2190 logical
/* each of these flags is TRUE iff: */
2191 incomm1
, /* point is inside {..} comment */
2192 incomm2
, /* point is inside (*..*) comment */
2193 inquote
, /* point is inside '..' string */
2194 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2195 /* keyword, so next item = potential tag */
2196 found_tag
, /* point is after a potential tag */
2197 inparms
, /* point is within parameter-list */
2198 verify_tag
; /* point has passed the parm-list, so the */
2199 /* next token will determine whether */
2200 /* this is a FORWARD/EXTERN to be */
2201 /* ignored, or whether it is a real tag */
2207 initbuffer (&tline
);
2209 incomm1
= incomm2
= inquote
= FALSE
;
2210 found_tag
= FALSE
; /* have a proc name; check if extern */
2211 get_tagname
= FALSE
; /* have found "procedure" keyword */
2212 inparms
= FALSE
; /* found '(' after "proc" */
2213 verify_tag
= FALSE
; /* check if "extern" is ahead */
2215 /* long main loop to get next char */
2219 if (c
== 0) /* if end of line */
2224 if (!((found_tag
&& verify_tag
) ||
2226 c
= *dbp
++; /* only if don't need *dbp pointing */
2227 /* to the beginning of the name of */
2228 /* the procedure or function */
2230 if (incomm1
) /* within { - } comments */
2236 else if (incomm2
) /* within (* - *) comments */
2240 while ((c
= *dbp
++) == '*')
2259 inquote
= TRUE
; /* found first quote */
2261 case '{': /* found open-{-comment */
2265 if (*dbp
== '*') /* found open-(*-comment */
2270 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2273 case ')': /* end of parms list */
2278 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2285 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2287 /* check if this is an "extern" declaration */
2290 if ((*dbp
== 'e') || (*dbp
== 'E'))
2292 if (tail ("extern")) /* superfluous, really! */
2298 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2300 if (tail ("forward")) /* check for forward reference */
2306 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2310 pfnote (nambuf
, TRUE
, FALSE
,
2311 tline
.buffer
, cp
- tline
.buffer
+ 1,
2312 save_lineno
, save_lcno
);
2316 if (get_tagname
) /* grab name of proc or fn */
2321 /* save all values for later tagging */
2322 tline
.size
= lb
.size
;
2323 strcpy (tline
.buffer
, lb
.buffer
);
2324 save_lineno
= lineno
;
2325 save_lcno
= linecharno
;
2327 /* grab block name */
2328 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2332 strcpy (nambuf
, dbp
);
2334 dbp
= cp
; /* restore dbp to e-o-token */
2335 get_tagname
= FALSE
;
2339 /* and proceed to check for "extern" */
2341 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2342 (!found_tag
) && (!get_tagname
))
2344 /* check for proc/fn keywords */
2348 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2352 if (tail ("unction"))
2357 } /* while not e-o-f */
2361 * lisp tag functions
2362 * just look for (def or (DEF
2376 linecharno
= charno
;
2377 charno
+= readline (&lb
, fi
);
2383 while (!isspace (*dbp
))
2385 while (isspace (*dbp
))
2391 /* Check for (foo::defmumble name-defined ... */
2392 while (*dbp
&& *dbp
!= ':' && !isspace (*dbp
)
2393 && *dbp
!= '(' && *dbp
!= ')')
2402 while (!isspace (*dbp
))
2404 while (isspace (*dbp
))
2418 return ((dbp
[1] == 'D' || dbp
[1] == 'd') &&
2419 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2420 (dbp
[3] == 'F' || dbp
[3] == 'f'));
2428 char nambuf
[BUFSIZ
];
2432 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ' '; cp
++)
2436 (void) strcpy (nambuf
, dbp
);
2438 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2443 * Scheme tag functions
2444 * look for (def... xyzzy
2445 * look for (def... (xyzzy
2446 * look for (def ... ((...(xyzzy ....
2447 * look for (set! xyzzy
2450 static void get_scheme ();
2463 linecharno
= charno
;
2464 charno
+= readline (&lb
, fi
);
2466 if (dbp
[0] == '(' &&
2467 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2468 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2469 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2471 while (!isspace (*dbp
))
2473 /* Skip over open parens and white space */
2474 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2478 if (dbp
[0] == '(' &&
2479 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2480 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2481 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2482 (dbp
[4] == '!' || dbp
[4] == '!') &&
2485 while (!isspace (*dbp
))
2487 /* Skip over white space */
2488 while (isspace (*dbp
))
2500 char nambuf
[BUFSIZ
];
2504 /* Go till you get to white space or a syntactic break */
2505 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2507 /* Null terminate the string there. */
2510 /* Copy the string */
2511 strcpy (nambuf
, dbp
);
2512 /* Unterminate the string */
2514 /* Announce the change */
2515 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2519 /* Find tags in TeX and LaTeX input files. */
2521 /* TEX_toktab is a table of TeX control sequences that define tags.
2522 Each TEX_tabent records one such control sequence.
2523 CONVERT THIS TO USE THE Stab TYPE!! */
2531 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2533 /* Default set of control sequences to put into TEX_toktab.
2534 The value of environment var TEXTAGS is prepended to this. */
2536 static char *TEX_defenv
=
2537 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2540 struct TEX_tabent
*TEX_decode_env ();
2544 static char TEX_esc
= '\\';
2545 static char TEX_opgrp
= '{';
2546 static char TEX_clgrp
= '}';
2549 * TeX/LaTeX scanning loop.
2562 /* Select either \ or ! as escape character. */
2565 /* Initialize token table once from environment. */
2567 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2570 { /* Scan each line in file */
2572 linecharno
= charno
;
2573 charno
+= readline (&lb
, fi
);
2576 while (dbp
= etags_index (dbp
, TEX_esc
)) /* Look at each escape in line */
2582 linecharno
+= dbp
- lasthit
;
2584 i
= TEX_Token (lasthit
);
2587 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2588 break; /* We only save a line once */
2594 #define TEX_LESC '\\'
2595 #define TEX_SESC '!'
2598 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2599 /* chars accordingly. */
2607 while ((c
= getc (f
)) != EOF
)
2609 /* Skip to next line if we hit the TeX comment char. */
2613 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2632 /* Read environment and prepend it to the default string. */
2633 /* Build token table. */
2636 TEX_decode_env (evarname
, defenv
)
2640 register char *env
, *p
;
2642 struct TEX_tabent
*tab
;
2645 /* Append default string to environment. */
2646 env
= getenv (evarname
);
2650 env
= concat (env
, defenv
, "");
2652 /* Allocate a token table */
2653 for (size
= 1, p
= env
; p
;)
2654 if ((p
= etags_index (p
, ':')) && *(++p
))
2656 /* Add 1 to leave room for null terminator. */
2657 tab
= xnew (size
+ 1, struct TEX_tabent
);
2659 /* Unpack environment string into token table. Be careful about */
2660 /* zero-length strings (leading ':', "::" and trailing ':') */
2663 p
= etags_index (env
, ':');
2664 if (!p
) /* End of environment string. */
2665 p
= env
+ strlen (env
);
2667 { /* Only non-zero strings. */
2668 tab
[i
].name
= savenstr (env
, p
- env
);
2669 tab
[i
].len
= strlen (tab
[i
].name
);
2676 tab
[i
].name
= NULL
; /* Mark end of table. */
2684 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2685 The name being defined actually starts at (NAME + LEN + 1).
2686 But we seem to include the TeX command in the tag name. */
2689 TEX_getit (name
, len
)
2693 char *p
= name
+ len
;
2694 char nambuf
[BUFSIZ
];
2699 /* Let tag name extend to next group close (or end of line) */
2700 while (*p
&& *p
!= TEX_clgrp
)
2702 (void) strncpy (nambuf
, name
, p
- name
);
2703 nambuf
[p
- name
] = 0;
2705 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2709 /* If the text at CP matches one of the tag-defining TeX command names,
2710 return the etags_index of that command in TEX_toktab.
2711 Otherwise return -1. */
2713 /* Keep the capital `T' in `Token' for dumb truncating compilers
2714 (this distinguishes it from `TEX_toktab' */
2721 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2722 if (strncmp (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
) == 0)
2727 /* Support for Prolog. */
2729 /* whole head (not only functor, but also arguments)
2730 is gotten in compound term. */
2733 prolog_getit (s
, lineno
, linecharno
)
2738 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2746 if (*s
== '\0') /* syntax error. */
2748 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2750 else if (*s
== '\'')
2752 insquote
= !insquote
;
2755 else if (!insquote
&& *s
== '(')
2760 else if (!insquote
&& *s
== ')')
2766 else if (npar
< 0) /* syntax error. */
2769 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2771 if (npar
!= 0) /* syntax error. */
2781 strcpy (nambuf
, save_s
);
2783 pfnote (nambuf
, TRUE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2786 /* It is assumed that prolog predicate starts from column 0. */
2792 void skip_comment (), prolog_getit ();
2794 lineno
= linecharno
= charno
= 0;
2798 linecharno
+= charno
;
2799 charno
= readline (&lb
, fi
) + 1; /* 1 for newline. */
2801 if (isspace (dbp
[0])) /* not predicate header. */
2803 else if (dbp
[0] == '%') /* comment. */
2805 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2806 skip_comment (&lb
, fi
, &lineno
, &linecharno
);
2808 prolog_getit (dbp
, lineno
, linecharno
);
2813 skip_comment (plb
, fi
, plineno
, plinecharno
)
2814 struct linebuffer
*plb
;
2816 int *plineno
; /* result */
2817 long *plinecharno
; /* result */
2819 while (!substr ("*/", plb
->buffer
))
2822 *plinecharno
+= readline (plb
, fi
) + 1;
2823 } /* 1 for newline. */
2826 /* Return TRUE if 'sub' exists somewhere in 's'. */
2833 while (*s
&& (s
= etags_index (s
, *sub
)))
2834 if (prestr (sub
, s
))
2841 /* Return TRUE if 'pre' is prefix of string 's'. */
2850 else if (*pre
== *s
)
2851 return (prestr (pre
+ 1, s
+ 1));
2856 /* Initialize a linebuffer for use */
2859 initbuffer (linebuffer
)
2860 struct linebuffer
*linebuffer
;
2862 linebuffer
->size
= 200;
2863 linebuffer
->buffer
= xnew (200, char);
2867 * Read a line of text from `stream' into `linebuffer'.
2868 * Return the number of characters read from `stream',
2869 * which is the length of the line including the newline, if any.
2872 readline (linebuffer
, stream
)
2873 struct linebuffer
*linebuffer
;
2874 register FILE *stream
;
2876 char *buffer
= linebuffer
->buffer
;
2877 register char *p
= linebuffer
->buffer
;
2878 register char *pend
;
2879 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2881 pend
= p
+ linebuffer
->size
; /* Separate to avoind 386/IX compiler bug. */
2885 register int c
= getc (stream
);
2888 linebuffer
->size
*= 2;
2889 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
2890 p
+= buffer
- linebuffer
->buffer
;
2891 pend
= buffer
+ linebuffer
->size
;
2892 linebuffer
->buffer
= buffer
;
2894 if (c
< 0 || c
== '\n')
2897 newline
= (c
== '\n' ? 1 : 0);
2903 return p
- buffer
+ newline
;
2910 return savenstr (cp
, strlen (cp
));
2920 dp
= xnew (len
+ 1, char);
2921 (void) strncpy (dp
, cp
, len
);
2927 * Return the ptr in sp at which the character c last
2928 * appears; NULL if not found
2930 * Identical to v7 rindex, included for portability.
2934 etags_rindex (sp
, c
)
2935 register char *sp
, c
;
2950 * Return the ptr in sp at which the character c first
2951 * appears; NULL if not found
2953 * Identical to v7 index, included for portability.
2958 register char *sp
, c
;
2968 /* Print error message and exit. */
2979 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
2986 fprintf (stderr
, "%s: ", progname
);
2987 fprintf (stderr
, s1
, s2
);
2988 fprintf (stderr
, "\n");
2991 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
2997 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
2998 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3000 (void) strcpy (result
, s1
);
3001 (void) strcpy (result
+ len1
, s2
);
3002 (void) strcpy (result
+ len1
+ len2
, s3
);
3003 *(result
+ len1
+ len2
+ len3
) = 0;
3008 /* Like malloc but get fatal error if memory is exhausted. */
3014 char *result
= malloc (size
);
3016 fatal ("virtual memory exhausted", 0);
3021 xrealloc (ptr
, size
)
3025 char *result
= realloc (ptr
, size
);
3027 fatal ("virtual memory exhausted");