1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 1987, 1988, 1989 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>
35 #define alloca __builtin_alloca
40 extern char *alloca ();
44 extern char *malloc (), *realloc ();
45 extern char *getenv ();
46 extern char *index (), *rindex ();
47 extern char *strcpy (), *strncpy ();
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)
413 /* C extensions. Currently all listed extensions are C++ dialects, so
414 * `c_ext' is used as an abbreviation for `c_ext&C_PLPL'. If a non-C++
415 * dialect is added, this must change.
417 #define C_PLPL 0x1 /* C++ */
418 #define C_STAR 0x3 /* C* */
420 char searchar
= '/'; /* use /.../ searches */
422 LINENO lineno
; /* line number of current line */
423 long charno
; /* current character number */
424 FILEPOS linepos
; /* start of line (C only) */
425 FILEPOS prev_linepos
; /* start of previous line (C only) */
427 long linecharno
; /* charno of start of line; not used by C, but
428 * by every other language.
431 char *curfile
, /* current input file name */
432 *outfile
, /* output file */
433 *white
= " \f\t\n", /* white chars */
434 *endtk
= " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
435 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$", /* token starting chars */
436 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789", /* valid in-token chars */
437 *notgd
= ",;"; /* non-valid after-function chars */
439 int file_num
; /* current file number */
440 int append_to_tagfile
; /* -a: append to tags */
441 int emacs_tags_format
; /* emacs style output (no -e option any more) */
442 /* The following three default to 1 for etags, but to 0 for ctags. */
443 int typedefs
; /* -t: create tags for typedefs */
444 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
445 /* 0 struct/enum/union decls, and C++ */
446 /* member functions */
447 int constantypedefs
; /* -d: create tags for C #define and enum */
448 /* constants. Default under etags. Enum */
449 /* constants not implemented. */
450 /* -D: opposite of -d. Default under ctags. */
451 int update
; /* -u: update tags */
452 int vgrind_style
; /* -v: create vgrind style index output */
453 int no_warnings
; /* -w: suppress warnings */
454 int cxref_style
; /* -x: create cxref style output */
455 int cplusplus
; /* .[hc] means C++, not C */
456 int noindentypedefs
; /* -S: ignore indentation in C */
458 /* Name this program was invoked with. */
461 FILE *inf
, /* ioptr for current input file */
462 *outf
; /* ioptr for tags file */
464 NODE
*head
; /* the head of the binary tree of tags */
466 int permit_duplicates
= 1; /* Nonzero means allow duplicate tags. */
468 /* A `struct linebuffer' is a structure which holds a line of text.
469 `readline' reads a line from a stream into a linebuffer
470 and works regardless of the length of the line. */
478 struct linebuffer lb
; /* the current line */
479 struct linebuffer lb1
; /* sometimes, a previous line in which a token lies */
480 struct linebuffer filename_lb
; /* used to read in filenames */
491 unsigned int nincluded_files
= 0;
492 char **included_files
= (char **) alloca (argc
* sizeof (char *));
497 extern char *gfnames ();
498 extern char *massage_name ();
504 emacs_tags_format
= 1;
506 emacs_tags_format
= 0;
510 * If etags, always find typedefs and structure tags. Why not?
511 * Also default is to find macro constants.
513 if (emacs_tags_format
)
514 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
516 for (; argc
> 1 && argv
[1][0] == '-' && argv
[1][1] != '\0'; argc
--, argv
++)
518 for (i
= 1; argv
[1][i
]; i
++)
522 /* Common options. */
539 "%s: -o flag may only be given once\n", progname
);
544 if (argc
<= 1 || argv
[1][0] == '\0')
547 "%s: -o flag must be followed by a filename\n",
561 typedefs_and_cplusplus
++;
566 if (!emacs_tags_format
)
570 if (argc
<= 1 || argv
[1][0] == '\0')
573 "%s: -i flag must be followed by a filename\n",
577 included_files
[nincluded_files
++] = argv
[1];
583 if (emacs_tags_format
)
588 if (emacs_tags_format
)
593 if (emacs_tags_format
)
601 if (emacs_tags_format
)
606 if (emacs_tags_format
)
620 fprintf (stderr
, "Usage:\n");
622 fprintf (stderr
, "\tetags [-aDiS] [-o tagsfile] file ...\n");
624 fprintf (stderr
, "\tctags [-aBdeFTStuwvx] [-o tagsfile] file ...\n");
631 outfile
= emacs_tags_format
? "TAGS" : "tags";
634 init (); /* set up boolean "functions" */
638 initbuffer (&filename_lb
);
640 * loop through files finding functions
642 if (emacs_tags_format
)
644 if (streq (outfile
, "-"))
647 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
658 (this_file
= gfnames (&argc
, &argv
, &got_err
)) != NULL
; file_num
++)
662 error ("Can't find file %s\n", this_file
);
667 this_file
= massage_name (this_file
);
670 } /* solely to balance out the ifdef'd parens above */
673 for (; file_num
< argc
; file_num
++)
675 this_file
= argv
[file_num
];
679 /* Input file named "-" means read file names from stdin
681 if (streq (this_file
, "-"))
683 while (!feof (stdin
))
685 (void) readline (&filename_lb
, stdin
);
686 if (strlen (filename_lb
.buffer
) > 0)
687 process_file (filename_lb
.buffer
);
691 process_file (this_file
);
695 if (emacs_tags_format
)
697 while (nincluded_files
-- > 0)
698 fprintf (outf
, "\f\n%s,include\n", *included_files
++);
700 (void) fclose (outf
);
709 if (update
) /* update cannot be set under VMS */
711 for (i
= 1; i
< argc
; i
++)
714 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
715 outfile
, argv
[i
], outfile
);
720 outf
= fopen (outfile
, append_to_tagfile
? "a" : "w");
727 (void) fclose (outf
);
730 sprintf (cmd
, "sort %s -o %s", outfile
, outfile
);
738 * This routine is called on each file argument.
744 struct stat stat_buf
;
746 stat (file
, &stat_buf
);
747 if (!(stat_buf
.st_mode
& S_IFREG
) || !(stat_buf
.st_mode
& S_IFLNK
))
749 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
753 if (streq (file
, outfile
) && !streq (outfile
, "-"))
755 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
758 if (emacs_tags_format
)
760 char *cp
= rindex (file
, '/');
767 if (emacs_tags_format
)
769 fprintf (outf
, "\f\n%s,%d\n",
770 file
, total_size_of_entries (head
));
778 * This routine sets up the boolean psuedo-functions which work
779 * by seting boolean flags dependent upon the corresponding character
780 * Every char which is NOT in that string is not a white char. Therefore,
781 * all of the array "_wht" is set to FALSE, and then the elements
782 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
783 * of a char is TRUE if it is the string "white", else FALSE.
791 for (i
= 0; i
< 0177; i
++)
793 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
796 for (sp
= white
; *sp
; sp
++)
798 for (sp
= endtk
; *sp
; sp
++)
800 for (sp
= intk
; *sp
; sp
++)
802 for (sp
= begtk
; *sp
; sp
++)
804 for (sp
= notgd
; *sp
; sp
++)
806 _wht
[0] = _wht
['\n'];
807 _etk
[0] = _etk
['\n'];
808 _btk
[0] = _btk
['\n'];
809 _itk
[0] = _itk
['\n'];
814 * This routine opens the specified file and calls the function
815 * which finds the function and type definitions.
822 void prolog_funcs ();
824 inf
= fopen (file
, "r");
830 curfile
= savestr (file
);
831 cp
= rindex (file
, '.');
833 header_file
= (cp
&& (streq (cp
+ 1, "h")));
835 /* .tex, .aux or .bbl implies LaTeX source code */
836 if (cp
&& (streq (cp
+ 1, "tex") || streq (cp
+ 1, "aux")
837 || streq (cp
+ 1, "bbl")))
840 goto close_and_return
;
842 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
843 if (cp
&& (streq (cp
+ 1, "l")
844 || streq (cp
+ 1, "el")
845 || streq (cp
+ 1, "lsp")
846 || streq (cp
+ 1, "lisp")
847 || streq (cp
+ 1, "cl")
848 || streq (cp
+ 1, "clisp")))
851 goto close_and_return
;
853 /* .scm or .sm or .scheme or ... implies scheme source code */
854 if (cp
&& (streq (cp
+ 1, "sm")
855 || streq (cp
+ 1, "scm")
856 || streq (cp
+ 1, "scheme")
857 || streq (cp
+ 1, "t")
858 || streq (cp
+ 1, "sch")
859 || streq (cp
+ 1, "SM")
860 || streq (cp
+ 1, "SCM")
861 /* The `SCM' or `scm' prefix with a version number */
862 || (cp
[-1] == 'm' && cp
[-2] == 'c' && cp
[-3] == 's'
863 && string_numeric_p (cp
+ 1))
864 || (cp
[-1] == 'M' && cp
[-2] == 'C' && cp
[-3] == 'S'
865 && string_numeric_p (cp
+ 1))))
871 /* Assume that ".s" or ".a" is assembly code. -wolfgang. */
872 if (cp
&& (cp
[1] == 's' || cp
[1] == 'a') && cp
[2] == '\0')
878 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
879 if (cp
&& (streq (cp
+ 1, "C")
880 || streq (cp
+ 1, "H")
881 || streq (cp
+ 1, "cxx")
882 || streq (cp
+ 1, "hxx")
883 || streq (cp
+ 1, "cc")))
885 C_entries (C_PLPL
); /* C++ */
886 goto close_and_return
;
888 /* .cs or .hs: a C* file */
889 if (cp
&& (cp
[1] == 'c' || cp
[1] == 'h') && cp
[2] == 's' && cp
[3] == '\0')
892 goto close_and_return
;
894 /* .pl implies prolog source code */
895 if (cp
&& !strcmp (cp
+ 1, "pl"))
898 goto close_and_return
;
900 /* .p or .pas: a Pascal file */
901 if (cp
&& (streq (cp
+ 1, "p")
902 || streq (cp
+ 1, "pas")))
905 goto close_and_return
;
907 /* if not a .c or .h or .y file, try fortran */
908 else if (cp
&& ((cp
[1] != 'c' && cp
[1] != 'h' && cp
[1] != 'y')
909 || (cp
[1] != 0 && cp
[2] != 0)))
911 if (PF_funcs (inf
) != 0)
912 goto close_and_return
;
913 rewind (inf
); /* no fortran tags found, try C */
915 C_entries (cplusplus
? C_PLPL
: 0);
921 /* Nonzero if string STR is composed of digits. */
924 string_numeric_p (str
)
929 if (*str
< '0' || *str
> '9')
936 /* Should take a TOKEN* instead!! */
939 pfnote (name
, is_func
, rewritten
, linestart
, linelen
, lno
, cno
)
940 char *name
; /* tag name */
941 logical is_func
; /* function or type name? */
942 logical rewritten
; /* tag different from text of definition? */
953 np
= (NODE
*) malloc (sizeof (NODE
));
956 if (!emacs_tags_format
)
958 /* It's okay to output early in etags -- it only disrupts the
959 * character count of the tag entries, which is no longer used
962 error ("too many entries to sort");
969 /* If ctags mode, change name "main" to M<thisfilename>. */
970 if (!emacs_tags_format
&& !cxref_style
&& streq (name
, "main"))
972 fp
= rindex (curfile
, '/');
973 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
974 fp
= rindex (name
, '.');
975 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
979 np
->name
= savestr (name
);
981 np
->is_func
= is_func
;
982 np
->rewritten
= rewritten
;
984 /* UNCOMMENT THE +1 HERE: */
985 np
->cno
= cno
/* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
986 np
->left
= np
->right
= 0;
987 if (emacs_tags_format
)
989 c
= linestart
[linelen
];
990 linestart
[linelen
] = 0;
992 else if (cxref_style
== 0)
994 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
997 np
->pat
= savestr (linestart
);
998 if (emacs_tags_format
)
1000 linestart
[linelen
] = c
;
1003 add_node (np
, &head
);
1008 * recurse on left children, iterate on right children.
1012 register NODE
*node
;
1016 register NODE
*node_right
= node
->right
;
1017 free_tree (node
->left
);
1020 free ((char *) node
);
1027 * Adds a node to the tree of nodes. In etags mode, we don't keep
1028 * it sorted; we just keep a linear list. In ctags mode, maintain
1029 * an ordered tree, with no attempt at balancing.
1031 * add_node is the only function allowed to add nodes, so it can
1035 add_node (node
, cur_node_p
)
1036 NODE
*node
, **cur_node_p
;
1039 register NODE
*cur_node
= *cur_node_p
;
1040 static NODE
*last_node
= NULL
;/* careful */
1042 if (cur_node
== NULL
)
1049 if (emacs_tags_format
)
1053 fatal ("internal error in add_node");
1054 last_node
->right
= node
;
1060 dif
= strcmp (node
->name
, cur_node
->name
);
1063 * If this tag name matches an existing one, then
1064 * do not add the node, but maybe print a warning.
1068 if (node
->file
== cur_node
->file
)
1072 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1073 node
->file
, lineno
, node
->name
);
1074 fprintf (stderr
, "Second entry ignored\n");
1078 if (!cur_node
->been_warned
&& !no_warnings
)
1081 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1082 node
->file
, cur_node
->file
, node
->name
);
1084 cur_node
->been_warned
= TRUE
;
1088 /* Maybe refuse to add duplicate nodes. */
1089 if (!permit_duplicates
)
1091 if (!strcmp (node
->name
, cur_node
->name
)
1092 && !strcmp (node
->file
, cur_node
->file
))
1096 /* Actually add the node */
1097 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1110 /* Output subentries that precede this one */
1111 put_entries (node
->left
);
1113 /* Output this entry */
1115 if (emacs_tags_format
)
1117 if (node
->rewritten
)
1119 fprintf (outf
, "%s\177%s\001%d,%d\n",
1120 node
->name
, node
->pat
, node
->lno
, node
->cno
);
1124 fprintf (outf
, "%s\177%d,%d\n",
1125 node
->pat
, node
->lno
, node
->cno
);
1128 else if (!cxref_style
)
1130 fprintf (outf
, "%s\t%s\t",
1131 node
->name
, node
->file
);
1135 putc (searchar
, outf
);
1138 for (sp
= node
->pat
; *sp
; sp
++)
1140 if (*sp
== '\\' || *sp
== searchar
)
1144 putc (searchar
, outf
);
1147 { /* a typedef; text pattern inadequate */
1148 fprintf (outf
, "%d", node
->lno
);
1152 else if (vgrind_style
)
1153 fprintf (stdout
, "%s %s %d\n",
1154 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1156 fprintf (stdout
, "%-16s%4d %-16s %s\n",
1157 node
->name
, node
->lno
, node
->file
, node
->pat
);
1159 /* Output subentries that follow this one */
1160 put_entries (node
->right
);
1163 /* Length of a number's decimal representation. */
1171 for (; num
; num
/= 10)
1177 * Return total number of characters that put_entries will output for
1178 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1179 * is set, but called only in that case. This count is irrelevant with
1180 * the new tags.el, but is still supplied for backward compatibility.
1183 total_size_of_entries (node
)
1192 for (; node
; node
= node
->right
)
1194 /* Count left subentries. */
1195 total
+= total_size_of_entries (node
->left
);
1197 /* Count this entry */
1198 total
+= strlen (node
->pat
) + 1;
1199 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1200 if (node
->rewritten
)
1201 total
+= 1 + strlen (node
->name
); /* \001name */
1208 * The C symbol tables.
1211 Stab
*C_stab
, *C_PLPL_stab
, *C_STAR_stab
;
1215 * Stab *get_C_stab (int c_ext);
1217 #define get_C_stab(c_ext) ((c_ext&C_STAR) ? C_STAR_stab : \
1218 c_ext ? C_PLPL_stab : \
1222 add_keyword (stab
, sym
, type
)
1227 stab_search (stab
, sym
, strlen (sym
))->type
= type
;
1231 C_create_stab (c_ext
)
1236 stab
= stab_create ();
1240 add_keyword (stab
, "class", st_C_struct
);
1242 add_keyword (stab
, "domain", st_C_struct
);
1243 add_keyword (stab
, "union", st_C_struct
);
1244 add_keyword (stab
, "struct", st_C_struct
);
1245 add_keyword (stab
, "enum", st_C_enum
);
1246 add_keyword (stab
, "typedef", st_C_typedef
);
1247 add_keyword (stab
, "define", st_C_define
);
1248 add_keyword (stab
, "long", st_C_typespec
);
1249 add_keyword (stab
, "short", st_C_typespec
);
1250 add_keyword (stab
, "int", st_C_typespec
);
1251 add_keyword (stab
, "char", st_C_typespec
);
1252 add_keyword (stab
, "float", st_C_typespec
);
1253 add_keyword (stab
, "double", st_C_typespec
);
1254 add_keyword (stab
, "signed", st_C_typespec
);
1255 add_keyword (stab
, "unsigned", st_C_typespec
);
1256 add_keyword (stab
, "const", st_C_typespec
);
1257 add_keyword (stab
, "volatile", st_C_typespec
);
1265 C_stab
= C_create_stab (0);
1266 C_PLPL_stab
= C_create_stab (C_PLPL
);
1267 C_STAR_stab
= C_create_stab (C_STAR
| C_PLPL
);
1272 * This routine finds functions and typedefs in C syntax and adds them
1276 #define CNL_SAVE_DEFINEDEF \
1278 prev_linepos = linepos; \
1279 SET_FILEPOS (linepos, inf, charno); \
1281 charno += readline (&lb, inf); \
1287 CNL_SAVE_DEFINEDEF; \
1288 definedef = dnone; \
1293 int c_ext
; /* extension of C? */
1295 register int c
; /* latest char read; '\0' for end of line */
1296 register int tokoff
; /* offset in line of beginning of latest token */
1297 register int toklen
; /* length of latest token */
1298 register char *lp
; /* pointer one beyond the character `c' */
1299 logical incomm
, inquote
, inchar
, midtoken
;
1300 int level
; /* current curly brace level */
1309 gotone
= midtoken
= inquote
= inchar
= incomm
= FALSE
;
1326 if (c
== '*' && *lp
== '/')
1335 * Too dumb to know about \" not being magic, but
1336 * they usually occur in pairs anyway.
1363 else if (c_ext
&& *lp
== '/')
1365 c
= 0; /* C++ comment: skip rest of line */
1369 if (lp
== lb
.buffer
+ 1 && definedef
== dnone
)
1370 definedef
= dsharpseen
;
1374 * The next two are to help the strucdef state machine.
1375 * They break when they are finished, so they don't interfere
1376 * with anything else that is going on.
1379 if (structdef
== stagseen
)
1380 structdef
= scolonseen
;
1382 /* Not a struct definition when semicolon seen in non-sinbody context. */
1384 if (structdef
!= snone
&& structdef
!= sinbody
)
1387 (void) strcpy (structtag
, "<error 1>");
1398 case skeyseen
: /* unnamed struct */
1399 structtag
[0] = '\0';
1402 case scolonseen
: /* named struct */
1403 structdef
= sinbody
;
1409 if (!noindentypedefs
&& lp
== lb
.buffer
+ 1)
1410 level
= 0; /* reset level if first column */
1413 if (level
== 0 && tydef
== middle
)
1420 (void) strcpy (structtag
, "<error 2>");
1424 if (LEVEL_OK_FOR_FUNCDEF () && !inquote
&& !incomm
&& gotone
== FALSE
)
1430 if (c_ext
&& c
== ':' && *lp
== ':' && intoken (*(lp
+ 1)))
1433 * This handles :: in the middle, but not at beginning
1441 /* The following is no longer true,
1442 now that we advance to the next line
1443 at the end of processing the character. */
1445 * We've just finished lexing an identifier.
1446 * Note that if `c' is '\0', `lb' is the NEXT
1447 * line, `lp' points to the beginning of it, and
1448 * old pointers into `lb.buffer' may no longer be
1449 * valid, since `lb.buffer' may have been
1450 * reallocated. In this case (which corresponds
1451 * to an identifier followed immediately by a
1452 * newline), we re-read the line into lb1.
1454 * This would be faster if the previous line's
1455 * buffer were always saved.
1460 logical bingo
, tok_at_end_of_line
;
1461 char *lp_tmp
; /* addressable */
1466 getline (GET_COOKIE (prev_linepos
));
1467 tok_linebuf
= lb1
.buffer
;
1468 tok_at_end_of_line
= TRUE
;
1469 tok
.linestart
= prev_linepos
;
1470 tok
.lineno
= lineno
- 1;
1475 tok_linebuf
= lb
.buffer
;
1476 tok_at_end_of_line
= FALSE
;
1477 tok
.linestart
= linepos
;
1478 tok
.lineno
= lineno
;
1480 tok
.p
= tok_linebuf
+ tokoff
;
1482 tok
.rewritten
= FALSE
;
1484 bingo
= consider_token (c
, &lp_tmp
, &tok
,
1485 &is_func
, c_ext
, level
);
1489 if (GET_CHARNO (tok
.linestart
) != GET_CHARNO (linepos
)
1490 && !tok_at_end_of_line
)
1493 * Resynchronize tok.p to point into the right
1496 getline (GET_COOKIE (tok
.linestart
));
1498 tok
.p
= lb1
.buffer
+ (tok
.p
- tok_linebuf
);
1499 tok_linebuf
= lb1
.buffer
;
1501 if (structdef
== sinbody
&& definedef
== dnone
&& is_func
)
1502 { /* function defined in C++ class body */
1503 sprintf (tokb
, "%s::%.*s",
1504 structtag
[0] == '\0' ? "_anonymous_"
1507 tok
.rewritten
= TRUE
;
1511 sprintf (tokb
, "%.*s", tok
.len
, tok
.p
);
1513 pfnote (tokb
, is_func
, tok
.rewritten
, tok_linebuf
,
1514 tokoff
+ toklen
+ (tok_at_end_of_line
? 0 : 1),
1515 tok
.lineno
, GET_CHARNO (tok
.linestart
));
1516 gotone
= is_func
; /* function */
1521 else if (intoken (c
))
1524 else if (begtoken (c
))
1526 tokoff
= lp
- 1 - lb
.buffer
;
1531 /* Detect end of line, after having handled the last token on the line. */
1537 if (c
== ';' && tydef
== end
) /* clean with typedefs */
1544 * checks to see if the current token is at the start of a
1545 * function, or corresponds to a typedef. It updates the input
1546 * line pointer *LPP so that the '(' will be in it when it returns.
1548 * *IS_FUNC gets TRUE iff the token is a function.
1549 * C_EXT is which language we are looking at.
1551 * In the future we will need some way to adjust where the end of
1552 * the token is; for instance, implementing the C++ keyword
1553 * `operator' properly will adjust the end of the token to be after
1554 * whatever follows `operator'.
1563 consider_token (c
, lpp
, tokp
, is_func
, c_ext
, level
)
1564 reg
char c
; /* IN: first char after the token */
1565 char **lpp
; /* IN OUT: *lpp points to 2nd char after the token */
1566 reg TOKEN
*tokp
; /* IN */
1567 logical
*is_func
; /* OUT */
1571 reg
char *lp
= *lpp
;
1573 * next_token_is_func
1574 * set this to TRUE, and the next token considered is called a function.
1576 static logical next_token_is_func
;
1577 logical firsttok
; /* TRUE if have seen first token in ()'s */
1578 Stab_entry
*tokse
= stab_find (get_C_stab (c_ext
), tokp
->p
, tokp
->len
);
1579 enum sym_type toktype
= stab_type (tokse
);
1581 *is_func
= TRUE
; /* a function */
1584 * Advance the definedef state machine. We set `gotone' for good measure;
1590 /* We're not on a preprocessor line. */
1593 if (toktype
== st_C_define
)
1595 definedef
= ddefineseen
;
1600 definedef
= dignorerest
;
1606 * Make a tag for any macro.
1607 * This will flub up if there is a newline immediately following
1610 *is_func
= (c
== '(');
1611 definedef
= dignorerest
;
1613 if (!*is_func
&& !constantypedefs
)
1619 error ("internal error: definedef value");
1623 * Skip whitespace and comments after the token. This loop should
1624 * also skip C++ comments.
1628 /* At whitespace => skip it. */
1633 /* At a comment => skip to end of comment. */
1634 else if (c
== '/' && *lp
== '*')
1636 /* If we find a comment, skip it. */
1637 while (!(c
== '*' && *lp
== '/'))
1646 if (c
== '*' && *lp
== '/')
1648 lp
++; /* lp now points past the '/' */
1649 c
= *lp
++; /* c is now the --whatever-- after the '/' */
1655 /* If we arrived at eof or eol, decide which one it is.
1656 If it's eol, advance to the next line. */
1666 * If you have custom token types, or when configuration files can
1667 * define custom token types, this switch will be larger.
1679 if (tydef
== begin
|| tydef
== end
)
1688 * This structdef business is currently only invoked when level==0.
1689 * It should be recursively invoked whatever the level, and a stack of
1690 * states kept, to allow for definitions of structs within structs.
1692 * This structdef business is NOT invoked when we are ctags and the
1693 * file is plain C. This is because a struct tag may have the same
1694 * name as another tag, and this loses with ctags.
1696 * This if statement deals with the tydef state machine as follows: if
1697 * tydef==begin and token is struct/union/class/enum, goto badone.
1698 * All the other code here is for the structdef state machine.
1704 if (tydef
== begin
|| (typedefs_and_cplusplus
&& level
== 0 && structdef
== snone
))
1706 structdef
= skeyseen
;
1712 if (structdef
== skeyseen
)
1714 /* If next char is '{' or (for C++) ':', found a structure tag. */
1715 if (c
== '{' || (c_ext
&& c
== ':'))
1718 * We should do this slightly differently for straight C:
1719 * instead of defining `tag', as we now do, we should define
1720 * `struct tag'. (Do this only if the find-tag defaulting is
1721 * done on a sophisticated per-mode basis, so that if the user
1722 * says meta-. anywhere in `struct foo', the default comes out
1723 * `struct foo', not `struct' or `foo'.) This will require
1724 * remembering which keyword (struct/union/class/enum) we saw, as a
1725 * Stab_entry* -- this will also make it possible to merge the
1726 * skeyseen and senumseen states, if we want.
1728 if (stab_type (structkey
) == st_C_struct
)
1730 (void) strncpy (structtag
, tokp
->p
, tokp
->len
);
1731 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1732 structdef
= stagseen
;
1736 structtag
[0] = '\0'; /* for enum */
1738 *is_func
= FALSE
; /* not a function */
1743 /* Not a definition: reset structdef */
1745 (void) strcpy (structtag
, "<error 3>");
1747 /* Now what? And how does/should this stuff interact with tydef?? */
1748 /* Also maybe reset lp to *lpp for benefit of the function finding code. */
1760 /* Detect GNUmacs's function-defining macros. */
1761 if (definedef
== dnone
&& strneq (tokp
->p
, "DEF", 3))
1763 next_token_is_func
= TRUE
;
1766 if (next_token_is_func
)
1768 next_token_is_func
= FALSE
;
1774 while ((c
= *lp
++) != ')')
1782 * This line used to confuse ctags:
1784 * This fixes it. A nonwhite char before the first
1785 * token, other than a / (in case of a comment in there)
1786 * makes this not a declaration.
1788 if (begtoken (c
) || c
== '/')
1790 else if (!iswhite (c
) && !firsttok
)
1793 while (iswhite (c
= *lp
++))
1817 long saveftell
= ftell (inf
);
1819 (void) fseek (inf
, atcookie
, 0);
1820 (void) readline (&lb1
, inf
);
1821 (void) fseek (inf
, saveftell
, 0);
1824 /* Fortran parsing */
1840 linecharno
= charno
;
1841 charno
+= readline (&lb
, fi
);
1844 dbp
++; /* Ratfor escape to fortran */
1845 while (isspace (*dbp
))
1852 if (tail ("integer"))
1860 if (tail ("logical"))
1864 if (tail ("complex") || tail ("character"))
1868 if (tail ("double"))
1870 while (isspace (*dbp
))
1874 if (tail ("precision"))
1880 while (isspace (*dbp
))
1887 if (tail ("function"))
1891 if (tail ("subroutine"))
1895 if (tail ("program"))
1900 if (tail ("procedure"))
1912 register int len
= 0;
1914 while (*cp
&& (*cp
& ~' ') == ((*(dbp
+ len
)) & ~' '))
1927 while (isspace (*dbp
))
1932 while (isspace (*dbp
))
1934 if (!isdigit (*dbp
))
1936 --dbp
; /* force failure */
1941 while (isdigit (*dbp
));
1949 char nambuf
[BUFSIZ
];
1951 while (isspace (*dbp
))
1953 if (*dbp
== 0 || (!isalpha (*dbp
)) && (*dbp
!= '_') && (*dbp
!= '$'))
1955 for (cp
= dbp
+ 1; *cp
&& (isalpha (*cp
) || isdigit (*cp
)
1956 || (*cp
== '_') || (*cp
== '$')); cp
++)
1960 (void) strcpy (nambuf
, dbp
);
1962 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
1966 /* Handle a file of assembler code. */
1982 linecharno
= charno
;
1983 charno
+= readline (&lb
, fi
);
1986 for (i
= 0; ((c
= dbp
[i
]) && !isspace (c
)) && (c
!= ':'); i
++)
1989 if ((i
> 0) && (c
== ':'))
1994 /* Added by Mosur Mohan, 4/22/88 */
1995 /* Pascal parsing */
1997 #define GET_NEW_LINE \
1999 linecharno = charno; lineno++; \
2000 charno += 1 + readline (&lb, inf); \
2004 /* Locates tags for procedures & functions.
2005 * Doesn't do any type- or var-definitions.
2006 * It does look for the keyword "extern" or "forward"
2007 * immediately following the procedure statement;
2008 * if found, the tag is skipped.
2015 struct linebuffer tline
; /* mostly copied from C_entries */
2019 char nambuf
[BUFSIZ
];
2021 logical
/* each of these flags is TRUE iff: */
2022 incomm1
, /* point is inside {..} comment */
2023 incomm2
, /* point is inside (*..*) comment */
2024 inquote
, /* point is inside '..' string */
2025 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2026 /* keyword, so next item = potential tag */
2027 found_tag
, /* point is after a potential tag */
2028 inparms
, /* point is within parameter-list */
2029 verify_tag
; /* point has passed the parm-list, so the */
2030 /* next token will determine whether */
2031 /* this is a FORWARD/EXTERN to be */
2032 /* ignored, or whether it is a real tag */
2038 initbuffer (&tline
);
2040 incomm1
= incomm2
= inquote
= FALSE
;
2041 found_tag
= FALSE
; /* have a proc name; check if extern */
2042 get_tagname
= FALSE
; /* have found "procedure" keyword */
2043 inparms
= FALSE
; /* found '(' after "proc" */
2044 verify_tag
= FALSE
; /* check if "extern" is ahead */
2046 /* long main loop to get next char */
2050 if (c
== 0) /* if end of line */
2055 if (!((found_tag
&& verify_tag
) ||
2057 c
= *dbp
++; /* only if don't need *dbp pointing */
2058 /* to the beginning of the name of */
2059 /* the procedure or function */
2061 if (incomm1
) /* within { - } comments */
2067 else if (incomm2
) /* within (* - *) comments */
2071 while ((c
= *dbp
++) == '*')
2090 inquote
= TRUE
; /* found first quote */
2092 case '{': /* found open-{-comment */
2096 if (*dbp
== '*') /* found open-(*-comment */
2101 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2104 case ')': /* end of parms list */
2109 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2116 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2118 /* check if this is an "extern" declaration */
2121 if ((*dbp
== 'e') || (*dbp
== 'E'))
2123 if (tail ("extern")) /* superfluous, really! */
2129 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2131 if (tail ("forward")) /* check for forward reference */
2137 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2141 pfnote (nambuf
, TRUE
, FALSE
,
2142 tline
.buffer
, cp
- tline
.buffer
+ 1,
2143 save_lineno
, save_lcno
);
2147 if (get_tagname
) /* grab name of proc or fn */
2152 /* save all values for later tagging */
2153 tline
.size
= lb
.size
;
2154 strcpy (tline
.buffer
, lb
.buffer
);
2155 save_lineno
= lineno
;
2156 save_lcno
= linecharno
;
2158 /* grab block name */
2159 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2163 strcpy (nambuf
, dbp
);
2165 dbp
= cp
; /* restore dbp to e-o-token */
2166 get_tagname
= FALSE
;
2170 /* and proceed to check for "extern" */
2172 if ((!incomm1
) && (!incomm2
) && (!inquote
) &&
2173 (!found_tag
) && (!get_tagname
))
2175 /* check for proc/fn keywords */
2179 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2183 if (tail ("unction"))
2188 } /* while not e-o-f */
2192 * lisp tag functions
2193 * just look for (def or (DEF
2207 linecharno
= charno
;
2208 charno
+= readline (&lb
, fi
);
2214 while (!isspace (*dbp
))
2216 while (isspace (*dbp
))
2222 /* Check for (foo::defmumble name-defined ... */
2223 while (*dbp
&& *dbp
!= ':' && !isspace (*dbp
)
2224 && *dbp
!= '(' && *dbp
!= ')')
2233 while (!isspace (*dbp
))
2235 while (isspace (*dbp
))
2249 return ((dbp
[1] == 'D' || dbp
[1] == 'd') &&
2250 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2251 (dbp
[3] == 'F' || dbp
[3] == 'f'));
2259 char nambuf
[BUFSIZ
];
2263 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ' '; cp
++)
2267 (void) strcpy (nambuf
, dbp
);
2269 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2274 * Scheme tag functions
2275 * look for (def... xyzzy
2276 * look for (def... (xyzzy
2277 * look for (def ... ((...(xyzzy ....
2278 * look for (set! xyzzy
2281 static void get_scheme ();
2294 linecharno
= charno
;
2295 charno
+= readline (&lb
, fi
);
2297 if (dbp
[0] == '(' &&
2298 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2299 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2300 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2302 while (!isspace (*dbp
))
2304 /* Skip over open parens and white space */
2305 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2309 if (dbp
[0] == '(' &&
2310 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2311 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2312 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2313 (dbp
[4] == '!' || dbp
[4] == '!') &&
2316 while (!isspace (*dbp
))
2318 /* Skip over white space */
2319 while (isspace (*dbp
))
2331 char nambuf
[BUFSIZ
];
2335 /* Go till you get to white space or a syntactic break */
2336 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
2338 /* Null terminate the string there. */
2341 /* Copy the string */
2342 strcpy (nambuf
, dbp
);
2343 /* Unterminate the string */
2345 /* Announce the change */
2346 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2350 /* Find tags in TeX and LaTeX input files. */
2352 /* TEX_toktab is a table of TeX control sequences that define tags.
2353 Each TEX_tabent records one such control sequence.
2354 CONVERT THIS TO USE THE Stab TYPE!! */
2362 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2364 /* Default set of control sequences to put into TEX_toktab.
2365 The value of environment var TEXTAGS is prepended to this. */
2367 static char *TEX_defenv
=
2368 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2371 struct TEX_tabent
*TEX_decode_env ();
2375 static char TEX_esc
= '\\';
2376 static char TEX_opgrp
= '{';
2377 static char TEX_clgrp
= '}';
2380 * TeX/LaTeX scanning loop.
2393 /* Select either \ or ! as escape character. */
2396 /* Initialize token table once from environment. */
2398 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
2403 linecharno
= charno
;
2404 charno
+= readline (&lb
, fi
);
2409 { /* Scan each line in file */
2411 linecharno
= charno
;
2412 charno
+= readline (&lb
, fi
);
2415 while (dbp
= index (dbp
, TEX_esc
)) /* Look at each escape in line */
2421 linecharno
+= dbp
- lasthit
;
2423 i
= TEX_Token (lasthit
);
2426 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
2427 break; /* We only save a line once */
2434 #define TEX_LESC '\\'
2435 #define TEX_SESC '!'
2438 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2439 /* chars accordingly. */
2447 while ((c
= getc (f
)) != EOF
)
2449 /* Skip to next line if we hit the TeX comment char. */
2453 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
2472 /* Read environment and prepend it to the default string. */
2473 /* Build token table. */
2476 TEX_decode_env (evarname
, defenv
)
2480 register char *env
, *p
;
2481 extern char *savenstr (), *index ();
2483 struct TEX_tabent
*tab
;
2486 /* Append default string to environment. */
2487 env
= getenv (evarname
);
2491 env
= concat (env
, defenv
, "");
2493 /* Allocate a token table */
2494 for (size
= 1, p
= env
; p
;)
2495 if ((p
= index (p
, ':')) && *(++p
))
2497 tab
= xnew (size
, struct TEX_tabent
);
2499 /* Unpack environment string into token table. Be careful about */
2500 /* zero-length strings (leading ':', "::" and trailing ':') */
2503 p
= index (env
, ':');
2504 if (!p
) /* End of environment string. */
2505 p
= env
+ strlen (env
);
2507 { /* Only non-zero strings. */
2508 tab
[i
].name
= savenstr (env
, p
- env
);
2509 tab
[i
].len
= strlen (tab
[i
].name
);
2516 tab
[i
].name
= NULL
; /* Mark end of table. */
2524 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2525 The name being defined actually starts at (NAME + LEN + 1).
2526 But we seem to include the TeX command in the tag name. */
2529 TEX_getit (name
, len
)
2533 char *p
= name
+ len
;
2534 char nambuf
[BUFSIZ
];
2539 /* Let tag name extend to next group close (or end of line) */
2540 while (*p
&& *p
!= TEX_clgrp
)
2542 (void) strncpy (nambuf
, name
, p
- name
);
2543 nambuf
[p
- name
] = 0;
2545 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
2549 /* If the text at CP matches one of the tag-defining TeX command names,
2550 return the index of that command in TEX_toktab.
2551 Otherwise return -1. */
2553 /* Keep the capital `T' in `Token' for dumb truncating compilers
2554 (this distinguishes it from `TEX_toktab' */
2561 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
2562 if (strncmp (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
) == 0)
2567 /* Support for Prolog. */
2569 /* whole head (not only functor, but also arguments)
2570 is gotten in compound term. */
2573 prolog_getit (s
, lineno
, linecharno
)
2578 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
2586 if (*s
== '\0') /* syntax error. */
2588 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
2590 else if (*s
== '\'')
2592 insquote
= !insquote
;
2595 else if (!insquote
&& *s
== '(')
2600 else if (!insquote
&& *s
== ')')
2606 else if (npar
< 0) /* syntax error. */
2609 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
2611 if (npar
!= 0) /* syntax error. */
2621 strcpy (nambuf
, save_s
);
2623 pfnote (nambuf
, TRUE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
2626 /* It is assumed that prolog predicate starts from column 0. */
2632 void skip_comment (), prolog_getit ();
2634 lineno
= linecharno
= charno
= 0;
2638 linecharno
+= charno
;
2639 charno
= readline (&lb
, fi
) + 1; /* 1 for newline. */
2641 if (isspace (dbp
[0])) /* not predicate header. */
2643 else if (dbp
[0] == '%') /* comment. */
2645 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
2646 skip_comment (&lb
, fi
, &lineno
, &linecharno
);
2648 prolog_getit (dbp
, lineno
, linecharno
);
2653 skip_comment (plb
, fi
, plineno
, plinecharno
)
2654 struct linebuffer
*plb
;
2656 int *plineno
; /* result */
2657 long *plinecharno
; /* result */
2659 while (!substr ("*/", plb
->buffer
))
2662 *plinecharno
+= readline (plb
, fi
) + 1;
2663 } /* 1 for newline. */
2666 /* Return TRUE if 'sub' exists somewhere in 's'. */
2673 while (*s
&& (s
= index (s
, *sub
)))
2674 if (prestr (sub
, s
))
2681 /* Return TRUE if 'pre' is prefix of string 's'. */
2690 else if (*pre
== *s
)
2691 return (prestr (pre
+ 1, s
+ 1));
2696 /* Initialize a linebuffer for use */
2699 initbuffer (linebuffer
)
2700 struct linebuffer
*linebuffer
;
2702 linebuffer
->size
= 200;
2703 linebuffer
->buffer
= xnew (200, char);
2707 * Read a line of text from `stream' into `linebuffer'.
2708 * Return the number of characters read from `stream',
2709 * which is the length of the line including the newline, if any.
2712 readline (linebuffer
, stream
)
2713 struct linebuffer
*linebuffer
;
2714 register FILE *stream
;
2716 char *buffer
= linebuffer
->buffer
;
2717 register char *p
= linebuffer
->buffer
;
2718 register char *pend
;
2719 int newline
; /* 1 if ended with newline, 0 if ended with EOF */
2721 pend
= p
+ linebuffer
->size
; /* Separate to avoind 386/IX compiler bug. */
2725 register int c
= getc (stream
);
2728 linebuffer
->size
*= 2;
2729 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
2730 p
+= buffer
- linebuffer
->buffer
;
2731 pend
= buffer
+ linebuffer
->size
;
2732 linebuffer
->buffer
= buffer
;
2734 if (c
< 0 || c
== '\n')
2737 newline
= (c
== '\n' ? 1 : 0);
2743 return p
- buffer
+ newline
;
2750 return savenstr (cp
, strlen (cp
));
2760 dp
= xnew (len
+ 1, char);
2761 (void) strncpy (dp
, cp
, len
);
2768 * Return the ptr in sp at which the character c last
2769 * appears; NULL if not found
2771 * Identical to v7 rindex, included for portability.
2776 register char *sp
, c
;
2790 * Return the ptr in sp at which the character c first
2791 * appears; NULL if not found
2793 * Identical to v7 index, included for portability.
2798 register char *sp
, c
;
2810 /* Print error message and exit. */
2821 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
2828 fprintf (stderr
, "%s: ", progname
);
2829 fprintf (stderr
, s1
, s2
);
2830 fprintf (stderr
, "\n");
2833 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
2839 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
2840 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
2842 (void) strcpy (result
, s1
);
2843 (void) strcpy (result
+ len1
, s2
);
2844 (void) strcpy (result
+ len1
+ len2
, s3
);
2845 *(result
+ len1
+ len2
+ len3
) = 0;
2850 /* Like malloc but get fatal error if memory is exhausted. */
2856 char *result
= malloc (size
);
2858 fatal ("virtual memory exhausted", 0);
2863 xrealloc (ptr
, size
)
2867 char *result
= realloc (ptr
, size
);
2869 fatal ("virtual memory exhausted");