Brent Benson's patch to support `cd -'.
[emacs.git] / lib-src / etags.c
blob95e235893938dafa2e97597ef0ee86d283e09541
1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 1987, 1988, 1989, 1993 Free Software Foundation, Inc. and Ken Arnold
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
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. */
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++.
29 #include <stdio.h>
30 #include <ctype.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
34 #include "getopt.h"
36 #ifdef __GNUC__
37 #define alloca __builtin_alloca
38 #else
39 #ifdef sparc
40 #include <alloca.h>
41 #else
42 extern char *alloca ();
43 #endif
44 #endif
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 rewritten; /* list name separately */
146 logical been_warned; /* set if noticed dup */
147 int lno; /* line number tag is on */
148 long cno; /* character number line starts on */
149 char *pat; /* search pattern */
150 struct nd_st *left, *right; /* left and right sons */
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 ();
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 rewritten;
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.0.\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 fputs ("\
451 -a, --append\n\
452 Append tag entries to existing tags file.\n\
453 -C, --c++\n\
454 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
455 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
456 extensions are always assumed to be C++ code.\n\
457 -d, --defines\n\
458 Create tag entries for #defines, too.", stdout);
460 #ifdef ETAGS
461 fputs (" This is the default\n\
462 behavior.", stdout);
463 #endif
465 fputs ("\n\
466 -D, --no-defines\n\
467 Don't create tag entries for #defines.", stdout);
469 #ifdef CTAGS
470 fputs (" This is the default\n\
471 behavior.", stdout);
472 #endif
474 puts ("\n\
475 -o FILE, --output=FILE\n\
476 Write the tags to FILE.\n\
477 -S, --ignore-indentation\n\
478 Don't rely on indentation quite as much as normal. Currently,\n\
479 this means not to assume that a closing brace in the first\n\
480 column is the final brace of a function or structure\n\
481 definition.\n\
482 -t, --typedefs\n\
483 Generate tag entries for typedefs. This is the default\n\
484 behavior.\n\
485 -T, --typedefs-and-c++\n\
486 Generate tag entries for typedefs, struct/enum/union tags, and\n\
487 C++ member functions.");
489 #ifdef ETAGS
490 puts ("-i FILE, --include=FILE\n\
491 Include a note in tag file indicating that, when searching for\n\
492 a tag, one should also consult the tags file FILE after\n\
493 checking the current file.");
494 #endif
496 #ifdef CTAGS
497 puts ("-B, --backward-search\n\
498 Write the search commands for the tag entries using '?', the\n\
499 backward-search command.\n\
500 -F, --forward-search\n\
501 Write the search commands for the tag entries using '/', the\n\
502 forward-search command.\n\
503 -u, --update\n\
504 Update the tag entries for the given files, leaving tag\n\
505 entries for other files in place. Currently, this is\n\
506 implemented by deleting the existing entries for the given\n\
507 files and then rewriting the new entries at the end of the\n\
508 tags file. It is often faster to simply rebuild the entire\n\
509 tag file than to use this.\n\
510 -v, --vgrind\n\
511 Generates an index of items intended for human consumption,\n\
512 similar to the output of vgrind. The index is sorted, and\n\
513 gives the page number of each item.\n\
514 -x, --cxref\n\
515 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
516 The output uses line numbers instead of page numbers, but\n\
517 beyond that the differences are cosmetic; try both to see\n\
518 which you like.\n\
519 -w, --no-warn\n\
520 Suppress warning messages about entries defined in multiple\n\
521 files.");
522 #endif
524 puts ("-V, --version\n\
525 Print the version of the program.\n\
526 -H, --help\n\
527 Print this help message.");
529 exit (0);
533 void
534 main (argc, argv)
535 int argc;
536 char *argv[];
538 char cmd[100];
539 int i;
540 unsigned int nincluded_files = 0;
541 char **included_files = (char **) alloca (argc * sizeof (char *));
542 char *this_file;
543 #ifdef VMS
544 char got_err;
546 extern char *gfnames ();
547 extern char *massage_name ();
548 #endif
550 progname = argv[0];
552 #ifndef CTAGS
553 emacs_tags_format = 1;
554 #else
555 emacs_tags_format = 0;
556 #endif
559 * If etags, always find typedefs and structure tags. Why not?
560 * Also default is to find macro constants.
562 if (emacs_tags_format)
563 typedefs = typedefs_and_cplusplus = constantypedefs = 1;
565 for (;;)
567 int opt;
568 opt = getopt_long (argc, argv, "aCdDo:StTi:BFuvxwVH", longopts, 0);
570 if (opt == EOF)
571 break;
573 switch (opt)
575 case '\0':
576 /* If getopt returns '\0', then it has already processed a
577 long-named option. We should do nothing. */
578 break;
580 /* Common options. */
581 case 'a':
582 append_to_tagfile++;
583 break;
584 case 'C':
585 cplusplus = 1;
586 break;
587 case 'd':
588 constantypedefs = 1;
589 break;
590 case 'D':
591 constantypedefs = 0;
592 break;
593 case 'o':
594 if (outfile)
596 fprintf (stderr,
597 "%s: -o flag may only be given once\n", progname);
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)
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 stat (file, &stat_buf);
792 if (!(stat_buf.st_mode & S_IFREG)
793 #ifdef S_IFLNK
794 || !(stat_buf.st_mode & S_IFLNK)
795 #endif
798 fprintf (stderr, "Skipping %s: it is not a regular file.\n", file);
799 return;
802 if (streq (file, outfile) && !streq (outfile, "-"))
804 fprintf (stderr, "Skipping inclusion of %s in self.\n", file);
805 return;
807 if (emacs_tags_format)
809 char *cp = etags_rindex (file, '/');
810 if (cp)
811 ++cp;
812 else
813 cp = file;
815 find_entries (file);
816 if (emacs_tags_format)
818 fprintf (outf, "\f\n%s,%d\n",
819 file, total_size_of_entries (head));
820 put_entries (head);
821 free_tree (head);
822 head = NULL;
827 * This routine sets up the boolean psuedo-functions which work
828 * by setting boolean flags dependent upon the corresponding character
829 * Every char which is NOT in that string is not a white char. Therefore,
830 * all of the array "_wht" is set to FALSE, and then the elements
831 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
832 * of a char is TRUE if it is the string "white", else FALSE.
834 void
835 init ()
837 register char *sp;
838 register int i;
840 for (i = 0; i < 0177; i++)
841 _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
842 for (sp = white; *sp; sp++)
843 _wht[*sp] = TRUE;
844 for (sp = endtk; *sp; sp++)
845 _etk[*sp] = TRUE;
846 for (sp = intk; *sp; sp++)
847 _itk[*sp] = TRUE;
848 for (sp = begtk; *sp; sp++)
849 _btk[*sp] = TRUE;
850 _wht[0] = _wht['\n'];
851 _etk[0] = _etk['\n'];
852 _btk[0] = _btk['\n'];
853 _itk[0] = _itk['\n'];
857 * This routine opens the specified file and calls the function
858 * which finds the function and type definitions.
860 void
861 find_entries (file)
862 char *file;
864 char *cp;
865 void prolog_funcs ();
867 inf = fopen (file, "r");
868 if (inf == NULL)
870 perror (file);
871 return;
873 curfile = savestr (file);
874 cp = etags_rindex (file, '.');
876 header_file = (cp && (streq (cp + 1, "h")));
878 /* .tex, .aux or .bbl implies LaTeX source code */
879 if (cp && (streq (cp + 1, "tex") || streq (cp + 1, "aux")
880 || streq (cp + 1, "bbl")))
882 TEX_funcs (inf);
883 goto close_and_return;
885 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
886 if (cp && (streq (cp + 1, "l")
887 || streq (cp + 1, "el")
888 || streq (cp + 1, "lsp")
889 || streq (cp + 1, "lisp")
890 || streq (cp + 1, "cl")
891 || streq (cp + 1, "clisp")))
893 L_funcs (inf);
894 goto close_and_return;
896 /* .scm or .sm or .scheme or ... implies scheme source code */
897 if (cp && (streq (cp + 1, "sm")
898 || streq (cp + 1, "scm")
899 || streq (cp + 1, "scheme")
900 || streq (cp + 1, "t")
901 || streq (cp + 1, "sch")
902 || streq (cp + 1, "SM")
903 || streq (cp + 1, "SCM")
904 /* The `SCM' or `scm' prefix with a version number */
905 || (cp[-1] == 'm' && cp[-2] == 'c' && cp[-3] == 's'
906 && string_numeric_p (cp + 1))
907 || (cp[-1] == 'M' && cp[-2] == 'C' && cp[-3] == 'S'
908 && string_numeric_p (cp + 1))))
910 Scheme_funcs (inf);
911 fclose (inf);
912 return;
914 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
915 Or even ".sa". */
916 if (cp && (streq (cp + 1, "s")
917 || streq (cp + 1, "a")
918 || streq (cp + 1, "sa")))
920 Asm_funcs (inf);
921 fclose (inf);
922 return;
924 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
925 if (cp && (streq (cp + 1, "C")
926 || streq (cp + 1, "H")
927 || streq (cp + 1, "cxx")
928 || streq (cp + 1, "hxx")
929 || streq (cp + 1, "cc")))
931 C_entries (C_PLPL); /* C++ */
932 goto close_and_return;
934 /* .cs or .hs: a C* file */
935 if (cp && (streq (cp + 1, "cs")
936 || streq (cp + 1, "hs")))
938 C_entries (C_STAR);
939 goto close_and_return;
941 /* .y: a yacc file */
942 if (cp && (streq (cp + 1, "y")))
944 C_entries (YACC);
945 goto close_and_return;
947 /* .pl implies prolog source code */
948 if (cp && streq (cp + 1, "pl"))
950 prolog_funcs (inf);
951 goto close_and_return;
953 /* .p or .pas: a Pascal file */
954 if (cp && (streq (cp + 1, "p")
955 || streq (cp + 1, "pas")))
957 PAS_funcs (inf);
958 goto close_and_return;
960 /* If .f or .for, assume it is fortran or nothing. */
961 if (cp && (streq (cp + 1, "f")
962 || streq (cp + 1, "for")))
964 PF_funcs (inf);
965 goto close_and_return;
967 /* if not a .c or .h or .y file, try fortran */
968 if (cp && ((cp[1] != 'c'
969 && cp[1] != 'h'
970 && cp[1] != 'y')
971 || (cp[1] != 0 && cp[2] != 0)))
973 if (PF_funcs (inf) != 0)
974 goto close_and_return;
975 rewind (inf); /* no fortran tags found, try C */
977 C_entries (cplusplus ? C_PLPL : 0);
979 close_and_return:
980 (void) fclose (inf);
983 /* Nonzero if string STR is composed of digits. */
986 string_numeric_p (str)
987 char *str;
989 while (*str)
991 if (*str < '0' || *str > '9')
992 return 0;
994 return 1;
997 /* Record a tag. */
998 /* Should take a TOKEN* instead!! */
999 void
1000 pfnote (name, is_func, rewritten, linestart, linelen, lno, cno)
1001 char *name; /* tag name */
1002 logical is_func; /* function or type name? */
1003 logical rewritten; /* tag different from text of definition? */
1004 char *linestart;
1005 int linelen;
1006 int lno;
1007 long cno;
1009 register char *fp;
1010 register NODE *np;
1011 char tem[51];
1012 char c;
1014 np = (NODE *) malloc (sizeof (NODE));
1015 if (np == NULL)
1017 if (!emacs_tags_format)
1019 /* It's okay to output early in etags -- it only disrupts the
1020 * character count of the tag entries, which is no longer used
1021 * by tags.el anyway.
1023 error ("too many entries to sort");
1025 put_entries (head);
1026 free_tree (head);
1027 head = NULL;
1028 np = xnew (1, NODE);
1030 /* If ctags mode, change name "main" to M<thisfilename>. */
1031 if (!emacs_tags_format && !cxref_style && streq (name, "main"))
1033 fp = etags_rindex (curfile, '/');
1034 name = concat ("M", fp == 0 ? curfile : fp + 1, "");
1035 fp = etags_rindex (name, '.');
1036 if (fp && fp[1] != '\0' && fp[2] == '\0')
1037 *fp = 0;
1038 rewritten = TRUE;
1040 np->name = savestr (name);
1041 np->file = curfile;
1042 np->is_func = is_func;
1043 np->rewritten = rewritten;
1044 np->lno = lno;
1045 /* UNCOMMENT THE +1 HERE: */
1046 np->cno = cno /* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
1047 np->left = np->right = 0;
1048 if (emacs_tags_format)
1050 c = linestart[linelen];
1051 linestart[linelen] = 0;
1053 else if (cxref_style == 0)
1055 sprintf (tem, strlen (linestart) < 50 ? "%s$" : "%.50s", linestart);
1056 linestart = tem;
1058 np->pat = savestr (linestart);
1059 if (emacs_tags_format)
1061 linestart[linelen] = c;
1064 add_node (np, &head);
1068 * free_tree ()
1069 * recurse on left children, iterate on right children.
1071 void
1072 free_tree (node)
1073 register NODE *node;
1075 while (node)
1077 register NODE *node_right = node->right;
1078 free_tree (node->left);
1079 free (node->name);
1080 free (node->pat);
1081 free ((char *) node);
1082 node = node_right;
1087 * add_node ()
1088 * Adds a node to the tree of nodes. In etags mode, we don't keep
1089 * it sorted; we just keep a linear list. In ctags mode, maintain
1090 * an ordered tree, with no attempt at balancing.
1092 * add_node is the only function allowed to add nodes, so it can
1093 * maintain state.
1095 void
1096 add_node (node, cur_node_p)
1097 NODE *node, **cur_node_p;
1099 register int dif;
1100 register NODE *cur_node = *cur_node_p;
1101 static NODE *last_node = NULL;/* careful */
1103 if (cur_node == NULL)
1105 *cur_node_p = node;
1106 last_node = node;
1107 return;
1110 if (emacs_tags_format)
1112 /* Etags Mode */
1113 if (!last_node)
1114 fatal ("internal error in add_node");
1115 last_node->right = node;
1116 last_node = node;
1118 else
1120 /* Ctags Mode */
1121 dif = strcmp (node->name, cur_node->name);
1124 * If this tag name matches an existing one, then
1125 * do not add the node, but maybe print a warning.
1127 if (!dif)
1129 if (node->file == cur_node->file)
1131 if (!no_warnings)
1133 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1134 node->file, lineno, node->name);
1135 fprintf (stderr, "Second entry ignored\n");
1137 return;
1139 if (!cur_node->been_warned && !no_warnings)
1141 fprintf (stderr,
1142 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1143 node->file, cur_node->file, node->name);
1145 cur_node->been_warned = TRUE;
1146 return;
1149 /* Maybe refuse to add duplicate nodes. */
1150 if (!permit_duplicates)
1152 if (!strcmp (node->name, cur_node->name)
1153 && !strcmp (node->file, cur_node->file))
1154 return;
1157 /* Actually add the node */
1158 add_node (node, dif < 0 ? &cur_node->left : &cur_node->right);
1162 void
1163 put_entries (node)
1164 register NODE *node;
1166 register char *sp;
1168 if (node == NULL)
1169 return;
1171 /* Output subentries that precede this one */
1172 put_entries (node->left);
1174 /* Output this entry */
1176 if (emacs_tags_format)
1178 if (node->rewritten)
1180 fprintf (outf, "%s\177%s\001%d,%d\n",
1181 node->name, node->pat, node->lno, node->cno);
1183 else
1185 fprintf (outf, "%s\177%d,%d\n",
1186 node->pat, node->lno, node->cno);
1189 else if (!cxref_style)
1191 fprintf (outf, "%s\t%s\t",
1192 node->name, node->file);
1194 if (node->is_func)
1195 { /* a function */
1196 putc (searchar, outf);
1197 putc ('^', outf);
1199 for (sp = node->pat; *sp; sp++)
1201 if (*sp == '\\' || *sp == searchar)
1202 putc ('\\', outf);
1203 putc (*sp, outf);
1205 putc (searchar, outf);
1207 else
1208 { /* a typedef; text pattern inadequate */
1209 fprintf (outf, "%d", node->lno);
1211 putc ('\n', outf);
1213 else if (vgrind_style)
1214 fprintf (stdout, "%s %s %d\n",
1215 node->name, node->file, (node->lno + 63) / 64);
1216 else
1217 fprintf (stdout, "%-16s %3d %-16s %s\n",
1218 node->name, node->lno, node->file, node->pat);
1220 /* Output subentries that follow this one */
1221 put_entries (node->right);
1224 /* Length of a number's decimal representation. */
1226 number_len (num)
1227 long num;
1229 int len = 0;
1230 if (!num)
1231 return 1;
1232 for (; num; num /= 10)
1233 ++len;
1234 return len;
1238 * Return total number of characters that put_entries will output for
1239 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1240 * is set, but called only in that case. This count is irrelevant with
1241 * the new tags.el, but is still supplied for backward compatibility.
1244 total_size_of_entries (node)
1245 register NODE *node;
1247 register int total;
1249 if (node == NULL)
1250 return 0;
1252 total = 0;
1253 for (; node; node = node->right)
1255 /* Count left subentries. */
1256 total += total_size_of_entries (node->left);
1258 /* Count this entry */
1259 total += strlen (node->pat) + 1;
1260 total += number_len ((long) node->lno) + 1 + number_len (node->cno) + 1;
1261 if (node->rewritten)
1262 total += 1 + strlen (node->name); /* \001name */
1265 return total;
1269 * The C symbol tables.
1272 Stab *C_stab, *C_PLPL_stab, *C_STAR_stab;
1275 * SYNOPSIS
1276 * Stab *get_C_stab (int c_ext);
1278 #define get_C_stab(c_ext) ((c_ext & C_STAR) ? C_STAR_stab : \
1279 (c_ext & C_PLPL) ? C_PLPL_stab : \
1280 C_stab)
1282 void
1283 add_keyword (stab, sym, type)
1284 Stab *stab;
1285 char *sym;
1286 enum sym_type type;
1288 stab_search (stab, sym, strlen (sym))->type = type;
1291 Stab *
1292 C_create_stab (c_ext)
1293 int c_ext;
1295 Stab *stab;
1297 stab = stab_create ();
1299 /* C, C++ and C* */
1300 if (c_ext & C_PLPL)
1301 add_keyword (stab, "class", st_C_struct);
1302 if (c_ext & C_STAR)
1303 add_keyword (stab, "domain", st_C_struct);
1304 add_keyword (stab, "union", st_C_struct);
1305 add_keyword (stab, "struct", st_C_struct);
1306 add_keyword (stab, "enum", st_C_enum);
1307 add_keyword (stab, "typedef", st_C_typedef);
1308 add_keyword (stab, "define", st_C_define);
1309 add_keyword (stab, "long", st_C_typespec);
1310 add_keyword (stab, "short", st_C_typespec);
1311 add_keyword (stab, "int", st_C_typespec);
1312 add_keyword (stab, "char", st_C_typespec);
1313 add_keyword (stab, "float", st_C_typespec);
1314 add_keyword (stab, "double", st_C_typespec);
1315 add_keyword (stab, "signed", st_C_typespec);
1316 add_keyword (stab, "unsigned", st_C_typespec);
1317 add_keyword (stab, "auto", st_C_typespec);
1318 add_keyword (stab, "void", st_C_typespec);
1319 add_keyword (stab, "extern", st_C_typespec);
1320 add_keyword (stab, "static", st_C_typespec);
1321 add_keyword (stab, "const", st_C_typespec);
1322 add_keyword (stab, "volatile", st_C_typespec);
1324 return stab;
1327 void
1328 C_create_stabs ()
1330 C_stab = C_create_stab (0);
1331 C_PLPL_stab = C_create_stab (C_PLPL);
1332 C_STAR_stab = C_create_stab (C_STAR | C_PLPL);
1336 * etags.c 4.2 1993/03/22 12:13:40 pot Exp
1337 * C functions are recognized using a simple finite automaton.
1338 * funcdef is its state variable.
1340 typedef enum
1342 fnone, ftagseen, finlist, flistseen
1343 } FUNCST;
1344 FUNCST funcdef;
1347 /* typedefs are recognized using a simple finite automaton.
1348 * typeddef is its state variable.
1350 typedef enum
1352 tnone, ttypedseen, tinbody, tend
1353 } TYPEDST;
1354 TYPEDST typdef;
1357 /* struct tags for C++ are recognized using another simple
1358 * finite automaton. `structdef' is its state variable.
1359 * This machinery is only invoked for C++; otherwise structdef
1360 * should remain snone. However, this machinery can easily be
1361 * adapted to find structure tags in normal C code.
1363 typedef enum
1365 snone, /* nothing seen yet */
1366 skeyseen, /* struct-like keyword seen */
1367 stagseen, /* struct-like tag seen */
1368 scolonseen, /* colon seen after struct-like tag */
1369 sinbody /* in class body: recognize member func defs */
1370 } STRUCTST;
1371 STRUCTST structdef;
1373 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1374 * struct tag, and structkey is the preceding struct-like keyword.
1376 char structtag[BUFSIZ];
1377 Stab_entry *structkey;
1380 * Yet another little state machine to deal with preprocessor lines.
1382 typedef enum
1384 dnone, /* nothing seen */
1385 dsharpseen, /* '#' seen as first char on line */
1386 ddefineseen, /* '#' and 'define' seen */
1387 dignorerest /* ignore rest of line */
1388 } DEFINEST;
1389 DEFINEST definedef;
1392 * Set this to TRUE, and the next token considered is called a function.
1393 * Used only for GNUmacs's function-defining macros.
1395 logical next_token_is_func;
1398 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1400 logical yacc_rules;
1403 * C_entries ()
1404 * This routine finds functions, typedefs, #define's and
1405 * struct/union/enum definitions in C syntax and adds them
1406 * to the list.
1410 * LEVEL_OK_FOR_FUNCDEF allows C++ function definition within class body.
1411 * Currently typdef and structdef stuff (typedefs and struct
1412 * definitions) are only noticed when level==0, but that may change.
1414 #define LEVEL_OK_FOR_FUNCDEF() \
1415 (level==0 || (cplpl && level==1 && structdef==sinbody))
1417 #define curlb (lbs[curndx].lb)
1418 #define othlb (lbs[1-curndx].lb)
1419 #define newlb (lbs[newndx].lb)
1420 #define curlinepos (lbs[curndx].linepos)
1421 #define othlinepos (lbs[1-curndx].linepos)
1422 #define newlinepos (lbs[newndx].linepos)
1424 #define CNL_SAVE_DEFINEDEF \
1425 do { \
1426 SET_FILEPOS (curlinepos, inf, charno); \
1427 lineno++; \
1428 charno += readline (&curlb, inf); \
1429 lp = curlb.buffer; \
1430 quotednl = FALSE; \
1431 newndx = curndx; \
1432 } while (FALSE)
1434 #define CNL \
1435 do { \
1436 CNL_SAVE_DEFINEDEF; \
1437 definedef = dnone; \
1438 } while (FALSE)
1440 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1441 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1442 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \
1443 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1445 void
1446 C_entries (c_ext)
1447 int c_ext; /* extension of C? */
1449 register char c; /* latest char read; '\0' for end of line */
1450 register char *lp; /* pointer one beyond the character `c' */
1451 int curndx, newndx; /* indices for current and new lb */
1452 TOKEN tok; /* latest token read for funcdef & structdef */
1453 char tokb[BUFSIZ]; /* latest token name for funcdef & structdef */
1454 register int tokoff; /* offset in line of start of latest token */
1455 register int toklen; /* length of latest token */
1456 int level; /* current curly brace level */
1457 logical incomm, inquote, inchar, quotednl, midtoken;
1458 logical cplpl;
1460 curndx = newndx = 0;
1461 lineno = 0;
1462 charno = 0;
1463 lp = curlb.buffer;
1464 *lp = 0;
1466 definedef = dnone; funcdef = fnone; typdef= tnone; structdef= snone;
1467 next_token_is_func = yacc_rules = FALSE;
1468 midtoken = inquote = inchar = incomm = quotednl = FALSE;
1469 level = 0;
1470 cplpl = c_ext & C_PLPL;
1472 C_create_stabs ();
1474 while (!feof (inf))
1476 c = *lp++;
1477 if (c == '\\')
1479 /* If we're at the end of the line, the next character is a
1480 '\0'; don't skip it, because it's the thing that tells us
1481 to read the next line. */
1482 if (*lp == '\0')
1484 quotednl = TRUE;
1485 continue;
1487 lp++;
1488 c = ' ';
1490 else if (incomm)
1492 switch (c)
1494 case '*':
1495 if (*lp == '/')
1497 c = *lp++;
1498 incomm = FALSE;
1500 break;
1501 case '\0':
1502 /* Newlines inside comments do not end macro definitions in
1503 traditional cpp. */
1504 CNL_SAVE_DEFINEDEF;
1505 break;
1507 continue;
1509 else if (inquote)
1511 switch (c)
1513 case '"':
1514 inquote = FALSE;
1515 break;
1516 case '\0':
1517 /* Newlines inside strings, do not end macro definitions
1518 in traditional cpp, even though compilers don't
1519 usually accept them. */
1520 CNL_SAVE_DEFINEDEF;
1521 break;
1523 continue;
1525 else if (inchar)
1527 if (c == '\'')
1528 inchar = FALSE;
1529 continue;
1531 else
1532 switch (c)
1534 case '"':
1535 inquote = TRUE;
1536 continue;
1537 case '\'':
1538 inchar = TRUE;
1539 continue;
1540 case '/':
1541 if (*lp == '*')
1543 lp++;
1544 incomm = TRUE;
1545 continue;
1547 else if (cplpl && *lp == '/')
1549 c = 0;
1550 break;
1552 continue;
1553 case '%':
1554 if ((c_ext & YACC) && *lp == '%')
1556 /* entering or exiting rules section in yacc file */
1557 lp++;
1558 definedef = dnone; funcdef = fnone;
1559 typdef= tnone; structdef= snone;
1560 next_token_is_func = FALSE;
1561 midtoken = inquote = inchar = incomm = quotednl = FALSE;
1562 level = 0;
1563 yacc_rules = !yacc_rules;
1564 continue;
1566 case '#':
1567 if (lp == newlb.buffer + 1 && definedef == dnone)
1568 definedef = dsharpseen;
1569 continue;
1570 } /* switch (c) */
1573 if (LEVEL_OK_FOR_FUNCDEF ()
1574 && definedef != dignorerest
1575 && structdef != scolonseen
1576 && funcdef != finlist)
1578 if (midtoken)
1580 if (endtoken (c))
1582 if (cplpl && c == ':' && *lp == ':' && intoken (*(lp + 1)))
1585 * This handles :: in the middle, but not at beginning
1586 * of an identifier.
1588 lp += 2;
1589 toklen += 3;
1591 else
1593 logical is_func;
1595 tok.lineno = lineno;
1596 tok.p = newlb.buffer + tokoff;
1597 tok.len = toklen;
1598 tok.rewritten = FALSE;
1599 if (yacc_rules
1600 || consider_token (c, lp, &tok,
1601 c_ext, level, &is_func))
1603 if (structdef == sinbody
1604 && definedef == dnone && is_func)
1605 { /* function defined in C++ class body */
1606 sprintf (tokb, "%s::%.*s",
1607 ((structtag[0] == '\0')
1608 ? "_anonymous_" : structtag),
1609 tok.len, tok.p);
1610 tok.rewritten = TRUE;
1612 else
1614 sprintf (tokb, "%.*s", tok.len, tok.p);
1617 if (funcdef == ftagseen || structdef == stagseen)
1619 if (newndx == curndx)
1620 curndx = 1 - curndx; /* switch line buffers */
1622 else
1623 MAKE_TAG_FROM_NEW_LB (is_func);
1625 midtoken = FALSE;
1627 } /* if (endtoken (c)) */
1628 else if (intoken (c))
1630 toklen++;
1631 continue;
1633 } /* if (midtoken) */
1634 else if (begtoken (c))
1636 switch (funcdef)
1638 case flistseen:
1639 MAKE_TAG_FROM_OTH_LB (TRUE);
1640 /* FALLTHRU */
1641 case ftagseen:
1642 funcdef = fnone;
1643 break;
1645 if (structdef == stagseen)
1646 structdef = snone;
1647 if (!yacc_rules || lp == newlb.buffer + 1)
1649 tokoff = lp - 1 - newlb.buffer;
1650 toklen = 1;
1651 midtoken = TRUE;
1653 continue;
1655 } /* if must look at token */
1658 /* Detect end of line, colon, comma, semicolon and various braces
1659 after having handled the last token on the line.*/
1660 switch (c)
1662 case ':':
1663 if (structdef == stagseen)
1664 structdef = scolonseen;
1665 else if (yacc_rules && funcdef == ftagseen)
1667 MAKE_TAG_FROM_OTH_LB (FALSE);
1668 funcdef == fnone;
1670 break;
1671 case ';':
1672 funcdef = fnone;
1673 /* FALLTHRU */
1674 case ',':
1675 if (funcdef != finlist)
1676 funcdef = fnone;
1677 if (level == 0 && typdef == tend)
1678 typdef = tnone;
1679 /* FALLTHRU */
1680 case '[':
1681 if (funcdef != finlist)
1682 funcdef = fnone;
1683 if (structdef == stagseen)
1684 structdef = snone;
1685 break;
1686 case '(':
1687 switch (funcdef)
1689 case ftagseen:
1690 funcdef = finlist;
1691 break;
1692 case finlist:
1693 case flistseen:
1694 funcdef = fnone;
1695 break;
1697 break;
1698 case ')':
1699 if (funcdef == finlist)
1700 funcdef = flistseen;
1701 break;
1702 case '{':
1703 if (typdef == ttypedseen)
1704 typdef = tinbody;
1705 switch (structdef)
1707 case skeyseen: /* unnamed struct */
1708 structtag[0] = '\0';
1709 structdef = sinbody;
1710 break;
1711 case stagseen:
1712 case scolonseen: /* named struct */
1713 structdef = sinbody;
1714 MAKE_TAG_FROM_OTH_LB (FALSE);
1715 break;
1717 level++;
1718 /* FALLTHRU */
1719 case '*':
1720 if (funcdef == flistseen)
1722 MAKE_TAG_FROM_OTH_LB (TRUE);
1723 funcdef = fnone;
1725 break;
1726 case '}':
1727 if (!noindentypedefs && lp == newlb.buffer + 1)
1728 level = 0; /* reset level if first column */
1729 else if (level > 0)
1730 level--;
1731 if (level == 0)
1733 if (typdef == tinbody)
1734 typdef = tend;
1735 structdef = snone;
1736 (void) strcpy (structtag, "<error 2>");
1738 break;
1739 case '\0':
1740 /* If a macro spans multiple lines don't reset its state. */
1741 if (quotednl)
1742 CNL_SAVE_DEFINEDEF;
1743 else
1744 CNL;
1745 break;
1746 } /* switch (c) */
1748 } /* while not eof */
1752 * consider_token ()
1753 * checks to see if the current token is at the start of a
1754 * function, or corresponds to a typedef, or is a struct/union/enum
1755 * tag.
1757 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1758 * C_EXT is which language we are looking at.
1760 * In the future we will need some way to adjust where the end of
1761 * the token is; for instance, implementing the C++ keyword
1762 * `operator' properly will adjust the end of the token to be after
1763 * whatever follows `operator'.
1765 * Globals
1766 * funcdef IN OUT
1767 * structdef IN OUT
1768 * definedef IN OUT
1769 * typdef IN OUT
1770 * next_token_is_func IN OUT
1773 logical
1774 consider_token (c, lp, tokp, c_ext, level, is_func)
1775 register char c; /* IN: first char after the token */
1776 register char *lp; /* IN: lp points to 2nd char after the token */
1777 register TOKEN *tokp; /* IN */
1778 int c_ext; /* IN */
1779 int level; /* IN */
1780 logical *is_func; /* OUT */
1782 logical firsttok; /* TRUE if have seen first token in ()'s */
1783 Stab_entry *tokse = stab_find (get_C_stab (c_ext), tokp->p, tokp->len);
1784 enum sym_type toktype = stab_type (tokse);
1786 *is_func = FALSE; /* not a function */
1789 * Advance the definedef state machine.
1791 switch (definedef)
1793 case dnone:
1794 /* We're not on a preprocessor line. */
1795 break;
1796 case dsharpseen:
1797 if (toktype == st_C_define)
1799 definedef = ddefineseen;
1801 else
1803 definedef = dignorerest;
1805 return (FALSE);
1806 case ddefineseen:
1808 * Make a tag for any macro.
1810 definedef = dignorerest;
1811 *is_func = (c == '(');
1812 if (!*is_func && !constantypedefs)
1813 return (FALSE);
1814 else
1815 return (TRUE);
1816 case dignorerest:
1817 return (FALSE);
1818 default:
1819 error ("internal error: definedef value");
1823 * Now typedefs
1825 switch (typdef)
1827 case tnone:
1828 if (toktype == st_C_typedef)
1830 if (typedefs)
1831 typdef = ttypedseen;
1832 return (FALSE);
1834 break;
1835 case ttypedseen:
1836 switch (toktype)
1838 case st_none:
1839 case st_C_typespec:
1840 typdef = tend;
1841 break;
1842 case st_C_struct:
1843 case st_C_enum:
1844 break;
1846 /* Do not return here, so the structdef stuff has a chance. */
1847 break;
1848 case tend:
1849 switch (toktype)
1851 case st_C_typespec:
1852 case st_C_struct:
1853 case st_C_enum:
1854 return (FALSE);
1856 return (TRUE);
1860 * This structdef business is currently only invoked when level==0.
1861 * It should be recursively invoked whatever the level, and a stack of
1862 * states kept, to allow for definitions of structs within structs.
1864 * This structdef business is NOT invoked when we are ctags and the
1865 * file is plain C. This is because a struct tag may have the same
1866 * name as another tag, and this loses with ctags.
1868 * This if statement deals with the typdef state machine as
1869 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1870 * return (FALSE). All the other code here is for the structdef
1871 * state machine.
1873 switch (toktype)
1875 case st_C_struct:
1876 case st_C_enum:
1877 if (typdef == ttypedseen
1878 || (typedefs_and_cplusplus && level == 0 && structdef == snone))
1880 structdef = skeyseen;
1881 structkey = tokse;
1883 return (FALSE);
1885 if (structdef == skeyseen)
1887 if (stab_type (structkey) == st_C_struct)
1889 (void) strncpy (structtag, tokp->p, tokp->len);
1890 structtag[tokp->len] = '\0'; /* for struct/union/class */
1892 else
1894 structtag[0] = '\0'; /* for enum (why is it treated differently?) */
1896 structdef = stagseen;
1897 return (TRUE);
1900 /* Avoid entering funcdef stuff if typdef is going on. */
1901 if (typdef != tnone)
1903 definedef = dnone;
1904 return (FALSE);
1907 /* Detect GNUmacs's function-defining macros. */
1908 if (definedef == dnone)
1910 if (strneq (tokp->p, "DEF", 3)
1911 || strneq (tokp->p, "ENTRY", 5)
1912 || strneq (tokp->p, "SYSCALL", 7)
1913 || strneq (tokp->p, "PSEUDO", 6))
1915 next_token_is_func = TRUE;
1916 return (FALSE);
1918 if (strneq (tokp->p, "EXFUN", 5))
1920 next_token_is_func = FALSE;
1921 return (FALSE);
1924 if (next_token_is_func)
1926 next_token_is_func = FALSE;
1927 return (TRUE);
1930 /* A function? */
1931 switch (toktype)
1933 case st_C_typespec:
1934 funcdef == fnone; /* should be useless */
1935 return (FALSE);
1936 default:
1937 funcdef = ftagseen;
1938 *is_func = TRUE;
1939 return (TRUE);
1943 /* Fortran parsing */
1945 char *dbp;
1946 int pfcnt;
1949 PF_funcs (fi)
1950 FILE *fi;
1952 lineno = 0;
1953 charno = 0;
1954 pfcnt = 0;
1956 while (!feof (fi))
1958 lineno++;
1959 linecharno = charno;
1960 charno += readline (&lb, fi);
1961 dbp = lb.buffer;
1962 if (*dbp == '%')
1963 dbp++; /* Ratfor escape to fortran */
1964 while (isspace (*dbp))
1965 dbp++;
1966 if (*dbp == 0)
1967 continue;
1968 switch (*dbp | ' ')
1970 case 'i':
1971 if (tail ("integer"))
1972 takeprec ();
1973 break;
1974 case 'r':
1975 if (tail ("real"))
1976 takeprec ();
1977 break;
1978 case 'l':
1979 if (tail ("logical"))
1980 takeprec ();
1981 break;
1982 case 'c':
1983 if (tail ("complex") || tail ("character"))
1984 takeprec ();
1985 break;
1986 case 'd':
1987 if (tail ("double"))
1989 while (isspace (*dbp))
1990 dbp++;
1991 if (*dbp == 0)
1992 continue;
1993 if (tail ("precision"))
1994 break;
1995 continue;
1997 break;
1999 while (isspace (*dbp))
2000 dbp++;
2001 if (*dbp == 0)
2002 continue;
2003 switch (*dbp | ' ')
2005 case 'f':
2006 if (tail ("function"))
2007 getit ();
2008 continue;
2009 case 's':
2010 if (tail ("subroutine"))
2011 getit ();
2012 continue;
2013 case 'e':
2014 if (tail ("entry"))
2015 getit ();
2016 continue;
2017 case 'p':
2018 if (tail ("program"))
2020 getit ();
2021 continue;
2023 if (tail ("procedure"))
2024 getit ();
2025 continue;
2028 return (pfcnt);
2031 logical
2032 tail (cp)
2033 char *cp;
2035 register int len = 0;
2037 while (*cp && (*cp & ~' ') == ((*(dbp + len)) & ~' '))
2038 cp++, len++;
2039 if (*cp == 0)
2041 dbp += len;
2042 return (1);
2044 return (0);
2047 void
2048 takeprec ()
2050 while (isspace (*dbp))
2051 dbp++;
2052 if (*dbp != '*')
2053 return;
2054 dbp++;
2055 while (isspace (*dbp))
2056 dbp++;
2057 if (!isdigit (*dbp))
2059 --dbp; /* force failure */
2060 return;
2063 dbp++;
2064 while (isdigit (*dbp));
2067 void
2068 getit ()
2070 register char *cp;
2071 char c;
2072 char nambuf[BUFSIZ];
2074 while (isspace (*dbp))
2075 dbp++;
2076 if (*dbp == 0
2077 || (!isalpha (*dbp)
2078 && *dbp != '_'
2079 && *dbp != '$'))
2080 return;
2081 for (cp = dbp + 1; *cp && (isalpha (*cp) || isdigit (*cp)
2082 || (*cp == '_') || (*cp == '$')); cp++)
2083 continue;
2084 c = cp[0];
2085 cp[0] = 0;
2086 (void) strcpy (nambuf, dbp);
2087 cp[0] = c;
2088 pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
2089 pfcnt++;
2092 /* Handle a file of assembler code. */
2094 void
2095 Asm_funcs (fi)
2096 FILE *fi;
2098 int i;
2099 register char c;
2101 lineno = 0;
2102 charno = 0;
2103 pfcnt = 0;
2105 while (!feof (fi))
2107 lineno++;
2108 linecharno = charno;
2109 charno += readline (&lb, fi);
2110 dbp = lb.buffer;
2112 for (i = 0; ((c = dbp[i]) && !isspace (c)) && (c != ':'); i++)
2115 if ((i > 0) && (c == ':'))
2116 getit ();
2120 /* Added by Mosur Mohan, 4/22/88 */
2121 /* Pascal parsing */
2123 #define GET_NEW_LINE \
2125 linecharno = charno; lineno++; \
2126 charno += 1 + readline (&lb, inf); \
2127 dbp = lb.buffer; \
2130 /* Locates tags for procedures & functions.
2131 * Doesn't do any type- or var-definitions.
2132 * It does look for the keyword "extern" or "forward"
2133 * immediately following the procedure statement;
2134 * if found, the tag is skipped.
2137 void
2138 PAS_funcs (fi)
2139 FILE *fi;
2141 struct linebuffer tline; /* mostly copied from C_entries */
2142 long save_lcno;
2143 int save_lineno;
2144 char c, *cp;
2145 char nambuf[BUFSIZ];
2147 logical /* each of these flags is TRUE iff: */
2148 incomm1, /* point is inside {..} comment */
2149 incomm2, /* point is inside (*..*) comment */
2150 inquote, /* point is inside '..' string */
2151 get_tagname, /* point is after PROCEDURE/FUNCTION */
2152 /* keyword, so next item = potential tag */
2153 found_tag, /* point is after a potential tag */
2154 inparms, /* point is within parameter-list */
2155 verify_tag; /* point has passed the parm-list, so the */
2156 /* next token will determine whether */
2157 /* this is a FORWARD/EXTERN to be */
2158 /* ignored, or whether it is a real tag */
2160 lineno = 0;
2161 charno = 0;
2162 dbp = lb.buffer;
2163 *dbp = 0;
2164 initbuffer (&tline);
2166 incomm1 = incomm2 = inquote = FALSE;
2167 found_tag = FALSE; /* have a proc name; check if extern */
2168 get_tagname = FALSE; /* have found "procedure" keyword */
2169 inparms = FALSE; /* found '(' after "proc" */
2170 verify_tag = FALSE; /* check if "extern" is ahead */
2172 /* long main loop to get next char */
2173 while (!feof (fi))
2175 c = *dbp++;
2176 if (c == 0) /* if end of line */
2178 GET_NEW_LINE;
2179 if (*dbp == 0)
2180 continue;
2181 if (!((found_tag && verify_tag) ||
2182 get_tagname))
2183 c = *dbp++; /* only if don't need *dbp pointing */
2184 /* to the beginning of the name of */
2185 /* the procedure or function */
2187 if (incomm1) /* within { - } comments */
2189 if (c == '}')
2190 incomm1 = FALSE;
2191 continue;
2193 else if (incomm2) /* within (* - *) comments */
2195 if (c == '*')
2197 while ((c = *dbp++) == '*')
2198 continue;
2199 if (c == 0)
2200 GET_NEW_LINE;
2201 if (c == ')')
2202 incomm2 = FALSE;
2204 continue;
2206 else if (inquote)
2208 if (c == '\'')
2209 inquote = FALSE;
2210 continue;
2212 else
2213 switch (c)
2215 case '\'':
2216 inquote = TRUE; /* found first quote */
2217 continue;
2218 case '{': /* found open-{-comment */
2219 incomm1 = TRUE;
2220 continue;
2221 case '(':
2222 if (*dbp == '*') /* found open-(*-comment */
2224 incomm2 = TRUE;
2225 dbp++;
2227 else if (found_tag) /* found '(' after tag, i.e., parm-list */
2228 inparms = TRUE;
2229 continue;
2230 case ')': /* end of parms list */
2231 if (inparms)
2232 inparms = FALSE;
2233 continue;
2234 case ';':
2235 if ((found_tag) && (!inparms)) /* end of proc or fn stmt */
2237 verify_tag = TRUE;
2238 break;
2240 continue;
2242 if ((found_tag) && (verify_tag) && (*dbp != ' '))
2244 /* check if this is an "extern" declaration */
2245 if (*dbp == 0)
2246 continue;
2247 if ((*dbp == 'e') || (*dbp == 'E'))
2249 if (tail ("extern")) /* superfluous, really! */
2251 found_tag = FALSE;
2252 verify_tag = FALSE;
2255 else if ((*dbp == 'f') || (*dbp == 'F'))
2257 if (tail ("forward")) /* check for forward reference */
2259 found_tag = FALSE;
2260 verify_tag = FALSE;
2263 if ((found_tag) && (verify_tag)) /* not external proc, so make tag */
2265 found_tag = FALSE;
2266 verify_tag = FALSE;
2267 pfnote (nambuf, TRUE, FALSE,
2268 tline.buffer, cp - tline.buffer + 1,
2269 save_lineno, save_lcno);
2270 continue;
2273 if (get_tagname) /* grab name of proc or fn */
2275 if (*dbp == 0)
2276 continue;
2278 /* save all values for later tagging */
2279 tline.size = lb.size;
2280 strcpy (tline.buffer, lb.buffer);
2281 save_lineno = lineno;
2282 save_lcno = linecharno;
2284 /* grab block name */
2285 for (cp = dbp + 1; *cp && (!endtoken (*cp)); cp++)
2286 continue;
2287 c = cp[0];
2288 cp[0] = 0;
2289 strcpy (nambuf, dbp);
2290 cp[0] = c;
2291 dbp = cp; /* restore dbp to e-o-token */
2292 get_tagname = FALSE;
2293 found_tag = TRUE;
2294 continue;
2296 /* and proceed to check for "extern" */
2298 if ((!incomm1) && (!incomm2) && (!inquote) &&
2299 (!found_tag) && (!get_tagname))
2301 /* check for proc/fn keywords */
2302 switch (c | ' ')
2304 case 'p':
2305 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2306 get_tagname = TRUE;
2307 continue;
2308 case 'f':
2309 if (tail ("unction"))
2310 get_tagname = TRUE;
2311 continue;
2314 } /* while not e-o-f */
2318 * lisp tag functions
2319 * just look for (def or (DEF
2322 void
2323 L_funcs (fi)
2324 FILE *fi;
2326 lineno = 0;
2327 charno = 0;
2328 pfcnt = 0;
2330 while (!feof (fi))
2332 lineno++;
2333 linecharno = charno;
2334 charno += readline (&lb, fi);
2335 dbp = lb.buffer;
2336 if (dbp[0] == '(')
2338 if (L_isdef (dbp))
2340 while (!isspace (*dbp))
2341 dbp++;
2342 while (isspace (*dbp))
2343 dbp++;
2344 L_getit ();
2346 else
2348 /* Check for (foo::defmumble name-defined ... */
2349 while (*dbp && *dbp != ':' && !isspace (*dbp)
2350 && *dbp != '(' && *dbp != ')')
2351 dbp++;
2352 if (*dbp == ':')
2354 while (*dbp == ':')
2355 dbp++;
2357 if (L_isdef (dbp))
2359 while (!isspace (*dbp))
2360 dbp++;
2361 while (isspace (*dbp))
2362 dbp++;
2363 L_getit ();
2372 L_isdef (dbp)
2373 char *dbp;
2375 return ((dbp[1] == 'D' || dbp[1] == 'd') &&
2376 (dbp[2] == 'E' || dbp[2] == 'e') &&
2377 (dbp[3] == 'F' || dbp[3] == 'f'));
2380 void
2381 L_getit ()
2383 register char *cp;
2384 char c;
2385 char nambuf[BUFSIZ];
2387 if (*dbp == 0)
2388 return;
2389 for (cp = dbp + 1; *cp && *cp != '(' && *cp != ' '; cp++)
2390 continue;
2391 c = cp[0];
2392 cp[0] = 0;
2393 (void) strcpy (nambuf, dbp);
2394 cp[0] = c;
2395 pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
2396 pfcnt++;
2400 * Scheme tag functions
2401 * look for (def... xyzzy
2402 * look for (def... (xyzzy
2403 * look for (def ... ((...(xyzzy ....
2404 * look for (set! xyzzy
2407 static void get_scheme ();
2409 void
2410 Scheme_funcs (fi)
2411 FILE *fi;
2413 lineno = 0;
2414 charno = 0;
2415 pfcnt = 0;
2417 while (!feof (fi))
2419 lineno++;
2420 linecharno = charno;
2421 charno += readline (&lb, fi);
2422 dbp = lb.buffer;
2423 if (dbp[0] == '(' &&
2424 (dbp[1] == 'D' || dbp[1] == 'd') &&
2425 (dbp[2] == 'E' || dbp[2] == 'e') &&
2426 (dbp[3] == 'F' || dbp[3] == 'f'))
2428 while (!isspace (*dbp))
2429 dbp++;
2430 /* Skip over open parens and white space */
2431 while (*dbp && (isspace (*dbp) || *dbp == '('))
2432 dbp++;
2433 get_scheme ();
2435 if (dbp[0] == '(' &&
2436 (dbp[1] == 'S' || dbp[1] == 's') &&
2437 (dbp[2] == 'E' || dbp[2] == 'e') &&
2438 (dbp[3] == 'T' || dbp[3] == 't') &&
2439 (dbp[4] == '!' || dbp[4] == '!') &&
2440 (isspace (dbp[5])))
2442 while (!isspace (*dbp))
2443 dbp++;
2444 /* Skip over white space */
2445 while (isspace (*dbp))
2446 dbp++;
2447 get_scheme ();
2452 static void
2453 get_scheme ()
2455 register char *cp;
2456 char c;
2457 char nambuf[BUFSIZ];
2459 if (*dbp == 0)
2460 return;
2461 /* Go till you get to white space or a syntactic break */
2462 for (cp = dbp + 1; *cp && *cp != '(' && *cp != ')' && !isspace (*cp); cp++)
2463 continue;
2464 /* Null terminate the string there. */
2465 c = cp[0];
2466 cp[0] = 0;
2467 /* Copy the string */
2468 strcpy (nambuf, dbp);
2469 /* Unterminate the string */
2470 cp[0] = c;
2471 /* Announce the change */
2472 pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
2473 pfcnt++;
2476 /* Find tags in TeX and LaTeX input files. */
2478 /* TEX_toktab is a table of TeX control sequences that define tags.
2479 Each TEX_tabent records one such control sequence.
2480 CONVERT THIS TO USE THE Stab TYPE!! */
2482 struct TEX_tabent
2484 char *name;
2485 int len;
2488 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
2490 /* Default set of control sequences to put into TEX_toktab.
2491 The value of environment var TEXTAGS is prepended to this. */
2493 static char *TEX_defenv =
2494 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2496 void TEX_mode ();
2497 struct TEX_tabent *TEX_decode_env ();
2498 void TEX_getit ();
2499 int TEX_Token ();
2501 static char TEX_esc = '\\';
2502 static char TEX_opgrp = '{';
2503 static char TEX_clgrp = '}';
2506 * TeX/LaTeX scanning loop.
2509 void
2510 TEX_funcs (fi)
2511 FILE *fi;
2513 char *lasthit;
2515 lineno = 0;
2516 charno = 0;
2517 pfcnt = 0;
2519 /* Select either \ or ! as escape character. */
2520 TEX_mode (fi);
2522 /* Initialize token table once from environment. */
2523 if (!TEX_toktab)
2524 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
2526 while (!feof (fi))
2527 { /* Scan each line in file */
2528 lineno++;
2529 linecharno = charno;
2530 charno += readline (&lb, fi);
2531 dbp = lb.buffer;
2532 lasthit = dbp;
2533 while (dbp = etags_index (dbp, TEX_esc)) /* Look at each escape in line */
2535 register int i;
2537 if (!*(++dbp))
2538 break;
2539 linecharno += dbp - lasthit;
2540 lasthit = dbp;
2541 i = TEX_Token (lasthit);
2542 if (0 <= i)
2544 TEX_getit (lasthit, TEX_toktab[i].len);
2545 break; /* We only save a line once */
2551 #define TEX_LESC '\\'
2552 #define TEX_SESC '!'
2553 #define TEX_cmt '%'
2555 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2556 /* chars accordingly. */
2558 void
2559 TEX_mode (f)
2560 FILE *f;
2562 int c;
2564 while ((c = getc (f)) != EOF)
2566 /* Skip to next line if we hit the TeX comment char. */
2567 if (c == TEX_cmt)
2568 while (c != '\n')
2569 c = getc (f);
2570 else if (c == TEX_LESC || c == TEX_SESC )
2571 break;
2574 if (c == TEX_LESC)
2576 TEX_esc = TEX_LESC;
2577 TEX_opgrp = '{';
2578 TEX_clgrp = '}';
2580 else
2582 TEX_esc = TEX_SESC;
2583 TEX_opgrp = '<';
2584 TEX_clgrp = '>';
2586 rewind (f);
2589 /* Read environment and prepend it to the default string. */
2590 /* Build token table. */
2592 struct TEX_tabent *
2593 TEX_decode_env (evarname, defenv)
2594 char *evarname;
2595 char *defenv;
2597 register char *env, *p;
2599 struct TEX_tabent *tab;
2600 int size, i;
2602 /* Append default string to environment. */
2603 env = getenv (evarname);
2604 if (!env)
2605 env = defenv;
2606 else
2607 env = concat (env, defenv, "");
2609 /* Allocate a token table */
2610 for (size = 1, p = env; p;)
2611 if ((p = etags_index (p, ':')) && *(++p))
2612 size++;
2613 /* Add 1 to leave room for null terminator. */
2614 tab = xnew (size + 1, struct TEX_tabent);
2616 /* Unpack environment string into token table. Be careful about */
2617 /* zero-length strings (leading ':', "::" and trailing ':') */
2618 for (i = 0; *env;)
2620 p = etags_index (env, ':');
2621 if (!p) /* End of environment string. */
2622 p = env + strlen (env);
2623 if (p - env > 0)
2624 { /* Only non-zero strings. */
2625 tab[i].name = savenstr (env, p - env);
2626 tab[i].len = strlen (tab[i].name);
2627 i++;
2629 if (*p)
2630 env = p + 1;
2631 else
2633 tab[i].name = NULL; /* Mark end of table. */
2634 tab[i].len = 0;
2635 break;
2638 return tab;
2641 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2642 The name being defined actually starts at (NAME + LEN + 1).
2643 But we seem to include the TeX command in the tag name. */
2645 void
2646 TEX_getit (name, len)
2647 char *name;
2648 int len;
2650 char *p = name + len;
2651 char nambuf[BUFSIZ];
2653 if (*name == 0)
2654 return;
2656 /* Let tag name extend to next group close (or end of line) */
2657 while (*p && *p != TEX_clgrp)
2658 p++;
2659 (void) strncpy (nambuf, name, p - name);
2660 nambuf[p - name] = 0;
2662 pfnote (nambuf, TRUE, FALSE, lb.buffer, strlen (lb.buffer), lineno, linecharno);
2663 pfcnt++;
2666 /* If the text at CP matches one of the tag-defining TeX command names,
2667 return the etags_index of that command in TEX_toktab.
2668 Otherwise return -1. */
2670 /* Keep the capital `T' in `Token' for dumb truncating compilers
2671 (this distinguishes it from `TEX_toktab' */
2673 TEX_Token (cp)
2674 char *cp;
2676 int i;
2678 for (i = 0; TEX_toktab[i].len > 0; i++)
2679 if (strncmp (TEX_toktab[i].name, cp, TEX_toktab[i].len) == 0)
2680 return i;
2681 return -1;
2684 /* Support for Prolog. */
2686 /* whole head (not only functor, but also arguments)
2687 is gotten in compound term. */
2689 void
2690 prolog_getit (s, lineno, linecharno)
2691 char *s;
2692 int lineno;
2693 long linecharno;
2695 char nambuf[BUFSIZ], *save_s, tmpc;
2696 int insquote, npar;
2698 save_s = s;
2699 insquote = FALSE;
2700 npar = 0;
2701 while (1)
2703 if (*s == '\0') /* syntax error. */
2704 return;
2705 else if (insquote && *s == '\'' && *(s + 1) == '\'')
2706 s += 2;
2707 else if (*s == '\'')
2709 insquote = !insquote;
2710 s++;
2712 else if (!insquote && *s == '(')
2714 npar++;
2715 s++;
2717 else if (!insquote && *s == ')')
2719 npar--;
2720 s++;
2721 if (npar == 0)
2722 break;
2723 else if (npar < 0) /* syntax error. */
2724 return;
2726 else if (!insquote && *s == '.' && (isspace (*(s + 1)) || *(s + 1) == '\0'))
2727 { /* fullstop. */
2728 if (npar != 0) /* syntax error. */
2729 return;
2730 s++;
2731 break;
2733 else
2734 s++;
2736 tmpc = *s;
2737 *s = '\0';
2738 strcpy (nambuf, save_s);
2739 *s = tmpc;
2740 pfnote (nambuf, TRUE, save_s, strlen (nambuf), lineno, linecharno);
2743 /* It is assumed that prolog predicate starts from column 0. */
2745 void
2746 prolog_funcs (fi)
2747 FILE *fi;
2749 void skip_comment (), prolog_getit ();
2751 lineno = linecharno = charno = 0;
2752 while (!feof (fi))
2754 lineno++;
2755 linecharno += charno;
2756 charno = readline (&lb, fi) + 1; /* 1 for newline. */
2757 dbp = lb.buffer;
2758 if (isspace (dbp[0])) /* not predicate header. */
2759 continue;
2760 else if (dbp[0] == '%') /* comment. */
2761 continue;
2762 else if (dbp[0] == '/' && dbp[1] == '*') /* comment. */
2763 skip_comment (&lb, fi, &lineno, &linecharno);
2764 else /* found. */
2765 prolog_getit (dbp, lineno, linecharno);
2769 void
2770 skip_comment (plb, fi, plineno, plinecharno)
2771 struct linebuffer *plb;
2772 FILE *fi;
2773 int *plineno; /* result */
2774 long *plinecharno; /* result */
2776 while (!substr ("*/", plb->buffer))
2778 (*plineno)++;
2779 *plinecharno += readline (plb, fi) + 1;
2780 } /* 1 for newline. */
2783 /* Return TRUE if 'sub' exists somewhere in 's'. */
2786 substr (sub, s)
2787 char *sub;
2788 char *s;
2790 while (*s && (s = etags_index (s, *sub)))
2791 if (prestr (sub, s))
2792 return (TRUE);
2793 else
2794 s++;
2795 return (FALSE);
2798 /* Return TRUE if 'pre' is prefix of string 's'. */
2801 prestr (pre, s)
2802 char *pre;
2803 char *s;
2805 if (*pre == '\0')
2806 return (TRUE);
2807 else if (*pre == *s)
2808 return (prestr (pre + 1, s + 1));
2809 else
2810 return (FALSE);
2813 /* Initialize a linebuffer for use */
2815 void
2816 initbuffer (linebuffer)
2817 struct linebuffer *linebuffer;
2819 linebuffer->size = 200;
2820 linebuffer->buffer = xnew (200, char);
2824 * Read a line of text from `stream' into `linebuffer'.
2825 * Return the number of characters read from `stream',
2826 * which is the length of the line including the newline, if any.
2828 long
2829 readline (linebuffer, stream)
2830 struct linebuffer *linebuffer;
2831 register FILE *stream;
2833 char *buffer = linebuffer->buffer;
2834 register char *p = linebuffer->buffer;
2835 register char *pend;
2836 int newline; /* 1 if ended with newline, 0 if ended with EOF */
2838 pend = p + linebuffer->size; /* Separate to avoind 386/IX compiler bug. */
2840 while (1)
2842 register int c = getc (stream);
2843 if (p == pend)
2845 linebuffer->size *= 2;
2846 buffer = (char *) xrealloc (buffer, linebuffer->size);
2847 p += buffer - linebuffer->buffer;
2848 pend = buffer + linebuffer->size;
2849 linebuffer->buffer = buffer;
2851 if (c < 0 || c == '\n')
2853 *p = 0;
2854 newline = (c == '\n' ? 1 : 0);
2855 break;
2857 *p++ = c;
2860 return p - buffer + newline;
2863 char *
2864 savestr (cp)
2865 char *cp;
2867 return savenstr (cp, strlen (cp));
2870 char *
2871 savenstr (cp, len)
2872 char *cp;
2873 int len;
2875 register char *dp;
2877 dp = xnew (len + 1, char);
2878 (void) strncpy (dp, cp, len);
2879 dp[len] = '\0';
2880 return dp;
2884 * Return the ptr in sp at which the character c last
2885 * appears; NULL if not found
2887 * Identical to v7 rindex, included for portability.
2890 char *
2891 etags_rindex (sp, c)
2892 register char *sp, c;
2894 register char *r;
2896 r = NULL;
2899 if (*sp == c)
2900 r = sp;
2901 } while (*sp++);
2902 return (r);
2907 * Return the ptr in sp at which the character c first
2908 * appears; NULL if not found
2910 * Identical to v7 index, included for portability.
2913 char *
2914 etags_index (sp, c)
2915 register char *sp, c;
2919 if (*sp == c)
2920 return (sp);
2921 } while (*sp++);
2922 return (NULL);
2925 /* Print error message and exit. */
2927 /* VARARGS1 */
2928 void
2929 fatal (s1, s2)
2930 char *s1, *s2;
2932 error (s1, s2);
2933 exit (1);
2936 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
2938 /* VARARGS1 */
2939 void
2940 error (s1, s2)
2941 char *s1, *s2;
2943 fprintf (stderr, "%s: ", progname);
2944 fprintf (stderr, s1, s2);
2945 fprintf (stderr, "\n");
2948 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
2950 char *
2951 concat (s1, s2, s3)
2952 char *s1, *s2, *s3;
2954 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
2955 char *result = xnew (len1 + len2 + len3 + 1, char);
2957 (void) strcpy (result, s1);
2958 (void) strcpy (result + len1, s2);
2959 (void) strcpy (result + len1 + len2, s3);
2960 *(result + len1 + len2 + len3) = 0;
2962 return result;
2965 /* Like malloc but get fatal error if memory is exhausted. */
2967 char *
2968 xmalloc (size)
2969 int size;
2971 char *result = malloc (size);
2972 if (!result)
2973 fatal ("virtual memory exhausted", 0);
2974 return result;
2977 char *
2978 xrealloc (ptr, size)
2979 char *ptr;
2980 int size;
2982 char *result = realloc (ptr, size);
2983 if (!result)
2984 fatal ("virtual memory exhausted");
2985 return result;