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 *index (), *rindex ();
49 extern char *strcpy (), *strncpy ();
56 /* Define the symbol ETAGS to make the program "etags",
57 which makes emacs-style tag tables by default.
58 Define CTAGS to make the program "ctags" compatible with the usual one.
59 Define neither one to get behavior that depends
60 on the name with which the program is invoked
61 (but we don't normally compile it that way). */
63 #if !defined(ETAGS) && !defined(CTAGS)
64 /* If neither is defined, program can be run as either. */
69 /* On VMS, CTAGS is not useful, so always do ETAGS. */
76 /* Exit codes for success and failure. */
86 * The FILEPOS abstract type, which represents a position in a file,
87 * plus the following accessor functions:
89 * long GET_CHARNO (pos)
90 * returns absolute char number.
91 * long GET_COOKIE (pos)
92 * returns ftell () cookie.
93 * void SET_FILEPOS (pos, fp, charno)
94 * FILE *fp; long charno;
95 * sets `pos' from the current file
96 * position of `fp' and from `charno',
97 * which must be the absolute character
98 * number corresponding to the current
101 * The `pos' parameter is an lvalue expression of type FILEPOS.
102 * Parameters to the accessor functions are evaluated 0 or more times,
103 * and so must have no side effects.
105 * FILEPOS objects can also be assigned and passed to and from
106 * functions in the normal C manner.
108 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
117 #define GET_CHARNO(pos) ((pos).charno + 0)
118 #define GET_COOKIE(pos) ((pos).cookie + 0)
119 #define SET_FILEPOS(pos, fp, cno) \
120 ((void) ((pos).cookie = ftell (fp), (pos).charno = (cno)))
123 /* UNIX real implementation */
124 typedef long FILEPOS
;
125 #define GET_CHARNO(pos) ((pos) + 0)
126 #define GET_COOKIE(pos) GET_CHARNO (pos)
127 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
129 /* UNIX debugging implementation */
135 #define GET_CHARNO(pos) ((pos).charno + 0)
136 #define GET_COOKIE(pos) GET_CHARNO (pos)
137 #define SET_FILEPOS(pos, fp, cno) \
138 ((void) ((pos).charno = (cno), \
139 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
144 #define streq(s, t) (strcmp (s, t) == 0)
145 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
152 #define iswhite(arg) (_wht[arg]) /* T if char is white */
153 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
154 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
155 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
156 #define isgood(arg) (_gd[arg]) /* T if char can be after ')' */
158 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
161 { /* sorting structure */
162 char *name
; /* function or type name */
163 char *file
; /* file name */
164 logical is_func
; /* use pattern or line no */
165 logical rewritten
; /* list name separately */
166 logical been_warned
; /* set if noticed dup */
167 int lno
; /* line number tag is on */
168 long cno
; /* character number line starts on */
169 char *pat
; /* search pattern */
170 struct nd_st
*left
, *right
; /* left and right sons */
174 typedef struct nd_st NODE
;
176 logical gotone
, /* found a func already on line */
177 /* boolean "func" (see init) */
178 header_file
, /* TRUE if .h file, FALSE o.w. */
179 _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177], _gd
[0177];
189 int total_size_of_entries ();
190 logical
consider_token ();
198 void Scheme_funcs ();
203 void find_entries ();
211 void process_file ();
217 * xnew -- allocate storage
220 * Type *xnew (int n, Type);
222 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
227 * Symbol table stuff.
229 * Should probably be implemented with hash table; linked list for now.
234 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
242 struct stab_entry
*next
;
245 typedef struct stab_entry Stab_entry
;
246 typedef Stab_entry
*Stab
;
250 * Stab, Stab_entry, stab_create, stab_search, stab_find -- symbol table
253 * Types: Stab, Stab_entry, enum sym_type
255 * Stab * stab_create ()
257 * Stab_entry * stab_find (stab, sym)
261 * Stab_entry * stab_search (stab, sym)
266 * stab_create creates a Stab, a symbol table object, and returns a
267 * pointer to it. stab_find finds a symbol in a Stab; it returns a
268 * pointer to the Stab_entry if found, otherwise NULL. stab_search
269 * is like stab_find, except that it creates a new Stab_entry,
270 * initialized with type = st_none, if one did not exist already
271 * (it never returns NULL).
273 * A Stab_entry is a structure that contains at least the following
276 * char *name; // must not be modified
277 * enum sym_type type; // should be set
279 * The type field is initially set to st_none; it should be set to
280 * something else by the caller of stab_search. Other possible values
281 * of an enum sym_type can be added.
289 *sp
= NULL
; /* a Stab starts out as a null Stab_entry* */
294 stab_find (stab
, sym
, symlen
)
299 register Stab_entry
*se
;
300 for (se
= *stab
; se
!= NULL
; se
= se
->next
)
302 if (se
->symlen
== symlen
&& strneq (se
->sym
, sym
, symlen
))
310 stab_search (stab
, sym
, symlen
)
315 register Stab_entry
*se
;
316 se
= stab_find (stab
, sym
, symlen
);
321 se
= xnew (1, Stab_entry
);
322 se
->sym
= savenstr (sym
, symlen
);
334 * stab_type -- type of a symbol table entry
337 * enum sym_type stab_type (Stab_entry *se);
340 * May evaluate its argument more than once.
343 #define stab_type(se) ((se)==NULL ? st_none : (se)->type)
359 /* typedefs are recognized using a simple finite automaton.
360 * tydef is its state variable.
364 none
, begin
, middle
, end
370 /* struct tags for C++ are recognized using another simple
371 * finite automaton. `structdef' is its state variable.
372 * This machinery is only invoked for C++; otherwise structdef
373 * should remain snone. However, this machinery can easily be
374 * adapted to find structure tags in normal C code.
378 snone
, /* nothing seen yet */
379 skeyseen
, /* struct-like keyword seen */
380 stagseen
, /* struct-like tag seen */
381 scolonseen
, /* colon seen after struct-like tag */
382 sinbody
/* in a class body: recognize member func defs */
384 STRUCTST structdef
= snone
;
386 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
387 * struct tag, and structkey is the preceding struct-like keyword.
390 Stab_entry
*structkey
;
393 * Yet another little state machine to deal with preprocessor lines.
397 dnone
, /* nothing seen */
398 dsharpseen
, /* '#' seen as first char on line */
399 ddefineseen
, /* '#' and 'define' seen */
400 dignorerest
/* ignore rest of line */
405 * LEVEL_OK_FOR_FUNCDEF allows C++ function definition within class body.
406 * Currently tydef and structdef stuff (typedefs and struct definitions) are
407 * only noticed when level==0, but that may change.
409 * Note that this macro may only be evaluated inside C_entries(). It is
410 * for self-documentation only.
412 #define LEVEL_OK_FOR_FUNCDEF() \
413 (level==0 || c_ext && level==1 && structdef==sinbody)
417 * set this to TRUE, and the next token considered is called a function.
419 logical next_token_is_func
;
421 /* C extensions. Currently all listed extensions are C++ dialects, so
422 * `c_ext' is used as an abbreviation for `c_ext&C_PLPL'. If a non-C++
423 * dialect is added, this must change.
425 #define C_PLPL 0x1 /* C++ */
426 #define C_STAR 0x3 /* C* */
428 char searchar
= '/'; /* use /.../ searches */
430 LINENO lineno
; /* line number of current line */
431 long charno
; /* current character number */
432 FILEPOS linepos
; /* start of line (C only) */
433 FILEPOS prev_linepos
; /* start of previous line (C only) */
435 long linecharno
; /* charno of start of line; not used by C, but
436 * by every other language.
439 char *curfile
, /* current input file name */
440 *outfile
, /* output file */
441 *white
= " \f\t\n", /* white chars */
442 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
443 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$", /* token starting chars */
444 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789", /* valid in-token chars */
445 *notgd
= ",;"; /* non-valid after-function chars */
447 int append_to_tagfile
; /* -a: append to tags */
448 int emacs_tags_format
; /* emacs style output (no -e option any more) */
449 /* The following three default to 1 for etags, but to 0 for ctags. */
450 int typedefs
; /* -t: create tags for typedefs */
451 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
452 /* 0 struct/enum/union decls, and C++ */
453 /* member functions */
454 int constantypedefs
; /* -d: create tags for C #define and enum */
455 /* constants. Default under etags. Enum */
456 /* constants not implemented. */
457 /* -D: opposite of -d. Default under ctags. */
458 int update
; /* -u: update tags */
459 int vgrind_style
; /* -v: create vgrind style index output */
460 int no_warnings
; /* -w: suppress warnings */
461 int cxref_style
; /* -x: create cxref style output */
462 int cplusplus
; /* .[hc] means C++, not C */
463 int noindentypedefs
; /* -S: ignore indentation in C */
465 /* Name this program was invoked with. */
468 struct option longopts
[] = {
469 { "append", no_argument
, NULL
, 'a' },
470 { "backward-search", no_argument
, NULL
, 'B' },
471 { "c++", no_argument
, NULL
, 'C' },
472 { "cxref", no_argument
, NULL
, 'x' },
473 { "defines", no_argument
, NULL
, 'd' },
474 { "forward-search", no_argument
, NULL
, 'F' },
475 { "help", no_argument
, NULL
, 'H' },
476 { "ignore-indentation", no_argument
, NULL
, 'S' },
477 { "include", required_argument
, NULL
, 'i' },
478 { "no-defines", no_argument
, NULL
, 'D' },
479 { "no-warn", no_argument
, NULL
, 'w' },
480 { "output", required_argument
, NULL
, 'o' },
481 { "typedefs", no_argument
, NULL
, 't' },
482 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
483 { "update", no_argument
, NULL
, 'u' },
484 { "version", no_argument
, NULL
, 'V' },
485 { "vgrind", no_argument
, NULL
, 'v' },
489 FILE *inf
, /* ioptr for current input file */
490 *outf
; /* ioptr for tags file */
492 NODE
*head
; /* the head of the binary tree of tags */
494 int permit_duplicates
= 1; /* Nonzero means allow duplicate tags. */
496 /* A `struct linebuffer' is a structure which holds a line of text.
497 `readline' reads a line from a stream into a linebuffer
498 and works regardless of the length of the line. */
506 struct linebuffer lb
; /* the current line */
507 struct linebuffer lb1
; /* sometimes, a previous line in which a token lies */
508 struct linebuffer filename_lb
; /* used to read in filenames */
523 printf ("for Emacs version 19.0.\n");
531 printf ("These are the options accepted by %s. You may use unambiguous\n\
532 abbreviations for the long option names.\n\n", progname
);
536 Append tag entries to existing tags file.\n\
538 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
539 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
540 extensions are always assumed to be C++ code.\n\
542 Create tag entries for #defines, too.", stdout
);
545 fputs (" This is the default\n\
551 Don't create tag entries for #defines.", stdout
);
554 fputs (" This is the default\n\
559 -o FILE, --output=FILE\n\
560 Write the tags to FILE.\n\
561 -S, --ignore-indentation\n\
562 Don't rely on indentation quite as much as normal. Currently,\n\
563 this means not to assume that a closing brace in the first\n\
564 column is the final brace of a function or structure\n\
567 Generate tag entries for typedefs. This is the default\n\
569 -T, --typedefs-and-c++\n\
570 Generate tag entries for typedefs, struct/enum/union tags, and\n\
571 C++ member functions.");
574 puts ("-i FILE, --include=FILE\n\
575 Include a note in tag file indicating that, when searching for\n\
576 a tag, one should also consult the tags file FILE after\n\
577 checking the current file.");
581 puts ("-B, --backward-search\n\
582 Write the search commands for the tag entries using '?', the\n\
583 backward-search command.\n\
584 -F, --forward-search\n\
585 Write the search commands for the tag entries using '/', the\n\
586 forward-search command.\n\
588 Update the tag entries for the given files, leaving tag\n\
589 entries for other files in place. Currently, this is\n\
590 implemented by deleting the existing entries for the given\n\
591 files and then rewriting the new entries at the end of the\n\
592 tags file. It is often faster to simply rebuild the entire\n\
593 tag file than to use this.\n\
595 Generates an index of items intended for human consumption,\n\
596 similar to the output of vgrind. The index is sorted, and\n\
597 gives the page number of each item.\n\
599 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
600 The output uses line numbers instead of page numbers, but\n\
601 beyond that the differences are cosmetic; try both to see\n\
604 Suppress warning messages about entries defined in multiple\n\
608 puts ("-V, --version\n\
609 Print the version of the program.\n\
611 Print this help message.");
624 unsigned int nincluded_files
= 0;
625 char **included_files
= (char **) alloca (argc
* sizeof (char *));
630 extern char *gfnames ();
631 extern char *massage_name ();
637 emacs_tags_format
= 1;
639 emacs_tags_format
= 0;
643 * If etags, always find typedefs and structure tags. Why not?
644 * Also default is to find macro constants.
646 if (emacs_tags_format
)
647 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
652 opt
= getopt_long (argc
, argv
, "aCdDo:StTi:BFuvxwVH", longopts
, 0);
660 /* If getopt returns '\0', then it has already processed a
661 long-named option. We should do nothing. */
664 /* Common options. */
681 "%s: -o flag may only be given once\n", progname
);
694 typedefs_and_cplusplus
++;
705 if (!emacs_tags_format
)
707 included_files
[nincluded_files
++] = optarg
;
713 if (emacs_tags_format
)
718 if (emacs_tags_format
)
723 if (emacs_tags_format
)
731 if (emacs_tags_format
)
736 if (emacs_tags_format
)
747 fprintf (stderr
, "%s: No input files specified.\n", progname
);
750 fprintf (stderr
, "%s: Try '%s --help' for a complete list of options.\n",
757 outfile
= emacs_tags_format
? "TAGS" : "tags";
760 init (); /* set up boolean "functions" */
764 initbuffer (&filename_lb
);
766 * loop through files finding functions
768 if (emacs_tags_format
)
770 if (streq (outfile
, "-"))
773 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
784 while (gfnames (&argc
, &argv
, &got_err
) != NULL
)
788 error ("Can't find file %s\n", this_file
);
793 this_file
= massage_name (this_file
);
796 } /* solely to balance out the ifdef'd parens above */
799 for (; optind
< argc
; optind
++)
801 this_file
= argv
[optind
];
805 /* Input file named "-" means read file names from stdin
807 if (streq (this_file
, "-"))
809 while (!feof (stdin
))
811 (void) readline (&filename_lb
, stdin
);
812 if (strlen (filename_lb
.buffer
) > 0)
813 process_file (filename_lb
.buffer
);
817 process_file (this_file
);
821 if (emacs_tags_format
)
823 while (nincluded_files
-- > 0)
824 fprintf (outf
, "\f\n%s,include\n", *included_files
++);
826 (void) fclose (outf
);
837 /* update cannot be set under VMS, so we may assume that argc
838 and argv have not been munged. */
839 for (i
= optind
; i
< argc
; i
++)
842 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
843 outfile
, argv
[i
], outfile
);
848 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
855 (void) fclose (outf
);
858 sprintf (cmd
, "sort %s -o %s", outfile
, outfile
);
866 * This routine is called on each file argument.
872 struct stat stat_buf
;
874 stat (file
, &stat_buf
);
875 if (!(stat_buf
.st_mode
& S_IFREG
) || !(stat_buf
.st_mode
& S_IFLNK
))
877 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
881 if (streq (file
, outfile
) && !streq (outfile
, "-"))
883 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
886 if (emacs_tags_format
)
888 char *cp
= rindex (file
, '/');
895 if (emacs_tags_format
)
897 fprintf (outf
, "\f\n%s,%d\n",
898 file
, total_size_of_entries (head
));
906 * This routine sets up the boolean psuedo-functions which work
907 * by seting boolean flags dependent upon the corresponding character
908 * Every char which is NOT in that string is not a white char. Therefore,
909 * all of the array "_wht" is set to FALSE, and then the elements
910 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
911 * of a char is TRUE if it is the string "white", else FALSE.
919 for (i
= 0; i
< 0177; i
++)
921 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
924 for (sp
= white
; *sp
; sp
++)
926 for (sp
= endtk
; *sp
; sp
++)
928 for (sp
= intk
; *sp
; sp
++)
930 for (sp
= begtk
; *sp
; sp
++)
932 for (sp
= notgd
; *sp
; sp
++)
934 _wht
[0] = _wht
['\n'];
935 _etk
[0] = _etk
['\n'];
936 _btk
[0] = _btk
['\n'];
937 _itk
[0] = _itk
['\n'];
942 * This routine opens the specified file and calls the function
943 * which finds the function and type definitions.
950 void prolog_funcs ();
952 inf
= fopen (file
, "r");
958 curfile
= savestr (file
);
959 cp
= rindex (file
, '.');
961 header_file
= (cp
&& (streq (cp
+ 1, "h")));
963 /* .tex, .aux or .bbl implies LaTeX source code */
964 if (cp
&& (streq (cp
+ 1, "tex") || streq (cp
+ 1, "aux")
965 || streq (cp
+ 1, "bbl")))
968 goto close_and_return
;
970 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
971 if (cp
&& (streq (cp
+ 1, "l")
972 || streq (cp
+ 1, "el")
973 || streq (cp
+ 1, "lsp")
974 || streq (cp
+ 1, "lisp")
975 || streq (cp
+ 1, "cl")
976 || streq (cp
+ 1, "clisp")))
979 goto close_and_return
;
981 /* .scm or .sm or .scheme or ... implies scheme source code */
982 if (cp
&& (streq (cp
+ 1, "sm")
983 || streq (cp
+ 1, "scm")
984 || streq (cp
+ 1, "scheme")
985 || streq (cp
+ 1, "t")
986 || streq (cp
+ 1, "sch")
987 || streq (cp
+ 1, "SM")
988 || streq (cp
+ 1, "SCM")
989 /* The `SCM' or `scm' prefix with a version number */
990 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
991 && string_numeric_p (cp
+ 1))
992 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
993 && string_numeric_p (cp
+ 1))))
999 /* Assume that ".s" or ".a" is assembly code. -wolfgang. */
1000 if (cp
&& (cp
[1] == 's' || cp
[1] == 'a') && cp
[2] == '\0')
1006 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
1007 if (cp
&& (streq (cp
+ 1, "C")
1008 || streq (cp
+ 1, "H")
1009 || streq (cp
+ 1, "cxx")
1010 || streq (cp
+ 1, "hxx")
1011 || streq (cp
+ 1, "cc")))
1013 C_entries (C_PLPL
); /* C++ */
1014 goto close_and_return
;
1016 /* .cs or .hs: a C* file */
1017 if (cp
&& (cp
[1] == 'c' || cp
[1] == 'h') && cp
[2] == 's' && cp
[3] == '\0')
1020 goto close_and_return
;
1022 /* .pl implies prolog source code */
1023 if (cp
&& !strcmp (cp
+ 1, "pl"))
1026 goto close_and_return
;
1028 /* .p or .pas: a Pascal file */
1029 if (cp
&& (streq (cp
+ 1, "p")
1030 || streq (cp
+ 1, "pas")))
1033 goto close_and_return
;
1035 /* if not a .c or .h or .y file, try fortran */
1036 else if (cp
&& ((cp
[1] != 'c'
1039 || (cp
[1] != 0 && cp
[2] != 0)))
1041 if (PF_funcs (inf
) != 0)
1042 goto close_and_return
;
1043 rewind (inf
); /* no fortran tags found, try C */
1045 C_entries (cplusplus
? C_PLPL
: 0);
1048 (void) fclose (inf
);
1051 /* Nonzero if string STR is composed of digits. */
1054 string_numeric_p (str
)
1059 if (*str
< '0' || *str
> '9')
1066 /* Should take a TOKEN* instead!! */
1069 pfnote (name
, is_func
, rewritten
, linestart
, linelen
, lno
, cno
)
1070 char *name
; /* tag name */
1071 logical is_func
; /* function or type name? */
1072 logical rewritten
; /* tag different from text of definition? */
1083 np
= (NODE
*) malloc (sizeof (NODE
));
1086 if (!emacs_tags_format
)
1088 /* It's okay to output early in etags -- it only disrupts the
1089 * character count of the tag entries, which is no longer used
1090 * by tags.el anyway.
1092 error ("too many entries to sort");
1097 np
= xnew (1, NODE
);
1099 /* If ctags mode, change name "main" to M<thisfilename>. */
1100 if (!emacs_tags_format
&& !cxref_style
&& streq (name
, "main"))
1102 fp
= rindex (curfile
, '/');
1103 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
1104 fp
= rindex (name
, '.');
1105 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
1109 np
->name
= savestr (name
);
1111 np
->is_func
= is_func
;
1112 np
->rewritten
= rewritten
;
1114 /* UNCOMMENT THE +1 HERE: */
1115 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
1116 np
->left
= np
->right
= 0;
1117 if (emacs_tags_format
)
1119 c
= linestart
[linelen
];
1120 linestart
[linelen
] = 0;
1122 else if (cxref_style
== 0)
1124 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
1127 np
->pat
= savestr (linestart
);
1128 if (emacs_tags_format
)
1130 linestart
[linelen
] = c
;
1133 add_node (np
, &head
);
1138 * recurse on left children, iterate on right children.
1142 register NODE
*node
;
1146 register NODE
*node_right
= node
->right
;
1147 free_tree (node
->left
);
1150 free ((char *) node
);
1157 * Adds a node to the tree of nodes. In etags mode, we don't keep
1158 * it sorted; we just keep a linear list. In ctags mode, maintain
1159 * an ordered tree, with no attempt at balancing.
1161 * add_node is the only function allowed to add nodes, so it can
1165 add_node (node
, cur_node_p
)
1166 NODE
*node
, **cur_node_p
;
1169 register NODE
*cur_node
= *cur_node_p
;
1170 static NODE
*last_node
= NULL
;/* careful */
1172 if (cur_node
== NULL
)
1179 if (emacs_tags_format
)
1183 fatal ("internal error in add_node");
1184 last_node
->right
= node
;
1190 dif
= strcmp (node
->name
, cur_node
->name
);
1193 * If this tag name matches an existing one, then
1194 * do not add the node, but maybe print a warning.
1198 if (node
->file
== cur_node
->file
)
1202 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1203 node
->file
, lineno
, node
->name
);
1204 fprintf (stderr
, "Second entry ignored\n");
1208 if (!cur_node
->been_warned
&& !no_warnings
)
1211 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1212 node
->file
, cur_node
->file
, node
->name
);
1214 cur_node
->been_warned
= TRUE
;
1218 /* Maybe refuse to add duplicate nodes. */
1219 if (!permit_duplicates
)
1221 if (!strcmp (node
->name
, cur_node
->name
)
1222 && !strcmp (node
->file
, cur_node
->file
))
1226 /* Actually add the node */
1227 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1240 /* Output subentries that precede this one */
1241 put_entries (node
->left
);
1243 /* Output this entry */
1245 if (emacs_tags_format
)
1247 if (node
->rewritten
)
1249 fprintf (outf
, "%s\177%s\001%d,%d\n",
1250 node
->name
, node
->pat
, node
->lno
, node
->cno
);
1254 fprintf (outf
, "%s\177%d,%d\n",
1255 node
->pat
, node
->lno
, node
->cno
);
1258 else if (!cxref_style
)
1260 fprintf (outf
, "%s\t%s\t",
1261 node
->name
, node
->file
);
1265 putc (searchar
, outf
);
1268 for (sp
= node
->pat
; *sp
; sp
++)
1270 if (*sp
== '\\' || *sp
== searchar
)
1274 putc (searchar
, outf
);
1277 { /* a typedef; text pattern inadequate */
1278 fprintf (outf
, "%d", node
->lno
);
1282 else if (vgrind_style
)
1283 fprintf (stdout
, "%s %s %d\n",
1284 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1286 fprintf (stdout
, "%-16s%4d %-16s %s\n",
1287 node
->name
, node
->lno
, node
->file
, node
->pat
);
1289 /* Output subentries that follow this one */
1290 put_entries (node
->right
);
1293 /* Length of a number's decimal representation. */
1301 for (; num
; num
/= 10)
1307 * Return total number of characters that put_entries will output for
1308 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1309 * is set, but called only in that case. This count is irrelevant with
1310 * the new tags.el, but is still supplied for backward compatibility.
1313 total_size_of_entries (node
)
1322 for (; node
; node
= node
->right
)
1324 /* Count left subentries. */
1325 total
+= total_size_of_entries (node
->left
);
1327 /* Count this entry */
1328 total
+= strlen (node
->pat
) + 1;
1329 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1330 if (node
->rewritten
)
1331 total
+= 1 + strlen (node
->name
); /* \001name */
1338 * The C symbol tables.
1341 Stab
*C_stab
, *C_PLPL_stab
, *C_STAR_stab
;
1345 * Stab *get_C_stab (int c_ext);
1347 #define get_C_stab(c_ext) ((c_ext&C_STAR) ? C_STAR_stab : \
1348 c_ext ? C_PLPL_stab : \
1352 add_keyword (stab
, sym
, type
)
1357 stab_search (stab
, sym
, strlen (sym
))->type
= type
;
1361 C_create_stab (c_ext
)
1366 stab
= stab_create ();
1370 add_keyword (stab
, "class", st_C_struct
);
1372 add_keyword (stab
, "domain", st_C_struct
);
1373 add_keyword (stab
, "union", st_C_struct
);
1374 add_keyword (stab
, "struct", st_C_struct
);
1375 add_keyword (stab
, "enum", st_C_enum
);
1376 add_keyword (stab
, "typedef", st_C_typedef
);
1377 add_keyword (stab
, "define", st_C_define
);
1378 add_keyword (stab
, "long", st_C_typespec
);
1379 add_keyword (stab
, "short", st_C_typespec
);
1380 add_keyword (stab
, "int", st_C_typespec
);
1381 add_keyword (stab
, "char", st_C_typespec
);
1382 add_keyword (stab
, "float", st_C_typespec
);
1383 add_keyword (stab
, "double", st_C_typespec
);
1384 add_keyword (stab
, "signed", st_C_typespec
);
1385 add_keyword (stab
, "unsigned", st_C_typespec
);
1386 add_keyword (stab
, "const", st_C_typespec
);
1387 add_keyword (stab
, "volatile", st_C_typespec
);
1395 C_stab
= C_create_stab (0);
1396 C_PLPL_stab
= C_create_stab (C_PLPL
);
1397 C_STAR_stab
= C_create_stab (C_STAR
| C_PLPL
);
1402 * This routine finds functions and typedefs in C syntax and adds them
1406 #define CNL_SAVE_DEFINEDEF \
1408 prev_linepos = linepos; \
1409 SET_FILEPOS (linepos, inf, charno); \
1411 charno += readline (&lb, inf); \
1417 CNL_SAVE_DEFINEDEF; \
1418 definedef = dnone; \
1423 int c_ext
; /* extension of C? */
1425 register int c
; /* latest char read; '\0' for end of line */
1426 register int tokoff
; /* offset in line of beginning of latest token */
1427 register int toklen
; /* length of latest token */
1428 register char *lp
; /* pointer one beyond the character `c' */
1429 logical incomm
, inquote
, inchar
, midtoken
;
1430 int level
; /* current curly brace level */
1439 gotone
= midtoken
= inquote
= inchar
= incomm
= FALSE
;
1442 next_token_is_func
= 0;
1451 /* If we're at the end of the line, the next character is a
1452 '\0'; don't skip it, because it's the thing that tells us
1453 to read the next line. */
1461 if (c
== '*' && *lp
== '/')
1494 else if (c_ext
&& *lp
== '/')
1496 c
= 0; /* C++ comment: skip rest of line */
1500 if (lp
== lb
.buffer
+ 1 && definedef
== dnone
)
1501 definedef
= dsharpseen
;
1505 * The next two are to help the strucdef state machine.
1506 * They break when they are finished, so they don't interfere
1507 * with anything else that is going on.
1510 if (structdef
== stagseen
)
1511 structdef
= scolonseen
;
1513 /* Not a struct definition when semicolon seen in non-sinbody context. */
1515 if (structdef
!= snone
&& structdef
!= sinbody
)
1518 (void) strcpy (structtag
, "<error 1>");
1529 case skeyseen
: /* unnamed struct */
1530 structtag
[0] = '\0';
1533 case scolonseen
: /* named struct */
1534 structdef
= sinbody
;
1540 if (!noindentypedefs
&& lp
== lb
.buffer
+ 1)
1541 level
= 0; /* reset level if first column */
1544 if (level
== 0 && tydef
== middle
)
1551 (void) strcpy (structtag
, "<error 2>");
1555 if (LEVEL_OK_FOR_FUNCDEF () && !inquote
&& !incomm
&& gotone
== FALSE
)
1561 if (c_ext
&& c
== ':' && *lp
== ':' && intoken (*(lp
+ 1)))
1564 * This handles :: in the middle, but not at beginning
1572 /* The following is no longer true,
1573 now that we advance to the next line
1574 at the end of processing the character. */
1576 * We've just finished lexing an identifier.
1577 * Note that if `c' is '\0', `lb' is the NEXT
1578 * line, `lp' points to the beginning of it, and
1579 * old pointers into `lb.buffer' may no longer be
1580 * valid, since `lb.buffer' may have been
1581 * reallocated. In this case (which corresponds
1582 * to an identifier followed immediately by a
1583 * newline), we re-read the line into lb1.
1585 * This would be faster if the previous line's
1586 * buffer were always saved.
1591 logical bingo
, tok_at_end_of_line
;
1592 char *lp_tmp
; /* addressable */
1597 getline (GET_COOKIE (prev_linepos
));
1598 tok_linebuf
= lb1
.buffer
;
1599 tok_at_end_of_line
= TRUE
;
1600 tok
.linestart
= prev_linepos
;
1601 tok
.lineno
= lineno
- 1;
1606 tok_linebuf
= lb
.buffer
;
1607 tok_at_end_of_line
= FALSE
;
1608 tok
.linestart
= linepos
;
1609 tok
.lineno
= lineno
;
1611 tok
.p
= tok_linebuf
+ tokoff
;
1613 tok
.rewritten
= FALSE
;
1615 bingo
= consider_token (c
, &lp_tmp
, &tok
,
1616 &is_func
, c_ext
, level
);
1620 if (GET_CHARNO (tok
.linestart
) != GET_CHARNO (linepos
)
1621 && !tok_at_end_of_line
)
1624 * Resynchronize tok.p to point into the right
1627 getline (GET_COOKIE (tok
.linestart
));
1629 tok
.p
= lb1
.buffer
+ (tok
.p
- tok_linebuf
);
1630 tok_linebuf
= lb1
.buffer
;
1632 if (structdef
== sinbody
&& definedef
== dnone
&& is_func
)
1633 { /* function defined in C++ class body */
1634 sprintf (tokb
, "%s::%.*s",
1635 structtag
[0] == '\0' ? "_anonymous_"
1638 tok
.rewritten
= TRUE
;
1642 sprintf (tokb
, "%.*s", tok
.len
, tok
.p
);
1644 pfnote (tokb
, is_func
, tok
.rewritten
, tok_linebuf
,
1645 tokoff
+ toklen
+ (tok_at_end_of_line
? 0 : 1),
1646 tok
.lineno
, GET_CHARNO (tok
.linestart
));
1647 gotone
= is_func
; /* function */
1652 else if (intoken (c
))
1655 else if (begtoken (c
))
1657 tokoff
= lp
- 1 - lb
.buffer
;
1662 /* Detect end of line, after having handled the last token on the line. */
1668 if (c
== ';' && tydef
== end
) /* clean with typedefs */
1675 * checks to see if the current token is at the start of a
1676 * function, or corresponds to a typedef. It updates the input
1677 * line pointer *LPP so that the '(' will be in it when it returns.
1679 * *IS_FUNC gets TRUE iff the token is a function.
1680 * C_EXT is which language we are looking at.
1682 * In the future we will need some way to adjust where the end of
1683 * the token is; for instance, implementing the C++ keyword
1684 * `operator' properly will adjust the end of the token to be after
1685 * whatever follows `operator'.
1694 consider_token (c
, lpp
, tokp
, is_func
, c_ext
, level
)
1695 reg
char c
; /* IN: first char after the token */
1696 char **lpp
; /* IN OUT: *lpp points to 2nd char after the token */
1697 reg TOKEN
*tokp
; /* IN */
1698 logical
*is_func
; /* OUT */
1702 reg
char *lp
= *lpp
;
1703 logical firsttok
; /* TRUE if have seen first token in ()'s */
1704 Stab_entry
*tokse
= stab_find (get_C_stab (c_ext
), tokp
->p
, tokp
->len
);
1705 enum sym_type toktype
= stab_type (tokse
);
1707 *is_func
= TRUE
; /* a function */
1710 * Advance the definedef state machine. We set `gotone' for good measure;
1716 /* We're not on a preprocessor line. */
1719 if (toktype
== st_C_define
)
1721 definedef
= ddefineseen
;
1726 definedef
= dignorerest
;
1732 * Make a tag for any macro.
1733 * This will flub up if there is a newline immediately following
1736 *is_func
= (c
== '(');
1737 definedef
= dignorerest
;
1739 if (!*is_func
&& !constantypedefs
)
1745 error ("internal error: definedef value");
1749 * Skip whitespace and comments after the token. This loop should
1750 * also skip C++ comments.
1754 /* At whitespace => skip it. */
1759 /* At a comment => skip to end of comment. */
1760 else if (c
== '/' && *lp
== '*')
1762 /* If we find a comment, skip it. */
1763 while (!(c
== '*' && *lp
== '/'))
1772 if (c
== '*' && *lp
== '/')
1774 lp
++; /* lp now points past the '/' */
1775 c
= *lp
++; /* c is now the --whatever-- after the '/' */
1781 /* If we arrived at eof or eol, decide which one it is.
1782 If it's eol, advance to the next line. */
1792 * If you have custom token types, or when configuration files can
1793 * define custom token types, this switch will be larger.
1805 if (tydef
== begin
|| tydef
== end
)
1814 * This structdef business is currently only invoked when level==0.
1815 * It should be recursively invoked whatever the level, and a stack of
1816 * states kept, to allow for definitions of structs within structs.
1818 * This structdef business is NOT invoked when we are ctags and the
1819 * file is plain C. This is because a struct tag may have the same
1820 * name as another tag, and this loses with ctags.
1822 * This if statement deals with the tydef state machine as follows: if
1823 * tydef==begin and token is struct/union/class/enum, goto badone.
1824 * All the other code here is for the structdef state machine.
1830 if (tydef
== begin
|| (typedefs_and_cplusplus
&& level
== 0 && structdef
== snone
))
1832 structdef
= skeyseen
;
1838 if (structdef
== skeyseen
)
1840 /* If next char is '{' or (for C++) ':', found a structure tag. */
1841 if (c
== '{' || (c_ext
&& c
== ':'))
1844 * We should do this slightly differently for straight C:
1845 * instead of defining `tag', as we now do, we should define
1846 * `struct tag'. (Do this only if the find-tag defaulting is
1847 * done on a sophisticated per-mode basis, so that if the user
1848 * says meta-. anywhere in `struct foo', the default comes out
1849 * `struct foo', not `struct' or `foo'.) This will require
1850 * remembering which keyword (struct/union/class/enum) we saw, as a
1851 * Stab_entry* -- this will also make it possible to merge the
1852 * skeyseen and senumseen states, if we want.
1854 if (stab_type (structkey
) == st_C_struct
)
1856 (void) strncpy (structtag
, tokp
->p
, tokp
->len
);
1857 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1858 structdef
= stagseen
;
1862 structtag
[0] = '\0'; /* for enum */
1864 *is_func
= FALSE
; /* not a function */
1869 /* Not a definition: reset structdef */
1871 (void) strcpy (structtag
, "<error 3>");
1873 /* Now what? And how does/should this stuff interact with tydef?? */
1874 /* Also maybe reset lp to *lpp for benefit of the function finding code. */
1886 /* Detect GNUmacs's function-defining macros. */
1887 if (definedef
== dnone
)
1889 if (strneq (tokp
->p
, "DEF", 3))
1891 next_token_is_func
= TRUE
;
1894 else if (strneq (tokp
->p
, "EXFUN", 5))
1896 next_token_is_func
= FALSE
;
1900 if (next_token_is_func
)
1902 next_token_is_func
= FALSE
;
1908 while ((c
= *lp
++) != ')')
1916 * This line used to confuse ctags:
1918 * This fixes it. A nonwhite char before the first
1919 * token, other than a / (in case of a comment in there)
1920 * makes this not a declaration.
1922 if (begtoken (c
) || c
== '/')
1924 else if (!iswhite (c
) && !firsttok
)
1927 while (iswhite (c
= *lp
++))
1951 long saveftell
= ftell (inf
);
1953 (void) fseek (inf
, atcookie
, 0);
1954 (void) readline (&lb1
, inf
);
1955 (void) fseek (inf
, saveftell
, 0);
1958 /* Fortran parsing */
1974 linecharno
= charno
;
1975 charno
+= readline (&lb
, fi
);
1978 dbp
++; /* Ratfor escape to fortran */
1979 while (isspace (*dbp
))
1986 if (tail ("integer"))
1994 if (tail ("logical"))
1998 if (tail ("complex") || tail ("character"))
2002 if (tail ("double"))
2004 while (isspace (*dbp
))
2008 if (tail ("precision"))
2014 while (isspace (*dbp
))
2021 if (tail ("function"))
2025 if (tail ("subroutine"))
2029 if (tail ("program"))
2034 if (tail ("procedure"))
2046 register int len
= 0;
2048 while (*cp
&& (*cp
& ~' ') == ((*(dbp
+ len
)) & ~' '))
2061 while (isspace (*dbp
))
2066 while (isspace (*dbp
))
2068 if (!isdigit (*dbp
))
2070 --dbp
; /* force failure */
2075 while (isdigit (*dbp
));
2083 char nambuf
[BUFSIZ
];
2085 while (isspace (*dbp
))
2087 if (*dbp
== 0 || (!isalpha (*dbp
)) && (*dbp
!= '_') && (*dbp
!= '$'))
2089 for (cp
= dbp
+ 1; *cp
&& (isalpha (*cp
) || isdigit (*cp
)
2090 || (*cp
== '_') || (*cp
== '$')); cp
++)
2094 (void) strcpy (nambuf
, dbp
);
2096 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2100 /* Handle a file of assembler code. */
2116 linecharno
= charno
;
2117 charno
+= readline (&lb
, fi
);
2120 for (i
= 0; ((c
= dbp
[i
]) && !isspace (c
)) && (c
!= ':'); i
++)
2123 if ((i
> 0) && (c
== ':'))
2128 /* Added by Mosur Mohan, 4/22/88 */
2129 /* Pascal parsing */
2131 #define GET_NEW_LINE \
2133 linecharno = charno; lineno++; \
2134 charno += 1 + readline (&lb, inf); \
2138 /* Locates tags for procedures & functions.
2139 * Doesn't do any type- or var-definitions.
2140 * It does look for the keyword "extern" or "forward"
2141 * immediately following the procedure statement;
2142 * if found, the tag is skipped.
2149 struct linebuffer tline
; /* mostly copied from C_entries */
2153 char nambuf
[BUFSIZ
];
2155 logical
/* each of these flags is TRUE iff: */
2156 incomm1
, /* point is inside {..} comment */
2157 incomm2
, /* point is inside (*..*) comment */
2158 inquote
, /* point is inside '..' string */
2159 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2160 /* keyword, so next item = potential tag */
2161 found_tag
, /* point is after a potential tag */
2162 inparms
, /* point is within parameter-list */
2163 verify_tag
; /* point has passed the parm-list, so the */
2164 /* next token will determine whether */
2165 /* this is a FORWARD/EXTERN to be */
2166 /* ignored, or whether it is a real tag */
2172 initbuffer (&tline
);
2174 incomm1
= incomm2
= inquote
= FALSE
;
2175 found_tag
= FALSE
; /* have a proc name; check if extern */
2176 get_tagname
= FALSE
; /* have found "procedure" keyword */
2177 inparms
= FALSE
; /* found '(' after "proc" */
2178 verify_tag
= FALSE
; /* check if "extern" is ahead */
2180 /* long main loop to get next char */
2184 if (c
== 0) /* if end of line */
2189 if (!((found_tag
&& verify_tag
) ||
2191 c
= *dbp
++; /* only if don't need *dbp pointing */
2192 /* to the beginning of the name of */
2193 /* the procedure or function */
2195 if (incomm1
) /* within { - } comments */
2201 else if (incomm2
) /* within (* - *) comments */
2205 while ((c
= *dbp
++) == '*')
2224 inquote
= TRUE
; /* found first quote */
2226 case '{': /* found open-{-comment */
2230 if (*dbp
== '*') /* found open-(*-comment */
2235 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2238 case ')': /* end of parms list */
2243 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2250 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2252 /* check if this is an "extern" declaration */
2255 if ((*dbp
== 'e') || (*dbp
== 'E'))
2257 if (tail ("extern")) /* superfluous, really! */
2263 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2265 if (tail ("forward")) /* check for forward reference */
2271 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2275 pfnote (nambuf
, TRUE
, FALSE
,
2276 tline
.buffer
, cp
- tline
.buffer
+ 1,
2277 save_lineno
, save_lcno
);
2281 if (get_tagname
) /* grab name of proc or fn */
2286 /* save all values for later tagging */
2287 tline
.size
= lb
.size
;
2288 strcpy (tline
.buffer
, lb
.buffer
);
2289 save_lineno
= lineno
;
2290 save_lcno
= linecharno
;
2292 /* grab block name */
2293 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2297 strcpy (nambuf
, dbp
);
2299 dbp
= cp
; /* restore dbp to e-o-token */
2300 get_tagname
= FALSE
;
2304 /* and proceed to check for "extern" */
2306 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2307 (!found_tag
) && (!get_tagname
))
2309 /* check for proc/fn keywords */
2313 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2317 if (tail ("unction"))
2322 } /* while not e-o-f */
2326 * lisp tag functions
2327 * just look for (def or (DEF
2341 linecharno
= charno
;
2342 charno
+= readline (&lb
, fi
);
2348 while (!isspace (*dbp
))
2350 while (isspace (*dbp
))
2356 /* Check for (foo::defmumble name-defined ... */
2357 while (*dbp
&& *dbp
!= ':' && !isspace (*dbp
)
2358 && *dbp
!= '(' && *dbp
!= ')')
2367 while (!isspace (*dbp
))
2369 while (isspace (*dbp
))
2383 return ((dbp
[1] == 'D' || dbp
[1] == 'd') &&
2384 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2385 (dbp
[3] == 'F' || dbp
[3] == 'f'));
2393 char nambuf
[BUFSIZ
];
2397 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ' '; cp
++)
2401 (void) strcpy (nambuf
, dbp
);
2403 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2408 * Scheme tag functions
2409 * look for (def... xyzzy
2410 * look for (def... (xyzzy
2411 * look for (def ... ((...(xyzzy ....
2412 * look for (set! xyzzy
2415 static void get_scheme ();
2428 linecharno
= charno
;
2429 charno
+= readline (&lb
, fi
);
2431 if (dbp
[0] == '(' &&
2432 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2433 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2434 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2436 while (!isspace (*dbp
))
2438 /* Skip over open parens and white space */
2439 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2443 if (dbp
[0] == '(' &&
2444 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2445 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2446 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2447 (dbp
[4] == '!' || dbp
[4] == '!') &&
2450 while (!isspace (*dbp
))
2452 /* Skip over white space */
2453 while (isspace (*dbp
))
2465 char nambuf
[BUFSIZ
];
2469 /* Go till you get to white space or a syntactic break */
2470 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2472 /* Null terminate the string there. */
2475 /* Copy the string */
2476 strcpy (nambuf
, dbp
);
2477 /* Unterminate the string */
2479 /* Announce the change */
2480 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2484 /* Find tags in TeX and LaTeX input files. */
2486 /* TEX_toktab is a table of TeX control sequences that define tags.
2487 Each TEX_tabent records one such control sequence.
2488 CONVERT THIS TO USE THE Stab TYPE!! */
2496 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2498 /* Default set of control sequences to put into TEX_toktab.
2499 The value of environment var TEXTAGS is prepended to this. */
2501 static char *TEX_defenv
=
2502 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2505 struct TEX_tabent
*TEX_decode_env ();
2509 static char TEX_esc
= '\\';
2510 static char TEX_opgrp
= '{';
2511 static char TEX_clgrp
= '}';
2514 * TeX/LaTeX scanning loop.
2527 /* Select either \ or ! as escape character. */
2530 /* Initialize token table once from environment. */
2532 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2537 linecharno
= charno
;
2538 charno
+= readline (&lb
, fi
);
2543 { /* Scan each line in file */
2545 linecharno
= charno
;
2546 charno
+= readline (&lb
, fi
);
2549 while (dbp
= index (dbp
, TEX_esc
)) /* Look at each escape in line */
2555 linecharno
+= dbp
- lasthit
;
2557 i
= TEX_Token (lasthit
);
2560 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2561 break; /* We only save a line once */
2568 #define TEX_LESC '\\'
2569 #define TEX_SESC '!'
2572 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2573 /* chars accordingly. */
2581 while ((c
= getc (f
)) != EOF
)
2583 /* Skip to next line if we hit the TeX comment char. */
2587 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2606 /* Read environment and prepend it to the default string. */
2607 /* Build token table. */
2610 TEX_decode_env (evarname
, defenv
)
2614 register char *env
, *p
;
2615 extern char *savenstr (), *index ();
2617 struct TEX_tabent
*tab
;
2620 /* Append default string to environment. */
2621 env
= getenv (evarname
);
2625 env
= concat (env
, defenv
, "");
2627 /* Allocate a token table */
2628 for (size
= 1, p
= env
; p
;)
2629 if ((p
= index (p
, ':')) && *(++p
))
2631 tab
= xnew (size
, struct TEX_tabent
);
2633 /* Unpack environment string into token table. Be careful about */
2634 /* zero-length strings (leading ':', "::" and trailing ':') */
2637 p
= index (env
, ':');
2638 if (!p
) /* End of environment string. */
2639 p
= env
+ strlen (env
);
2641 { /* Only non-zero strings. */
2642 tab
[i
].name
= savenstr (env
, p
- env
);
2643 tab
[i
].len
= strlen (tab
[i
].name
);
2650 tab
[i
].name
= NULL
; /* Mark end of table. */
2658 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2659 The name being defined actually starts at (NAME + LEN + 1).
2660 But we seem to include the TeX command in the tag name. */
2663 TEX_getit (name
, len
)
2667 char *p
= name
+ len
;
2668 char nambuf
[BUFSIZ
];
2673 /* Let tag name extend to next group close (or end of line) */
2674 while (*p
&& *p
!= TEX_clgrp
)
2676 (void) strncpy (nambuf
, name
, p
- name
);
2677 nambuf
[p
- name
] = 0;
2679 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2683 /* If the text at CP matches one of the tag-defining TeX command names,
2684 return the index of that command in TEX_toktab.
2685 Otherwise return -1. */
2687 /* Keep the capital `T' in `Token' for dumb truncating compilers
2688 (this distinguishes it from `TEX_toktab' */
2695 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2696 if (strncmp (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
) == 0)
2701 /* Support for Prolog. */
2703 /* whole head (not only functor, but also arguments)
2704 is gotten in compound term. */
2707 prolog_getit (s
, lineno
, linecharno
)
2712 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2720 if (*s
== '\0') /* syntax error. */
2722 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2724 else if (*s
== '\'')
2726 insquote
= !insquote
;
2729 else if (!insquote
&& *s
== '(')
2734 else if (!insquote
&& *s
== ')')
2740 else if (npar
< 0) /* syntax error. */
2743 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2745 if (npar
!= 0) /* syntax error. */
2755 strcpy (nambuf
, save_s
);
2757 pfnote (nambuf
, TRUE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2760 /* It is assumed that prolog predicate starts from column 0. */
2766 void skip_comment (), prolog_getit ();
2768 lineno
= linecharno
= charno
= 0;
2772 linecharno
+= charno
;
2773 charno
= readline (&lb
, fi
) + 1; /* 1 for newline. */
2775 if (isspace (dbp
[0])) /* not predicate header. */
2777 else if (dbp
[0] == '%') /* comment. */
2779 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2780 skip_comment (&lb
, fi
, &lineno
, &linecharno
);
2782 prolog_getit (dbp
, lineno
, linecharno
);
2787 skip_comment (plb
, fi
, plineno
, plinecharno
)
2788 struct linebuffer
*plb
;
2790 int *plineno
; /* result */
2791 long *plinecharno
; /* result */
2793 while (!substr ("*/", plb
->buffer
))
2796 *plinecharno
+= readline (plb
, fi
) + 1;
2797 } /* 1 for newline. */
2800 /* Return TRUE if 'sub' exists somewhere in 's'. */
2807 while (*s
&& (s
= index (s
, *sub
)))
2808 if (prestr (sub
, s
))
2815 /* Return TRUE if 'pre' is prefix of string 's'. */
2824 else if (*pre
== *s
)
2825 return (prestr (pre
+ 1, s
+ 1));
2830 /* Initialize a linebuffer for use */
2833 initbuffer (linebuffer
)
2834 struct linebuffer
*linebuffer
;
2836 linebuffer
->size
= 200;
2837 linebuffer
->buffer
= xnew (200, char);
2841 * Read a line of text from `stream' into `linebuffer'.
2842 * Return the number of characters read from `stream',
2843 * which is the length of the line including the newline, if any.
2846 readline (linebuffer
, stream
)
2847 struct linebuffer
*linebuffer
;
2848 register FILE *stream
;
2850 char *buffer
= linebuffer
->buffer
;
2851 register char *p
= linebuffer
->buffer
;
2852 register char *pend
;
2853 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2855 pend
= p
+ linebuffer
->size
; /* Separate to avoind 386/IX compiler bug. */
2859 register int c
= getc (stream
);
2862 linebuffer
->size
*= 2;
2863 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
2864 p
+= buffer
- linebuffer
->buffer
;
2865 pend
= buffer
+ linebuffer
->size
;
2866 linebuffer
->buffer
= buffer
;
2868 if (c
< 0 || c
== '\n')
2871 newline
= (c
== '\n' ? 1 : 0);
2877 return p
- buffer
+ newline
;
2884 return savenstr (cp
, strlen (cp
));
2894 dp
= xnew (len
+ 1, char);
2895 (void) strncpy (dp
, cp
, len
);
2902 * Return the ptr in sp at which the character c last
2903 * appears; NULL if not found
2905 * Identical to v7 rindex, included for portability.
2910 register char *sp
, c
;
2924 * Return the ptr in sp at which the character c first
2925 * appears; NULL if not found
2927 * Identical to v7 index, included for portability.
2932 register char *sp
, c
;
2944 /* Print error message and exit. */
2955 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
2962 fprintf (stderr
, "%s: ", progname
);
2963 fprintf (stderr
, s1
, s2
);
2964 fprintf (stderr
, "\n");
2967 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
2973 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
2974 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
2976 (void) strcpy (result
, s1
);
2977 (void) strcpy (result
+ len1
, s2
);
2978 (void) strcpy (result
+ len1
+ len2
, s3
);
2979 *(result
+ len1
+ len2
+ len3
) = 0;
2984 /* Like malloc but get fatal error if memory is exhausted. */
2990 char *result
= malloc (size
);
2992 fatal ("virtual memory exhausted", 0);
2997 xrealloc (ptr
, size
)
3001 char *result
= realloc (ptr
, size
);
3003 fatal ("virtual memory exhausted");