* etags.c (absolute_pathnames, cwd): added global vars.
[bpt/emacs.git] / lib-src / etags.c
1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 1987, 1988, 1989, 1993 Free Software Foundation, Inc. and Ken Arnold
3
4 This file is not considered part of GNU Emacs.
5
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.
10
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.
15
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. */
19
20 /*
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++.
27 *
28 * Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer. 10.7
29 */
30
31 #ifdef MSDOS
32 #include <fcntl.h>
33 #endif /* MSDOS */
34
35 #ifdef HAVE_CONFIG_H
36 #include <../src/config.h>
37 #endif
38
39 #include <stdio.h>
40 #include <ctype.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43
44 #if !defined (S_ISREG) && defined (S_IFREG)
45 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
46 #endif
47
48 #include "getopt.h"
49
50 extern char *getenv ();
51 extern char *getcwd ();
52
53 char *etags_index (), *etags_rindex ();
54 char *savenstr ();
55
56 /* Define the symbol ETAGS to make the program "etags",
57 which makes emacs-style tag tables by default.
58 Define CTAGS to make the program "ctags" compatible with the usual one.
59 Define neither one to get behavior that depends
60 on the name with which the program is invoked
61 (but we don't normally compile it that way). */
62
63 #if !defined(ETAGS) && !defined(CTAGS)
64 /* If neither is defined, program can be run as either. */
65 #define ETAGS
66 #define CTAGS
67 #endif
68
69 /* On VMS, CTAGS is not useful, so always do ETAGS. */
70 #ifdef VMS
71 #ifndef ETAGS
72 #define ETAGS
73 #endif
74 #endif
75
76 /* Exit codes for success and failure. */
77 #ifdef VMS
78 #define GOOD (1)
79 #define BAD (0)
80 #else
81 #define GOOD (0)
82 #define BAD (1)
83 #endif
84
85 /*
86 * The FILEPOS abstract type, which represents a position in a file,
87 * plus the following accessor functions:
88 *
89 * long GET_CHARNO (pos)
90 * returns absolute char number.
91 * void SET_FILEPOS (pos, fp, charno)
92 * FILE *fp; long charno;
93 * sets `pos' from the current file
94 * position of `fp' and from `charno',
95 * which must be the absolute character
96 * number corresponding to the current
97 * position of `fp'.
98 *
99 * The `pos' parameter is an lvalue expression of type FILEPOS.
100 * Parameters to the accessor functions are evaluated 0 or more times,
101 * and so must have no side effects.
102 *
103 * FILEPOS objects can also be assigned and passed to and from
104 * functions in the normal C manner.
105 *
106 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
107 */
108
109 #ifndef DEBUG
110 /* real implementation */
111 typedef long FILEPOS;
112 #define GET_CHARNO(pos) ((pos) + 0)
113 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
114 #else
115 /* debugging implementation */
116 typedef struct
117 {
118 long charno;
119 } FILEPOS;
120
121 #define GET_CHARNO(pos) ((pos).charno + 0)
122 #define SET_FILEPOS(pos, fp, cno) \
123 ((void) ((pos).charno = (cno), \
124 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
125 : 0))
126 #endif
127
128 #define streq(s, t) (strcmp (s, t) == 0)
129 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
130 #define logical int
131
132 #define TRUE 1
133 #define FALSE 0
134
135 #define iswhite(arg) (_wht[arg]) /* T if char is white */
136 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
137 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
138 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
139
140 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
141
142 struct nd_st
143 { /* sorting structure */
144 char *name; /* function or type name */
145 char *file; /* file name */
146 logical is_func; /* use pattern or line no */
147 logical named; /* list name separately */
148 logical been_warned; /* set if noticed dup */
149 int lno; /* line number tag is on */
150 long cno; /* character number line starts on */
151 char *pat; /* search pattern */
152 struct nd_st *left, *right; /* left and right sons */
153 };
154
155 long ftell ();
156 typedef struct nd_st NODE;
157
158 logical header_file; /* TRUE if .h file, FALSE o.w. */
159 /* boolean "functions" (see init) */
160 logical _wht[0177], _etk[0177], _itk[0177], _btk[0177];
161
162
163 char *concat ();
164 char *savenstr ();
165 char *savestr ();
166 char *xmalloc ();
167 char *xrealloc ();
168 int L_isdef (), L_isquote ();
169 int PF_funcs ();
170 int total_size_of_entries ();
171 logical consider_token ();
172 logical tail ();
173 long readline ();
174 void Asm_funcs ();
175 void C_entries ();
176 void L_funcs ();
177 void L_getit ();
178 void PAS_funcs ();
179 void Scheme_funcs ();
180 void TEX_funcs ();
181 void add_node ();
182 void error ();
183 void fatal ();
184 logical find_entries ();
185 void free_tree ();
186 void getit ();
187 void init ();
188 void initbuffer ();
189 void initbuffer ();
190 void pfnote ();
191 void process_file ();
192 void put_entries ();
193 void takeprec ();
194
195 /*
196 * MACRO
197 * xnew -- allocate storage
198 *
199 * SYNOPSIS
200 * Type *xnew (int n, Type);
201 */
202 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
203
204 /*
205 * Symbol table types.
206 */
207 enum sym_type
208 {
209 st_none, st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
210 };
211 \f
212
213
214 typedef int LINENO;
215
216 typedef struct
217 {
218 char *p;
219 int len;
220 LINENO lineno;
221 logical named;
222 } TOKEN;
223
224 /* C extensions.
225 */
226 #define C_PLPL 0x00001 /* C++ */
227 #define C_STAR 0x00003 /* C* */
228 #define YACC 0x10000 /* yacc file */
229
230 char searchar = '/'; /* use /.../ searches */
231
232 LINENO lineno; /* line number of current line */
233 long charno; /* current character number */
234
235 long linecharno; /* charno of start of line; not used by C, but
236 * by every other language.
237 */
238
239 char *curfile, /* current input file name */
240 *outfile, /* output file */
241 *white = " \f\t\n", /* white chars */
242 *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
243 /* token starting chars */
244 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
245 /* valid in-token chars */
246 *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
247
248 int append_to_tagfile; /* -a: append to tags */
249 int absolute_pathnames; /* -A: use absolute pathnames in tag file */
250 int emacs_tags_format; /* emacs style output (no -e option any more) */
251 /* The following three default to 1 for etags, but to 0 for ctags. */
252 int typedefs; /* -t: create tags for typedefs */
253 int typedefs_and_cplusplus; /* -T: create tags for typedefs, level */
254 /* 0 struct/enum/union decls, and C++ */
255 /* member functions */
256 int constantypedefs; /* -d: create tags for C #define and enum */
257 /* constants. Default under etags. Enum */
258 /* constants not implemented. */
259 /* -D: opposite of -d. Default under ctags. */
260 int update; /* -u: update tags */
261 int vgrind_style; /* -v: create vgrind style index output */
262 int no_warnings; /* -w: suppress warnings */
263 int cxref_style; /* -x: create cxref style output */
264 int cplusplus; /* .[hc] means C++, not C */
265 int noindentypedefs; /* -S: ignore indentation in C */
266
267 /* Name this program was invoked with. */
268 char *progname;
269
270 /* The current working directory, used if --absolute-pathnames. */
271 char *cwd;
272
273 struct option longopts[] = {
274 { "append", no_argument, NULL, 'a' },
275 { "absolute-pathnames", no_argument, NULL, 'A' },
276 { "backward-search", no_argument, NULL, 'B' },
277 { "c++", no_argument, NULL, 'C' },
278 { "cxref", no_argument, NULL, 'x' },
279 { "defines", no_argument, NULL, 'd' },
280 { "forward-search", no_argument, NULL, 'F' },
281 { "help", no_argument, NULL, 'H' },
282 { "ignore-indentation", no_argument, NULL, 'S' },
283 { "include", required_argument, NULL, 'i' },
284 { "no-defines", no_argument, NULL, 'D' },
285 { "no-warn", no_argument, NULL, 'w' },
286 { "output", required_argument, NULL, 'o' },
287 { "typedefs", no_argument, NULL, 't' },
288 { "typedefs-and-c++", no_argument, NULL, 'T' },
289 { "update", no_argument, NULL, 'u' },
290 { "version", no_argument, NULL, 'V' },
291 { "vgrind", no_argument, NULL, 'v' },
292 { 0 }
293 };
294
295 FILE *inf, /* ioptr for current input file */
296 *outf; /* ioptr for tags file */
297
298 NODE *head; /* the head of the binary tree of tags */
299
300 int permit_duplicates = 1; /* Nonzero means allow duplicate tags. */
301
302 /* A `struct linebuffer' is a structure which holds a line of text.
303 `readline' reads a line from a stream into a linebuffer
304 and works regardless of the length of the line. */
305
306 struct linebuffer
307 {
308 long size;
309 char *buffer;
310 };
311
312 struct linebuffer lb; /* the current line */
313 struct linebuffer filename_lb; /* used to read in filenames */
314 struct
315 {
316 FILEPOS linepos;
317 struct linebuffer lb; /* used by C_entries instead of lb */
318 } lbs[2];
319 \f
320 void
321 print_version ()
322 {
323 #ifdef CTAGS
324 printf ("CTAGS ");
325 #ifdef ETAGS
326 printf ("and ");
327 #endif
328 #endif
329 #ifdef ETAGS
330 printf ("ETAGS ");
331 #endif
332 printf ("for Emacs version 19.\n");
333
334 exit (GOOD);
335 }
336
337 void
338 print_help ()
339 {
340 printf ("These are the options accepted by %s. You may use unambiguous\n\
341 abbreviations for the long option names. A - as file name means read file\n\
342 names from stdin.\n\n", progname);
343
344 puts ("-a, --append\n\
345 Append tag entries to existing tags file.");
346 puts ("-A, --absolute-pathnames\n\
347 Use absolute pathnames for tagged files.");
348
349 #ifdef CTAGS
350 puts ("-B, --backward-search\n\
351 Write the search commands for the tag entries using '?', the\n\
352 backward-search command.");
353 #endif
354
355 puts ("-C, --c++\n\
356 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
357 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
358 extensions are always assumed to be C++ code.");
359
360 #ifdef ETAGS
361 puts ("-d, --defines\n\
362 Create tag entries for #defines, too. This is the default\n\
363 behavior.");
364 #else
365 puts ("-d, --defines\n\
366 Create tag entries for #defines, too.");
367 #endif
368
369 #ifdef CTAGS
370 puts ("-D, --no-defines\n\
371 Don't create tag entries for #defines. This is the default\n\
372 behavior.");
373 #else
374 puts ("-D, --no-defines\n\
375 Don't create tag entries for #defines.");
376 #endif
377
378 #ifdef CTAGS
379 puts ("-F, --forward-search\n\
380 Write the search commands for the tag entries using '/', the\n\
381 forward-search command.");
382 #endif
383
384
385 #ifdef ETAGS
386 puts ("-i FILE, --include=FILE\n\
387 Include a note in tag file indicating that, when searching for\n\
388 a tag, one should also consult the tags file FILE after\n\
389 checking the current file.");
390 #endif
391
392 puts ("-o FILE, --output=FILE\n\
393 Write the tags to FILE.");
394 puts ("-S, --ignore-indentation\n\
395 Don't rely on indentation quite as much as normal. Currently,\n\
396 this means not to assume that a closing brace in the first\n\
397 column is the final brace of a function or structure\n\
398 definition.");
399 puts ("-t, --typedefs\n\
400 Generate tag entries for typedefs. This is the default\n\
401 behavior.");
402 puts ("-T, --typedefs-and-c++\n\
403 Generate tag entries for typedefs, struct/enum/union tags, and\n\
404 C++ member functions.");
405
406 #ifdef CTAGS
407 puts ("-u, --update\n\
408 Update the tag entries for the given files, leaving tag\n\
409 entries for other files in place. Currently, this is\n\
410 implemented by deleting the existing entries for the given\n\
411 files and then rewriting the new entries at the end of the\n\
412 tags file. It is often faster to simply rebuild the entire\n\
413 tag file than to use this.");
414 puts ("-v, --vgrind\n\
415 Generates an index of items intended for human consumption,\n\
416 similar to the output of vgrind. The index is sorted, and\n\
417 gives the page number of each item.");
418 puts ("-x, --cxref\n\
419 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
420 The output uses line numbers instead of page numbers, but\n\
421 beyond that the differences are cosmetic; try both to see\n\
422 which you like.");
423 puts ("-w, --no-warn\n\
424 Suppress warning messages about entries defined in multiple\n\
425 files.");
426 #endif
427
428 puts ("-V, --version\n\
429 Print the version of the program.\n\
430 -H, --help\n\
431 Print this help message.");
432
433 exit (GOOD);
434 }
435
436 \f
437 void
438 main (argc, argv)
439 int argc;
440 char *argv[];
441 {
442 char cmd[100];
443 int i;
444 unsigned int nincluded_files = 0;
445 char **included_files = xnew (argc, char *);
446 char *this_file;
447 #ifdef VMS
448 char got_err;
449
450 extern char *gfnames ();
451 extern char *massage_name ();
452 #endif
453
454 #ifdef MSDOS
455 _fmode = O_BINARY; /* all of files are treated as binary files */
456 #endif /* MSDOS */
457
458 progname = argv[0];
459
460 #ifndef CTAGS
461 emacs_tags_format = 1;
462 #else
463 emacs_tags_format = 0;
464 #endif
465
466 /*
467 * If etags, always find typedefs and structure tags. Why not?
468 * Also default is to find macro constants.
469 */
470 if (emacs_tags_format)
471 typedefs = typedefs_and_cplusplus = constantypedefs = 1;
472
473 for (;;)
474 {
475 int opt;
476 opt = getopt_long (argc, argv, "aACdDo:f:StTi:BFuvxwVH", longopts, 0);
477
478 if (opt == EOF)
479 break;
480
481 switch (opt)
482 {
483 case '\0':
484 /* If getopt returns '\0', then it has already processed a
485 long-named option. We should do nothing. */
486 break;
487
488 /* Common options. */
489 case 'a':
490 append_to_tagfile++;
491 break;
492 case 'A':
493 absolute_pathnames++;
494 break;
495 case 'C':
496 cplusplus = 1;
497 break;
498 case 'd':
499 constantypedefs = 1;
500 break;
501 case 'D':
502 constantypedefs = 0;
503 break;
504 case 'f':
505 case 'o':
506 if (outfile)
507 {
508 fprintf (stderr,
509 "%s: -%c flag may only be given once\n", progname, opt);
510 goto usage;
511 }
512 outfile = optarg;
513 break;
514 case 'S':
515 noindentypedefs++;
516 break;
517 case 't':
518 typedefs++;
519 break;
520 case 'T':
521 typedefs++;
522 typedefs_and_cplusplus++;
523 break;
524 case 'V':
525 print_version ();
526 break;
527 case 'H':
528 print_help ();
529 break;
530
531 /* Etags options */
532 case 'i':
533 if (!emacs_tags_format)
534 goto usage;
535 included_files[nincluded_files++] = optarg;
536 break;
537
538 /* Ctags options. */
539 case 'B':
540 searchar = '?';
541 if (emacs_tags_format)
542 goto usage;
543 break;
544 case 'F':
545 searchar = '/';
546 if (emacs_tags_format)
547 goto usage;
548 break;
549 case 'u':
550 update++;
551 if (emacs_tags_format)
552 goto usage;
553 break;
554 case 'v':
555 vgrind_style++;
556 /*FALLTHRU*/
557 case 'x':
558 cxref_style++;
559 if (emacs_tags_format)
560 goto usage;
561 break;
562 case 'w':
563 no_warnings++;
564 if (emacs_tags_format)
565 goto usage;
566 break;
567
568 default:
569 goto usage;
570 }
571 }
572
573 if (optind == argc && nincluded_files == 0)
574 {
575 fprintf (stderr, "%s: No input files specified.\n", progname);
576
577 usage:
578 fprintf (stderr, "%s: Try `%s --help' for a complete list of options.\n",
579 progname, progname);
580 exit (BAD);
581 }
582
583 if (outfile == 0)
584 {
585 outfile = emacs_tags_format ? "TAGS" : "tags";
586 }
587
588 init (); /* set up boolean "functions" */
589
590 initbuffer (&lb);
591 initbuffer (&lbs[0].lb);
592 initbuffer (&lbs[1].lb);
593 initbuffer (&filename_lb);
594 /*
595 * loop through files finding functions
596 */
597 if (emacs_tags_format)
598 {
599 if (streq (outfile, "-"))
600 outf = stdout;
601 else
602 outf = fopen (outfile, append_to_tagfile ? "a" : "w");
603 if (outf == NULL)
604 {
605 perror (outfile);
606 exit (BAD);
607 }
608 }
609
610 #ifdef VMS
611 argc -= optind;
612 argv += optind;
613 while (gfnames (&argc, &argv, &got_err) != NULL)
614 {
615 if (got_err)
616 {
617 error ("Can't find file %s\n", this_file);
618 argc--, argv++;
619 }
620 else
621 {
622 this_file = massage_name (this_file);
623 #if 0
624 }
625 } /* solely to balance out the ifdef'd parens above */
626 #endif
627 #else
628 if (absolute_pathnames)
629 {
630 cwd = getcwd (NULL, 2*BUFSIZ);
631 if (cwd == NULL)
632 {
633 perror ("pwd");
634 exit (BAD);
635 }
636 strcat (cwd, "/");
637 }
638 for (; optind < argc; optind++)
639 {
640 this_file = argv[optind];
641 #endif
642 /* Input file named "-" means read file names from stdin and use them. */
643 if (streq (this_file, "-"))
644 {
645 while (!feof (stdin))
646 {
647 (void) readline (&filename_lb, stdin);
648 if (strlen (filename_lb.buffer) > 0)
649 process_file (filename_lb.buffer);
650 }
651 }
652 else
653 process_file (this_file);
654 }
655
656 if (emacs_tags_format)
657 {
658 while (nincluded_files-- > 0)
659 fprintf (outf, "\f\n%s,include\n", *included_files++);
660
661 (void) fclose (outf);
662 exit (GOOD);
663 }
664
665 if (cxref_style)
666 {
667 put_entries (head);
668 exit (GOOD);
669 }
670 if (update)
671 {
672 /* update cannot be set under VMS, so we may assume that argc
673 and argv have not been munged. */
674 for (i = optind; i < argc; i++)
675 {
676 sprintf (cmd,
677 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
678 outfile, argv[i], outfile);
679 (void) system (cmd);
680 }
681 append_to_tagfile++;
682 }
683 outf = fopen (outfile, append_to_tagfile ? "a" : "w");
684 if (outf == NULL)
685 {
686 perror (outfile);
687 exit (GOOD);
688 }
689 put_entries (head);
690 (void) fclose (outf);
691 if (update)
692 {
693 sprintf (cmd, "sort %s -o %s", outfile, outfile);
694 (void) system (cmd);
695 }
696 exit (GOOD);
697 }
698
699
700 /*
701 * This routine is called on each file argument.
702 */
703 void
704 process_file (file)
705 char *file;
706 {
707 struct stat stat_buf;
708
709 if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode))
710 {
711 fprintf (stderr, "Skipping %s: it is not a regular file.\n", file);
712 return;
713 }
714 if (streq (file, outfile) && !streq (outfile, "-"))
715 {
716 fprintf (stderr, "Skipping inclusion of %s in self.\n", file);
717 return;
718 }
719 if (!find_entries (file))
720 {
721 return;
722 }
723 if (emacs_tags_format)
724 {
725 fprintf (outf, "\f\n%s%s,%d\n",
726 ((absolute_pathnames && file[0] != '/') ? cwd : ""),
727 file, total_size_of_entries (head));
728 put_entries (head);
729 free_tree (head);
730 head = NULL;
731 }
732 }
733
734 /*
735 * This routine sets up the boolean pseudo-functions which work
736 * by setting boolean flags dependent upon the corresponding character
737 * Every char which is NOT in that string is not a white char. Therefore,
738 * all of the array "_wht" is set to FALSE, and then the elements
739 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
740 * of a char is TRUE if it is the string "white", else FALSE.
741 */
742 void
743 init ()
744 {
745 register char *sp;
746 register int i;
747
748 for (i = 0; i < 0177; i++)
749 _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
750 for (sp = white; *sp; sp++)
751 _wht[*sp] = TRUE;
752 for (sp = endtk; *sp; sp++)
753 _etk[*sp] = TRUE;
754 for (sp = intk; *sp; sp++)
755 _itk[*sp] = TRUE;
756 for (sp = begtk; *sp; sp++)
757 _btk[*sp] = TRUE;
758 _wht[0] = _wht['\n'];
759 _etk[0] = _etk['\n'];
760 _btk[0] = _btk['\n'];
761 _itk[0] = _itk['\n'];
762 }
763
764 /*
765 * This routine opens the specified file and calls the function
766 * which finds the function and type definitions.
767 */
768 logical
769 find_entries (file)
770 char *file;
771 {
772 char *cp;
773 void prolog_funcs ();
774
775 inf = fopen (file, "r");
776 if (inf == NULL)
777 {
778 perror (file);
779 return FALSE;
780 }
781 curfile = savestr (file);
782 cp = etags_rindex (file, '.');
783
784 header_file = (cp && (streq (cp + 1, "h")));
785
786 /* .tex, .aux or .bbl implies LaTeX source code */
787 if (cp && (streq (cp + 1, "tex") || streq (cp + 1, "aux")
788 || streq (cp + 1, "bbl")))
789 {
790 TEX_funcs (inf);
791 goto close_and_return;
792 }
793 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
794 if (cp && (streq (cp + 1, "l")
795 || streq (cp + 1, "el")
796 || streq (cp + 1, "lsp")
797 || streq (cp + 1, "lisp")
798 || streq (cp + 1, "cl")
799 || streq (cp + 1, "clisp")))
800 {
801 L_funcs (inf);
802 goto close_and_return;
803 }
804 /* .scm or .sm or .scheme or ... implies scheme source code */
805 if (cp && (streq (cp + 1, "sm")
806 || streq (cp + 1, "scm")
807 || streq (cp + 1, "scheme")
808 || streq (cp + 1, "t")
809 || streq (cp + 1, "sch")
810 || streq (cp + 1, "SM")
811 || streq (cp + 1, "SCM")
812 /* The `SCM' or `scm' prefix with a version number */
813 || (cp[-1] == 'm' && cp[-2] == 'c' && cp[-3] == 's'
814 && string_numeric_p (cp + 1))
815 || (cp[-1] == 'M' && cp[-2] == 'C' && cp[-3] == 'S'
816 && string_numeric_p (cp + 1))))
817 {
818 Scheme_funcs (inf);
819 goto close_and_return;
820 }
821 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
822 Or even ".sa". */
823 if (cp && (streq (cp + 1, "s")
824 || streq (cp + 1, "a")
825 || streq (cp + 1, "sa")))
826 {
827 Asm_funcs (inf);
828 goto close_and_return;
829 }
830 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
831 if (cp && (streq (cp + 1, "C")
832 || streq (cp + 1, "H")
833 || streq (cp + 1, "cxx")
834 || streq (cp + 1, "hxx")
835 || streq (cp + 1, "cc")))
836 {
837 C_entries (C_PLPL); /* C++ */
838 goto close_and_return;
839 }
840 /* .cs or .hs: a C* file */
841 if (cp && (streq (cp + 1, "cs")
842 || streq (cp + 1, "hs")))
843 {
844 C_entries (C_STAR);
845 goto close_and_return;
846 }
847 /* .y: a yacc file */
848 if (cp && (streq (cp + 1, "y")))
849 {
850 C_entries (YACC);
851 goto close_and_return;
852 }
853 /* .pl implies prolog source code */
854 if (cp && streq (cp + 1, "pl"))
855 {
856 prolog_funcs (inf);
857 goto close_and_return;
858 }
859 /* .p or .pas: a Pascal file */
860 if (cp && (streq (cp + 1, "p")
861 || streq (cp + 1, "pas")))
862 {
863 PAS_funcs (inf);
864 goto close_and_return;
865 }
866 /* If .f or .for, assume it is fortran or nothing. */
867 if (cp && (streq (cp + 1, "f")
868 || streq (cp + 1, "for")))
869 {
870 (void) PF_funcs (inf);
871 goto close_and_return;
872 }
873 /* if not a .c or .h or .y file, try fortran */
874 if (cp && ((cp[1] != 'c'
875 && cp[1] != 'h'
876 && cp[1] != 'y')
877 || (cp[1] != 0 && cp[2] != 0)))
878 {
879 if (PF_funcs (inf) != 0)
880 goto close_and_return;
881 rewind (inf); /* no fortran tags found, try C */
882 }
883 C_entries (cplusplus ? C_PLPL : 0);
884
885 close_and_return:
886 (void) fclose (inf);
887 return TRUE;
888 }
889
890 /* Nonzero if string STR is composed of digits. */
891
892 int
893 string_numeric_p (str)
894 char *str;
895 {
896 while (*str)
897 {
898 if (*str < '0' || *str > '9')
899 return 0;
900 }
901 return 1;
902 }
903 \f
904 /* Record a tag. */
905 /* Should take a TOKEN* instead!! */
906 void
907 pfnote (name, is_func, named, linestart, linelen, lno, cno)
908 char *name; /* tag name */
909 logical is_func; /* function or type name? */
910 logical named; /* tag different from text of definition? */
911 char *linestart;
912 int linelen;
913 int lno;
914 long cno;
915 {
916 register char *fp;
917 register NODE *np;
918 char tem[51];
919 char c;
920
921 np = xnew (1, NODE);
922 if (np == NULL)
923 {
924 if (!emacs_tags_format)
925 {
926 /* It's okay to output early in etags -- it only disrupts the
927 * character count of the tag entries, which is no longer used
928 * by tags.el anyway.
929 */
930 error ("too many entries to sort", 0);
931 }
932 put_entries (head);
933 free_tree (head);
934 head = NULL;
935 np = xnew (1, NODE);
936 }
937 /* If ctags mode, change name "main" to M<thisfilename>. */
938 if (!emacs_tags_format && !cxref_style && streq (name, "main"))
939 {
940 fp = etags_rindex (curfile, '/');
941 name = concat ("M", fp == 0 ? curfile : fp + 1, "");
942 fp = etags_rindex (name, '.');
943 if (fp && fp[1] != '\0' && fp[2] == '\0')
944 *fp = 0;
945 named = TRUE;
946 }
947 np->name = savestr (name);
948 np->file = curfile;
949 np->is_func = is_func;
950 np->named = named;
951 np->lno = lno;
952 /* UNCOMMENT THE +1 HERE: */
953 np->cno = cno /* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
954 np->left = np->right = 0;
955 if (emacs_tags_format)
956 {
957 c = linestart[linelen];
958 linestart[linelen] = 0;
959 }
960 else if (cxref_style == 0)
961 {
962 sprintf (tem, strlen (linestart) < 50 ? "%s$" : "%.50s", linestart);
963 linestart = tem;
964 }
965 np->pat = savestr (linestart);
966 if (emacs_tags_format)
967 {
968 linestart[linelen] = c;
969 }
970
971 add_node (np, &head);
972 }
973
974 /*
975 * free_tree ()
976 * recurse on left children, iterate on right children.
977 */
978 void
979 free_tree (node)
980 register NODE *node;
981 {
982 while (node)
983 {
984 register NODE *node_right = node->right;
985 free_tree (node->left);
986 free (node->name);
987 free (node->pat);
988 free ((char *) node);
989 node = node_right;
990 }
991 }
992
993 /*
994 * add_node ()
995 * Adds a node to the tree of nodes. In etags mode, we don't keep
996 * it sorted; we just keep a linear list. In ctags mode, maintain
997 * an ordered tree, with no attempt at balancing.
998 *
999 * add_node is the only function allowed to add nodes, so it can
1000 * maintain state.
1001 */
1002 /* Must avoid static vars within functions since some systems
1003 #define static as nothing. */
1004 static NODE *last_node = NULL;
1005
1006 void
1007 add_node (node, cur_node_p)
1008 NODE *node, **cur_node_p;
1009 {
1010 register int dif;
1011 register NODE *cur_node = *cur_node_p;
1012
1013 if (cur_node == NULL)
1014 {
1015 *cur_node_p = node;
1016 last_node = node;
1017 return;
1018 }
1019
1020 if (emacs_tags_format)
1021 {
1022 /* Etags Mode */
1023 if (last_node == NULL)
1024 fatal ("internal error in add_node", 0);
1025 last_node->right = node;
1026 last_node = node;
1027 }
1028 else
1029 {
1030 /* Ctags Mode */
1031 dif = strcmp (node->name, cur_node->name);
1032
1033 /*
1034 * If this tag name matches an existing one, then
1035 * do not add the node, but maybe print a warning.
1036 */
1037 if (!dif)
1038 {
1039 if (node->file == cur_node->file)
1040 {
1041 if (!no_warnings)
1042 {
1043 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1044 node->file, lineno, node->name);
1045 fprintf (stderr, "Second entry ignored\n");
1046 }
1047 return;
1048 }
1049 if (!cur_node->been_warned && !no_warnings)
1050 {
1051 fprintf (stderr,
1052 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1053 node->file, cur_node->file, node->name);
1054 }
1055 cur_node->been_warned = TRUE;
1056 return;
1057 }
1058
1059 /* Maybe refuse to add duplicate nodes. */
1060 if (!permit_duplicates)
1061 {
1062 if (streq (node->name, cur_node->name)
1063 && streq (node->file, cur_node->file))
1064 return;
1065 }
1066
1067 /* Actually add the node */
1068 add_node (node, dif < 0 ? &cur_node->left : &cur_node->right);
1069 }
1070 }
1071 \f
1072 void
1073 put_entries (node)
1074 register NODE *node;
1075 {
1076 register char *sp;
1077
1078 if (node == NULL)
1079 return;
1080
1081 /* Output subentries that precede this one */
1082 put_entries (node->left);
1083
1084 /* Output this entry */
1085
1086 if (emacs_tags_format)
1087 {
1088 if (node->named)
1089 {
1090 fprintf (outf, "%s\177%s\001%d,%d\n",
1091 node->pat, node->name,
1092 node->lno, node->cno);
1093 }
1094 else
1095 {
1096 fprintf (outf, "%s\177%d,%d\n",
1097 node->pat,
1098 node->lno, node->cno);
1099 }
1100 }
1101 else if (!cxref_style)
1102 {
1103 fprintf (outf, "%s\t%s\t",
1104 node->name, node->file);
1105
1106 if (node->is_func)
1107 { /* a function */
1108 putc (searchar, outf);
1109 putc ('^', outf);
1110
1111 for (sp = node->pat; *sp; sp++)
1112 {
1113 if (*sp == '\\' || *sp == searchar)
1114 putc ('\\', outf);
1115 putc (*sp, outf);
1116 }
1117 putc (searchar, outf);
1118 }
1119 else
1120 { /* a typedef; text pattern inadequate */
1121 fprintf (outf, "%d", node->lno);
1122 }
1123 putc ('\n', outf);
1124 }
1125 else if (vgrind_style)
1126 fprintf (stdout, "%s %s %d\n",
1127 node->name, node->file, (node->lno + 63) / 64);
1128 else
1129 fprintf (stdout, "%-16s %3d %-16s %s\n",
1130 node->name, node->lno, node->file, node->pat);
1131
1132 /* Output subentries that follow this one */
1133 put_entries (node->right);
1134 }
1135
1136 /* Length of a number's decimal representation. */
1137 int
1138 number_len (num)
1139 long num;
1140 {
1141 int len = 0;
1142 if (!num)
1143 return 1;
1144 for (; num; num /= 10)
1145 ++len;
1146 return len;
1147 }
1148
1149 /*
1150 * Return total number of characters that put_entries will output for
1151 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1152 * is set, but called only in that case. This count is irrelevant with
1153 * the new tags.el, but is still supplied for backward compatibility.
1154 */
1155 int
1156 total_size_of_entries (node)
1157 register NODE *node;
1158 {
1159 register int total;
1160
1161 if (node == NULL)
1162 return 0;
1163
1164 total = 0;
1165 for (; node; node = node->right)
1166 {
1167 /* Count left subentries. */
1168 total += total_size_of_entries (node->left);
1169
1170 /* Count this entry */
1171 total += strlen (node->pat) + 1;
1172 total += number_len ((long) node->lno) + 1 + number_len (node->cno) + 1;
1173 if (node->named)
1174 total += 1 + strlen (node->name); /* \001name */
1175 }
1176
1177 return total;
1178 }
1179 \f
1180 /*
1181 * The C symbol tables.
1182 */
1183
1184 /* Feed stuff between (but not including) %[ and %] lines to:
1185 gperf -c -k1,3 -o -p -r -t
1186 %[
1187 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1188 %%
1189 class, C_PLPL, st_C_struct
1190 domain, C_STAR, st_C_struct
1191 union, 0, st_C_struct
1192 struct, 0, st_C_struct
1193 enum, 0, st_C_enum
1194 typedef, 0, st_C_typedef
1195 define, 0, st_C_define
1196 long, 0, st_C_typespec
1197 short, 0, st_C_typespec
1198 int, 0, st_C_typespec
1199 char, 0, st_C_typespec
1200 float, 0, st_C_typespec
1201 double, 0, st_C_typespec
1202 signed, 0, st_C_typespec
1203 unsigned, 0, st_C_typespec
1204 auto, 0, st_C_typespec
1205 void, 0, st_C_typespec
1206 extern, 0, st_C_typespec
1207 static, 0, st_C_typespec
1208 const, 0, st_C_typespec
1209 volatile, 0, st_C_typespec
1210 %]
1211 and replace lines between %< and %> with its output. */
1212 /*%<*/
1213 /* C code produced by gperf version 1.8.1 (K&R C version) */
1214 /* Command-line: gperf -c -k1,3 -o -p -r -t */
1215
1216
1217 struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
1218
1219 #define MIN_WORD_LENGTH 3
1220 #define MAX_WORD_LENGTH 8
1221 #define MIN_HASH_VALUE 10
1222 #define MAX_HASH_VALUE 62
1223 /*
1224 21 keywords
1225 53 is the maximum key range
1226 */
1227
1228 static int
1229 hash (str, len)
1230 register char *str;
1231 register int len;
1232 {
1233 static unsigned char hash_table[] =
1234 {
1235 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1236 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1237 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1238 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1239 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1240 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1241 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1242 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1243 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1244 62, 62, 62, 62, 62, 62, 62, 2, 62, 7,
1245 6, 9, 15, 30, 62, 24, 62, 62, 1, 24,
1246 7, 27, 13, 62, 19, 26, 18, 27, 1, 62,
1247 62, 62, 62, 62, 62, 62, 62, 62,
1248 };
1249 return len + hash_table[str[2]] + hash_table[str[0]];
1250 }
1251
1252 struct C_stab_entry *
1253 in_word_set (str, len)
1254 register char *str;
1255 register int len;
1256 {
1257
1258 static struct C_stab_entry wordlist[] =
1259 {
1260 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1261 {"",},
1262 {"volatile", 0, st_C_typespec},
1263 {"",},
1264 {"long", 0, st_C_typespec},
1265 {"char", 0, st_C_typespec},
1266 {"class", C_PLPL, st_C_struct},
1267 {"",}, {"",}, {"",}, {"",},
1268 {"const", 0, st_C_typespec},
1269 {"",}, {"",}, {"",}, {"",},
1270 {"auto", 0, st_C_typespec},
1271 {"",}, {"",},
1272 {"define", 0, st_C_define},
1273 {"",},
1274 {"void", 0, st_C_typespec},
1275 {"",}, {"",}, {"",},
1276 {"extern", 0, st_C_typespec},
1277 {"static", 0, st_C_typespec},
1278 {"",},
1279 {"domain", C_STAR, st_C_struct},
1280 {"",},
1281 {"typedef", 0, st_C_typedef},
1282 {"double", 0, st_C_typespec},
1283 {"enum", 0, st_C_enum},
1284 {"",}, {"",}, {"",}, {"",},
1285 {"int", 0, st_C_typespec},
1286 {"",},
1287 {"float", 0, st_C_typespec},
1288 {"",}, {"",}, {"",},
1289 {"struct", 0, st_C_struct},
1290 {"",}, {"",}, {"",}, {"",},
1291 {"union", 0, st_C_struct},
1292 {"",},
1293 {"short", 0, st_C_typespec},
1294 {"",}, {"",},
1295 {"unsigned", 0, st_C_typespec},
1296 {"signed", 0, st_C_typespec},
1297 };
1298
1299 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
1300 {
1301 register int key = hash (str, len);
1302
1303 if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)
1304 {
1305 register char *s = wordlist[key].name;
1306
1307 if (*s == *str && strneq (str + 1, s + 1, len - 1))
1308 return &wordlist[key];
1309 }
1310 }
1311 return 0;
1312 }
1313 /*%>*/
1314
1315 enum sym_type
1316 C_symtype(str, len, c_ext)
1317 char *str;
1318 int len;
1319 int c_ext;
1320 {
1321 register struct C_stab_entry *se = in_word_set(str, len);
1322
1323 if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
1324 return st_none;
1325 return se->type;
1326 }
1327 \f
1328 /*
1329 * C functions are recognized using a simple finite automaton.
1330 * funcdef is its state variable.
1331 */
1332 typedef enum
1333 {
1334 fnone, /* nothing seen */
1335 ftagseen, /* function-like tag seen */
1336 fstartlist, /* just after open parenthesis */
1337 finlist, /* in parameter list */
1338 flistseen, /* after parameter list */
1339 fignore /* before open brace */
1340 } FUNCST;
1341 FUNCST funcdef;
1342
1343
1344 /* typedefs are recognized using a simple finite automaton.
1345 * typeddef is its state variable.
1346 */
1347 typedef enum
1348 {
1349 tnone, /* nothing seen */
1350 ttypedseen, /* typedef keyword seen */
1351 tinbody, /* inside typedef body */
1352 tend /* just before typedef tag */
1353 } TYPEDST;
1354 TYPEDST typdef;
1355
1356
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.
1362 */
1363 typedef enum
1364 {
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 struct body: recognize member func defs*/
1370 } STRUCTST;
1371 STRUCTST structdef;
1372 /*
1373 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1374 * struct tag, and structtype is the type of the preceding struct-like
1375 * keyword.
1376 */
1377 char structtag[BUFSIZ];
1378 enum sym_type structtype;
1379
1380 /*
1381 * Yet another little state machine to deal with preprocessor lines.
1382 */
1383 typedef enum
1384 {
1385 dnone, /* nothing seen */
1386 dsharpseen, /* '#' seen as first char on line */
1387 ddefineseen, /* '#' and 'define' seen */
1388 dignorerest /* ignore rest of line */
1389 } DEFINEST;
1390 DEFINEST definedef;
1391
1392 /*
1393 * Set this to TRUE, and the next token considered is called a function.
1394 * Used only for GNUmacs's function-defining macros.
1395 */
1396 logical next_token_is_func;
1397
1398 /*
1399 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1400 */
1401 logical yacc_rules;
1402
1403 /*
1404 * C_entries ()
1405 * This routine finds functions, typedefs, #define's and
1406 * struct/union/enum definitions in C syntax and adds them
1407 * to the list.
1408 */
1409
1410 #define curlb (lbs[curndx].lb)
1411 #define othlb (lbs[1-curndx].lb)
1412 #define newlb (lbs[newndx].lb)
1413 #define curlinepos (lbs[curndx].linepos)
1414 #define othlinepos (lbs[1-curndx].linepos)
1415 #define newlinepos (lbs[newndx].linepos)
1416
1417 /* Save and restore token state. This is used when preprocessor defines
1418 are handled, to avoid disturbing active function/typedef/struct states. */
1419 #define TOKEN_SAVED_P (savetok.lineno > 0)
1420 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1421 savetok.len = toklen, strcpy(savenameb, nameb))
1422 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1423 toklen = tok.len, strcpy(nameb, savenameb), \
1424 savetok.lineno = 0)
1425
1426 #define CNL_SAVE_DEFINEDEF \
1427 do { \
1428 SET_FILEPOS (curlinepos, inf, charno); \
1429 lineno++; \
1430 charno += readline (&curlb, inf); \
1431 lp = curlb.buffer; \
1432 quotednl = FALSE; \
1433 newndx = curndx; \
1434 } while (FALSE)
1435
1436 #define CNL \
1437 do { \
1438 CNL_SAVE_DEFINEDEF; \
1439 if (TOKEN_SAVED_P) \
1440 RESTORE_TOKEN; \
1441 definedef = dnone; \
1442 } while (FALSE)
1443
1444 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1445 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1446 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1447 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1448
1449 void
1450 C_entries (c_ext)
1451 int c_ext; /* extension of C? */
1452 {
1453 register char c; /* latest char read; '\0' for end of line */
1454 register char *lp; /* pointer one beyond the character `c' */
1455 int curndx, newndx; /* indices for current and new lb */
1456 TOKEN tok; /* latest token read for funcdef & structdef */
1457 char nameb[BUFSIZ]; /* latest token name for funcdef & structdef */
1458 register int tokoff; /* offset in line of start of latest token */
1459 register int toklen; /* length of latest token */
1460 int cblev; /* current curly brace level */
1461 int parlev; /* current parenthesis level */
1462 logical incomm, inquote, inchar, quotednl, midtoken;
1463 logical cplpl;
1464 TOKEN savetok; /* saved token during preprocessor handling */
1465 char savenameb[BUFSIZ]; /* ouch! */
1466
1467 savetok.lineno = 0;
1468 curndx = newndx = 0;
1469 lineno = 0;
1470 charno = 0;
1471 lp = curlb.buffer;
1472 *lp = 0;
1473
1474 definedef = dnone; funcdef = fnone; typdef= tnone; structdef= snone;
1475 next_token_is_func = yacc_rules = FALSE;
1476 midtoken = inquote = inchar = incomm = quotednl = FALSE;
1477 cblev = 0;
1478 parlev = 0;
1479 cplpl = c_ext & C_PLPL;
1480
1481 while (!feof (inf))
1482 {
1483 c = *lp++;
1484 if (c == '\\')
1485 {
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')
1490 {
1491 quotednl = TRUE;
1492 continue;
1493 }
1494 lp++;
1495 c = ' ';
1496 }
1497 else if (incomm)
1498 {
1499 switch (c)
1500 {
1501 case '*':
1502 if (*lp == '/')
1503 {
1504 c = *lp++;
1505 incomm = FALSE;
1506 }
1507 break;
1508 case '\0':
1509 /* Newlines inside comments do not end macro definitions in
1510 traditional cpp. */
1511 CNL_SAVE_DEFINEDEF;
1512 break;
1513 }
1514 continue;
1515 }
1516 else if (inquote)
1517 {
1518 switch (c)
1519 {
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;
1529 }
1530 continue;
1531 }
1532 else if (inchar)
1533 {
1534 switch (c)
1535 {
1536 case '\0':
1537 /* Hmmm, something went wrong. */
1538 CNL;
1539 /* FALLTHRU */
1540 case '\'':
1541 inchar = FALSE;
1542 break;
1543 }
1544 continue;
1545 }
1546 else
1547 switch (c)
1548 {
1549 case '"':
1550 inquote = TRUE;
1551 if (funcdef != finlist && funcdef != fignore)
1552 funcdef = fnone;
1553 continue;
1554 case '\'':
1555 inchar = TRUE;
1556 if (funcdef != finlist && funcdef != fignore)
1557 funcdef = fnone;
1558 continue;
1559 case '/':
1560 if (*lp == '*')
1561 {
1562 lp++;
1563 incomm = TRUE;
1564 continue;
1565 }
1566 else if (cplpl && *lp == '/')
1567 {
1568 c = 0;
1569 break;
1570 }
1571 else
1572 break;
1573 case '%':
1574 if ((c_ext & YACC) && *lp == '%')
1575 {
1576 /* entering or exiting rules section in yacc file */
1577 lp++;
1578 definedef = dnone; funcdef = fnone;
1579 typdef= tnone; structdef= snone;
1580 next_token_is_func = FALSE;
1581 midtoken = inquote = inchar = incomm = quotednl = FALSE;
1582 cblev = 0;
1583 yacc_rules = !yacc_rules;
1584 continue;
1585 }
1586 else
1587 break;
1588 case '#':
1589 if (lp == newlb.buffer + 1 && definedef == dnone)
1590 definedef = dsharpseen;
1591 continue;
1592 } /* switch (c) */
1593
1594
1595 /* Consider token only if some complicated conditions are satisfied. */
1596 if (((cblev == 0 && structdef != scolonseen)
1597 || (cblev == 1 && cplpl && structdef == sinbody))
1598 && definedef != dignorerest
1599 && (funcdef != finlist
1600 || (definedef != dnone && definedef != dignorerest)))
1601 {
1602 if (midtoken)
1603 {
1604 if (endtoken (c))
1605 {
1606 if (cplpl && c == ':' && *lp == ':' && begtoken(*(lp + 1)))
1607 {
1608 /*
1609 * This handles :: in the middle, but not at beginning
1610 * of an identifier.
1611 */
1612 lp += 2;
1613 toklen += 3;
1614 }
1615 else
1616 {
1617 logical is_func = FALSE;
1618
1619 tok.lineno = lineno;
1620 tok.p = newlb.buffer + tokoff;
1621 tok.len = toklen;
1622 tok.named = FALSE;
1623 if (yacc_rules
1624 || consider_token (c, &tok, c_ext, cblev, &is_func))
1625 {
1626 if (structdef == sinbody
1627 && definedef == dnone
1628 && is_func)
1629 /* function defined in C++ class body */
1630 {
1631 tok.named = TRUE;
1632 sprintf (nameb, "%s::%.*s",
1633 ((structtag[0] == '\0')
1634 ? "_anonymous_" : structtag),
1635 tok.len, tok.p);
1636 }
1637 else
1638 {
1639 sprintf (nameb, "%.*s", tok.len, tok.p);
1640 }
1641
1642 if (structdef == stagseen
1643 || typdef == tend)
1644 tok.named = TRUE;
1645
1646 if (definedef == dnone
1647 && (funcdef == ftagseen
1648 || structdef == stagseen
1649 || typdef == tend))
1650 {
1651 if (newndx == curndx)
1652 curndx = 1 - curndx; /* switch line buffers */
1653 }
1654 else
1655 MAKE_TAG_FROM_NEW_LB (is_func);
1656 }
1657 midtoken = FALSE;
1658 }
1659 } /* if (endtoken (c)) */
1660 else if (intoken (c))
1661 {
1662 toklen++;
1663 continue;
1664 }
1665 } /* if (midtoken) */
1666 else if (begtoken (c))
1667 {
1668 switch (definedef)
1669 {
1670 case dnone:
1671 switch (funcdef)
1672 {
1673 case fstartlist:
1674 funcdef = finlist;
1675 continue;
1676 case flistseen:
1677 MAKE_TAG_FROM_OTH_LB (TRUE);
1678 funcdef = fignore;
1679 break;
1680 case ftagseen:
1681 funcdef = fnone;
1682 break;
1683 }
1684 if (structdef == stagseen)
1685 structdef = snone;
1686 break;
1687 case dsharpseen:
1688 /* Take a quick peek ahead for define directive,
1689 so we can avoid saving the token when not absolutely
1690 necessary. [This is a speed hack.] */
1691 if (c == 'd' && strneq(lp, "efine", 5)
1692 && iswhite(*(lp + 5)))
1693 {
1694 SAVE_TOKEN;
1695 definedef = ddefineseen;
1696 lp += 6;
1697 }
1698 else
1699 definedef = dignorerest;
1700 continue;
1701 }
1702 if (!yacc_rules || lp == newlb.buffer + 1)
1703 {
1704 tokoff = lp - 1 - newlb.buffer;
1705 toklen = 1;
1706 midtoken = TRUE;
1707 }
1708 continue;
1709 }
1710 } /* if must look at token */
1711
1712
1713 /* Detect end of line, colon, comma, semicolon and various braces
1714 after having handled a token.*/
1715 switch (c)
1716 {
1717 case ':':
1718 if (definedef != dnone)
1719 break;
1720 if (structdef == stagseen)
1721 structdef = scolonseen;
1722 else
1723 switch (funcdef)
1724 {
1725 case ftagseen:
1726 if (yacc_rules)
1727 {
1728 MAKE_TAG_FROM_OTH_LB (FALSE);
1729 funcdef = fignore;
1730 }
1731 break;
1732 case fstartlist:
1733 funcdef = fnone;
1734 break;
1735 }
1736 break;
1737 case ';':
1738 if (definedef != dnone)
1739 break;
1740 if (cblev == 0 && typdef == tend)
1741 {
1742 typdef = tnone;
1743 MAKE_TAG_FROM_OTH_LB (FALSE);
1744 }
1745 if (funcdef != fignore)
1746 funcdef = fnone;
1747 /* FALLTHRU */
1748 case ',':
1749 /* FALLTHRU */
1750 case '[':
1751 if (definedef != dnone)
1752 break;
1753 if (funcdef != finlist && funcdef != fignore)
1754 funcdef = fnone;
1755 if (structdef == stagseen)
1756 structdef = snone;
1757 break;
1758 case '(':
1759 if (definedef != dnone)
1760 break;
1761 switch (funcdef)
1762 {
1763 case ftagseen:
1764 funcdef = fstartlist;
1765 break;
1766 case flistseen:
1767 funcdef = finlist;
1768 break;
1769 }
1770 parlev++;
1771 break;
1772 case ')':
1773 if (definedef != dnone)
1774 break;
1775 if (--parlev == 0)
1776 {
1777 switch (funcdef)
1778 {
1779 case fstartlist:
1780 case finlist:
1781 funcdef = flistseen;
1782 break;
1783 }
1784 }
1785 else if (parlev < 0) /* can happen due to ill-conceived #if's. */
1786 parlev = 0;
1787 break;
1788 case '{':
1789 if (definedef != dnone)
1790 break;
1791 if (typdef == ttypedseen)
1792 typdef = tinbody;
1793 switch (structdef)
1794 {
1795 case skeyseen: /* unnamed struct */
1796 structtag[0] = '\0';
1797 structdef = sinbody;
1798 break;
1799 case stagseen:
1800 case scolonseen: /* named struct */
1801 structdef = sinbody;
1802 MAKE_TAG_FROM_OTH_LB (FALSE);
1803 break;
1804 }
1805 switch (funcdef)
1806 {
1807 case flistseen:
1808 MAKE_TAG_FROM_OTH_LB (TRUE);
1809 /* FALLTHRU */
1810 case fignore:
1811 funcdef = fnone;
1812 }
1813 cblev++;
1814 break;
1815 case '*':
1816 if (definedef != dnone)
1817 break;
1818 if (funcdef == fstartlist)
1819 funcdef = fnone; /* avoid tagging `foo' in `foo (*bar()) ()' */
1820 break;
1821 case '}':
1822 if (definedef != dnone)
1823 break;
1824 if (!noindentypedefs && lp == newlb.buffer + 1)
1825 {
1826 cblev = 0; /* reset curly brace level if first column */
1827 parlev = 0; /* also reset paren level, just in case... */
1828 }
1829 else if (cblev > 0)
1830 cblev--;
1831 if (cblev == 0)
1832 {
1833 if (typdef == tinbody)
1834 typdef = tend;
1835 structdef = snone;
1836 strcpy (structtag, "<error 2>");
1837 }
1838 break;
1839 case '=':
1840 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
1841 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
1842 if (definedef != dnone)
1843 break;
1844 /* These surely cannot follow a function tag. */
1845 if (funcdef != finlist && funcdef != fignore)
1846 funcdef = fnone;
1847 break;
1848 case '\0':
1849 /* If a macro spans multiple lines don't reset its state. */
1850 if (quotednl)
1851 CNL_SAVE_DEFINEDEF;
1852 else
1853 CNL;
1854 break;
1855 } /* switch (c) */
1856
1857 } /* while not eof */
1858 }
1859
1860 /*
1861 * consider_token ()
1862 * checks to see if the current token is at the start of a
1863 * function, or corresponds to a typedef, or is a struct/union/enum
1864 * tag.
1865 *
1866 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1867 * C_EXT is which language we are looking at.
1868 *
1869 * In the future we will need some way to adjust where the end of
1870 * the token is; for instance, implementing the C++ keyword
1871 * `operator' properly will adjust the end of the token to be after
1872 * whatever follows `operator'.
1873 *
1874 * Globals
1875 * funcdef IN OUT
1876 * structdef IN OUT
1877 * definedef IN OUT
1878 * typdef IN OUT
1879 * next_token_is_func IN OUT
1880 */
1881
1882 logical
1883 consider_token (c, tokp, c_ext, cblev, is_func)
1884 register char c; /* IN: first char after the token */
1885 register TOKEN *tokp; /* IN: token pointer */
1886 int c_ext; /* IN: C extensions mask */
1887 int cblev; /* IN: curly brace level */
1888 logical *is_func; /* OUT */
1889 {
1890 enum sym_type toktype = C_symtype(tokp->p, tokp->len, c_ext);
1891
1892 /*
1893 * Advance the definedef state machine.
1894 */
1895 switch (definedef)
1896 {
1897 case dnone:
1898 /* We're not on a preprocessor line. */
1899 break;
1900 case dsharpseen:
1901 if (toktype == st_C_define)
1902 {
1903 definedef = ddefineseen;
1904 }
1905 else
1906 {
1907 definedef = dignorerest;
1908 }
1909 return (FALSE);
1910 case ddefineseen:
1911 /*
1912 * Make a tag for any macro.
1913 */
1914 definedef = dignorerest;
1915 *is_func = (c == '(');
1916 if (!*is_func && !constantypedefs)
1917 return (FALSE);
1918 else
1919 return (TRUE);
1920 case dignorerest:
1921 return (FALSE);
1922 default:
1923 error ("internal error: definedef value is %d", definedef);
1924 }
1925
1926 /*
1927 * Now typedefs
1928 */
1929 switch (typdef)
1930 {
1931 case tnone:
1932 if (toktype == st_C_typedef)
1933 {
1934 if (typedefs)
1935 typdef = ttypedseen;
1936 return (FALSE);
1937 }
1938 break;
1939 case ttypedseen:
1940 switch (toktype)
1941 {
1942 case st_none:
1943 case st_C_typespec:
1944 typdef = tend;
1945 break;
1946 case st_C_struct:
1947 case st_C_enum:
1948 break;
1949 }
1950 /* Do not return here, so the structdef stuff has a chance. */
1951 break;
1952 case tend:
1953 switch (toktype)
1954 {
1955 case st_C_typespec:
1956 case st_C_struct:
1957 case st_C_enum:
1958 return (FALSE);
1959 }
1960 return (TRUE);
1961 }
1962
1963 /*
1964 * This structdef business is currently only invoked when cblev==0.
1965 * It should be recursively invoked whatever the curly brace level,
1966 * and a stack of states kept, to allow for definitions of structs
1967 * within structs.
1968 *
1969 * This structdef business is NOT invoked when we are ctags and the
1970 * file is plain C. This is because a struct tag may have the same
1971 * name as another tag, and this loses with ctags.
1972 *
1973 * This if statement deals with the typdef state machine as
1974 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1975 * return (FALSE). All the other code here is for the structdef
1976 * state machine.
1977 */
1978 switch (toktype)
1979 {
1980 case st_C_struct:
1981 case st_C_enum:
1982 if (typdef == ttypedseen
1983 || (typedefs_and_cplusplus && cblev == 0 && structdef == snone))
1984 {
1985 structdef = skeyseen;
1986 structtype = toktype;
1987 }
1988 return (FALSE);
1989 }
1990 if (structdef == skeyseen)
1991 {
1992 if (structtype == st_C_struct)
1993 {
1994 strncpy (structtag, tokp->p, tokp->len);
1995 structtag[tokp->len] = '\0'; /* for struct/union/class */
1996 }
1997 else
1998 {
1999 structtag[0] = '\0'; /* for enum (why is it treated differently?) */
2000 }
2001 structdef = stagseen;
2002 return (TRUE);
2003 }
2004
2005 /* Avoid entering funcdef stuff if typdef is going on. */
2006 if (typdef != tnone)
2007 {
2008 definedef = dnone;
2009 return (FALSE);
2010 }
2011
2012 /* Detect GNUmacs's function-defining macros. */
2013 if (definedef == dnone)
2014 {
2015 if (strneq (tokp->p, "DEF", 3)
2016 || strneq (tokp->p, "ENTRY", 5)
2017 || strneq (tokp->p, "SYSCALL", 7)
2018 || strneq (tokp->p, "PSEUDO", 6))
2019 {
2020 next_token_is_func = TRUE;
2021 return (FALSE);
2022 }
2023 if (strneq (tokp->p, "EXFUN", 5))
2024 {
2025 next_token_is_func = FALSE;
2026 return (FALSE);
2027 }
2028 }
2029 if (next_token_is_func)
2030 {
2031 next_token_is_func = FALSE;
2032 funcdef = fnone;
2033 *is_func = TRUE; /* to force search string in ctags */
2034 return (TRUE);
2035 }
2036
2037 /* A function? */
2038 switch (toktype)
2039 {
2040 case st_C_typespec:
2041 funcdef = fnone; /* should be useless */
2042 return (FALSE);
2043 default:
2044 if (funcdef == fnone)
2045 {
2046 funcdef = ftagseen;
2047 *is_func = TRUE;
2048 return (TRUE);
2049 }
2050 }
2051
2052 return (FALSE);
2053 }
2054 \f
2055 /* Fortran parsing */
2056
2057 char *dbp;
2058 int pfcnt;
2059
2060 int
2061 PF_funcs (fi)
2062 FILE *fi;
2063 {
2064 lineno = 0;
2065 charno = 0;
2066 pfcnt = 0;
2067
2068 while (!feof (fi))
2069 {
2070 lineno++;
2071 linecharno = charno;
2072 charno += readline (&lb, fi);
2073 dbp = lb.buffer;
2074 if (*dbp == '%')
2075 dbp++; /* Ratfor escape to fortran */
2076 while (isspace (*dbp))
2077 dbp++;
2078 if (*dbp == 0)
2079 continue;
2080 switch (*dbp | ' ')
2081 {
2082 case 'i':
2083 if (tail ("integer"))
2084 takeprec ();
2085 break;
2086 case 'r':
2087 if (tail ("real"))
2088 takeprec ();
2089 break;
2090 case 'l':
2091 if (tail ("logical"))
2092 takeprec ();
2093 break;
2094 case 'c':
2095 if (tail ("complex") || tail ("character"))
2096 takeprec ();
2097 break;
2098 case 'd':
2099 if (tail ("double"))
2100 {
2101 while (isspace (*dbp))
2102 dbp++;
2103 if (*dbp == 0)
2104 continue;
2105 if (tail ("precision"))
2106 break;
2107 continue;
2108 }
2109 break;
2110 }
2111 while (isspace (*dbp))
2112 dbp++;
2113 if (*dbp == 0)
2114 continue;
2115 switch (*dbp | ' ')
2116 {
2117 case 'f':
2118 if (tail ("function"))
2119 getit (fi);
2120 continue;
2121 case 's':
2122 if (tail ("subroutine"))
2123 getit (fi);
2124 continue;
2125 case 'e':
2126 if (tail ("entry"))
2127 getit (fi);
2128 continue;
2129 case 'p':
2130 if (tail ("program"))
2131 {
2132 getit (fi);
2133 continue;
2134 }
2135 if (tail ("procedure"))
2136 getit (fi);
2137 continue;
2138 }
2139 }
2140 return (pfcnt);
2141 }
2142
2143 logical
2144 tail (cp)
2145 char *cp;
2146 {
2147 register int len = 0;
2148
2149 while (*cp && (*cp | ' ') == (dbp[len] | ' '))
2150 cp++, len++;
2151 if (*cp == 0)
2152 {
2153 dbp += len;
2154 return (TRUE);
2155 }
2156 return (FALSE);
2157 }
2158
2159 void
2160 takeprec ()
2161 {
2162 while (isspace (*dbp))
2163 dbp++;
2164 if (*dbp != '*')
2165 return;
2166 dbp++;
2167 while (isspace (*dbp))
2168 dbp++;
2169 if (!isdigit (*dbp))
2170 {
2171 --dbp; /* force failure */
2172 return;
2173 }
2174 do
2175 dbp++;
2176 while (isdigit (*dbp));
2177 }
2178
2179 void
2180 getit (fi)
2181 FILE *fi;
2182 {
2183 register char *cp;
2184 char c;
2185 char nambuf[BUFSIZ];
2186
2187 while (isspace (*dbp))
2188 dbp++;
2189 if (*dbp == '\0')
2190 {
2191 lineno++;
2192 linecharno = charno;
2193 charno += readline (&lb, fi);
2194 dbp = lb.buffer;
2195 if (dbp[5] != '&')
2196 return;
2197 dbp += 6;
2198 while (isspace (*dbp))
2199 dbp++;
2200 }
2201 if (!isalpha (*dbp)
2202 && *dbp != '_'
2203 && *dbp != '$')
2204 return;
2205 for (cp = dbp + 1;
2206 (*cp
2207 && (isalpha (*cp) || isdigit (*cp) || (*cp == '_') || (*cp == '$')));
2208 cp++)
2209 continue;
2210 c = *cp;
2211 *cp = '\0';
2212 strcpy (nambuf, dbp);
2213 *cp = c;
2214 pfnote (nambuf, TRUE, FALSE, lb.buffer,
2215 cp - lb.buffer + 1, lineno, linecharno);
2216 pfcnt++;
2217 }
2218
2219 /* Handle a file of assembler code. */
2220
2221 void
2222 Asm_funcs (fi)
2223 FILE *fi;
2224 {
2225 int i;
2226 register char c;
2227
2228 lineno = 0;
2229 charno = 0;
2230 pfcnt = 0;
2231
2232 while (!feof (fi))
2233 {
2234 lineno++;
2235 linecharno = charno;
2236 charno += readline (&lb, fi);
2237 dbp = lb.buffer;
2238
2239 for (i = 0; ((c = dbp[i]) && !isspace (c)) && (c != ':'); i++)
2240 ;
2241
2242 if ((i > 0) && (c == ':'))
2243 getit (fi);
2244 }
2245 }
2246 \f
2247 /* Added by Mosur Mohan, 4/22/88 */
2248 /* Pascal parsing */
2249
2250 #define GET_NEW_LINE \
2251 { \
2252 linecharno = charno; lineno++; \
2253 charno += 1 + readline (&lb, inf); \
2254 dbp = lb.buffer; \
2255 }
2256
2257 /* Locates tags for procedures & functions.
2258 * Doesn't do any type- or var-definitions.
2259 * It does look for the keyword "extern" or "forward"
2260 * immediately following the procedure statement;
2261 * if found, the tag is skipped.
2262 */
2263
2264 void
2265 PAS_funcs (fi)
2266 FILE *fi;
2267 {
2268 struct linebuffer tline; /* mostly copied from C_entries */
2269 long save_lcno;
2270 int save_lineno;
2271 char c, *cp;
2272 char nambuf[BUFSIZ];
2273
2274 logical /* each of these flags is TRUE iff: */
2275 incomm1, /* point is inside {..} comment */
2276 incomm2, /* point is inside (*..*) comment */
2277 inquote, /* point is inside '..' string */
2278 get_tagname, /* point is after PROCEDURE/FUNCTION */
2279 /* keyword, so next item = potential tag */
2280 found_tag, /* point is after a potential tag */
2281 inparms, /* point is within parameter-list */
2282 verify_tag; /* point has passed the parm-list, so the */
2283 /* next token will determine whether */
2284 /* this is a FORWARD/EXTERN to be */
2285 /* ignored, or whether it is a real tag */
2286
2287 lineno = 0;
2288 charno = 0;
2289 dbp = lb.buffer;
2290 *dbp = 0;
2291 initbuffer (&tline);
2292
2293 incomm1 = incomm2 = inquote = FALSE;
2294 found_tag = FALSE; /* have a proc name; check if extern */
2295 get_tagname = FALSE; /* have found "procedure" keyword */
2296 inparms = FALSE; /* found '(' after "proc" */
2297 verify_tag = FALSE; /* check if "extern" is ahead */
2298
2299 /* long main loop to get next char */
2300 while (!feof (fi))
2301 {
2302 c = *dbp++;
2303 if (c == 0) /* if end of line */
2304 {
2305 GET_NEW_LINE;
2306 if (*dbp == 0)
2307 continue;
2308 if (!((found_tag && verify_tag) ||
2309 get_tagname))
2310 c = *dbp++; /* only if don't need *dbp pointing */
2311 /* to the beginning of the name of */
2312 /* the procedure or function */
2313 }
2314 if (incomm1) /* within { - } comments */
2315 {
2316 if (c == '}')
2317 incomm1 = FALSE;
2318 continue;
2319 }
2320 else if (incomm2) /* within (* - *) comments */
2321 {
2322 if (c == '*')
2323 {
2324 while ((c = *dbp++) == '*')
2325 continue;
2326 if (c == 0)
2327 GET_NEW_LINE;
2328 if (c == ')')
2329 incomm2 = FALSE;
2330 }
2331 continue;
2332 }
2333 else if (inquote)
2334 {
2335 if (c == '\'')
2336 inquote = FALSE;
2337 continue;
2338 }
2339 else
2340 switch (c)
2341 {
2342 case '\'':
2343 inquote = TRUE; /* found first quote */
2344 continue;
2345 case '{': /* found open-{-comment */
2346 incomm1 = TRUE;
2347 continue;
2348 case '(':
2349 if (*dbp == '*') /* found open-(*-comment */
2350 {
2351 incomm2 = TRUE;
2352 dbp++;
2353 }
2354 else if (found_tag) /* found '(' after tag, i.e., parm-list */
2355 inparms = TRUE;
2356 continue;
2357 case ')': /* end of parms list */
2358 if (inparms)
2359 inparms = FALSE;
2360 continue;
2361 case ';':
2362 if ((found_tag) && (!inparms)) /* end of proc or fn stmt */
2363 {
2364 verify_tag = TRUE;
2365 break;
2366 }
2367 continue;
2368 }
2369 if ((found_tag) && (verify_tag) && (*dbp != ' '))
2370 {
2371 /* check if this is an "extern" declaration */
2372 if (*dbp == 0)
2373 continue;
2374 if ((*dbp == 'e') || (*dbp == 'E'))
2375 {
2376 if (tail ("extern")) /* superfluous, really! */
2377 {
2378 found_tag = FALSE;
2379 verify_tag = FALSE;
2380 }
2381 }
2382 else if ((*dbp == 'f') || (*dbp == 'F'))
2383 {
2384 if (tail ("forward")) /* check for forward reference */
2385 {
2386 found_tag = FALSE;
2387 verify_tag = FALSE;
2388 }
2389 }
2390 if ((found_tag) && (verify_tag)) /* not external proc, so make tag */
2391 {
2392 found_tag = FALSE;
2393 verify_tag = FALSE;
2394 pfnote (nambuf, TRUE, FALSE,
2395 tline.buffer, cp - tline.buffer + 1,
2396 save_lineno, save_lcno);
2397 continue;
2398 }
2399 }
2400 if (get_tagname) /* grab name of proc or fn */
2401 {
2402 if (*dbp == 0)
2403 continue;
2404
2405 /* save all values for later tagging */
2406 tline.size = lb.size;
2407 strcpy (tline.buffer, lb.buffer);
2408 save_lineno = lineno;
2409 save_lcno = linecharno;
2410
2411 /* grab block name */
2412 for (cp = dbp + 1; *cp && (!endtoken (*cp)); cp++)
2413 continue;
2414 c = cp[0];
2415 cp[0] = 0;
2416 strcpy (nambuf, dbp);
2417 cp[0] = c;
2418 dbp = cp; /* restore dbp to e-o-token */
2419 get_tagname = FALSE;
2420 found_tag = TRUE;
2421 continue;
2422
2423 /* and proceed to check for "extern" */
2424 }
2425 if ((!incomm1) && (!incomm2) && (!inquote) &&
2426 (!found_tag) && (!get_tagname))
2427 {
2428 /* check for proc/fn keywords */
2429 switch (c | ' ')
2430 {
2431 case 'p':
2432 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2433 get_tagname = TRUE;
2434 continue;
2435 case 'f':
2436 if (tail ("unction"))
2437 get_tagname = TRUE;
2438 continue;
2439 }
2440 }
2441 } /* while not e-o-f */
2442 }
2443 \f
2444 /*
2445 * lisp tag functions
2446 * just look for (def or (DEF
2447 */
2448
2449 void
2450 L_funcs (fi)
2451 FILE *fi;
2452 {
2453 lineno = 0;
2454 charno = 0;
2455 pfcnt = 0;
2456
2457 while (!feof (fi))
2458 {
2459 lineno++;
2460 linecharno = charno;
2461 charno += readline (&lb, fi);
2462 dbp = lb.buffer;
2463 if (dbp[0] == '(')
2464 {
2465 if (L_isdef (dbp))
2466 {
2467 while (!isspace (*dbp))
2468 dbp++;
2469 while (isspace (*dbp))
2470 dbp++;
2471 L_getit ();
2472 }
2473 else
2474 {
2475 /* Check for (foo::defmumble name-defined ... */
2476 do
2477 dbp++;
2478 while (*dbp && !isspace (*dbp)
2479 && *dbp != ':' && *dbp != '(' && *dbp != ')');
2480 if (*dbp == ':')
2481 {
2482 do
2483 dbp++;
2484 while (*dbp == ':');
2485
2486 if (L_isdef (dbp - 1))
2487 {
2488 while (!isspace (*dbp))
2489 dbp++;
2490 while (isspace (*dbp))
2491 dbp++;
2492 L_getit ();
2493 }
2494 }
2495 }
2496 }
2497 }
2498 }
2499
2500 int
2501 L_isdef (dbp)
2502 register char *dbp;
2503 {
2504 return ((dbp[1] == 'd' || dbp[1] == 'D')
2505 && (dbp[2] == 'e' || dbp[2] == 'E')
2506 && (dbp[3] == 'f' || dbp[3] == 'F'));
2507 }
2508
2509 int
2510 L_isquote (dbp)
2511 register char *dbp;
2512 {
2513 return ((*(++dbp) == 'q' || *dbp == 'Q')
2514 && (*(++dbp) == 'u' || *dbp == 'U')
2515 && (*(++dbp) == 'o' || *dbp == 'O')
2516 && (*(++dbp) == 't' || *dbp == 'T')
2517 && (*(++dbp) == 'e' || *dbp == 'E')
2518 && isspace(*(++dbp)));
2519 }
2520
2521 void
2522 L_getit ()
2523 {
2524 register char *cp;
2525 char c;
2526 char nambuf[BUFSIZ];
2527
2528 if (*dbp == '\'') /* Skip prefix quote */
2529 dbp++;
2530 else if (*dbp == '(' && L_isquote (dbp)) /* Skip "(quote " */
2531 {
2532 dbp += 7;
2533 while (isspace(*dbp))
2534 dbp++;
2535 }
2536 for (cp = dbp /*+1*/; *cp && *cp != '(' && *cp != ' ' && *cp != ')'; cp++)
2537 continue;
2538 if (cp == dbp)
2539 return;
2540
2541 c = cp[0];
2542 cp[0] = 0;
2543 strcpy (nambuf, dbp);
2544 cp[0] = c;
2545 pfnote (nambuf, TRUE, FALSE, lb.buffer,
2546 cp - lb.buffer + 1, lineno, linecharno);
2547 pfcnt++;
2548 }
2549 \f
2550 /*
2551 * Scheme tag functions
2552 * look for (def... xyzzy
2553 * look for (def... (xyzzy
2554 * look for (def ... ((...(xyzzy ....
2555 * look for (set! xyzzy
2556 */
2557
2558 static void get_scheme ();
2559
2560 void
2561 Scheme_funcs (fi)
2562 FILE *fi;
2563 {
2564 lineno = 0;
2565 charno = 0;
2566 pfcnt = 0;
2567
2568 while (!feof (fi))
2569 {
2570 lineno++;
2571 linecharno = charno;
2572 charno += readline (&lb, fi);
2573 dbp = lb.buffer;
2574 if (dbp[0] == '(' &&
2575 (dbp[1] == 'D' || dbp[1] == 'd') &&
2576 (dbp[2] == 'E' || dbp[2] == 'e') &&
2577 (dbp[3] == 'F' || dbp[3] == 'f'))
2578 {
2579 while (!isspace (*dbp))
2580 dbp++;
2581 /* Skip over open parens and white space */
2582 while (*dbp && (isspace (*dbp) || *dbp == '('))
2583 dbp++;
2584 get_scheme ();
2585 }
2586 if (dbp[0] == '(' &&
2587 (dbp[1] == 'S' || dbp[1] == 's') &&
2588 (dbp[2] == 'E' || dbp[2] == 'e') &&
2589 (dbp[3] == 'T' || dbp[3] == 't') &&
2590 (dbp[4] == '!' || dbp[4] == '!') &&
2591 (isspace (dbp[5])))
2592 {
2593 while (!isspace (*dbp))
2594 dbp++;
2595 /* Skip over white space */
2596 while (isspace (*dbp))
2597 dbp++;
2598 get_scheme ();
2599 }
2600 }
2601 }
2602
2603 static void
2604 get_scheme ()
2605 {
2606 register char *cp;
2607 char c;
2608 char nambuf[BUFSIZ];
2609
2610 if (*dbp == 0)
2611 return;
2612 /* Go till you get to white space or a syntactic break */
2613 for (cp = dbp + 1; *cp && *cp != '(' && *cp != ')' && !isspace (*cp); cp++)
2614 continue;
2615 /* Null terminate the string there. */
2616 c = cp[0];
2617 cp[0] = 0;
2618 /* Copy the string */
2619 strcpy (nambuf, dbp);
2620 /* Unterminate the string */
2621 cp[0] = c;
2622 /* Announce the change */
2623 pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
2624 pfcnt++;
2625 }
2626 \f
2627 /* Find tags in TeX and LaTeX input files. */
2628
2629 /* TEX_toktab is a table of TeX control sequences that define tags.
2630 Each TEX_tabent records one such control sequence.
2631 CONVERT THIS TO USE THE Stab TYPE!! */
2632
2633 struct TEX_tabent
2634 {
2635 char *name;
2636 int len;
2637 };
2638
2639 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
2640
2641 /* Default set of control sequences to put into TEX_toktab.
2642 The value of environment var TEXTAGS is prepended to this. */
2643
2644 static char *TEX_defenv =
2645 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2646
2647 void TEX_mode ();
2648 struct TEX_tabent *TEX_decode_env ();
2649 void TEX_getit ();
2650 int TEX_Token ();
2651
2652 static char TEX_esc = '\\';
2653 static char TEX_opgrp = '{';
2654 static char TEX_clgrp = '}';
2655
2656 /*
2657 * TeX/LaTeX scanning loop.
2658 */
2659
2660 void
2661 TEX_funcs (fi)
2662 FILE *fi;
2663 {
2664 char *lasthit;
2665
2666 lineno = 0;
2667 charno = 0;
2668 pfcnt = 0;
2669
2670 /* Select either \ or ! as escape character. */
2671 TEX_mode (fi);
2672
2673 /* Initialize token table once from environment. */
2674 if (!TEX_toktab)
2675 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
2676
2677 while (!feof (fi))
2678 { /* Scan each line in file */
2679 lineno++;
2680 linecharno = charno;
2681 charno += readline (&lb, fi);
2682 dbp = lb.buffer;
2683 lasthit = dbp;
2684 while (dbp = etags_index (dbp, TEX_esc)) /* Look at each escape in line */
2685 {
2686 register int i;
2687
2688 if (!*(++dbp))
2689 break;
2690 linecharno += dbp - lasthit;
2691 lasthit = dbp;
2692 i = TEX_Token (lasthit);
2693 if (0 <= i)
2694 {
2695 TEX_getit (lasthit, TEX_toktab[i].len);
2696 break; /* We only save a line once */
2697 }
2698 }
2699 }
2700 }
2701
2702 #define TEX_LESC '\\'
2703 #define TEX_SESC '!'
2704 #define TEX_cmt '%'
2705
2706 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2707 /* chars accordingly. */
2708
2709 void
2710 TEX_mode (f)
2711 FILE *f;
2712 {
2713 int c;
2714
2715 while ((c = getc (f)) != EOF)
2716 {
2717 /* Skip to next line if we hit the TeX comment char. */
2718 if (c == TEX_cmt)
2719 while (c != '\n')
2720 c = getc (f);
2721 else if (c == TEX_LESC || c == TEX_SESC )
2722 break;
2723 }
2724
2725 if (c == TEX_LESC)
2726 {
2727 TEX_esc = TEX_LESC;
2728 TEX_opgrp = '{';
2729 TEX_clgrp = '}';
2730 }
2731 else
2732 {
2733 TEX_esc = TEX_SESC;
2734 TEX_opgrp = '<';
2735 TEX_clgrp = '>';
2736 }
2737 rewind (f);
2738 }
2739
2740 /* Read environment and prepend it to the default string. */
2741 /* Build token table. */
2742
2743 struct TEX_tabent *
2744 TEX_decode_env (evarname, defenv)
2745 char *evarname;
2746 char *defenv;
2747 {
2748 register char *env, *p;
2749
2750 struct TEX_tabent *tab;
2751 int size, i;
2752
2753 /* Append default string to environment. */
2754 env = getenv (evarname);
2755 if (!env)
2756 env = defenv;
2757 else
2758 env = concat (env, defenv, "");
2759
2760 /* Allocate a token table */
2761 for (size = 1, p = env; p;)
2762 if ((p = etags_index (p, ':')) && *(++p))
2763 size++;
2764 /* Add 1 to leave room for null terminator. */
2765 tab = xnew (size + 1, struct TEX_tabent);
2766
2767 /* Unpack environment string into token table. Be careful about */
2768 /* zero-length strings (leading ':', "::" and trailing ':') */
2769 for (i = 0; *env;)
2770 {
2771 p = etags_index (env, ':');
2772 if (!p) /* End of environment string. */
2773 p = env + strlen (env);
2774 if (p - env > 0)
2775 { /* Only non-zero strings. */
2776 tab[i].name = savenstr (env, p - env);
2777 tab[i].len = strlen (tab[i].name);
2778 i++;
2779 }
2780 if (*p)
2781 env = p + 1;
2782 else
2783 {
2784 tab[i].name = NULL; /* Mark end of table. */
2785 tab[i].len = 0;
2786 break;
2787 }
2788 }
2789 return tab;
2790 }
2791
2792 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2793 The name being defined actually starts at (NAME + LEN + 1).
2794 But we seem to include the TeX command in the tag name. */
2795
2796 void
2797 TEX_getit (name, len)
2798 char *name;
2799 int len;
2800 {
2801 char *p = name + len;
2802 char nambuf[BUFSIZ];
2803
2804 if (*name == 0)
2805 return;
2806
2807 /* Let tag name extend to next group close (or end of line) */
2808 while (*p && *p != TEX_clgrp)
2809 p++;
2810 strncpy (nambuf, name, p - name);
2811 nambuf[p - name] = 0;
2812
2813 pfnote (nambuf, TRUE, FALSE, lb.buffer, strlen (lb.buffer), lineno, linecharno);
2814 pfcnt++;
2815 }
2816
2817 /* If the text at CP matches one of the tag-defining TeX command names,
2818 return the etags_index of that command in TEX_toktab.
2819 Otherwise return -1. */
2820
2821 /* Keep the capital `T' in `Token' for dumb truncating compilers
2822 (this distinguishes it from `TEX_toktab' */
2823 int
2824 TEX_Token (cp)
2825 char *cp;
2826 {
2827 int i;
2828
2829 for (i = 0; TEX_toktab[i].len > 0; i++)
2830 if (strneq (TEX_toktab[i].name, cp, TEX_toktab[i].len))
2831 return i;
2832 return -1;
2833 }
2834 \f
2835 /* Support for Prolog. */
2836
2837 /* whole head (not only functor, but also arguments)
2838 is gotten in compound term. */
2839
2840 void
2841 prolog_getit (s, lineno, linecharno)
2842 char *s;
2843 int lineno;
2844 long linecharno;
2845 {
2846 char nambuf[BUFSIZ], *save_s, tmpc;
2847 int insquote, npar;
2848
2849 save_s = s;
2850 insquote = FALSE;
2851 npar = 0;
2852 while (1)
2853 {
2854 if (*s == '\0') /* syntax error. */
2855 return;
2856 else if (insquote && *s == '\'' && *(s + 1) == '\'')
2857 s += 2;
2858 else if (*s == '\'')
2859 {
2860 insquote = !insquote;
2861 s++;
2862 }
2863 else if (!insquote && *s == '(')
2864 {
2865 npar++;
2866 s++;
2867 }
2868 else if (!insquote && *s == ')')
2869 {
2870 npar--;
2871 s++;
2872 if (npar == 0)
2873 break;
2874 else if (npar < 0) /* syntax error. */
2875 return;
2876 }
2877 else if (!insquote && *s == '.' && (isspace (*(s + 1)) || *(s + 1) == '\0'))
2878 { /* fullstop. */
2879 if (npar != 0) /* syntax error. */
2880 return;
2881 s++;
2882 break;
2883 }
2884 else
2885 s++;
2886 }
2887 tmpc = *s;
2888 *s = '\0';
2889 strcpy (nambuf, save_s);
2890 *s = tmpc;
2891 pfnote (nambuf, TRUE, FALSE, save_s, strlen (nambuf), lineno, linecharno);
2892 }
2893
2894 /* It is assumed that prolog predicate starts from column 0. */
2895
2896 void
2897 prolog_funcs (fi)
2898 FILE *fi;
2899 {
2900 void skip_comment (), prolog_getit ();
2901
2902 lineno = linecharno = charno = 0;
2903 while (!feof (fi))
2904 {
2905 lineno++;
2906 linecharno += charno;
2907 charno = readline (&lb, fi) + 1; /* 1 for newline. */
2908 dbp = lb.buffer;
2909 if (isspace (dbp[0])) /* not predicate header. */
2910 continue;
2911 else if (dbp[0] == '%') /* comment. */
2912 continue;
2913 else if (dbp[0] == '/' && dbp[1] == '*') /* comment. */
2914 skip_comment (&lb, fi, &lineno, &linecharno);
2915 else /* found. */
2916 prolog_getit (dbp, lineno, linecharno);
2917 }
2918 }
2919
2920 void
2921 skip_comment (plb, fi, plineno, plinecharno)
2922 struct linebuffer *plb;
2923 FILE *fi;
2924 int *plineno; /* result */
2925 long *plinecharno; /* result */
2926 {
2927 while (!substr ("*/", plb->buffer))
2928 {
2929 (*plineno)++;
2930 *plinecharno += readline (plb, fi) + 1;
2931 } /* 1 for newline. */
2932 }
2933
2934 /* Return TRUE if 'sub' exists somewhere in 's'. */
2935
2936 int
2937 substr (sub, s)
2938 char *sub;
2939 char *s;
2940 {
2941 while (*s && (s = etags_index (s, *sub)))
2942 if (prestr (sub, s))
2943 return (TRUE);
2944 else
2945 s++;
2946 return (FALSE);
2947 }
2948
2949 /* Return TRUE if 'pre' is prefix of string 's'. */
2950
2951 int
2952 prestr (pre, s)
2953 char *pre;
2954 char *s;
2955 {
2956 if (*pre == '\0')
2957 return (TRUE);
2958 else if (*pre == *s)
2959 return (prestr (pre + 1, s + 1));
2960 else
2961 return (FALSE);
2962 }
2963 \f
2964 /* Initialize a linebuffer for use */
2965
2966 void
2967 initbuffer (linebuffer)
2968 struct linebuffer *linebuffer;
2969 {
2970 linebuffer->size = 200;
2971 linebuffer->buffer = xnew (200, char);
2972 }
2973
2974 /*
2975 * Read a line of text from `stream' into `linebuffer'.
2976 * Return the number of characters read from `stream',
2977 * which is the length of the line including the newline, if any.
2978 */
2979 long
2980 readline (linebuffer, stream)
2981 struct linebuffer *linebuffer;
2982 register FILE *stream;
2983 {
2984 char *buffer = linebuffer->buffer;
2985 register char *p = linebuffer->buffer;
2986 register char *pend;
2987 int newline; /* 1 if ended with newline, 0 if ended with EOF */
2988
2989 pend = p + linebuffer->size; /* Separate to avoid 386/IX compiler bug. */
2990
2991 while (1)
2992 {
2993 register int c = getc (stream);
2994 if (p == pend)
2995 {
2996 linebuffer->size *= 2;
2997 buffer = (char *) xrealloc (buffer, linebuffer->size);
2998 p += buffer - linebuffer->buffer;
2999 pend = buffer + linebuffer->size;
3000 linebuffer->buffer = buffer;
3001 }
3002 if (c == EOF || c == '\n')
3003 {
3004 *p = 0;
3005 newline = (c == '\n') ? 1 : 0;
3006 break;
3007 }
3008 *p++ = c;
3009 }
3010
3011 return p - buffer + newline;
3012 }
3013 \f
3014 char *
3015 savestr (cp)
3016 char *cp;
3017 {
3018 return savenstr (cp, strlen (cp));
3019 }
3020
3021 char *
3022 savenstr (cp, len)
3023 char *cp;
3024 int len;
3025 {
3026 register char *dp;
3027
3028 dp = xnew (len + 1, char);
3029 strncpy (dp, cp, len);
3030 dp[len] = '\0';
3031 return dp;
3032 }
3033
3034 /*
3035 * Return the ptr in sp at which the character c last
3036 * appears; NULL if not found
3037 *
3038 * Identical to v7 rindex, included for portability.
3039 */
3040
3041 char *
3042 etags_rindex (sp, c)
3043 register char *sp, c;
3044 {
3045 register char *r;
3046
3047 r = NULL;
3048 do
3049 {
3050 if (*sp == c)
3051 r = sp;
3052 } while (*sp++);
3053 return (r);
3054 }
3055
3056
3057 /*
3058 * Return the ptr in sp at which the character c first
3059 * appears; NULL if not found
3060 *
3061 * Identical to v7 index, included for portability.
3062 */
3063
3064 char *
3065 etags_index (sp, c)
3066 register char *sp, c;
3067 {
3068 do
3069 {
3070 if (*sp == c)
3071 return (sp);
3072 } while (*sp++);
3073 return (NULL);
3074 }
3075
3076 /* Print error message and exit. */
3077
3078 /* VARARGS1 */
3079 void
3080 fatal (s1, s2)
3081 char *s1, *s2;
3082 {
3083 error (s1, s2);
3084 exit (BAD);
3085 }
3086
3087 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3088
3089 /* VARARGS1 */
3090 void
3091 error (s1, s2)
3092 char *s1, *s2;
3093 {
3094 fprintf (stderr, "%s: ", progname);
3095 fprintf (stderr, s1, s2);
3096 fprintf (stderr, "\n");
3097 }
3098
3099 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
3100
3101 char *
3102 concat (s1, s2, s3)
3103 char *s1, *s2, *s3;
3104 {
3105 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
3106 char *result = xnew (len1 + len2 + len3 + 1, char);
3107
3108 strcpy (result, s1);
3109 strcpy (result + len1, s2);
3110 strcpy (result + len1 + len2, s3);
3111 *(result + len1 + len2 + len3) = 0;
3112
3113 return result;
3114 }
3115
3116 /* Like malloc but get fatal error if memory is exhausted. */
3117
3118 char *
3119 xmalloc (size)
3120 unsigned int size;
3121 {
3122 char *result = (char *) malloc (size);
3123 if (result == NULL)
3124 fatal ("virtual memory exhausted", 0);
3125 return result;
3126 }
3127
3128 char *
3129 xrealloc (ptr, size)
3130 char *ptr;
3131 unsigned int size;
3132 {
3133 char *result = (char *) realloc (ptr, size);
3134 if (result == NULL)
3135 fatal ("virtual memory exhausted");
3136 return result;
3137 }