Added `kibo', who actually greps for his name on Usenet.
[emacs.git] / lib-src / etags.c
blob5f7ee3437f8f332a0519a25e3ac9c7a3aa7427b3
1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 1987, 1988, 1989, 1993 Free Software Foundation, Inc. and Ken Arnold
4 This file is not considered part of GNU Emacs.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21 * Authors:
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++.
28 * Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer. 9.8
31 #ifdef HAVE_CONFIG_H
32 #include <../src/config.h>
33 #endif
35 #include <stdio.h>
36 #include <ctype.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
40 #if !defined (S_ISREG) && defined (S_IFREG)
41 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
42 #endif
44 #include "getopt.h"
46 extern char *malloc (), *realloc ();
47 extern char *getenv ();
48 extern char *strcpy (), *strncpy ();
49 extern int strcmp ();
51 char *etags_index (), *etags_rindex ();
52 char *savenstr ();
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. */
63 #define ETAGS
64 #define CTAGS
65 #endif
67 /* On VMS, CTAGS is not useful, so always do ETAGS. */
68 #ifdef VMS
69 #ifndef ETAGS
70 #define ETAGS
71 #endif
72 #endif
74 /* Exit codes for success and failure. */
75 #ifdef VMS
76 #define GOOD (1)
77 #define BAD (0)
78 #else
79 #define GOOD (0)
80 #define BAD (1)
81 #endif
84 * The FILEPOS abstract type, which represents a position in a file,
85 * plus the following accessor functions:
87 * long GET_CHARNO (pos)
88 * returns absolute char number.
89 * void SET_FILEPOS (pos, fp, charno)
90 * FILE *fp; long charno;
91 * sets `pos' from the current file
92 * position of `fp' and from `charno',
93 * which must be the absolute character
94 * number corresponding to the current
95 * position of `fp'.
97 * The `pos' parameter is an lvalue expression of type FILEPOS.
98 * Parameters to the accessor functions are evaluated 0 or more times,
99 * and so must have no side effects.
101 * FILEPOS objects can also be assigned and passed to and from
102 * functions in the normal C manner.
104 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
107 #ifndef DEBUG
108 /* real implementation */
109 typedef long FILEPOS;
110 #define GET_CHARNO(pos) ((pos) + 0)
111 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
112 #else
113 /* debugging implementation */
114 typedef struct
116 long charno;
117 } FILEPOS;
119 #define GET_CHARNO(pos) ((pos).charno + 0)
120 #define SET_FILEPOS(pos, fp, cno) \
121 ((void) ((pos).charno = (cno), \
122 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
123 : 0))
124 #endif
126 #define streq(s, t) (strcmp (s, t) == 0)
127 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
128 #define logical int
130 #define TRUE 1
131 #define FALSE 0
133 #define iswhite(arg) (_wht[arg]) /* T if char is white */
134 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
135 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
136 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
138 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
140 struct nd_st
141 { /* sorting structure */
142 char *name; /* function or type name */
143 char *file; /* file name */
144 logical is_func; /* use pattern or line no */
145 logical named; /* list name separately */
146 logical been_warned; /* set if noticed dup */
147 int lno; /* line number tag is on */
148 long cno; /* character number line starts on */
149 char *pat; /* search pattern */
150 struct nd_st *left, *right; /* left and right sons */
153 long ftell ();
154 typedef struct nd_st NODE;
156 logical header_file; /* TRUE if .h file, FALSE o.w. */
157 /* boolean "functions" (see init) */
158 logical _wht[0177], _etk[0177], _itk[0177], _btk[0177];
161 char *concat ();
162 char *savenstr ();
163 char *savestr ();
164 char *xmalloc ();
165 char *xrealloc ();
166 int L_isdef (), L_isquote ();
167 int PF_funcs ();
168 int total_size_of_entries ();
169 logical consider_token ();
170 logical tail ();
171 long readline ();
172 void Asm_funcs ();
173 void C_entries ();
174 void L_funcs ();
175 void L_getit ();
176 void PAS_funcs ();
177 void Scheme_funcs ();
178 void TEX_funcs ();
179 void add_node ();
180 void error ();
181 void fatal ();
182 void find_entries ();
183 void free_tree ();
184 void getit ();
185 void getline ();
186 void init ();
187 void initbuffer ();
188 void initbuffer ();
189 void pfnote ();
190 void process_file ();
191 void put_entries ();
192 void takeprec ();
195 * MACRO
196 * xnew -- allocate storage
198 * SYNOPSIS
199 * Type *xnew (int n, Type);
201 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
206 * Symbol table stuff.
208 * Should probably be implemented with hash table; linked list for now.
211 enum sym_type
213 st_none, st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
216 struct stab_entry
218 char *sym;
219 int symlen;
220 enum sym_type type;
221 struct stab_entry *next;
224 typedef struct stab_entry Stab_entry;
225 typedef Stab_entry *Stab;
228 * NAME
229 * Stab, Stab_entry, stab_create, stab_search, stab_find -- symbol table
231 * SYNOPSIS
232 * Types: Stab, Stab_entry, enum sym_type
234 * Stab * stab_create ()
236 * Stab_entry * stab_find (stab, sym)
237 * Stab *stab;
238 * char *sym;
240 * Stab_entry * stab_search (stab, sym)
241 * Stab *stab;
242 * char *sym;
244 * DESCRIPTION
245 * stab_create creates a Stab, a symbol table object, and returns a
246 * pointer to it. stab_find finds a symbol in a Stab; it returns a
247 * pointer to the Stab_entry if found, otherwise NULL. stab_search
248 * is like stab_find, except that it creates a new Stab_entry,
249 * initialized with type = st_none, if one did not exist already
250 * (it never returns NULL).
252 * A Stab_entry is a structure that contains at least the following
253 * members:
255 * char *name; // must not be modified
256 * enum sym_type type; // should be set
258 * The type field is initially set to st_none; it should be set to
259 * something else by the caller of stab_search. Other possible values
260 * of an enum sym_type can be added.
263 Stab *
264 stab_create ()
266 Stab *sp;
267 sp = xnew (1, Stab);
268 *sp = NULL; /* a Stab starts out as a null Stab_entry* */
269 return sp;
272 Stab_entry *
273 stab_find (stab, sym, symlen)
274 Stab *stab;
275 register char *sym;
276 register int symlen;
278 register Stab_entry *se;
279 for (se = *stab; se != NULL; se = se->next)
281 if (se->symlen == symlen && strneq (se->sym, sym, symlen))
282 return se;
285 return NULL;
288 Stab_entry *
289 stab_search (stab, sym, symlen)
290 register Stab *stab;
291 char *sym;
292 int symlen;
294 register Stab_entry *se;
295 se = stab_find (stab, sym, symlen);
297 if (se == NULL)
299 /* make a new one */
300 se = xnew (1, Stab_entry);
301 se->sym = savenstr (sym, symlen);
302 se->symlen = symlen;
303 se->type = st_none;
304 se->next = *stab;
305 *stab = se;
308 return se;
312 * NAME
313 * stab_type -- type of a symbol table entry
315 * SYNOPSIS
316 * enum sym_type stab_type (Stab_entry *se);
318 * WARNING
319 * May evaluate its argument more than once.
322 #define stab_type(se) ((se)==NULL ? st_none : (se)->type)
326 typedef int LINENO;
328 typedef struct
330 char *p;
331 int len;
332 LINENO lineno;
333 logical named;
334 } TOKEN;
336 /* C extensions.
338 #define C_PLPL 0x00001 /* C++ */
339 #define C_STAR 0x00003 /* C* */
340 #define YACC 0x10000 /* yacc file */
342 char searchar = '/'; /* use /.../ searches */
344 LINENO lineno; /* line number of current line */
345 long charno; /* current character number */
347 long linecharno; /* charno of start of line; not used by C, but
348 * by every other language.
351 char *curfile, /* current input file name */
352 *outfile, /* output file */
353 *white = " \f\t\n", /* white chars */
354 *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
355 /* token starting chars */
356 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
357 /* valid in-token chars */
358 *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
360 int append_to_tagfile; /* -a: append to tags */
361 int emacs_tags_format; /* emacs style output (no -e option any more) */
362 /* The following three default to 1 for etags, but to 0 for ctags. */
363 int typedefs; /* -t: create tags for typedefs */
364 int typedefs_and_cplusplus; /* -T: create tags for typedefs, level */
365 /* 0 struct/enum/union decls, and C++ */
366 /* member functions */
367 int constantypedefs; /* -d: create tags for C #define and enum */
368 /* constants. Default under etags. Enum */
369 /* constants not implemented. */
370 /* -D: opposite of -d. Default under ctags. */
371 int update; /* -u: update tags */
372 int vgrind_style; /* -v: create vgrind style index output */
373 int no_warnings; /* -w: suppress warnings */
374 int cxref_style; /* -x: create cxref style output */
375 int cplusplus; /* .[hc] means C++, not C */
376 int noindentypedefs; /* -S: ignore indentation in C */
378 /* Name this program was invoked with. */
379 char *progname;
381 struct option longopts[] = {
382 { "append", no_argument, NULL, 'a' },
383 { "backward-search", no_argument, NULL, 'B' },
384 { "c++", no_argument, NULL, 'C' },
385 { "cxref", no_argument, NULL, 'x' },
386 { "defines", no_argument, NULL, 'd' },
387 { "forward-search", no_argument, NULL, 'F' },
388 { "help", no_argument, NULL, 'H' },
389 { "ignore-indentation", no_argument, NULL, 'S' },
390 { "include", required_argument, NULL, 'i' },
391 { "no-defines", no_argument, NULL, 'D' },
392 { "no-warn", no_argument, NULL, 'w' },
393 { "output", required_argument, NULL, 'o' },
394 { "typedefs", no_argument, NULL, 't' },
395 { "typedefs-and-c++", no_argument, NULL, 'T' },
396 { "update", no_argument, NULL, 'u' },
397 { "version", no_argument, NULL, 'V' },
398 { "vgrind", no_argument, NULL, 'v' },
399 { 0 }
402 FILE *inf, /* ioptr for current input file */
403 *outf; /* ioptr for tags file */
405 NODE *head; /* the head of the binary tree of tags */
407 int permit_duplicates = 1; /* Nonzero means allow duplicate tags. */
409 /* A `struct linebuffer' is a structure which holds a line of text.
410 `readline' reads a line from a stream into a linebuffer
411 and works regardless of the length of the line. */
413 struct linebuffer
415 long size;
416 char *buffer;
419 struct linebuffer lb; /* the current line */
420 struct linebuffer filename_lb; /* used to read in filenames */
421 struct
423 FILEPOS linepos;
424 struct linebuffer lb; /* used by C_entries instead of lb */
425 } lbs[2];
427 void
428 print_version ()
430 #ifdef CTAGS
431 printf ("CTAGS ");
432 #ifdef ETAGS
433 printf ("and ");
434 #endif
435 #endif
436 #ifdef ETAGS
437 printf ("ETAGS ");
438 #endif
439 printf ("for Emacs version 19.\n");
441 exit (0);
444 void
445 print_help ()
447 printf ("These are the options accepted by %s. You may use unambiguous\n\
448 abbreviations for the long option names.\n\n", progname);
450 puts ("-a, --append\n\
451 Append tag entries to existing tags file.");
452 puts ("-C, --c++\n\
453 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
454 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
455 extensions are always assumed to be C++ code.");
456 fputs ("-d, --defines\n\
457 Create tag entries for #defines, too.", stdout);
459 #ifdef ETAGS
460 fputs (" This is the default\n\
461 behavior.", stdout);
462 #endif
464 fputs ("\n\
465 -D, --no-defines\n\
466 Don't create tag entries for #defines.", stdout);
468 #ifdef CTAGS
469 fputs (" This is the default\n\
470 behavior.", stdout);
471 #endif
473 puts ("\n\
474 -o FILE, --output=FILE\n\
475 Write the tags to FILE.\n\
476 -S, --ignore-indentation\n\
477 Don't rely on indentation quite as much as normal. Currently,\n\
478 this means not to assume that a closing brace in the first\n\
479 column is the final brace of a function or structure\n\
480 definition.");
481 puts ("-t, --typedefs\n\
482 Generate tag entries for typedefs. This is the default\n\
483 behavior.");
484 puts ("-T, --typedefs-and-c++\n\
485 Generate tag entries for typedefs, struct/enum/union tags, and\n\
486 C++ member functions.");
488 #ifdef ETAGS
489 puts ("-i FILE, --include=FILE\n\
490 Include a note in tag file indicating that, when searching for\n\
491 a tag, one should also consult the tags file FILE after\n\
492 checking the current file.");
493 #endif
495 #ifdef CTAGS
496 puts ("-B, --backward-search\n\
497 Write the search commands for the tag entries using '?', the\n\
498 backward-search command.");
499 puts ("-F, --forward-search\n\
500 Write the search commands for the tag entries using '/', the\n\
501 forward-search command.");
502 puts ("-u, --update\n\
503 Update the tag entries for the given files, leaving tag\n\
504 entries for other files in place. Currently, this is\n\
505 implemented by deleting the existing entries for the given\n\
506 files and then rewriting the new entries at the end of the\n\
507 tags file. It is often faster to simply rebuild the entire\n\
508 tag file than to use this.");
509 puts ("-v, --vgrind\n\
510 Generates an index of items intended for human consumption,\n\
511 similar to the output of vgrind. The index is sorted, and\n\
512 gives the page number of each item.");
513 puts ("-x, --cxref\n\
514 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
515 The output uses line numbers instead of page numbers, but\n\
516 beyond that the differences are cosmetic; try both to see\n\
517 which you like.");
518 puts ("-w, --no-warn\n\
519 Suppress warning messages about entries defined in multiple\n\
520 files.");
521 #endif
523 puts ("-V, --version\n\
524 Print the version of the program.\n\
525 -H, --help\n\
526 Print this help message.");
528 exit (0);
532 void
533 main (argc, argv)
534 int argc;
535 char *argv[];
537 char cmd[100];
538 int i;
539 unsigned int nincluded_files = 0;
540 char **included_files = xnew (argc, char *);
541 char *this_file;
542 #ifdef VMS
543 char got_err;
545 extern char *gfnames ();
546 extern char *massage_name ();
547 #endif
549 progname = argv[0];
551 #ifndef CTAGS
552 emacs_tags_format = 1;
553 #else
554 emacs_tags_format = 0;
555 #endif
558 * If etags, always find typedefs and structure tags. Why not?
559 * Also default is to find macro constants.
561 if (emacs_tags_format)
562 typedefs = typedefs_and_cplusplus = constantypedefs = 1;
564 for (;;)
566 int opt;
567 opt = getopt_long (argc, argv, "aCdDo:f:StTi:BFuvxwVH", longopts, 0);
569 if (opt == EOF)
570 break;
572 switch (opt)
574 case '\0':
575 /* If getopt returns '\0', then it has already processed a
576 long-named option. We should do nothing. */
577 break;
579 /* Common options. */
580 case 'a':
581 append_to_tagfile++;
582 break;
583 case 'C':
584 cplusplus = 1;
585 break;
586 case 'd':
587 constantypedefs = 1;
588 break;
589 case 'D':
590 constantypedefs = 0;
591 break;
592 case 'f':
593 case 'o':
594 if (outfile)
596 fprintf (stderr,
597 "%s: -%c flag may only be given once\n", progname, opt);
598 goto usage;
600 outfile = optarg;
601 break;
602 case 'S':
603 noindentypedefs++;
604 break;
605 case 't':
606 typedefs++;
607 break;
608 case 'T':
609 typedefs++;
610 typedefs_and_cplusplus++;
611 break;
612 case 'V':
613 print_version ();
614 break;
615 case 'H':
616 print_help ();
617 break;
619 /* Etags options */
620 case 'i':
621 if (!emacs_tags_format)
622 goto usage;
623 included_files[nincluded_files++] = optarg;
624 break;
626 /* Ctags options. */
627 case 'B':
628 searchar = '?';
629 if (emacs_tags_format)
630 goto usage;
631 break;
632 case 'F':
633 searchar = '/';
634 if (emacs_tags_format)
635 goto usage;
636 break;
637 case 'u':
638 update++;
639 if (emacs_tags_format)
640 goto usage;
641 break;
642 case 'v':
643 vgrind_style++;
644 /*FALLTHRU*/
645 case 'x':
646 cxref_style++;
647 if (emacs_tags_format)
648 goto usage;
649 break;
650 case 'w':
651 no_warnings++;
652 if (emacs_tags_format)
653 goto usage;
654 break;
656 default:
657 goto usage;
661 if (optind == argc && nincluded_files == 0)
663 fprintf (stderr, "%s: No input files specified.\n", progname);
665 usage:
666 fprintf (stderr, "%s: Try `%s --help' for a complete list of options.\n",
667 progname, progname);
668 exit (BAD);
671 if (outfile == 0)
673 outfile = emacs_tags_format ? "TAGS" : "tags";
676 init (); /* set up boolean "functions" */
678 initbuffer (&lb);
679 initbuffer (&lbs[0].lb);
680 initbuffer (&lbs[1].lb);
681 initbuffer (&filename_lb);
683 * loop through files finding functions
685 if (emacs_tags_format)
687 if (streq (outfile, "-"))
688 outf = stdout;
689 else
690 outf = fopen (outfile, append_to_tagfile ? "a" : "w");
691 if (!outf)
693 perror (outfile);
694 exit (1);
698 #ifdef VMS
699 argc -= optind;
700 argv += optind;
701 while (gfnames (&argc, &argv, &got_err) != NULL)
703 if (got_err)
705 error ("Can't find file %s\n", this_file);
706 argc--, argv++;
708 else
710 this_file = massage_name (this_file);
711 #if 0
713 } /* solely to balance out the ifdef'd parens above */
714 #endif
715 #else
716 for (; optind < argc; optind++)
718 this_file = argv[optind];
719 if (1)
721 #endif
722 /* Input file named "-" means read file names from stdin
723 and use them. */
724 if (streq (this_file, "-"))
726 while (!feof (stdin))
728 (void) readline (&filename_lb, stdin);
729 if (strlen (filename_lb.buffer) > 0)
730 process_file (filename_lb.buffer);
733 else
734 process_file (this_file);
738 if (emacs_tags_format)
740 while (nincluded_files-- > 0)
741 fprintf (outf, "\f\n%s,include\n", *included_files++);
743 (void) fclose (outf);
744 exit (0);
747 if (cxref_style)
749 put_entries (head);
750 exit (GOOD);
752 if (update)
754 /* update cannot be set under VMS, so we may assume that argc
755 and argv have not been munged. */
756 for (i = optind; i < argc; i++)
758 sprintf (cmd,
759 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
760 outfile, argv[i], outfile);
761 (void) system (cmd);
763 append_to_tagfile++;
765 outf = fopen (outfile, append_to_tagfile ? "a" : "w");
766 if (outf == NULL)
768 perror (outfile);
769 exit (GOOD);
771 put_entries (head);
772 (void) fclose (outf);
773 if (update)
775 sprintf (cmd, "sort %s -o %s", outfile, outfile);
776 (void) system (cmd);
778 exit (GOOD);
783 * This routine is called on each file argument.
785 void
786 process_file (file)
787 char *file;
789 struct stat stat_buf;
791 if (stat (file, &stat_buf) || !S_ISREG (stat_buf.st_mode))
793 fprintf (stderr, "Skipping %s: it is not a regular file.\n", file);
794 return;
797 if (streq (file, outfile) && !streq (outfile, "-"))
799 fprintf (stderr, "Skipping inclusion of %s in self.\n", file);
800 return;
802 find_entries (file);
803 if (emacs_tags_format)
805 fprintf (outf, "\f\n%s,%d\n", file, total_size_of_entries (head));
806 put_entries (head);
807 free_tree (head);
808 head = NULL;
813 * This routine sets up the boolean pseudo-functions which work
814 * by setting boolean flags dependent upon the corresponding character
815 * Every char which is NOT in that string is not a white char. Therefore,
816 * all of the array "_wht" is set to FALSE, and then the elements
817 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
818 * of a char is TRUE if it is the string "white", else FALSE.
820 void
821 init ()
823 register char *sp;
824 register int i;
826 for (i = 0; i < 0177; i++)
827 _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
828 for (sp = white; *sp; sp++)
829 _wht[*sp] = TRUE;
830 for (sp = endtk; *sp; sp++)
831 _etk[*sp] = TRUE;
832 for (sp = intk; *sp; sp++)
833 _itk[*sp] = TRUE;
834 for (sp = begtk; *sp; sp++)
835 _btk[*sp] = TRUE;
836 _wht[0] = _wht['\n'];
837 _etk[0] = _etk['\n'];
838 _btk[0] = _btk['\n'];
839 _itk[0] = _itk['\n'];
843 * This routine opens the specified file and calls the function
844 * which finds the function and type definitions.
846 void
847 find_entries (file)
848 char *file;
850 char *cp;
851 void prolog_funcs ();
853 inf = fopen (file, "r");
854 if (inf == NULL)
856 perror (file);
857 return;
859 curfile = savestr (file);
860 cp = etags_rindex (file, '.');
862 header_file = (cp && (streq (cp + 1, "h")));
864 /* .tex, .aux or .bbl implies LaTeX source code */
865 if (cp && (streq (cp + 1, "tex") || streq (cp + 1, "aux")
866 || streq (cp + 1, "bbl")))
868 TEX_funcs (inf);
869 goto close_and_return;
871 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
872 if (cp && (streq (cp + 1, "l")
873 || streq (cp + 1, "el")
874 || streq (cp + 1, "lsp")
875 || streq (cp + 1, "lisp")
876 || streq (cp + 1, "cl")
877 || streq (cp + 1, "clisp")))
879 L_funcs (inf);
880 goto close_and_return;
882 /* .scm or .sm or .scheme or ... implies scheme source code */
883 if (cp && (streq (cp + 1, "sm")
884 || streq (cp + 1, "scm")
885 || streq (cp + 1, "scheme")
886 || streq (cp + 1, "t")
887 || streq (cp + 1, "sch")
888 || streq (cp + 1, "SM")
889 || streq (cp + 1, "SCM")
890 /* The `SCM' or `scm' prefix with a version number */
891 || (cp[-1] == 'm' && cp[-2] == 'c' && cp[-3] == 's'
892 && string_numeric_p (cp + 1))
893 || (cp[-1] == 'M' && cp[-2] == 'C' && cp[-3] == 'S'
894 && string_numeric_p (cp + 1))))
896 Scheme_funcs (inf);
897 fclose (inf);
898 return;
900 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
901 Or even ".sa". */
902 if (cp && (streq (cp + 1, "s")
903 || streq (cp + 1, "a")
904 || streq (cp + 1, "sa")))
906 Asm_funcs (inf);
907 fclose (inf);
908 return;
910 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
911 if (cp && (streq (cp + 1, "C")
912 || streq (cp + 1, "H")
913 || streq (cp + 1, "cxx")
914 || streq (cp + 1, "hxx")
915 || streq (cp + 1, "cc")))
917 C_entries (C_PLPL); /* C++ */
918 goto close_and_return;
920 /* .cs or .hs: a C* file */
921 if (cp && (streq (cp + 1, "cs")
922 || streq (cp + 1, "hs")))
924 C_entries (C_STAR);
925 goto close_and_return;
927 /* .y: a yacc file */
928 if (cp && (streq (cp + 1, "y")))
930 C_entries (YACC);
931 goto close_and_return;
933 /* .pl implies prolog source code */
934 if (cp && streq (cp + 1, "pl"))
936 prolog_funcs (inf);
937 goto close_and_return;
939 /* .p or .pas: a Pascal file */
940 if (cp && (streq (cp + 1, "p")
941 || streq (cp + 1, "pas")))
943 PAS_funcs (inf);
944 goto close_and_return;
946 /* If .f or .for, assume it is fortran or nothing. */
947 if (cp && (streq (cp + 1, "f")
948 || streq (cp + 1, "for")))
950 PF_funcs (inf);
951 goto close_and_return;
953 /* if not a .c or .h or .y file, try fortran */
954 if (cp && ((cp[1] != 'c'
955 && cp[1] != 'h'
956 && cp[1] != 'y')
957 || (cp[1] != 0 && cp[2] != 0)))
959 if (PF_funcs (inf) != 0)
960 goto close_and_return;
961 rewind (inf); /* no fortran tags found, try C */
963 C_entries (cplusplus ? C_PLPL : 0);
965 close_and_return:
966 (void) fclose (inf);
969 /* Nonzero if string STR is composed of digits. */
972 string_numeric_p (str)
973 char *str;
975 while (*str)
977 if (*str < '0' || *str > '9')
978 return 0;
980 return 1;
983 /* Record a tag. */
984 /* Should take a TOKEN* instead!! */
985 void
986 pfnote (name, is_func, named, linestart, linelen, lno, cno)
987 char *name; /* tag name */
988 logical is_func; /* function or type name? */
989 logical named; /* tag different from text of definition? */
990 char *linestart;
991 int linelen;
992 int lno;
993 long cno;
995 register char *fp;
996 register NODE *np;
997 char tem[51];
998 char c;
1000 np = (NODE *) malloc (sizeof (NODE));
1001 if (np == NULL)
1003 if (!emacs_tags_format)
1005 /* It's okay to output early in etags -- it only disrupts the
1006 * character count of the tag entries, which is no longer used
1007 * by tags.el anyway.
1009 error ("too many entries to sort");
1011 put_entries (head);
1012 free_tree (head);
1013 head = NULL;
1014 np = xnew (1, NODE);
1016 /* If ctags mode, change name "main" to M<thisfilename>. */
1017 if (!emacs_tags_format && !cxref_style && streq (name, "main"))
1019 fp = etags_rindex (curfile, '/');
1020 name = concat ("M", fp == 0 ? curfile : fp + 1, "");
1021 fp = etags_rindex (name, '.');
1022 if (fp && fp[1] != '\0' && fp[2] == '\0')
1023 *fp = 0;
1024 named = TRUE;
1026 np->name = savestr (name);
1027 np->file = curfile;
1028 np->is_func = is_func;
1029 np->named = named;
1030 np->lno = lno;
1031 /* UNCOMMENT THE +1 HERE: */
1032 np->cno = cno /* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
1033 np->left = np->right = 0;
1034 if (emacs_tags_format)
1036 c = linestart[linelen];
1037 linestart[linelen] = 0;
1039 else if (cxref_style == 0)
1041 sprintf (tem, strlen (linestart) < 50 ? "%s$" : "%.50s", linestart);
1042 linestart = tem;
1044 np->pat = savestr (linestart);
1045 if (emacs_tags_format)
1047 linestart[linelen] = c;
1050 add_node (np, &head);
1054 * free_tree ()
1055 * recurse on left children, iterate on right children.
1057 void
1058 free_tree (node)
1059 register NODE *node;
1061 while (node)
1063 register NODE *node_right = node->right;
1064 free_tree (node->left);
1065 free (node->name);
1066 free (node->pat);
1067 free ((char *) node);
1068 node = node_right;
1073 * add_node ()
1074 * Adds a node to the tree of nodes. In etags mode, we don't keep
1075 * it sorted; we just keep a linear list. In ctags mode, maintain
1076 * an ordered tree, with no attempt at balancing.
1078 * add_node is the only function allowed to add nodes, so it can
1079 * maintain state.
1081 /* Must avoid static vars within functions since some systems
1082 #define static as nothing. */
1083 static NODE *last_node = NULL;
1085 void
1086 add_node (node, cur_node_p)
1087 NODE *node, **cur_node_p;
1089 register int dif;
1090 register NODE *cur_node = *cur_node_p;
1092 if (cur_node == NULL)
1094 *cur_node_p = node;
1095 last_node = node;
1096 return;
1099 if (emacs_tags_format)
1101 /* Etags Mode */
1102 if (!last_node)
1103 fatal ("internal error in add_node");
1104 last_node->right = node;
1105 last_node = node;
1107 else
1109 /* Ctags Mode */
1110 dif = strcmp (node->name, cur_node->name);
1113 * If this tag name matches an existing one, then
1114 * do not add the node, but maybe print a warning.
1116 if (!dif)
1118 if (node->file == cur_node->file)
1120 if (!no_warnings)
1122 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1123 node->file, lineno, node->name);
1124 fprintf (stderr, "Second entry ignored\n");
1126 return;
1128 if (!cur_node->been_warned && !no_warnings)
1130 fprintf (stderr,
1131 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1132 node->file, cur_node->file, node->name);
1134 cur_node->been_warned = TRUE;
1135 return;
1138 /* Maybe refuse to add duplicate nodes. */
1139 if (!permit_duplicates)
1141 if (!strcmp (node->name, cur_node->name)
1142 && !strcmp (node->file, cur_node->file))
1143 return;
1146 /* Actually add the node */
1147 add_node (node, dif < 0 ? &cur_node->left : &cur_node->right);
1151 void
1152 put_entries (node)
1153 register NODE *node;
1155 register char *sp;
1157 if (node == NULL)
1158 return;
1160 /* Output subentries that precede this one */
1161 put_entries (node->left);
1163 /* Output this entry */
1165 if (emacs_tags_format)
1167 if (node->named)
1169 fprintf (outf, "%s\177%s\001%d,%d\n",
1170 node->pat, node->name,
1171 node->lno, node->cno);
1173 else
1175 fprintf (outf, "%s\177%d,%d\n",
1176 node->pat,
1177 node->lno, node->cno);
1180 else if (!cxref_style)
1182 fprintf (outf, "%s\t%s\t",
1183 node->name, node->file);
1185 if (node->is_func)
1186 { /* a function */
1187 putc (searchar, outf);
1188 putc ('^', outf);
1190 for (sp = node->pat; *sp; sp++)
1192 if (*sp == '\\' || *sp == searchar)
1193 putc ('\\', outf);
1194 putc (*sp, outf);
1196 putc (searchar, outf);
1198 else
1199 { /* a typedef; text pattern inadequate */
1200 fprintf (outf, "%d", node->lno);
1202 putc ('\n', outf);
1204 else if (vgrind_style)
1205 fprintf (stdout, "%s %s %d\n",
1206 node->name, node->file, (node->lno + 63) / 64);
1207 else
1208 fprintf (stdout, "%-16s %3d %-16s %s\n",
1209 node->name, node->lno, node->file, node->pat);
1211 /* Output subentries that follow this one */
1212 put_entries (node->right);
1215 /* Length of a number's decimal representation. */
1217 number_len (num)
1218 long num;
1220 int len = 0;
1221 if (!num)
1222 return 1;
1223 for (; num; num /= 10)
1224 ++len;
1225 return len;
1229 * Return total number of characters that put_entries will output for
1230 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1231 * is set, but called only in that case. This count is irrelevant with
1232 * the new tags.el, but is still supplied for backward compatibility.
1235 total_size_of_entries (node)
1236 register NODE *node;
1238 register int total;
1240 if (node == NULL)
1241 return 0;
1243 total = 0;
1244 for (; node; node = node->right)
1246 /* Count left subentries. */
1247 total += total_size_of_entries (node->left);
1249 /* Count this entry */
1250 total += strlen (node->pat) + 1;
1251 total += number_len ((long) node->lno) + 1 + number_len (node->cno) + 1;
1252 if (node->named)
1253 total += 1 + strlen (node->name); /* \001name */
1256 return total;
1260 * The C symbol tables.
1263 Stab *C_stab, *C_PLPL_stab, *C_STAR_stab;
1266 * SYNOPSIS
1267 * Stab *get_C_stab (int c_ext);
1269 #define get_C_stab(c_ext) ((c_ext & C_STAR) ? C_STAR_stab : \
1270 (c_ext & C_PLPL) ? C_PLPL_stab : \
1271 C_stab)
1273 void
1274 add_keyword (stab, sym, type)
1275 Stab *stab;
1276 char *sym;
1277 enum sym_type type;
1279 stab_search (stab, sym, strlen (sym))->type = type;
1282 Stab *
1283 C_create_stab (c_ext)
1284 int c_ext;
1286 Stab *stab;
1288 stab = stab_create ();
1290 /* C, C++ and C* */
1291 if (c_ext & C_PLPL)
1292 add_keyword (stab, "class", st_C_struct);
1293 if (c_ext & C_STAR)
1294 add_keyword (stab, "domain", st_C_struct);
1295 add_keyword (stab, "union", st_C_struct);
1296 add_keyword (stab, "struct", st_C_struct);
1297 add_keyword (stab, "enum", st_C_enum);
1298 add_keyword (stab, "typedef", st_C_typedef);
1299 add_keyword (stab, "define", st_C_define);
1300 add_keyword (stab, "long", st_C_typespec);
1301 add_keyword (stab, "short", st_C_typespec);
1302 add_keyword (stab, "int", st_C_typespec);
1303 add_keyword (stab, "char", st_C_typespec);
1304 add_keyword (stab, "float", st_C_typespec);
1305 add_keyword (stab, "double", st_C_typespec);
1306 add_keyword (stab, "signed", st_C_typespec);
1307 add_keyword (stab, "unsigned", st_C_typespec);
1308 add_keyword (stab, "auto", st_C_typespec);
1309 add_keyword (stab, "void", st_C_typespec);
1310 add_keyword (stab, "extern", st_C_typespec);
1311 add_keyword (stab, "static", st_C_typespec);
1312 add_keyword (stab, "const", st_C_typespec);
1313 add_keyword (stab, "volatile", st_C_typespec);
1315 return stab;
1318 void
1319 C_create_stabs ()
1321 C_stab = C_create_stab (0);
1322 C_PLPL_stab = C_create_stab (C_PLPL);
1323 C_STAR_stab = C_create_stab (C_STAR | C_PLPL);
1327 * C functions are recognized using a simple finite automaton.
1328 * funcdef is its state variable.
1330 typedef enum
1332 fnone, /* nothing seen */
1333 ftagseen, /* function-like tag seen */
1334 fstartlist, /* just after open parenthesis */
1335 finlist, /* in parameter list */
1336 flistseen, /* after parameter list */
1337 fignore /* before open brace */
1338 } FUNCST;
1339 FUNCST funcdef;
1342 /* typedefs are recognized using a simple finite automaton.
1343 * typeddef is its state variable.
1345 typedef enum
1347 tnone, /* nothing seen */
1348 ttypedseen, /* typedef keyword seen */
1349 tinbody, /* inside typedef body */
1350 tend /* just before typedef tag */
1351 } TYPEDST;
1352 TYPEDST typdef;
1355 /* struct tags for C++ are recognized using another simple
1356 * finite automaton. `structdef' is its state variable.
1357 * This machinery is only invoked for C++; otherwise structdef
1358 * should remain snone. However, this machinery can easily be
1359 * adapted to find structure tags in normal C code.
1361 typedef enum
1363 snone, /* nothing seen yet */
1364 skeyseen, /* struct-like keyword seen */
1365 stagseen, /* struct-like tag seen */
1366 scolonseen, /* colon seen after struct-like tag */
1367 sinbody /* in struct body: recognize member func defs*/
1368 } STRUCTST;
1369 STRUCTST structdef;
1371 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1372 * struct tag, and structkey is the preceding struct-like keyword.
1374 char structtag[BUFSIZ];
1375 Stab_entry *structkey;
1378 * Yet another little state machine to deal with preprocessor lines.
1380 typedef enum
1382 dnone, /* nothing seen */
1383 dsharpseen, /* '#' seen as first char on line */
1384 ddefineseen, /* '#' and 'define' seen */
1385 dignorerest /* ignore rest of line */
1386 } DEFINEST;
1387 DEFINEST definedef;
1390 * Set this to TRUE, and the next token considered is called a function.
1391 * Used only for GNUmacs's function-defining macros.
1393 logical next_token_is_func;
1396 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1398 logical yacc_rules;
1401 * C_entries ()
1402 * This routine finds functions, typedefs, #define's and
1403 * struct/union/enum definitions in C syntax and adds them
1404 * to the list.
1407 #define curlb (lbs[curndx].lb)
1408 #define othlb (lbs[1-curndx].lb)
1409 #define newlb (lbs[newndx].lb)
1410 #define curlinepos (lbs[curndx].linepos)
1411 #define othlinepos (lbs[1-curndx].linepos)
1412 #define newlinepos (lbs[newndx].linepos)
1414 /* Save and restore token state. This is used when preprocessor defines
1415 are handled, to avoid disturbing active function/typedef/struct states. */
1416 #define TOKEN_SAVED_P (savetok.lineno > 0)
1417 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1418 savetok.len = toklen, strcpy(savenameb, nameb))
1419 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1420 toklen = tok.len, strcpy(nameb, savenameb), \
1421 savetok.lineno = 0)
1423 #define CNL_SAVE_DEFINEDEF \
1424 do { \
1425 SET_FILEPOS (curlinepos, inf, charno); \
1426 lineno++; \
1427 charno += readline (&curlb, inf); \
1428 lp = curlb.buffer; \
1429 quotednl = FALSE; \
1430 newndx = curndx; \
1431 } while (FALSE)
1433 #define CNL \
1434 do { \
1435 CNL_SAVE_DEFINEDEF; \
1436 if (TOKEN_SAVED_P) \
1437 RESTORE_TOKEN; \
1438 definedef = dnone; \
1439 } while (FALSE)
1441 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1442 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1443 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1444 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1446 void
1447 C_entries (c_ext)
1448 int c_ext; /* extension of C? */
1450 register char c; /* latest char read; '\0' for end of line */
1451 register char *lp; /* pointer one beyond the character `c' */
1452 int curndx, newndx; /* indices for current and new lb */
1453 TOKEN tok; /* latest token read for funcdef & structdef */
1454 char nameb[BUFSIZ]; /* latest token name for funcdef & structdef */
1455 register int tokoff; /* offset in line of start of latest token */
1456 register int toklen; /* length of latest token */
1457 int cblev; /* current curly brace level */
1458 int parlev; /* current parenthesis level */
1459 logical incomm, inquote, inchar, quotednl, midtoken;
1460 logical cplpl;
1461 TOKEN savetok; /* saved token during preprocessor handling */
1462 logical saveisfunc;
1463 char savenameb[BUFSIZ]; /* ouch! */
1465 savetok.lineno = 0;
1466 curndx = newndx = 0;
1467 lineno = 0;
1468 charno = 0;
1469 lp = curlb.buffer;
1470 *lp = 0;
1472 definedef = dnone; funcdef = fnone; typdef= tnone; structdef= snone;
1473 next_token_is_func = yacc_rules = FALSE;
1474 midtoken = inquote = inchar = incomm = quotednl = FALSE;
1475 cblev = 0;
1476 parlev = 0;
1477 cplpl = c_ext & C_PLPL;
1479 C_create_stabs ();
1481 while (!feof (inf))
1483 c = *lp++;
1484 if (c == '\\')
1486 /* If we're at the end of the line, the next character is a
1487 '\0'; don't skip it, because it's the thing that tells us
1488 to read the next line. */
1489 if (*lp == '\0')
1491 quotednl = TRUE;
1492 continue;
1494 lp++;
1495 c = ' ';
1497 else if (incomm)
1499 switch (c)
1501 case '*':
1502 if (*lp == '/')
1504 c = *lp++;
1505 incomm = FALSE;
1507 break;
1508 case '\0':
1509 /* Newlines inside comments do not end macro definitions in
1510 traditional cpp. */
1511 CNL_SAVE_DEFINEDEF;
1512 break;
1514 continue;
1516 else if (inquote)
1518 switch (c)
1520 case '"':
1521 inquote = FALSE;
1522 break;
1523 case '\0':
1524 /* Newlines inside strings, do not end macro definitions
1525 in traditional cpp, even though compilers don't
1526 usually accept them. */
1527 CNL_SAVE_DEFINEDEF;
1528 break;
1530 continue;
1532 else if (inchar)
1534 if (c == '\'')
1535 inchar = FALSE;
1536 continue;
1538 else
1539 switch (c)
1541 case '"':
1542 inquote = TRUE;
1543 if (funcdef != finlist && funcdef != fignore)
1544 funcdef = fnone;
1545 continue;
1546 case '\'':
1547 inchar = TRUE;
1548 if (funcdef != finlist && funcdef != fignore)
1549 funcdef = fnone;
1550 continue;
1551 case '/':
1552 if (*lp == '*')
1554 lp++;
1555 incomm = TRUE;
1556 continue;
1558 else if (cplpl && *lp == '/')
1560 c = 0;
1561 break;
1563 else
1564 break;
1565 case '%':
1566 if ((c_ext & YACC) && *lp == '%')
1568 /* entering or exiting rules section in yacc file */
1569 lp++;
1570 definedef = dnone; funcdef = fnone;
1571 typdef= tnone; structdef= snone;
1572 next_token_is_func = FALSE;
1573 midtoken = inquote = inchar = incomm = quotednl = FALSE;
1574 cblev = 0;
1575 yacc_rules = !yacc_rules;
1576 continue;
1578 else
1579 break;
1580 case '#':
1581 if (lp == newlb.buffer + 1 && definedef == dnone)
1582 definedef = dsharpseen;
1583 continue;
1584 } /* switch (c) */
1587 /* Consider token only if some complicated conditions are satisfied. */
1588 if (((cblev == 0 && structdef != scolonseen)
1589 || (cblev == 1 && cplpl && structdef == sinbody))
1590 && definedef != dignorerest
1591 && (funcdef != finlist
1592 || (definedef != dnone && definedef != dignorerest)))
1594 if (midtoken)
1596 if (endtoken (c))
1598 if (cplpl && c == ':' && *lp == ':' && begtoken(*(lp + 1)))
1601 * This handles :: in the middle, but not at beginning
1602 * of an identifier.
1604 lp += 2;
1605 toklen += 3;
1607 else
1609 logical is_func = FALSE;
1611 tok.lineno = lineno;
1612 tok.p = newlb.buffer + tokoff;
1613 tok.len = toklen;
1614 tok.named = FALSE;
1615 if (yacc_rules
1616 || consider_token (c, lp, &tok,
1617 c_ext, cblev, &is_func))
1619 if (structdef == sinbody
1620 && definedef == dnone
1621 && is_func)
1622 /* function defined in C++ class body */
1624 tok.named = TRUE;
1625 sprintf (nameb, "%s::%.*s",
1626 ((structtag[0] == '\0')
1627 ? "_anonymous_" : structtag),
1628 tok.len, tok.p);
1630 else
1632 sprintf (nameb, "%.*s", tok.len, tok.p);
1635 if (structdef == stagseen
1636 || typdef == tend)
1637 tok.named = TRUE;
1639 if (definedef == dnone
1640 && (funcdef == ftagseen
1641 || structdef == stagseen
1642 || typdef == tend))
1644 if (newndx == curndx)
1645 curndx = 1 - curndx; /* switch line buffers */
1647 else
1648 MAKE_TAG_FROM_NEW_LB (is_func);
1650 midtoken = FALSE;
1652 } /* if (endtoken (c)) */
1653 else if (intoken (c))
1655 toklen++;
1656 continue;
1658 } /* if (midtoken) */
1659 else if (begtoken (c))
1661 switch (definedef)
1663 case dnone:
1664 switch (funcdef)
1666 case fstartlist:
1667 funcdef = finlist;
1668 continue;
1669 case flistseen:
1670 MAKE_TAG_FROM_OTH_LB (TRUE);
1671 funcdef = fignore;
1672 break;
1673 case ftagseen:
1674 funcdef = fnone;
1675 break;
1677 if (structdef == stagseen)
1678 structdef = snone;
1679 break;
1680 case dsharpseen:
1681 /* Take a quick peek ahead for define directive,
1682 so we can avoid saving the token when not absolutely
1683 necessary. [This is a speed hack.] */
1684 if (c == 'd' && strneq(lp, "efine", 5)
1685 && iswhite(*(lp + 5)))
1687 SAVE_TOKEN;
1688 definedef = ddefineseen;
1689 lp += 6;
1691 else
1692 definedef = dignorerest;
1693 continue;
1695 if (!yacc_rules || lp == newlb.buffer + 1)
1697 tokoff = lp - 1 - newlb.buffer;
1698 toklen = 1;
1699 midtoken = TRUE;
1701 continue;
1703 } /* if must look at token */
1706 /* Detect end of line, colon, comma, semicolon and various braces
1707 after having handled a token.*/
1708 switch (c)
1710 case ':':
1711 if (definedef != dnone)
1712 break;
1713 if (structdef == stagseen)
1714 structdef = scolonseen;
1715 else
1716 switch (funcdef)
1718 case ftagseen:
1719 if (yacc_rules)
1721 MAKE_TAG_FROM_OTH_LB (FALSE);
1722 funcdef = fignore;
1724 break;
1725 case fstartlist:
1726 funcdef = fnone;
1727 break;
1729 break;
1730 case ';':
1731 if (definedef != dnone)
1732 break;
1733 if (cblev == 0 && typdef == tend)
1735 typdef = tnone;
1736 MAKE_TAG_FROM_OTH_LB (FALSE);
1738 if (funcdef != fignore)
1739 funcdef = fnone;
1740 /* FALLTHRU */
1741 case ',':
1742 /* FALLTHRU */
1743 case '[':
1744 if (definedef != dnone)
1745 break;
1746 if (funcdef != finlist && funcdef != fignore)
1747 funcdef = fnone;
1748 if (structdef == stagseen)
1749 structdef = snone;
1750 break;
1751 case '(':
1752 if (definedef != dnone)
1753 break;
1754 switch (funcdef)
1756 case ftagseen:
1757 funcdef = fstartlist;
1758 break;
1759 case flistseen:
1760 funcdef = finlist;
1761 break;
1763 parlev++;
1764 break;
1765 case ')':
1766 if (definedef != dnone)
1767 break;
1768 if (--parlev == 0)
1770 switch (funcdef)
1772 case fstartlist:
1773 case finlist:
1774 funcdef = flistseen;
1775 break;
1778 else if (parlev < 0) /* can happen due to ill-conceived #if's. */
1779 parlev = 0;
1780 break;
1781 case '{':
1782 if (definedef != dnone)
1783 break;
1784 if (typdef == ttypedseen)
1785 typdef = tinbody;
1786 switch (structdef)
1788 case skeyseen: /* unnamed struct */
1789 structtag[0] = '\0';
1790 structdef = sinbody;
1791 break;
1792 case stagseen:
1793 case scolonseen: /* named struct */
1794 structdef = sinbody;
1795 MAKE_TAG_FROM_OTH_LB (FALSE);
1796 break;
1798 switch (funcdef)
1800 case flistseen:
1801 MAKE_TAG_FROM_OTH_LB (TRUE);
1802 /* FALLTHRU */
1803 case fignore:
1804 funcdef = fnone;
1806 cblev++;
1807 break;
1808 case '*':
1809 if (definedef != dnone)
1810 break;
1811 if (funcdef == fstartlist)
1812 funcdef = fnone; /* avoid tagging `foo' in `foo (*bar()) ()' */
1813 break;
1814 case '}':
1815 if (definedef != dnone)
1816 break;
1817 if (!noindentypedefs && lp == newlb.buffer + 1)
1819 cblev = 0; /* reset curly brace level if first column */
1820 parlev = 0; /* also reset paren level, just in case... */
1822 else if (cblev > 0)
1823 cblev--;
1824 if (cblev == 0)
1826 if (typdef == tinbody)
1827 typdef = tend;
1828 structdef = snone;
1829 (void) strcpy (structtag, "<error 2>");
1831 break;
1832 case '=':
1833 case '#':
1834 case '+':
1835 case '-':
1836 case '~':
1837 case '&':
1838 case '%':
1839 case '/':
1840 case '|':
1841 case '^':
1842 case '!':
1843 case '<':
1844 case '>':
1845 case '.':
1846 case '?':
1847 if (definedef != dnone)
1848 break;
1849 /* These surely cannot follow a function tag. */
1850 if (funcdef != finlist && funcdef != fignore)
1851 funcdef = fnone;
1852 break;
1853 case '\0':
1854 /* If a macro spans multiple lines don't reset its state. */
1855 if (quotednl)
1856 CNL_SAVE_DEFINEDEF;
1857 else
1858 CNL;
1859 break;
1860 } /* switch (c) */
1862 } /* while not eof */
1866 * consider_token ()
1867 * checks to see if the current token is at the start of a
1868 * function, or corresponds to a typedef, or is a struct/union/enum
1869 * tag.
1871 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1872 * C_EXT is which language we are looking at.
1874 * In the future we will need some way to adjust where the end of
1875 * the token is; for instance, implementing the C++ keyword
1876 * `operator' properly will adjust the end of the token to be after
1877 * whatever follows `operator'.
1879 * Globals
1880 * funcdef IN OUT
1881 * structdef IN OUT
1882 * definedef IN OUT
1883 * typdef IN OUT
1884 * next_token_is_func IN OUT
1887 logical
1888 consider_token (c, lp, tokp, c_ext, cblev, is_func)
1889 register char c; /* IN: first char after the token */
1890 register char *lp; /* IN: lp points to 2nd char after the token */
1891 register TOKEN *tokp; /* IN: token pointer */
1892 int c_ext; /* IN: C extensions mask */
1893 int cblev; /* IN: curly brace level */
1894 logical *is_func; /* OUT */
1896 Stab_entry *tokse = stab_find (get_C_stab (c_ext), tokp->p, tokp->len);
1897 enum sym_type toktype = stab_type (tokse);
1900 * Advance the definedef state machine.
1902 switch (definedef)
1904 case dnone:
1905 /* We're not on a preprocessor line. */
1906 break;
1907 case dsharpseen:
1908 if (toktype == st_C_define)
1910 definedef = ddefineseen;
1912 else
1914 definedef = dignorerest;
1916 return (FALSE);
1917 case ddefineseen:
1919 * Make a tag for any macro.
1921 definedef = dignorerest;
1922 *is_func = (c == '(');
1923 if (!*is_func && !constantypedefs)
1924 return (FALSE);
1925 else
1926 return (TRUE);
1927 case dignorerest:
1928 return (FALSE);
1929 default:
1930 error ("internal error: definedef value");
1934 * Now typedefs
1936 switch (typdef)
1938 case tnone:
1939 if (toktype == st_C_typedef)
1941 if (typedefs)
1942 typdef = ttypedseen;
1943 return (FALSE);
1945 break;
1946 case ttypedseen:
1947 switch (toktype)
1949 case st_none:
1950 case st_C_typespec:
1951 typdef = tend;
1952 break;
1953 case st_C_struct:
1954 case st_C_enum:
1955 break;
1957 /* Do not return here, so the structdef stuff has a chance. */
1958 break;
1959 case tend:
1960 switch (toktype)
1962 case st_C_typespec:
1963 case st_C_struct:
1964 case st_C_enum:
1965 return (FALSE);
1967 return (TRUE);
1971 * This structdef business is currently only invoked when cblev==0.
1972 * It should be recursively invoked whatever the curly brace level,
1973 * and a stack of states kept, to allow for definitions of structs
1974 * within structs.
1976 * This structdef business is NOT invoked when we are ctags and the
1977 * file is plain C. This is because a struct tag may have the same
1978 * name as another tag, and this loses with ctags.
1980 * This if statement deals with the typdef state machine as
1981 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1982 * return (FALSE). All the other code here is for the structdef
1983 * state machine.
1985 switch (toktype)
1987 case st_C_struct:
1988 case st_C_enum:
1989 if (typdef == ttypedseen
1990 || (typedefs_and_cplusplus && cblev == 0 && structdef == snone))
1992 structdef = skeyseen;
1993 structkey = tokse;
1995 return (FALSE);
1997 if (structdef == skeyseen)
1999 if (stab_type (structkey) == st_C_struct)
2001 (void) strncpy (structtag, tokp->p, tokp->len);
2002 structtag[tokp->len] = '\0'; /* for struct/union/class */
2004 else
2006 structtag[0] = '\0'; /* for enum (why is it treated differently?) */
2008 structdef = stagseen;
2009 return (TRUE);
2012 /* Avoid entering funcdef stuff if typdef is going on. */
2013 if (typdef != tnone)
2015 definedef = dnone;
2016 return (FALSE);
2019 /* Detect GNUmacs's function-defining macros. */
2020 if (definedef == dnone)
2022 if (strneq (tokp->p, "DEF", 3)
2023 || strneq (tokp->p, "ENTRY", 5)
2024 || strneq (tokp->p, "SYSCALL", 7)
2025 || strneq (tokp->p, "PSEUDO", 6))
2027 next_token_is_func = TRUE;
2028 return (FALSE);
2030 if (strneq (tokp->p, "EXFUN", 5))
2032 next_token_is_func = FALSE;
2033 return (FALSE);
2036 if (next_token_is_func)
2038 next_token_is_func = FALSE;
2039 funcdef = fnone;
2040 *is_func = TRUE; /* to force search string in ctags */
2041 return (TRUE);
2044 /* A function? */
2045 switch (toktype)
2047 case st_C_typespec:
2048 funcdef = fnone; /* should be useless */
2049 return (FALSE);
2050 default:
2051 if (funcdef == fnone)
2053 funcdef = ftagseen;
2054 *is_func = TRUE;
2055 return (TRUE);
2059 return (FALSE);
2062 /* Fortran parsing */
2064 char *dbp;
2065 int pfcnt;
2068 PF_funcs (fi)
2069 FILE *fi;
2071 lineno = 0;
2072 charno = 0;
2073 pfcnt = 0;
2075 while (!feof (fi))
2077 lineno++;
2078 linecharno = charno;
2079 charno += readline (&lb, fi);
2080 dbp = lb.buffer;
2081 if (*dbp == '%')
2082 dbp++; /* Ratfor escape to fortran */
2083 while (isspace (*dbp))
2084 dbp++;
2085 if (*dbp == 0)
2086 continue;
2087 switch (*dbp | ' ')
2089 case 'i':
2090 if (tail ("integer"))
2091 takeprec ();
2092 break;
2093 case 'r':
2094 if (tail ("real"))
2095 takeprec ();
2096 break;
2097 case 'l':
2098 if (tail ("logical"))
2099 takeprec ();
2100 break;
2101 case 'c':
2102 if (tail ("complex") || tail ("character"))
2103 takeprec ();
2104 break;
2105 case 'd':
2106 if (tail ("double"))
2108 while (isspace (*dbp))
2109 dbp++;
2110 if (*dbp == 0)
2111 continue;
2112 if (tail ("precision"))
2113 break;
2114 continue;
2116 break;
2118 while (isspace (*dbp))
2119 dbp++;
2120 if (*dbp == 0)
2121 continue;
2122 switch (*dbp | ' ')
2124 case 'f':
2125 if (tail ("function"))
2126 getit ();
2127 continue;
2128 case 's':
2129 if (tail ("subroutine"))
2130 getit ();
2131 continue;
2132 case 'e':
2133 if (tail ("entry"))
2134 getit ();
2135 continue;
2136 case 'p':
2137 if (tail ("program"))
2139 getit ();
2140 continue;
2142 if (tail ("procedure"))
2143 getit ();
2144 continue;
2147 return (pfcnt);
2150 logical
2151 tail (cp)
2152 char *cp;
2154 register int len = 0;
2156 while (*cp && (*cp & ~' ') == ((*(dbp + len)) & ~' '))
2157 cp++, len++;
2158 if (*cp == 0)
2160 dbp += len;
2161 return (1);
2163 return (0);
2166 void
2167 takeprec ()
2169 while (isspace (*dbp))
2170 dbp++;
2171 if (*dbp != '*')
2172 return;
2173 dbp++;
2174 while (isspace (*dbp))
2175 dbp++;
2176 if (!isdigit (*dbp))
2178 --dbp; /* force failure */
2179 return;
2182 dbp++;
2183 while (isdigit (*dbp));
2186 void
2187 getit ()
2189 register char *cp;
2190 char c;
2191 char nambuf[BUFSIZ];
2193 while (isspace (*dbp))
2194 dbp++;
2195 if (*dbp == 0
2196 || (!isalpha (*dbp)
2197 && *dbp != '_'
2198 && *dbp != '$'))
2199 return;
2200 for (cp = dbp + 1; *cp && (isalpha (*cp) || isdigit (*cp)
2201 || (*cp == '_') || (*cp == '$')); cp++)
2202 continue;
2203 c = cp[0];
2204 cp[0] = 0;
2205 (void) strcpy (nambuf, dbp);
2206 cp[0] = c;
2207 pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
2208 pfcnt++;
2211 /* Handle a file of assembler code. */
2213 void
2214 Asm_funcs (fi)
2215 FILE *fi;
2217 int i;
2218 register char c;
2220 lineno = 0;
2221 charno = 0;
2222 pfcnt = 0;
2224 while (!feof (fi))
2226 lineno++;
2227 linecharno = charno;
2228 charno += readline (&lb, fi);
2229 dbp = lb.buffer;
2231 for (i = 0; ((c = dbp[i]) && !isspace (c)) && (c != ':'); i++)
2234 if ((i > 0) && (c == ':'))
2235 getit ();
2239 /* Added by Mosur Mohan, 4/22/88 */
2240 /* Pascal parsing */
2242 #define GET_NEW_LINE \
2244 linecharno = charno; lineno++; \
2245 charno += 1 + readline (&lb, inf); \
2246 dbp = lb.buffer; \
2249 /* Locates tags for procedures & functions.
2250 * Doesn't do any type- or var-definitions.
2251 * It does look for the keyword "extern" or "forward"
2252 * immediately following the procedure statement;
2253 * if found, the tag is skipped.
2256 void
2257 PAS_funcs (fi)
2258 FILE *fi;
2260 struct linebuffer tline; /* mostly copied from C_entries */
2261 long save_lcno;
2262 int save_lineno;
2263 char c, *cp;
2264 char nambuf[BUFSIZ];
2266 logical /* each of these flags is TRUE iff: */
2267 incomm1, /* point is inside {..} comment */
2268 incomm2, /* point is inside (*..*) comment */
2269 inquote, /* point is inside '..' string */
2270 get_tagname, /* point is after PROCEDURE/FUNCTION */
2271 /* keyword, so next item = potential tag */
2272 found_tag, /* point is after a potential tag */
2273 inparms, /* point is within parameter-list */
2274 verify_tag; /* point has passed the parm-list, so the */
2275 /* next token will determine whether */
2276 /* this is a FORWARD/EXTERN to be */
2277 /* ignored, or whether it is a real tag */
2279 lineno = 0;
2280 charno = 0;
2281 dbp = lb.buffer;
2282 *dbp = 0;
2283 initbuffer (&tline);
2285 incomm1 = incomm2 = inquote = FALSE;
2286 found_tag = FALSE; /* have a proc name; check if extern */
2287 get_tagname = FALSE; /* have found "procedure" keyword */
2288 inparms = FALSE; /* found '(' after "proc" */
2289 verify_tag = FALSE; /* check if "extern" is ahead */
2291 /* long main loop to get next char */
2292 while (!feof (fi))
2294 c = *dbp++;
2295 if (c == 0) /* if end of line */
2297 GET_NEW_LINE;
2298 if (*dbp == 0)
2299 continue;
2300 if (!((found_tag && verify_tag) ||
2301 get_tagname))
2302 c = *dbp++; /* only if don't need *dbp pointing */
2303 /* to the beginning of the name of */
2304 /* the procedure or function */
2306 if (incomm1) /* within { - } comments */
2308 if (c == '}')
2309 incomm1 = FALSE;
2310 continue;
2312 else if (incomm2) /* within (* - *) comments */
2314 if (c == '*')
2316 while ((c = *dbp++) == '*')
2317 continue;
2318 if (c == 0)
2319 GET_NEW_LINE;
2320 if (c == ')')
2321 incomm2 = FALSE;
2323 continue;
2325 else if (inquote)
2327 if (c == '\'')
2328 inquote = FALSE;
2329 continue;
2331 else
2332 switch (c)
2334 case '\'':
2335 inquote = TRUE; /* found first quote */
2336 continue;
2337 case '{': /* found open-{-comment */
2338 incomm1 = TRUE;
2339 continue;
2340 case '(':
2341 if (*dbp == '*') /* found open-(*-comment */
2343 incomm2 = TRUE;
2344 dbp++;
2346 else if (found_tag) /* found '(' after tag, i.e., parm-list */
2347 inparms = TRUE;
2348 continue;
2349 case ')': /* end of parms list */
2350 if (inparms)
2351 inparms = FALSE;
2352 continue;
2353 case ';':
2354 if ((found_tag) && (!inparms)) /* end of proc or fn stmt */
2356 verify_tag = TRUE;
2357 break;
2359 continue;
2361 if ((found_tag) && (verify_tag) && (*dbp != ' '))
2363 /* check if this is an "extern" declaration */
2364 if (*dbp == 0)
2365 continue;
2366 if ((*dbp == 'e') || (*dbp == 'E'))
2368 if (tail ("extern")) /* superfluous, really! */
2370 found_tag = FALSE;
2371 verify_tag = FALSE;
2374 else if ((*dbp == 'f') || (*dbp == 'F'))
2376 if (tail ("forward")) /* check for forward reference */
2378 found_tag = FALSE;
2379 verify_tag = FALSE;
2382 if ((found_tag) && (verify_tag)) /* not external proc, so make tag */
2384 found_tag = FALSE;
2385 verify_tag = FALSE;
2386 pfnote (nambuf, TRUE, FALSE,
2387 tline.buffer, cp - tline.buffer + 1,
2388 save_lineno, save_lcno);
2389 continue;
2392 if (get_tagname) /* grab name of proc or fn */
2394 if (*dbp == 0)
2395 continue;
2397 /* save all values for later tagging */
2398 tline.size = lb.size;
2399 strcpy (tline.buffer, lb.buffer);
2400 save_lineno = lineno;
2401 save_lcno = linecharno;
2403 /* grab block name */
2404 for (cp = dbp + 1; *cp && (!endtoken (*cp)); cp++)
2405 continue;
2406 c = cp[0];
2407 cp[0] = 0;
2408 strcpy (nambuf, dbp);
2409 cp[0] = c;
2410 dbp = cp; /* restore dbp to e-o-token */
2411 get_tagname = FALSE;
2412 found_tag = TRUE;
2413 continue;
2415 /* and proceed to check for "extern" */
2417 if ((!incomm1) && (!incomm2) && (!inquote) &&
2418 (!found_tag) && (!get_tagname))
2420 /* check for proc/fn keywords */
2421 switch (c | ' ')
2423 case 'p':
2424 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2425 get_tagname = TRUE;
2426 continue;
2427 case 'f':
2428 if (tail ("unction"))
2429 get_tagname = TRUE;
2430 continue;
2433 } /* while not e-o-f */
2437 * lisp tag functions
2438 * just look for (def or (DEF
2441 void
2442 L_funcs (fi)
2443 FILE *fi;
2445 lineno = 0;
2446 charno = 0;
2447 pfcnt = 0;
2449 while (!feof (fi))
2451 lineno++;
2452 linecharno = charno;
2453 charno += readline (&lb, fi);
2454 dbp = lb.buffer;
2455 if (dbp[0] == '(')
2457 if (L_isdef (dbp))
2459 while (!isspace (*dbp))
2460 dbp++;
2461 while (isspace (*dbp))
2462 dbp++;
2463 L_getit ();
2465 else
2467 /* Check for (foo::defmumble name-defined ... */
2469 dbp++;
2470 while (*dbp && !isspace (*dbp)
2471 && *dbp != ':' && *dbp != '(' && *dbp != ')');
2472 if (*dbp == ':')
2475 dbp++;
2476 while (*dbp == ':');
2478 if (L_isdef (dbp - 1))
2480 while (!isspace (*dbp))
2481 dbp++;
2482 while (isspace (*dbp))
2483 dbp++;
2484 L_getit ();
2493 L_isdef (dbp)
2494 register char *dbp;
2496 return ((dbp[1] == 'd' || dbp[1] == 'D')
2497 && (dbp[2] == 'e' || dbp[2] == 'E')
2498 && (dbp[3] == 'f' || dbp[3] == 'F'));
2502 L_isquote (dbp)
2503 register char *dbp;
2505 return ((*(++dbp) == 'q' || *dbp == 'Q')
2506 && (*(++dbp) == 'u' || *dbp == 'U')
2507 && (*(++dbp) == 'o' || *dbp == 'O')
2508 && (*(++dbp) == 't' || *dbp == 'T')
2509 && (*(++dbp) == 'e' || *dbp == 'E')
2510 && isspace(*(++dbp)));
2513 void
2514 L_getit ()
2516 register char *cp;
2517 char c;
2518 char nambuf[BUFSIZ];
2520 if (*dbp == '\'') /* Skip prefix quote */
2521 dbp++;
2522 else if (*dbp == '(' && L_isquote (dbp)) /* Skip "(quote " */
2524 dbp += 7;
2525 while (isspace(*dbp))
2526 dbp++;
2528 for (cp = dbp /*+1*/; *cp && *cp != '(' && *cp != ' ' && *cp != ')'; cp++)
2529 continue;
2530 if (cp == dbp)
2531 return;
2533 c = cp[0];
2534 cp[0] = 0;
2535 (void) strcpy (nambuf, dbp);
2536 cp[0] = c;
2537 pfnote (nambuf, TRUE, FALSE, lb.buffer,
2538 cp - lb.buffer + 1, lineno, linecharno);
2539 pfcnt++;
2543 * Scheme tag functions
2544 * look for (def... xyzzy
2545 * look for (def... (xyzzy
2546 * look for (def ... ((...(xyzzy ....
2547 * look for (set! xyzzy
2550 static void get_scheme ();
2552 void
2553 Scheme_funcs (fi)
2554 FILE *fi;
2556 lineno = 0;
2557 charno = 0;
2558 pfcnt = 0;
2560 while (!feof (fi))
2562 lineno++;
2563 linecharno = charno;
2564 charno += readline (&lb, fi);
2565 dbp = lb.buffer;
2566 if (dbp[0] == '(' &&
2567 (dbp[1] == 'D' || dbp[1] == 'd') &&
2568 (dbp[2] == 'E' || dbp[2] == 'e') &&
2569 (dbp[3] == 'F' || dbp[3] == 'f'))
2571 while (!isspace (*dbp))
2572 dbp++;
2573 /* Skip over open parens and white space */
2574 while (*dbp && (isspace (*dbp) || *dbp == '('))
2575 dbp++;
2576 get_scheme ();
2578 if (dbp[0] == '(' &&
2579 (dbp[1] == 'S' || dbp[1] == 's') &&
2580 (dbp[2] == 'E' || dbp[2] == 'e') &&
2581 (dbp[3] == 'T' || dbp[3] == 't') &&
2582 (dbp[4] == '!' || dbp[4] == '!') &&
2583 (isspace (dbp[5])))
2585 while (!isspace (*dbp))
2586 dbp++;
2587 /* Skip over white space */
2588 while (isspace (*dbp))
2589 dbp++;
2590 get_scheme ();
2595 static void
2596 get_scheme ()
2598 register char *cp;
2599 char c;
2600 char nambuf[BUFSIZ];
2602 if (*dbp == 0)
2603 return;
2604 /* Go till you get to white space or a syntactic break */
2605 for (cp = dbp + 1; *cp && *cp != '(' && *cp != ')' && !isspace (*cp); cp++)
2606 continue;
2607 /* Null terminate the string there. */
2608 c = cp[0];
2609 cp[0] = 0;
2610 /* Copy the string */
2611 strcpy (nambuf, dbp);
2612 /* Unterminate the string */
2613 cp[0] = c;
2614 /* Announce the change */
2615 pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
2616 pfcnt++;
2619 /* Find tags in TeX and LaTeX input files. */
2621 /* TEX_toktab is a table of TeX control sequences that define tags.
2622 Each TEX_tabent records one such control sequence.
2623 CONVERT THIS TO USE THE Stab TYPE!! */
2625 struct TEX_tabent
2627 char *name;
2628 int len;
2631 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
2633 /* Default set of control sequences to put into TEX_toktab.
2634 The value of environment var TEXTAGS is prepended to this. */
2636 static char *TEX_defenv =
2637 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2639 void TEX_mode ();
2640 struct TEX_tabent *TEX_decode_env ();
2641 void TEX_getit ();
2642 int TEX_Token ();
2644 static char TEX_esc = '\\';
2645 static char TEX_opgrp = '{';
2646 static char TEX_clgrp = '}';
2649 * TeX/LaTeX scanning loop.
2652 void
2653 TEX_funcs (fi)
2654 FILE *fi;
2656 char *lasthit;
2658 lineno = 0;
2659 charno = 0;
2660 pfcnt = 0;
2662 /* Select either \ or ! as escape character. */
2663 TEX_mode (fi);
2665 /* Initialize token table once from environment. */
2666 if (!TEX_toktab)
2667 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
2669 while (!feof (fi))
2670 { /* Scan each line in file */
2671 lineno++;
2672 linecharno = charno;
2673 charno += readline (&lb, fi);
2674 dbp = lb.buffer;
2675 lasthit = dbp;
2676 while (dbp = etags_index (dbp, TEX_esc)) /* Look at each escape in line */
2678 register int i;
2680 if (!*(++dbp))
2681 break;
2682 linecharno += dbp - lasthit;
2683 lasthit = dbp;
2684 i = TEX_Token (lasthit);
2685 if (0 <= i)
2687 TEX_getit (lasthit, TEX_toktab[i].len);
2688 break; /* We only save a line once */
2694 #define TEX_LESC '\\'
2695 #define TEX_SESC '!'
2696 #define TEX_cmt '%'
2698 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2699 /* chars accordingly. */
2701 void
2702 TEX_mode (f)
2703 FILE *f;
2705 int c;
2707 while ((c = getc (f)) != EOF)
2709 /* Skip to next line if we hit the TeX comment char. */
2710 if (c == TEX_cmt)
2711 while (c != '\n')
2712 c = getc (f);
2713 else if (c == TEX_LESC || c == TEX_SESC )
2714 break;
2717 if (c == TEX_LESC)
2719 TEX_esc = TEX_LESC;
2720 TEX_opgrp = '{';
2721 TEX_clgrp = '}';
2723 else
2725 TEX_esc = TEX_SESC;
2726 TEX_opgrp = '<';
2727 TEX_clgrp = '>';
2729 rewind (f);
2732 /* Read environment and prepend it to the default string. */
2733 /* Build token table. */
2735 struct TEX_tabent *
2736 TEX_decode_env (evarname, defenv)
2737 char *evarname;
2738 char *defenv;
2740 register char *env, *p;
2742 struct TEX_tabent *tab;
2743 int size, i;
2745 /* Append default string to environment. */
2746 env = getenv (evarname);
2747 if (!env)
2748 env = defenv;
2749 else
2750 env = concat (env, defenv, "");
2752 /* Allocate a token table */
2753 for (size = 1, p = env; p;)
2754 if ((p = etags_index (p, ':')) && *(++p))
2755 size++;
2756 /* Add 1 to leave room for null terminator. */
2757 tab = xnew (size + 1, struct TEX_tabent);
2759 /* Unpack environment string into token table. Be careful about */
2760 /* zero-length strings (leading ':', "::" and trailing ':') */
2761 for (i = 0; *env;)
2763 p = etags_index (env, ':');
2764 if (!p) /* End of environment string. */
2765 p = env + strlen (env);
2766 if (p - env > 0)
2767 { /* Only non-zero strings. */
2768 tab[i].name = savenstr (env, p - env);
2769 tab[i].len = strlen (tab[i].name);
2770 i++;
2772 if (*p)
2773 env = p + 1;
2774 else
2776 tab[i].name = NULL; /* Mark end of table. */
2777 tab[i].len = 0;
2778 break;
2781 return tab;
2784 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2785 The name being defined actually starts at (NAME + LEN + 1).
2786 But we seem to include the TeX command in the tag name. */
2788 void
2789 TEX_getit (name, len)
2790 char *name;
2791 int len;
2793 char *p = name + len;
2794 char nambuf[BUFSIZ];
2796 if (*name == 0)
2797 return;
2799 /* Let tag name extend to next group close (or end of line) */
2800 while (*p && *p != TEX_clgrp)
2801 p++;
2802 (void) strncpy (nambuf, name, p - name);
2803 nambuf[p - name] = 0;
2805 pfnote (nambuf, TRUE, FALSE, lb.buffer, strlen (lb.buffer), lineno, linecharno);
2806 pfcnt++;
2809 /* If the text at CP matches one of the tag-defining TeX command names,
2810 return the etags_index of that command in TEX_toktab.
2811 Otherwise return -1. */
2813 /* Keep the capital `T' in `Token' for dumb truncating compilers
2814 (this distinguishes it from `TEX_toktab' */
2816 TEX_Token (cp)
2817 char *cp;
2819 int i;
2821 for (i = 0; TEX_toktab[i].len > 0; i++)
2822 if (strncmp (TEX_toktab[i].name, cp, TEX_toktab[i].len) == 0)
2823 return i;
2824 return -1;
2827 /* Support for Prolog. */
2829 /* whole head (not only functor, but also arguments)
2830 is gotten in compound term. */
2832 void
2833 prolog_getit (s, lineno, linecharno)
2834 char *s;
2835 int lineno;
2836 long linecharno;
2838 char nambuf[BUFSIZ], *save_s, tmpc;
2839 int insquote, npar;
2841 save_s = s;
2842 insquote = FALSE;
2843 npar = 0;
2844 while (1)
2846 if (*s == '\0') /* syntax error. */
2847 return;
2848 else if (insquote && *s == '\'' && *(s + 1) == '\'')
2849 s += 2;
2850 else if (*s == '\'')
2852 insquote = !insquote;
2853 s++;
2855 else if (!insquote && *s == '(')
2857 npar++;
2858 s++;
2860 else if (!insquote && *s == ')')
2862 npar--;
2863 s++;
2864 if (npar == 0)
2865 break;
2866 else if (npar < 0) /* syntax error. */
2867 return;
2869 else if (!insquote && *s == '.' && (isspace (*(s + 1)) || *(s + 1) == '\0'))
2870 { /* fullstop. */
2871 if (npar != 0) /* syntax error. */
2872 return;
2873 s++;
2874 break;
2876 else
2877 s++;
2879 tmpc = *s;
2880 *s = '\0';
2881 strcpy (nambuf, save_s);
2882 *s = tmpc;
2883 pfnote (nambuf, TRUE, FALSE, save_s, strlen (nambuf), lineno, linecharno);
2886 /* It is assumed that prolog predicate starts from column 0. */
2888 void
2889 prolog_funcs (fi)
2890 FILE *fi;
2892 void skip_comment (), prolog_getit ();
2894 lineno = linecharno = charno = 0;
2895 while (!feof (fi))
2897 lineno++;
2898 linecharno += charno;
2899 charno = readline (&lb, fi) + 1; /* 1 for newline. */
2900 dbp = lb.buffer;
2901 if (isspace (dbp[0])) /* not predicate header. */
2902 continue;
2903 else if (dbp[0] == '%') /* comment. */
2904 continue;
2905 else if (dbp[0] == '/' && dbp[1] == '*') /* comment. */
2906 skip_comment (&lb, fi, &lineno, &linecharno);
2907 else /* found. */
2908 prolog_getit (dbp, lineno, linecharno);
2912 void
2913 skip_comment (plb, fi, plineno, plinecharno)
2914 struct linebuffer *plb;
2915 FILE *fi;
2916 int *plineno; /* result */
2917 long *plinecharno; /* result */
2919 while (!substr ("*/", plb->buffer))
2921 (*plineno)++;
2922 *plinecharno += readline (plb, fi) + 1;
2923 } /* 1 for newline. */
2926 /* Return TRUE if 'sub' exists somewhere in 's'. */
2929 substr (sub, s)
2930 char *sub;
2931 char *s;
2933 while (*s && (s = etags_index (s, *sub)))
2934 if (prestr (sub, s))
2935 return (TRUE);
2936 else
2937 s++;
2938 return (FALSE);
2941 /* Return TRUE if 'pre' is prefix of string 's'. */
2944 prestr (pre, s)
2945 char *pre;
2946 char *s;
2948 if (*pre == '\0')
2949 return (TRUE);
2950 else if (*pre == *s)
2951 return (prestr (pre + 1, s + 1));
2952 else
2953 return (FALSE);
2956 /* Initialize a linebuffer for use */
2958 void
2959 initbuffer (linebuffer)
2960 struct linebuffer *linebuffer;
2962 linebuffer->size = 200;
2963 linebuffer->buffer = xnew (200, char);
2967 * Read a line of text from `stream' into `linebuffer'.
2968 * Return the number of characters read from `stream',
2969 * which is the length of the line including the newline, if any.
2971 long
2972 readline (linebuffer, stream)
2973 struct linebuffer *linebuffer;
2974 register FILE *stream;
2976 char *buffer = linebuffer->buffer;
2977 register char *p = linebuffer->buffer;
2978 register char *pend;
2979 int newline; /* 1 if ended with newline, 0 if ended with EOF */
2981 pend = p + linebuffer->size; /* Separate to avoid 386/IX compiler bug. */
2983 while (1)
2985 register int c = getc (stream);
2986 if (p == pend)
2988 linebuffer->size *= 2;
2989 buffer = (char *) xrealloc (buffer, linebuffer->size);
2990 p += buffer - linebuffer->buffer;
2991 pend = buffer + linebuffer->size;
2992 linebuffer->buffer = buffer;
2994 if (c < 0 || c == '\n')
2996 *p = 0;
2997 newline = (c == '\n' ? 1 : 0);
2998 break;
3000 *p++ = c;
3003 return p - buffer + newline;
3006 char *
3007 savestr (cp)
3008 char *cp;
3010 return savenstr (cp, strlen (cp));
3013 char *
3014 savenstr (cp, len)
3015 char *cp;
3016 int len;
3018 register char *dp;
3020 dp = xnew (len + 1, char);
3021 (void) strncpy (dp, cp, len);
3022 dp[len] = '\0';
3023 return dp;
3027 * Return the ptr in sp at which the character c last
3028 * appears; NULL if not found
3030 * Identical to v7 rindex, included for portability.
3033 char *
3034 etags_rindex (sp, c)
3035 register char *sp, c;
3037 register char *r;
3039 r = NULL;
3042 if (*sp == c)
3043 r = sp;
3044 } while (*sp++);
3045 return (r);
3050 * Return the ptr in sp at which the character c first
3051 * appears; NULL if not found
3053 * Identical to v7 index, included for portability.
3056 char *
3057 etags_index (sp, c)
3058 register char *sp, c;
3062 if (*sp == c)
3063 return (sp);
3064 } while (*sp++);
3065 return (NULL);
3068 /* Print error message and exit. */
3070 /* VARARGS1 */
3071 void
3072 fatal (s1, s2)
3073 char *s1, *s2;
3075 error (s1, s2);
3076 exit (1);
3079 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3081 /* VARARGS1 */
3082 void
3083 error (s1, s2)
3084 char *s1, *s2;
3086 fprintf (stderr, "%s: ", progname);
3087 fprintf (stderr, s1, s2);
3088 fprintf (stderr, "\n");
3091 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
3093 char *
3094 concat (s1, s2, s3)
3095 char *s1, *s2, *s3;
3097 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
3098 char *result = xnew (len1 + len2 + len3 + 1, char);
3100 (void) strcpy (result, s1);
3101 (void) strcpy (result + len1, s2);
3102 (void) strcpy (result + len1 + len2, s3);
3103 *(result + len1 + len2 + len3) = 0;
3105 return result;
3108 /* Like malloc but get fatal error if memory is exhausted. */
3110 char *
3111 xmalloc (size)
3112 int size;
3114 char *result = malloc (size);
3115 if (!result)
3116 fatal ("virtual memory exhausted", 0);
3117 return result;
3120 char *
3121 xrealloc (ptr, size)
3122 char *ptr;
3123 int size;
3125 char *result = realloc (ptr, size);
3126 if (!result)
3127 fatal ("virtual memory exhausted");
3128 return result;