*** empty log message ***
[emacs.git] / lib-src / etags.c
blob6cab322bf873e104484083d08a24b4c2f1e45f60
1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 1987, 1988, 1989, 1992 Free Software Foundation, Inc. and Ken Arnold
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
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 *index (), *rindex ();
49 extern char *strcpy (), *strncpy ();
50 extern int strcmp ();
52 #ifdef hpux
53 #define NEED_INDEX 1
54 #define NEED_RINDEX 1
55 #endif
57 /* Define the symbol ETAGS to make the program "etags",
58 which makes emacs-style tag tables by default.
59 Define CTAGS to make the program "ctags" compatible with the usual one.
60 Define neither one to get behavior that depends
61 on the name with which the program is invoked
62 (but we don't normally compile it that way). */
64 #if !defined(ETAGS) && !defined(CTAGS)
65 /* If neither is defined, program can be run as either. */
66 #define ETAGS
67 #define CTAGS
68 #endif
70 /* On VMS, CTAGS is not useful, so always do ETAGS. */
71 #ifdef VMS
72 #ifndef ETAGS
73 #define ETAGS
74 #endif
75 #endif
77 /* Exit codes for success and failure. */
78 #ifdef VMS
79 #define GOOD (1)
80 #define BAD (0)
81 #else
82 #define GOOD (0)
83 #define BAD (1)
84 #endif
87 * The FILEPOS abstract type, which represents a position in a file,
88 * plus the following accessor functions:
90 * long GET_CHARNO (pos)
91 * returns absolute char number.
92 * long GET_COOKIE (pos)
93 * returns ftell () cookie.
94 * void SET_FILEPOS (pos, fp, charno)
95 * FILE *fp; long charno;
96 * sets `pos' from the current file
97 * position of `fp' and from `charno',
98 * which must be the absolute character
99 * number corresponding to the current
100 * position of `fp'.
102 * The `pos' parameter is an lvalue expression of type FILEPOS.
103 * Parameters to the accessor functions are evaluated 0 or more times,
104 * and so must have no side effects.
106 * FILEPOS objects can also be assigned and passed to and from
107 * functions in the normal C manner.
109 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
111 #ifdef VMS
112 typedef struct
114 long cookie;
115 long charno;
116 } FILEPOS;
118 #define GET_CHARNO(pos) ((pos).charno + 0)
119 #define GET_COOKIE(pos) ((pos).cookie + 0)
120 #define SET_FILEPOS(pos, fp, cno) \
121 ((void) ((pos).cookie = ftell (fp), (pos).charno = (cno)))
122 #else
123 #ifndef DEBUG
124 /* UNIX real implementation */
125 typedef long FILEPOS;
126 #define GET_CHARNO(pos) ((pos) + 0)
127 #define GET_COOKIE(pos) GET_CHARNO (pos)
128 #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno)))
129 #else
130 /* UNIX debugging implementation */
131 typedef struct
133 long charno;
134 } FILEPOS;
136 #define GET_CHARNO(pos) ((pos).charno + 0)
137 #define GET_COOKIE(pos) GET_CHARNO (pos)
138 #define SET_FILEPOS(pos, fp, cno) \
139 ((void) ((pos).charno = (cno), \
140 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
141 : 0))
142 #endif
143 #endif
145 #define streq(s, t) (strcmp (s, t) == 0)
146 #define strneq(s, t, n) (strncmp (s, t, n) == 0)
147 #define reg register
148 #define logical char
150 #define TRUE 1
151 #define FALSE 0
153 #define iswhite(arg) (_wht[arg]) /* T if char is white */
154 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
155 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
156 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
157 #define isgood(arg) (_gd[arg]) /* T if char can be after ')' */
159 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
161 struct nd_st
162 { /* sorting structure */
163 char *name; /* function or type name */
164 char *file; /* file name */
165 logical is_func; /* use pattern or line no */
166 logical rewritten; /* list name separately */
167 logical been_warned; /* set if noticed dup */
168 int lno; /* line number tag is on */
169 long cno; /* character number line starts on */
170 char *pat; /* search pattern */
171 struct nd_st *left, *right; /* left and right sons */
174 long ftell ();
175 typedef struct nd_st NODE;
177 logical gotone, /* found a func already on line */
178 /* boolean "func" (see init) */
179 header_file, /* TRUE if .h file, FALSE o.w. */
180 _wht[0177], _etk[0177], _itk[0177], _btk[0177], _gd[0177];
183 char *concat ();
184 char *savenstr ();
185 char *savestr ();
186 char *xmalloc ();
187 char *xrealloc ();
188 int L_isdef ();
189 int PF_funcs ();
190 int total_size_of_entries ();
191 logical consider_token ();
192 logical tail ();
193 long readline ();
194 void Asm_funcs ();
195 void C_entries ();
196 void L_funcs ();
197 void L_getit ();
198 void PAS_funcs ();
199 void Scheme_funcs ();
200 void TEX_funcs ();
201 void add_node ();
202 void error ();
203 void fatal ();
204 void find_entries ();
205 void free_tree ();
206 void getit ();
207 void getline ();
208 void init ();
209 void initbuffer ();
210 void initbuffer ();
211 void pfnote ();
212 void process_file ();
213 void put_entries ();
214 void takeprec ();
217 * MACRO
218 * xnew -- allocate storage
220 * SYNOPSIS
221 * Type *xnew (int n, Type);
223 #define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
228 * Symbol table stuff.
230 * Should probably be implemented with hash table; linked list for now.
233 enum sym_type
235 st_none, st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
238 struct stab_entry
240 char *sym;
241 int symlen;
242 enum sym_type type;
243 struct stab_entry *next;
246 typedef struct stab_entry Stab_entry;
247 typedef Stab_entry *Stab;
250 * NAME
251 * Stab, Stab_entry, stab_create, stab_search, stab_find -- symbol table
253 * SYNOPSIS
254 * Types: Stab, Stab_entry, enum sym_type
256 * Stab * stab_create ()
258 * Stab_entry * stab_find (stab, sym)
259 * Stab *stab;
260 * char *sym;
262 * Stab_entry * stab_search (stab, sym)
263 * Stab *stab;
264 * char *sym;
266 * DESCRIPTION
267 * stab_create creates a Stab, a symbol table object, and returns a
268 * pointer to it. stab_find finds a symbol in a Stab; it returns a
269 * pointer to the Stab_entry if found, otherwise NULL. stab_search
270 * is like stab_find, except that it creates a new Stab_entry,
271 * initialized with type = st_none, if one did not exist already
272 * (it never returns NULL).
274 * A Stab_entry is a structure that contains at least the following
275 * members:
277 * char *name; // must not be modified
278 * enum sym_type type; // should be set
280 * The type field is initially set to st_none; it should be set to
281 * something else by the caller of stab_search. Other possible values
282 * of an enum sym_type can be added.
285 Stab *
286 stab_create ()
288 Stab *sp;
289 sp = xnew (1, Stab);
290 *sp = NULL; /* a Stab starts out as a null Stab_entry* */
291 return sp;
294 Stab_entry *
295 stab_find (stab, sym, symlen)
296 Stab *stab;
297 register char *sym;
298 register int symlen;
300 register Stab_entry *se;
301 for (se = *stab; se != NULL; se = se->next)
303 if (se->symlen == symlen && strneq (se->sym, sym, symlen))
304 return se;
307 return NULL;
310 Stab_entry *
311 stab_search (stab, sym, symlen)
312 register Stab *stab;
313 char *sym;
314 int symlen;
316 register Stab_entry *se;
317 se = stab_find (stab, sym, symlen);
319 if (se == NULL)
321 /* make a new one */
322 se = xnew (1, Stab_entry);
323 se->sym = savenstr (sym, symlen);
324 se->symlen = symlen;
325 se->type = st_none;
326 se->next = *stab;
327 *stab = se;
330 return se;
334 * NAME
335 * stab_type -- type of a symbol table entry
337 * SYNOPSIS
338 * enum sym_type stab_type (Stab_entry *se);
340 * WARNING
341 * May evaluate its argument more than once.
344 #define stab_type(se) ((se)==NULL ? st_none : (se)->type)
348 typedef int LINENO;
350 typedef struct
352 char *p;
353 int len;
354 FILEPOS linestart;
355 LINENO lineno;
356 logical rewritten;
357 } TOKEN;
360 /* typedefs are recognized using a simple finite automaton.
361 * tydef is its state variable.
363 typedef enum
365 none, begin, middle, end
366 } TYST;
368 TYST tydef = none;
371 /* struct tags for C++ are recognized using another simple
372 * finite automaton. `structdef' is its state variable.
373 * This machinery is only invoked for C++; otherwise structdef
374 * should remain snone. However, this machinery can easily be
375 * adapted to find structure tags in normal C code.
377 typedef enum
379 snone, /* nothing seen yet */
380 skeyseen, /* struct-like keyword seen */
381 stagseen, /* struct-like tag seen */
382 scolonseen, /* colon seen after struct-like tag */
383 sinbody /* in a class body: recognize member func defs */
384 } STRUCTST;
385 STRUCTST structdef = snone;
387 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
388 * struct tag, and structkey is the preceding struct-like keyword.
390 char structtag[512];
391 Stab_entry *structkey;
394 * Yet another little state machine to deal with preprocessor lines.
396 typedef enum
398 dnone, /* nothing seen */
399 dsharpseen, /* '#' seen as first char on line */
400 ddefineseen, /* '#' and 'define' seen */
401 dignorerest /* ignore rest of line */
402 } DEFINEST;
403 DEFINEST definedef;
406 * LEVEL_OK_FOR_FUNCDEF allows C++ function definition within class body.
407 * Currently tydef and structdef stuff (typedefs and struct definitions) are
408 * only noticed when level==0, but that may change.
410 * Note that this macro may only be evaluated inside C_entries(). It is
411 * for self-documentation only.
413 #define LEVEL_OK_FOR_FUNCDEF() \
414 (level==0 || (c_ext && level==1 && structdef==sinbody))
417 * next_token_is_func
418 * set this to TRUE, and the next token considered is called a function.
420 logical next_token_is_func;
422 /* C extensions. Currently all listed extensions are C++ dialects, so
423 * `c_ext' is used as an abbreviation for `c_ext&C_PLPL'. If a non-C++
424 * dialect is added, this must change.
426 #define C_PLPL 0x1 /* C++ */
427 #define C_STAR 0x3 /* C* */
429 char searchar = '/'; /* use /.../ searches */
431 LINENO lineno; /* line number of current line */
432 long charno; /* current character number */
433 FILEPOS linepos; /* start of line (C only) */
434 FILEPOS prev_linepos; /* start of previous line (C only) */
436 long linecharno; /* charno of start of line; not used by C, but
437 * by every other language.
440 char *curfile, /* current input file name */
441 *outfile, /* output file */
442 *white = " \f\t\n", /* white chars */
443 *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
444 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$", /* token starting chars */
445 *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789", /* valid in-token chars */
446 *notgd = ",;"; /* non-valid after-function chars */
448 int append_to_tagfile; /* -a: append to tags */
449 int emacs_tags_format; /* emacs style output (no -e option any more) */
450 /* The following three default to 1 for etags, but to 0 for ctags. */
451 int typedefs; /* -t: create tags for typedefs */
452 int typedefs_and_cplusplus; /* -T: create tags for typedefs, level */
453 /* 0 struct/enum/union decls, and C++ */
454 /* member functions */
455 int constantypedefs; /* -d: create tags for C #define and enum */
456 /* constants. Default under etags. Enum */
457 /* constants not implemented. */
458 /* -D: opposite of -d. Default under ctags. */
459 int update; /* -u: update tags */
460 int vgrind_style; /* -v: create vgrind style index output */
461 int no_warnings; /* -w: suppress warnings */
462 int cxref_style; /* -x: create cxref style output */
463 int cplusplus; /* .[hc] means C++, not C */
464 int noindentypedefs; /* -S: ignore indentation in C */
466 /* Name this program was invoked with. */
467 char *progname;
469 struct option longopts[] = {
470 { "append", no_argument, NULL, 'a' },
471 { "backward-search", no_argument, NULL, 'B' },
472 { "c++", no_argument, NULL, 'C' },
473 { "cxref", no_argument, NULL, 'x' },
474 { "defines", no_argument, NULL, 'd' },
475 { "forward-search", no_argument, NULL, 'F' },
476 { "help", no_argument, NULL, 'H' },
477 { "ignore-indentation", no_argument, NULL, 'S' },
478 { "include", required_argument, NULL, 'i' },
479 { "no-defines", no_argument, NULL, 'D' },
480 { "no-warn", no_argument, NULL, 'w' },
481 { "output", required_argument, NULL, 'o' },
482 { "typedefs", no_argument, NULL, 't' },
483 { "typedefs-and-c++", no_argument, NULL, 'T' },
484 { "update", no_argument, NULL, 'u' },
485 { "version", no_argument, NULL, 'V' },
486 { "vgrind", no_argument, NULL, 'v' },
487 { 0 }
490 FILE *inf, /* ioptr for current input file */
491 *outf; /* ioptr for tags file */
493 NODE *head; /* the head of the binary tree of tags */
495 int permit_duplicates = 1; /* Nonzero means allow duplicate tags. */
497 /* A `struct linebuffer' is a structure which holds a line of text.
498 `readline' reads a line from a stream into a linebuffer
499 and works regardless of the length of the line. */
501 struct linebuffer
503 long size;
504 char *buffer;
507 struct linebuffer lb; /* the current line */
508 struct linebuffer lb1; /* sometimes, a previous line in which a token lies */
509 struct linebuffer filename_lb; /* used to read in filenames */
512 void
513 print_version ()
515 #ifdef CTAGS
516 printf ("CTAGS ");
517 #ifdef ETAGS
518 printf ("and ");
519 #endif
520 #endif
521 #ifdef ETAGS
522 printf ("ETAGS ");
523 #endif
524 printf ("for Emacs version 19.0.\n");
526 exit (0);
529 void
530 print_help ()
532 printf ("These are the options accepted by %s. You may use unambiguous\n\
533 abbreviations for the long option names.\n\n", progname);
535 fputs ("\
536 -a, --append\n\
537 Append tag entries to existing tags file.\n\
538 -C, --c++\n\
539 Treat files with `.c' and `.h' extensions as C++ code, not C\n\
540 code. Files with `.C', `.H', `.cxx', `.hxx', or `.cc'\n\
541 extensions are always assumed to be C++ code.\n\
542 -d, --defines\n\
543 Create tag entries for #defines, too.", stdout);
545 #ifdef ETAGS
546 fputs (" This is the default\n\
547 behavior.", stdout);
548 #endif
550 fputs ("\n\
551 -D, --no-defines\n\
552 Don't create tag entries for #defines.", stdout);
554 #ifdef CTAGS
555 fputs (" This is the default\n\
556 behavior.", stdout);
557 #endif
559 puts ("\n\
560 -o FILE, --output=FILE\n\
561 Write the tags to FILE.\n\
562 -S, --ignore-indentation\n\
563 Don't rely on indentation quite as much as normal. Currently,\n\
564 this means not to assume that a closing brace in the first\n\
565 column is the final brace of a function or structure\n\
566 definition.\n\
567 -t, --typedefs\n\
568 Generate tag entries for typedefs. This is the default\n\
569 behavior.\n\
570 -T, --typedefs-and-c++\n\
571 Generate tag entries for typedefs, struct/enum/union tags, and\n\
572 C++ member functions.");
574 #ifdef ETAGS
575 puts ("-i FILE, --include=FILE\n\
576 Include a note in tag file indicating that, when searching for\n\
577 a tag, one should also consult the tags file FILE after\n\
578 checking the current file.");
579 #endif
581 #ifdef CTAGS
582 puts ("-B, --backward-search\n\
583 Write the search commands for the tag entries using '?', the\n\
584 backward-search command.\n\
585 -F, --forward-search\n\
586 Write the search commands for the tag entries using '/', the\n\
587 forward-search command.\n\
588 -u, --update\n\
589 Update the tag entries for the given files, leaving tag\n\
590 entries for other files in place. Currently, this is\n\
591 implemented by deleting the existing entries for the given\n\
592 files and then rewriting the new entries at the end of the\n\
593 tags file. It is often faster to simply rebuild the entire\n\
594 tag file than to use this.\n\
595 -v, --vgrind\n\
596 Generates an index of items intended for human consumption,\n\
597 similar to the output of vgrind. The index is sorted, and\n\
598 gives the page number of each item.\n\
599 -x, --cxref\n\
600 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
601 The output uses line numbers instead of page numbers, but\n\
602 beyond that the differences are cosmetic; try both to see\n\
603 which you like.\n\
604 -w, --no-warn\n\
605 Suppress warning messages about entries defined in multiple\n\
606 files.");
607 #endif
609 puts ("-V, --version\n\
610 Print the version of the program.\n\
611 -H, --help\n\
612 Print this help message.");
614 exit (0);
618 void
619 main (argc, argv)
620 int argc;
621 char *argv[];
623 char cmd[100];
624 int i;
625 unsigned int nincluded_files = 0;
626 char **included_files = (char **) alloca (argc * sizeof (char *));
627 char *this_file;
628 #ifdef VMS
629 char got_err;
631 extern char *gfnames ();
632 extern char *massage_name ();
633 #endif
635 progname = argv[0];
637 #ifndef CTAGS
638 emacs_tags_format = 1;
639 #else
640 emacs_tags_format = 0;
641 #endif
644 * If etags, always find typedefs and structure tags. Why not?
645 * Also default is to find macro constants.
647 if (emacs_tags_format)
648 typedefs = typedefs_and_cplusplus = constantypedefs = 1;
650 for (;;)
652 int opt;
653 opt = getopt_long (argc, argv, "aCdDo:StTi:BFuvxwVH", longopts, 0);
655 if (opt == EOF)
656 break;
658 switch (opt)
660 case '\0':
661 /* If getopt returns '\0', then it has already processed a
662 long-named option. We should do nothing. */
663 break;
665 /* Common options. */
666 case 'a':
667 append_to_tagfile++;
668 break;
669 case 'C':
670 cplusplus = 1;
671 break;
672 case 'd':
673 constantypedefs = 1;
674 break;
675 case 'D':
676 constantypedefs = 0;
677 break;
678 case 'o':
679 if (outfile)
681 fprintf (stderr,
682 "%s: -o flag may only be given once\n", progname);
683 goto usage;
685 outfile = optarg;
686 break;
687 case 'S':
688 noindentypedefs++;
689 break;
690 case 't':
691 typedefs++;
692 break;
693 case 'T':
694 typedefs++;
695 typedefs_and_cplusplus++;
696 break;
697 case 'V':
698 print_version ();
699 break;
700 case 'H':
701 print_help ();
702 break;
704 /* Etags options */
705 case 'i':
706 if (!emacs_tags_format)
707 goto usage;
708 included_files[nincluded_files++] = optarg;
709 break;
711 /* Ctags options. */
712 case 'B':
713 searchar = '?';
714 if (emacs_tags_format)
715 goto usage;
716 break;
717 case 'F':
718 searchar = '/';
719 if (emacs_tags_format)
720 goto usage;
721 break;
722 case 'u':
723 update++;
724 if (emacs_tags_format)
725 goto usage;
726 break;
727 case 'v':
728 vgrind_style++;
729 /*FALLTHRU*/
730 case 'x':
731 cxref_style++;
732 if (emacs_tags_format)
733 goto usage;
734 break;
735 case 'w':
736 no_warnings++;
737 if (emacs_tags_format)
738 goto usage;
739 break;
741 default:
742 goto usage;
746 if (optind == argc)
748 fprintf (stderr, "%s: No input files specified.\n", progname);
750 usage:
751 fprintf (stderr, "%s: Try '%s --help' for a complete list of options.\n",
752 progname, progname);
753 exit (BAD);
756 if (outfile == 0)
758 outfile = emacs_tags_format ? "TAGS" : "tags";
761 init (); /* set up boolean "functions" */
763 initbuffer (&lb);
764 initbuffer (&lb1);
765 initbuffer (&filename_lb);
767 * loop through files finding functions
769 if (emacs_tags_format)
771 if (streq (outfile, "-"))
772 outf = stdout;
773 else
774 outf = fopen (outfile, append_to_tagfile ? "a" : "w");
775 if (!outf)
777 perror (outfile);
778 exit (1);
782 #ifdef VMS
783 argc -= optind;
784 argv += optind;
785 while (gfnames (&argc, &argv, &got_err) != NULL)
787 if (got_err)
789 error ("Can't find file %s\n", this_file);
790 argc--, argv++;
792 else
794 this_file = massage_name (this_file);
795 #if 0
797 } /* solely to balance out the ifdef'd parens above */
798 #endif
799 #else
800 for (; optind < argc; optind++)
802 this_file = argv[optind];
803 if (1)
805 #endif
806 /* Input file named "-" means read file names from stdin
807 and use them. */
808 if (streq (this_file, "-"))
810 while (!feof (stdin))
812 (void) readline (&filename_lb, stdin);
813 if (strlen (filename_lb.buffer) > 0)
814 process_file (filename_lb.buffer);
817 else
818 process_file (this_file);
822 if (emacs_tags_format)
824 while (nincluded_files-- > 0)
825 fprintf (outf, "\f\n%s,include\n", *included_files++);
827 (void) fclose (outf);
828 exit (0);
831 if (cxref_style)
833 put_entries (head);
834 exit (GOOD);
836 if (update)
838 /* update cannot be set under VMS, so we may assume that argc
839 and argv have not been munged. */
840 for (i = optind; i < argc; i++)
842 sprintf (cmd,
843 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
844 outfile, argv[i], outfile);
845 (void) system (cmd);
847 append_to_tagfile++;
849 outf = fopen (outfile, append_to_tagfile ? "a" : "w");
850 if (outf == NULL)
852 perror (outfile);
853 exit (GOOD);
855 put_entries (head);
856 (void) fclose (outf);
857 if (update)
859 sprintf (cmd, "sort %s -o %s", outfile, outfile);
860 (void) system (cmd);
862 exit (GOOD);
867 * This routine is called on each file argument.
869 void
870 process_file (file)
871 char *file;
873 struct stat stat_buf;
875 stat (file, &stat_buf);
876 if (!(stat_buf.st_mode & S_IFREG) || !(stat_buf.st_mode & S_IFLNK))
878 fprintf (stderr, "Skipping %s: it is not a regular file.\n", file);
879 return;
882 if (streq (file, outfile) && !streq (outfile, "-"))
884 fprintf (stderr, "Skipping inclusion of %s in self.\n", file);
885 return;
887 if (emacs_tags_format)
889 char *cp = rindex (file, '/');
890 if (cp)
891 ++cp;
892 else
893 cp = file;
895 find_entries (file);
896 if (emacs_tags_format)
898 fprintf (outf, "\f\n%s,%d\n",
899 file, total_size_of_entries (head));
900 put_entries (head);
901 free_tree (head);
902 head = NULL;
907 * This routine sets up the boolean psuedo-functions which work
908 * by seting boolean flags dependent upon the corresponding character
909 * Every char which is NOT in that string is not a white char. Therefore,
910 * all of the array "_wht" is set to FALSE, and then the elements
911 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
912 * of a char is TRUE if it is the string "white", else FALSE.
914 void
915 init ()
917 reg char *sp;
918 reg int i;
920 for (i = 0; i < 0177; i++)
922 _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
923 _gd[i] = TRUE;
925 for (sp = white; *sp; sp++)
926 _wht[*sp] = TRUE;
927 for (sp = endtk; *sp; sp++)
928 _etk[*sp] = TRUE;
929 for (sp = intk; *sp; sp++)
930 _itk[*sp] = TRUE;
931 for (sp = begtk; *sp; sp++)
932 _btk[*sp] = TRUE;
933 for (sp = notgd; *sp; sp++)
934 _gd[*sp] = FALSE;
935 _wht[0] = _wht['\n'];
936 _etk[0] = _etk['\n'];
937 _btk[0] = _btk['\n'];
938 _itk[0] = _itk['\n'];
939 _gd[0] = _gd['\n'];
943 * This routine opens the specified file and calls the function
944 * which finds the function and type definitions.
946 void
947 find_entries (file)
948 char *file;
950 char *cp;
951 void prolog_funcs ();
953 inf = fopen (file, "r");
954 if (inf == NULL)
956 perror (file);
957 return;
959 curfile = savestr (file);
960 cp = rindex (file, '.');
962 header_file = (cp && (streq (cp + 1, "h")));
964 /* .tex, .aux or .bbl implies LaTeX source code */
965 if (cp && (streq (cp + 1, "tex") || streq (cp + 1, "aux")
966 || streq (cp + 1, "bbl")))
968 TEX_funcs (inf);
969 goto close_and_return;
971 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
972 if (cp && (streq (cp + 1, "l")
973 || streq (cp + 1, "el")
974 || streq (cp + 1, "lsp")
975 || streq (cp + 1, "lisp")
976 || streq (cp + 1, "cl")
977 || streq (cp + 1, "clisp")))
979 L_funcs (inf);
980 goto close_and_return;
982 /* .scm or .sm or .scheme or ... implies scheme source code */
983 if (cp && (streq (cp + 1, "sm")
984 || streq (cp + 1, "scm")
985 || streq (cp + 1, "scheme")
986 || streq (cp + 1, "t")
987 || streq (cp + 1, "sch")
988 || streq (cp + 1, "SM")
989 || streq (cp + 1, "SCM")
990 /* The `SCM' or `scm' prefix with a version number */
991 || (cp[-1] == 'm' && cp[-2] == 'c' && cp[-3] == 's'
992 && string_numeric_p (cp + 1))
993 || (cp[-1] == 'M' && cp[-2] == 'C' && cp[-3] == 'S'
994 && string_numeric_p (cp + 1))))
996 Scheme_funcs (inf);
997 fclose (inf);
998 return;
1000 /* Assume that ".s" or ".a" is assembly code. -wolfgang. */
1001 if (cp && (cp[1] == 's' || cp[1] == 'a') && cp[2] == '\0')
1003 Asm_funcs (inf);
1004 fclose (inf);
1005 return;
1007 /* .C or .H or .cxx or .hxx or .cc: a C++ file */
1008 if (cp && (streq (cp + 1, "C")
1009 || streq (cp + 1, "H")
1010 || streq (cp + 1, "cxx")
1011 || streq (cp + 1, "hxx")
1012 || streq (cp + 1, "cc")))
1014 C_entries (C_PLPL); /* C++ */
1015 goto close_and_return;
1017 /* .cs or .hs: a C* file */
1018 if (cp && (cp[1] == 'c' || cp[1] == 'h') && cp[2] == 's' && cp[3] == '\0')
1020 C_entries (C_STAR);
1021 goto close_and_return;
1023 /* .pl implies prolog source code */
1024 if (cp && !strcmp (cp + 1, "pl"))
1026 prolog_funcs (inf);
1027 goto close_and_return;
1029 /* .p or .pas: a Pascal file */
1030 if (cp && (streq (cp + 1, "p")
1031 || streq (cp + 1, "pas")))
1033 PAS_funcs (inf);
1034 goto close_and_return;
1036 /* if not a .c or .h or .y file, try fortran */
1037 else if (cp && ((cp[1] != 'c'
1038 && cp[1] != 'h'
1039 && cp[1] != 'y')
1040 || (cp[1] != 0 && cp[2] != 0)))
1042 if (PF_funcs (inf) != 0)
1043 goto close_and_return;
1044 rewind (inf); /* no fortran tags found, try C */
1046 C_entries (cplusplus ? C_PLPL : 0);
1048 close_and_return:
1049 (void) fclose (inf);
1052 /* Nonzero if string STR is composed of digits. */
1055 string_numeric_p (str)
1056 char *str;
1058 while (*str)
1060 if (*str < '0' || *str > '9')
1061 return 0;
1063 return 1;
1066 /* Record a tag. */
1067 /* Should take a TOKEN* instead!! */
1069 void
1070 pfnote (name, is_func, rewritten, linestart, linelen, lno, cno)
1071 char *name; /* tag name */
1072 logical is_func; /* function or type name? */
1073 logical rewritten; /* tag different from text of definition? */
1074 char *linestart;
1075 int linelen;
1076 int lno;
1077 long cno;
1079 register char *fp;
1080 register NODE *np;
1081 char tem[51];
1082 char c;
1084 np = (NODE *) malloc (sizeof (NODE));
1085 if (np == NULL)
1087 if (!emacs_tags_format)
1089 /* It's okay to output early in etags -- it only disrupts the
1090 * character count of the tag entries, which is no longer used
1091 * by tags.el anyway.
1093 error ("too many entries to sort");
1095 put_entries (head);
1096 free_tree (head);
1097 head = NULL;
1098 np = xnew (1, NODE);
1100 /* If ctags mode, change name "main" to M<thisfilename>. */
1101 if (!emacs_tags_format && !cxref_style && streq (name, "main"))
1103 fp = rindex (curfile, '/');
1104 name = concat ("M", fp == 0 ? curfile : fp + 1, "");
1105 fp = rindex (name, '.');
1106 if (fp && fp[1] != '\0' && fp[2] == '\0')
1107 *fp = 0;
1108 rewritten = TRUE;
1110 np->name = savestr (name);
1111 np->file = curfile;
1112 np->is_func = is_func;
1113 np->rewritten = rewritten;
1114 np->lno = lno;
1115 /* UNCOMMENT THE +1 HERE: */
1116 np->cno = cno /* + 1 */ ; /* our char numbers are 0-base; emacs's are 1-base */
1117 np->left = np->right = 0;
1118 if (emacs_tags_format)
1120 c = linestart[linelen];
1121 linestart[linelen] = 0;
1123 else if (cxref_style == 0)
1125 sprintf (tem, strlen (linestart) < 50 ? "%s$" : "%.50s", linestart);
1126 linestart = tem;
1128 np->pat = savestr (linestart);
1129 if (emacs_tags_format)
1131 linestart[linelen] = c;
1134 add_node (np, &head);
1138 * free_tree ()
1139 * recurse on left children, iterate on right children.
1141 void
1142 free_tree (node)
1143 register NODE *node;
1145 while (node)
1147 register NODE *node_right = node->right;
1148 free_tree (node->left);
1149 free (node->name);
1150 free (node->pat);
1151 free ((char *) node);
1152 node = node_right;
1157 * add_node ()
1158 * Adds a node to the tree of nodes. In etags mode, we don't keep
1159 * it sorted; we just keep a linear list. In ctags mode, maintain
1160 * an ordered tree, with no attempt at balancing.
1162 * add_node is the only function allowed to add nodes, so it can
1163 * maintain state.
1165 void
1166 add_node (node, cur_node_p)
1167 NODE *node, **cur_node_p;
1169 register int dif;
1170 register NODE *cur_node = *cur_node_p;
1171 static NODE *last_node = NULL;/* careful */
1173 if (cur_node == NULL)
1175 *cur_node_p = node;
1176 last_node = node;
1177 return;
1180 if (emacs_tags_format)
1182 /* Etags Mode */
1183 if (!last_node)
1184 fatal ("internal error in add_node");
1185 last_node->right = node;
1186 last_node = node;
1188 else
1190 /* Ctags Mode */
1191 dif = strcmp (node->name, cur_node->name);
1194 * If this tag name matches an existing one, then
1195 * do not add the node, but maybe print a warning.
1197 if (!dif)
1199 if (node->file == cur_node->file)
1201 if (!no_warnings)
1203 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1204 node->file, lineno, node->name);
1205 fprintf (stderr, "Second entry ignored\n");
1207 return;
1209 if (!cur_node->been_warned && !no_warnings)
1211 fprintf (stderr,
1212 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1213 node->file, cur_node->file, node->name);
1215 cur_node->been_warned = TRUE;
1216 return;
1219 /* Maybe refuse to add duplicate nodes. */
1220 if (!permit_duplicates)
1222 if (!strcmp (node->name, cur_node->name)
1223 && !strcmp (node->file, cur_node->file))
1224 return;
1227 /* Actually add the node */
1228 add_node (node, dif < 0 ? &cur_node->left : &cur_node->right);
1232 void
1233 put_entries (node)
1234 reg NODE *node;
1236 reg char *sp;
1238 if (node == NULL)
1239 return;
1241 /* Output subentries that precede this one */
1242 put_entries (node->left);
1244 /* Output this entry */
1246 if (emacs_tags_format)
1248 if (node->rewritten)
1250 fprintf (outf, "%s\177%s\001%d,%d\n",
1251 node->name, node->pat, node->lno, node->cno);
1253 else
1255 fprintf (outf, "%s\177%d,%d\n",
1256 node->pat, node->lno, node->cno);
1259 else if (!cxref_style)
1261 fprintf (outf, "%s\t%s\t",
1262 node->name, node->file);
1264 if (node->is_func)
1265 { /* a function */
1266 putc (searchar, outf);
1267 putc ('^', outf);
1269 for (sp = node->pat; *sp; sp++)
1271 if (*sp == '\\' || *sp == searchar)
1272 putc ('\\', outf);
1273 putc (*sp, outf);
1275 putc (searchar, outf);
1277 else
1278 { /* a typedef; text pattern inadequate */
1279 fprintf (outf, "%d", node->lno);
1281 putc ('\n', outf);
1283 else if (vgrind_style)
1284 fprintf (stdout, "%s %s %d\n",
1285 node->name, node->file, (node->lno + 63) / 64);
1286 else
1287 fprintf (stdout, "%-16s %3d %-16s %s\n",
1288 node->name, node->lno, node->file, node->pat);
1290 /* Output subentries that follow this one */
1291 put_entries (node->right);
1294 /* Length of a number's decimal representation. */
1296 number_len (num)
1297 long num;
1299 int len = 0;
1300 if (!num)
1301 return 1;
1302 for (; num; num /= 10)
1303 ++len;
1304 return len;
1308 * Return total number of characters that put_entries will output for
1309 * the nodes in the subtree of the specified node. Works only if emacs_tags_format
1310 * is set, but called only in that case. This count is irrelevant with
1311 * the new tags.el, but is still supplied for backward compatibility.
1314 total_size_of_entries (node)
1315 reg NODE *node;
1317 reg int total;
1319 if (node == NULL)
1320 return 0;
1322 total = 0;
1323 for (; node; node = node->right)
1325 /* Count left subentries. */
1326 total += total_size_of_entries (node->left);
1328 /* Count this entry */
1329 total += strlen (node->pat) + 1;
1330 total += number_len ((long) node->lno) + 1 + number_len (node->cno) + 1;
1331 if (node->rewritten)
1332 total += 1 + strlen (node->name); /* \001name */
1335 return total;
1339 * The C symbol tables.
1342 Stab *C_stab, *C_PLPL_stab, *C_STAR_stab;
1345 * SYNOPSIS
1346 * Stab *get_C_stab (int c_ext);
1348 #define get_C_stab(c_ext) ((c_ext&C_STAR) ? C_STAR_stab : \
1349 c_ext ? C_PLPL_stab : \
1350 C_stab)
1352 void
1353 add_keyword (stab, sym, type)
1354 Stab *stab;
1355 char *sym;
1356 enum sym_type type;
1358 stab_search (stab, sym, strlen (sym))->type = type;
1361 Stab *
1362 C_create_stab (c_ext)
1363 int c_ext;
1365 Stab *stab;
1367 stab = stab_create ();
1369 /* C, C++ and C* */
1370 if (c_ext & C_PLPL)
1371 add_keyword (stab, "class", st_C_struct);
1372 if (c_ext & C_STAR)
1373 add_keyword (stab, "domain", st_C_struct);
1374 add_keyword (stab, "union", st_C_struct);
1375 add_keyword (stab, "struct", st_C_struct);
1376 add_keyword (stab, "enum", st_C_enum);
1377 add_keyword (stab, "typedef", st_C_typedef);
1378 add_keyword (stab, "define", st_C_define);
1379 add_keyword (stab, "long", st_C_typespec);
1380 add_keyword (stab, "short", st_C_typespec);
1381 add_keyword (stab, "int", st_C_typespec);
1382 add_keyword (stab, "char", st_C_typespec);
1383 add_keyword (stab, "float", st_C_typespec);
1384 add_keyword (stab, "double", st_C_typespec);
1385 add_keyword (stab, "signed", st_C_typespec);
1386 add_keyword (stab, "unsigned", st_C_typespec);
1387 add_keyword (stab, "const", st_C_typespec);
1388 add_keyword (stab, "volatile", st_C_typespec);
1390 return stab;
1393 void
1394 C_create_stabs ()
1396 C_stab = C_create_stab (0);
1397 C_PLPL_stab = C_create_stab (C_PLPL);
1398 C_STAR_stab = C_create_stab (C_STAR | C_PLPL);
1402 * C_entries ()
1403 * This routine finds functions and typedefs in C syntax and adds them
1404 * to the list.
1407 #define CNL_SAVE_DEFINEDEF \
1409 prev_linepos = linepos; \
1410 SET_FILEPOS (linepos, inf, charno); \
1411 lineno++; \
1412 charno += readline (&lb, inf); \
1413 lp = lb.buffer; \
1416 #define CNL \
1418 CNL_SAVE_DEFINEDEF; \
1419 definedef = dnone; \
1422 void
1423 C_entries (c_ext)
1424 int c_ext; /* extension of C? */
1426 register int c; /* latest char read; '\0' for end of line */
1427 register int tokoff; /* offset in line of beginning of latest token */
1428 register int toklen; /* length of latest token */
1429 register char *lp; /* pointer one beyond the character `c' */
1430 logical incomm, inquote, inchar, midtoken;
1431 int level; /* current curly brace level */
1432 char tokb[BUFSIZ];
1434 lineno = 0;
1435 charno = 0;
1436 lp = lb.buffer;
1437 *lp = 0;
1439 definedef = dnone;
1440 gotone = midtoken = inquote = inchar = incomm = FALSE;
1441 level = 0;
1442 tydef = none;
1443 next_token_is_func = 0;
1445 C_create_stabs ();
1447 while (!feof (inf))
1449 c = *lp++;
1450 if (c == '\\')
1452 /* If we're at the end of the line, the next character is a
1453 '\0'; don't skip it, because it's the thing that tells us
1454 to read the next line. */
1455 if (*lp == 0)
1456 continue;
1457 lp++;
1458 c = ' ';
1460 else if (incomm)
1462 if (c == '*' && *lp == '/')
1464 c = *lp++;
1465 incomm = FALSE;
1468 else if (inquote)
1470 if (c == '"')
1471 inquote = FALSE;
1472 else if (c == '\\')
1473 c = *lp++;
1475 else if (inchar)
1477 if (c == '\'')
1478 inchar = FALSE;
1479 continue;
1481 else
1482 switch (c)
1484 case '"':
1485 inquote = TRUE;
1486 continue;
1487 case '\'':
1488 inchar = TRUE;
1489 continue;
1490 case '/':
1491 if (*lp == '*')
1493 lp++;
1494 incomm = TRUE;
1496 else if (c_ext && *lp == '/')
1498 c = 0;
1499 break;
1501 continue;
1502 case '#':
1503 if (lp == lb.buffer + 1 && definedef == dnone)
1504 definedef = dsharpseen;
1505 continue;
1508 * The next two are to help the strucdef state machine.
1509 * They break when they are finished, so they don't interfere
1510 * with anything else that is going on.
1512 case ':':
1513 if (structdef == stagseen)
1514 structdef = scolonseen;
1515 break;
1516 /* Not a struct definition when semicolon seen in non-sinbody context. */
1517 case ';':
1518 if (structdef != snone && structdef != sinbody)
1520 structdef = snone;
1521 (void) strcpy (structtag, "<error 1>");
1523 break;
1525 case '{':
1526 if (tydef == begin)
1528 tydef = middle;
1530 switch (structdef)
1532 case skeyseen: /* unnamed struct */
1533 structtag[0] = '\0';
1534 /* FALLTHRU */
1535 case stagseen:
1536 case scolonseen: /* named struct */
1537 structdef = sinbody;
1538 break;
1540 level++;
1541 continue;
1542 case '}':
1543 if (!noindentypedefs && lp == lb.buffer + 1)
1544 level = 0; /* reset level if first column */
1545 else if (level > 0)
1546 level--;
1547 if (level == 0 && tydef == middle)
1549 tydef = end;
1551 if (level == 0)
1553 structdef = snone;
1554 (void) strcpy (structtag, "<error 2>");
1556 continue;
1558 if (LEVEL_OK_FOR_FUNCDEF () && !inquote && !incomm && gotone == FALSE)
1560 if (midtoken)
1562 if (endtoken (c))
1564 if (c_ext && c == ':' && *lp == ':' && intoken (*(lp + 1)))
1567 * This handles :: in the middle, but not at beginning
1568 * of an identifier.
1570 lp += 2;
1571 toklen += 3;
1573 else
1575 /* The following is no longer true,
1576 now that we advance to the next line
1577 at the end of processing the character. */
1579 * We've just finished lexing an identifier.
1580 * Note that if `c' is '\0', `lb' is the NEXT
1581 * line, `lp' points to the beginning of it, and
1582 * old pointers into `lb.buffer' may no longer be
1583 * valid, since `lb.buffer' may have been
1584 * reallocated. In this case (which corresponds
1585 * to an identifier followed immediately by a
1586 * newline), we re-read the line into lb1.
1588 * This would be faster if the previous line's
1589 * buffer were always saved.
1591 logical is_func;
1592 char *tok_linebuf;
1593 TOKEN tok;
1594 logical bingo, tok_at_end_of_line;
1595 char *lp_tmp; /* addressable */
1597 #if 0
1598 if (c == '\0')
1600 getline (GET_COOKIE (prev_linepos));
1601 tok_linebuf = lb1.buffer;
1602 tok_at_end_of_line = TRUE;
1603 tok.linestart = prev_linepos;
1604 tok.lineno = lineno - 1;
1606 else
1607 #endif
1609 tok_linebuf = lb.buffer;
1610 tok_at_end_of_line = FALSE;
1611 tok.linestart = linepos;
1612 tok.lineno = lineno;
1614 tok.p = tok_linebuf + tokoff;
1615 tok.len = toklen;
1616 tok.rewritten = FALSE;
1617 lp_tmp = lp;
1618 bingo = consider_token (c, &lp_tmp, &tok,
1619 &is_func, c_ext, level);
1620 lp = lp_tmp;
1621 if (bingo)
1623 if (GET_CHARNO (tok.linestart) != GET_CHARNO (linepos)
1624 && !tok_at_end_of_line)
1627 * Resynchronize tok.p to point into the right
1628 * linebuffer.
1630 getline (GET_COOKIE (tok.linestart));
1631 if (!tok.rewritten)
1632 tok.p = lb1.buffer + (tok.p - tok_linebuf);
1633 tok_linebuf = lb1.buffer;
1635 if (structdef == sinbody && definedef == dnone && is_func)
1636 { /* function defined in C++ class body */
1637 sprintf (tokb, "%s::%.*s",
1638 structtag[0] == '\0' ? "_anonymous_"
1639 : structtag,
1640 tok.len, tok.p);
1641 tok.rewritten = TRUE;
1643 else
1645 sprintf (tokb, "%.*s", tok.len, tok.p);
1647 pfnote (tokb, is_func, tok.rewritten, tok_linebuf,
1648 tokoff + toklen + (tok_at_end_of_line ? 0 : 1),
1649 tok.lineno, GET_CHARNO (tok.linestart));
1650 gotone = is_func; /* function */
1652 midtoken = FALSE;
1655 else if (intoken (c))
1656 toklen++;
1658 else if (begtoken (c))
1660 tokoff = lp - 1 - lb.buffer;
1661 toklen = 1;
1662 midtoken = TRUE;
1665 /* Detect end of line, after having handled the last token on the line. */
1666 if (c == 0)
1668 CNL;
1669 gotone = FALSE;
1671 if (c == ';' && tydef == end) /* clean with typedefs */
1672 tydef = none;
1677 * consider_token ()
1678 * checks to see if the current token is at the start of a
1679 * function, or corresponds to a typedef. It updates the input
1680 * line pointer *LPP so that the '(' will be in it when it returns.
1682 * *IS_FUNC gets TRUE iff the token is a function.
1683 * C_EXT is which language we are looking at.
1685 * In the future we will need some way to adjust where the end of
1686 * the token is; for instance, implementing the C++ keyword
1687 * `operator' properly will adjust the end of the token to be after
1688 * whatever follows `operator'.
1690 * Globals
1691 * structdef IN OUT
1692 * definedef IN OUT
1693 * tydef IN OUT
1696 logical
1697 consider_token (c, lpp, tokp, is_func, c_ext, level)
1698 reg char c; /* IN: first char after the token */
1699 char **lpp; /* IN OUT: *lpp points to 2nd char after the token */
1700 reg TOKEN *tokp; /* IN */
1701 logical *is_func; /* OUT */
1702 int c_ext; /* IN */
1703 int level; /* IN */
1705 reg char *lp = *lpp;
1706 logical firsttok; /* TRUE if have seen first token in ()'s */
1707 Stab_entry *tokse = stab_find (get_C_stab (c_ext), tokp->p, tokp->len);
1708 enum sym_type toktype = stab_type (tokse);
1710 *is_func = TRUE; /* a function */
1713 * Advance the definedef state machine. We set `gotone' for good measure;
1714 * it's redundant.
1716 switch (definedef)
1718 case dnone:
1719 /* We're not on a preprocessor line. */
1720 break;
1721 case dsharpseen:
1722 if (toktype == st_C_define)
1724 definedef = ddefineseen;
1725 gotone = FALSE;
1727 else
1729 definedef = dignorerest;
1730 gotone = TRUE;
1732 goto badone;
1733 case ddefineseen:
1735 * Make a tag for any macro.
1736 * This will flub up if there is a newline immediately following
1737 * the macro name.
1739 *is_func = (c == '(');
1740 definedef = dignorerest;
1741 gotone = TRUE;
1742 if (!*is_func && !constantypedefs)
1743 goto badone;
1744 goto goodone;
1745 case dignorerest:
1746 goto badone;
1747 default:
1748 error ("internal error: definedef value");
1752 * Skip whitespace and comments after the token. This loop should
1753 * also skip C++ comments.
1755 while (1)
1757 /* At whitespace => skip it. */
1758 if (iswhite (c))
1760 c = *lp++;
1762 /* At a comment => skip to end of comment. */
1763 else if (c == '/' && *lp == '*')
1765 /* If we find a comment, skip it. */
1766 while (!(c == '*' && *lp == '/'))
1768 c = *lp++;
1769 if (c == 0)
1771 lp--;
1772 break;
1775 if (c == '*' && *lp == '/')
1777 lp++; /* lp now points past the '/' */
1778 c = *lp++; /* c is now the --whatever-- after the '/' */
1781 else
1782 break;
1784 /* If we arrived at eof or eol, decide which one it is.
1785 If it's eol, advance to the next line. */
1787 if (c == 0)
1789 lp--;
1790 break;
1795 * If you have custom token types, or when configuration files can
1796 * define custom token types, this switch will be larger.
1798 switch (toktype)
1800 case st_C_typedef:
1801 if (typedefs)
1803 tydef = begin;
1804 goto badone;
1806 break;
1807 case st_C_typespec:
1808 if (tydef == begin || tydef == end)
1810 tydef = end;
1811 goto badone;
1813 break;
1817 * This structdef business is currently only invoked when level==0.
1818 * It should be recursively invoked whatever the level, and a stack of
1819 * states kept, to allow for definitions of structs within structs.
1821 * This structdef business is NOT invoked when we are ctags and the
1822 * file is plain C. This is because a struct tag may have the same
1823 * name as another tag, and this loses with ctags.
1825 * This if statement deals with the tydef state machine as follows: if
1826 * tydef==begin and token is struct/union/class/enum, goto badone.
1827 * All the other code here is for the structdef state machine.
1829 switch (toktype)
1831 case st_C_struct:
1832 case st_C_enum:
1833 if (tydef == begin || (typedefs_and_cplusplus && level == 0 && structdef == snone))
1835 structdef = skeyseen;
1836 structkey = tokse;
1838 goto badone;
1841 if (structdef == skeyseen)
1843 /* If next char is '{' or (for C++) ':', found a structure tag. */
1844 if (c == '{' || (c_ext && c == ':'))
1847 * We should do this slightly differently for straight C:
1848 * instead of defining `tag', as we now do, we should define
1849 * `struct tag'. (Do this only if the find-tag defaulting is
1850 * done on a sophisticated per-mode basis, so that if the user
1851 * says meta-. anywhere in `struct foo', the default comes out
1852 * `struct foo', not `struct' or `foo'.) This will require
1853 * remembering which keyword (struct/union/class/enum) we saw, as a
1854 * Stab_entry* -- this will also make it possible to merge the
1855 * skeyseen and senumseen states, if we want.
1857 if (stab_type (structkey) == st_C_struct)
1859 (void) strncpy (structtag, tokp->p, tokp->len);
1860 structtag[tokp->len] = '\0'; /* for struct/union/class */
1861 structdef = stagseen;
1863 else
1865 structtag[0] = '\0'; /* for enum */
1867 *is_func = FALSE; /* not a function */
1868 goto goodone;
1870 else
1872 /* Not a definition: reset structdef */
1873 structdef = snone;
1874 (void) strcpy (structtag, "<error 3>");
1876 /* Now what? And how does/should this stuff interact with tydef?? */
1877 /* Also maybe reset lp to *lpp for benefit of the function finding code. */
1879 if (tydef == begin)
1881 tydef = end;
1882 goto badone;
1884 if (tydef == end)
1886 *is_func = 0;
1887 goto goodone;
1889 /* Detect GNUmacs's function-defining macros. */
1890 if (definedef == dnone)
1892 if (strneq (tokp->p, "DEF", 3)
1893 || strneq (tokp->p, "ENTRY", 5)
1894 || strneq (tokp->p, "SYSCALL", 7)
1895 || strneq (tokp->p, "PSEUDO", 6))
1897 next_token_is_func = TRUE;
1898 goto badone;
1900 else if (strneq (tokp->p, "EXFUN", 5))
1902 next_token_is_func = FALSE;
1903 goto badone;
1906 if (next_token_is_func)
1908 next_token_is_func = FALSE;
1909 goto goodone;
1911 if (c != '(')
1912 goto badone;
1913 firsttok = FALSE;
1914 while ((c = *lp++) != ')')
1916 if (c == 0)
1918 lp--;
1919 break;
1922 * This line used to confuse ctags:
1923 * int (*oldhup)();
1924 * This fixes it. A nonwhite char before the first
1925 * token, other than a / (in case of a comment in there)
1926 * makes this not a declaration.
1928 if (begtoken (c) || c == '/')
1929 firsttok++;
1930 else if (!iswhite (c) && !firsttok)
1931 goto badone;
1933 while (iswhite (c = *lp++))
1935 if (c == 0)
1937 lp--;
1938 break;
1941 if (!isgood (c))
1942 goto badone;
1944 goodone:
1945 *lpp = lp - 1;
1946 return TRUE;
1948 badone:
1949 *lpp = lp - 1;
1950 return FALSE;
1953 void
1954 getline (atcookie)
1955 long atcookie;
1957 long saveftell = ftell (inf);
1959 (void) fseek (inf, atcookie, 0);
1960 (void) readline (&lb1, inf);
1961 (void) fseek (inf, saveftell, 0);
1964 /* Fortran parsing */
1966 char *dbp;
1967 int pfcnt;
1970 PF_funcs (fi)
1971 FILE *fi;
1973 lineno = 0;
1974 charno = 0;
1975 pfcnt = 0;
1977 while (!feof (fi))
1979 lineno++;
1980 linecharno = charno;
1981 charno += readline (&lb, fi);
1982 dbp = lb.buffer;
1983 if (*dbp == '%')
1984 dbp++; /* Ratfor escape to fortran */
1985 while (isspace (*dbp))
1986 dbp++;
1987 if (*dbp == 0)
1988 continue;
1989 switch (*dbp | ' ')
1991 case 'i':
1992 if (tail ("integer"))
1993 takeprec ();
1994 break;
1995 case 'r':
1996 if (tail ("real"))
1997 takeprec ();
1998 break;
1999 case 'l':
2000 if (tail ("logical"))
2001 takeprec ();
2002 break;
2003 case 'c':
2004 if (tail ("complex") || tail ("character"))
2005 takeprec ();
2006 break;
2007 case 'd':
2008 if (tail ("double"))
2010 while (isspace (*dbp))
2011 dbp++;
2012 if (*dbp == 0)
2013 continue;
2014 if (tail ("precision"))
2015 break;
2016 continue;
2018 break;
2020 while (isspace (*dbp))
2021 dbp++;
2022 if (*dbp == 0)
2023 continue;
2024 switch (*dbp | ' ')
2026 case 'f':
2027 if (tail ("function"))
2028 getit ();
2029 continue;
2030 case 's':
2031 if (tail ("subroutine"))
2032 getit ();
2033 continue;
2034 case 'p':
2035 if (tail ("program"))
2037 getit ();
2038 continue;
2040 if (tail ("procedure"))
2041 getit ();
2042 continue;
2045 return (pfcnt);
2048 logical
2049 tail (cp)
2050 char *cp;
2052 register int len = 0;
2054 while (*cp && (*cp & ~' ') == ((*(dbp + len)) & ~' '))
2055 cp++, len++;
2056 if (*cp == 0)
2058 dbp += len;
2059 return (1);
2061 return (0);
2064 void
2065 takeprec ()
2067 while (isspace (*dbp))
2068 dbp++;
2069 if (*dbp != '*')
2070 return;
2071 dbp++;
2072 while (isspace (*dbp))
2073 dbp++;
2074 if (!isdigit (*dbp))
2076 --dbp; /* force failure */
2077 return;
2080 dbp++;
2081 while (isdigit (*dbp));
2084 void
2085 getit ()
2087 register char *cp;
2088 char c;
2089 char nambuf[BUFSIZ];
2091 while (isspace (*dbp))
2092 dbp++;
2093 if (*dbp == 0
2094 || (!isalpha (*dbp)
2095 && *dbp != '_'
2096 && *dbp != '$'))
2097 return;
2098 for (cp = dbp + 1; *cp && (isalpha (*cp) || isdigit (*cp)
2099 || (*cp == '_') || (*cp == '$')); cp++)
2100 continue;
2101 c = cp[0];
2102 cp[0] = 0;
2103 (void) strcpy (nambuf, dbp);
2104 cp[0] = c;
2105 pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
2106 pfcnt++;
2109 /* Handle a file of assembler code. */
2111 void
2112 Asm_funcs (fi)
2113 FILE *fi;
2115 int i;
2116 register char c;
2118 lineno = 0;
2119 charno = 0;
2120 pfcnt = 0;
2122 while (!feof (fi))
2124 lineno++;
2125 linecharno = charno;
2126 charno += readline (&lb, fi);
2127 dbp = lb.buffer;
2129 for (i = 0; ((c = dbp[i]) && !isspace (c)) && (c != ':'); i++)
2132 if ((i > 0) && (c == ':'))
2133 getit ();
2137 /* Added by Mosur Mohan, 4/22/88 */
2138 /* Pascal parsing */
2140 #define GET_NEW_LINE \
2142 linecharno = charno; lineno++; \
2143 charno += 1 + readline (&lb, inf); \
2144 dbp = lb.buffer; \
2147 /* Locates tags for procedures & functions.
2148 * Doesn't do any type- or var-definitions.
2149 * It does look for the keyword "extern" or "forward"
2150 * immediately following the procedure statement;
2151 * if found, the tag is skipped.
2154 void
2155 PAS_funcs (fi)
2156 FILE *fi;
2158 struct linebuffer tline; /* mostly copied from C_entries */
2159 long save_lcno;
2160 int save_lineno;
2161 char c, *cp;
2162 char nambuf[BUFSIZ];
2164 logical /* each of these flags is TRUE iff: */
2165 incomm1, /* point is inside {..} comment */
2166 incomm2, /* point is inside (*..*) comment */
2167 inquote, /* point is inside '..' string */
2168 get_tagname, /* point is after PROCEDURE/FUNCTION */
2169 /* keyword, so next item = potential tag */
2170 found_tag, /* point is after a potential tag */
2171 inparms, /* point is within parameter-list */
2172 verify_tag; /* point has passed the parm-list, so the */
2173 /* next token will determine whether */
2174 /* this is a FORWARD/EXTERN to be */
2175 /* ignored, or whether it is a real tag */
2177 lineno = 0;
2178 charno = 0;
2179 dbp = lb.buffer;
2180 *dbp = 0;
2181 initbuffer (&tline);
2183 incomm1 = incomm2 = inquote = FALSE;
2184 found_tag = FALSE; /* have a proc name; check if extern */
2185 get_tagname = FALSE; /* have found "procedure" keyword */
2186 inparms = FALSE; /* found '(' after "proc" */
2187 verify_tag = FALSE; /* check if "extern" is ahead */
2189 /* long main loop to get next char */
2190 while (!feof (fi))
2192 c = *dbp++;
2193 if (c == 0) /* if end of line */
2195 GET_NEW_LINE;
2196 if (*dbp == 0)
2197 continue;
2198 if (!((found_tag && verify_tag) ||
2199 get_tagname))
2200 c = *dbp++; /* only if don't need *dbp pointing */
2201 /* to the beginning of the name of */
2202 /* the procedure or function */
2204 if (incomm1) /* within { - } comments */
2206 if (c == '}')
2207 incomm1 = FALSE;
2208 continue;
2210 else if (incomm2) /* within (* - *) comments */
2212 if (c == '*')
2214 while ((c = *dbp++) == '*')
2215 continue;
2216 if (c == 0)
2217 GET_NEW_LINE;
2218 if (c == ')')
2219 incomm2 = FALSE;
2221 continue;
2223 else if (inquote)
2225 if (c == '\'')
2226 inquote = FALSE;
2227 continue;
2229 else
2230 switch (c)
2232 case '\'':
2233 inquote = TRUE; /* found first quote */
2234 continue;
2235 case '{': /* found open-{-comment */
2236 incomm1 = TRUE;
2237 continue;
2238 case '(':
2239 if (*dbp == '*') /* found open-(*-comment */
2241 incomm2 = TRUE;
2242 dbp++;
2244 else if (found_tag) /* found '(' after tag, i.e., parm-list */
2245 inparms = TRUE;
2246 continue;
2247 case ')': /* end of parms list */
2248 if (inparms)
2249 inparms = FALSE;
2250 continue;
2251 case ';':
2252 if ((found_tag) && (!inparms)) /* end of proc or fn stmt */
2254 verify_tag = TRUE;
2255 break;
2257 continue;
2259 if ((found_tag) && (verify_tag) && (*dbp != ' '))
2261 /* check if this is an "extern" declaration */
2262 if (*dbp == 0)
2263 continue;
2264 if ((*dbp == 'e') || (*dbp == 'E'))
2266 if (tail ("extern")) /* superfluous, really! */
2268 found_tag = FALSE;
2269 verify_tag = FALSE;
2272 else if ((*dbp == 'f') || (*dbp == 'F'))
2274 if (tail ("forward")) /* check for forward reference */
2276 found_tag = FALSE;
2277 verify_tag = FALSE;
2280 if ((found_tag) && (verify_tag)) /* not external proc, so make tag */
2282 found_tag = FALSE;
2283 verify_tag = FALSE;
2284 pfnote (nambuf, TRUE, FALSE,
2285 tline.buffer, cp - tline.buffer + 1,
2286 save_lineno, save_lcno);
2287 continue;
2290 if (get_tagname) /* grab name of proc or fn */
2292 if (*dbp == 0)
2293 continue;
2295 /* save all values for later tagging */
2296 tline.size = lb.size;
2297 strcpy (tline.buffer, lb.buffer);
2298 save_lineno = lineno;
2299 save_lcno = linecharno;
2301 /* grab block name */
2302 for (cp = dbp + 1; *cp && (!endtoken (*cp)); cp++)
2303 continue;
2304 c = cp[0];
2305 cp[0] = 0;
2306 strcpy (nambuf, dbp);
2307 cp[0] = c;
2308 dbp = cp; /* restore dbp to e-o-token */
2309 get_tagname = FALSE;
2310 found_tag = TRUE;
2311 continue;
2313 /* and proceed to check for "extern" */
2315 if ((!incomm1) && (!incomm2) && (!inquote) &&
2316 (!found_tag) && (!get_tagname))
2318 /* check for proc/fn keywords */
2319 switch (c | ' ')
2321 case 'p':
2322 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2323 get_tagname = TRUE;
2324 continue;
2325 case 'f':
2326 if (tail ("unction"))
2327 get_tagname = TRUE;
2328 continue;
2331 } /* while not e-o-f */
2335 * lisp tag functions
2336 * just look for (def or (DEF
2339 void
2340 L_funcs (fi)
2341 FILE *fi;
2343 lineno = 0;
2344 charno = 0;
2345 pfcnt = 0;
2347 while (!feof (fi))
2349 lineno++;
2350 linecharno = charno;
2351 charno += readline (&lb, fi);
2352 dbp = lb.buffer;
2353 if (dbp[0] == '(')
2355 if (L_isdef (dbp))
2357 while (!isspace (*dbp))
2358 dbp++;
2359 while (isspace (*dbp))
2360 dbp++;
2361 L_getit ();
2363 else
2365 /* Check for (foo::defmumble name-defined ... */
2366 while (*dbp && *dbp != ':' && !isspace (*dbp)
2367 && *dbp != '(' && *dbp != ')')
2368 dbp++;
2369 if (*dbp == ':')
2371 while (*dbp == ':')
2372 dbp++;
2374 if (L_isdef (dbp))
2376 while (!isspace (*dbp))
2377 dbp++;
2378 while (isspace (*dbp))
2379 dbp++;
2380 L_getit ();
2389 L_isdef (dbp)
2390 char *dbp;
2392 return ((dbp[1] == 'D' || dbp[1] == 'd') &&
2393 (dbp[2] == 'E' || dbp[2] == 'e') &&
2394 (dbp[3] == 'F' || dbp[3] == 'f'));
2397 void
2398 L_getit ()
2400 register char *cp;
2401 char c;
2402 char nambuf[BUFSIZ];
2404 if (*dbp == 0)
2405 return;
2406 for (cp = dbp + 1; *cp && *cp != '(' && *cp != ' '; cp++)
2407 continue;
2408 c = cp[0];
2409 cp[0] = 0;
2410 (void) strcpy (nambuf, dbp);
2411 cp[0] = c;
2412 pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
2413 pfcnt++;
2417 * Scheme tag functions
2418 * look for (def... xyzzy
2419 * look for (def... (xyzzy
2420 * look for (def ... ((...(xyzzy ....
2421 * look for (set! xyzzy
2424 static void get_scheme ();
2426 void
2427 Scheme_funcs (fi)
2428 FILE *fi;
2430 lineno = 0;
2431 charno = 0;
2432 pfcnt = 0;
2434 while (!feof (fi))
2436 lineno++;
2437 linecharno = charno;
2438 charno += readline (&lb, fi);
2439 dbp = lb.buffer;
2440 if (dbp[0] == '(' &&
2441 (dbp[1] == 'D' || dbp[1] == 'd') &&
2442 (dbp[2] == 'E' || dbp[2] == 'e') &&
2443 (dbp[3] == 'F' || dbp[3] == 'f'))
2445 while (!isspace (*dbp))
2446 dbp++;
2447 /* Skip over open parens and white space */
2448 while (*dbp && (isspace (*dbp) || *dbp == '('))
2449 dbp++;
2450 get_scheme ();
2452 if (dbp[0] == '(' &&
2453 (dbp[1] == 'S' || dbp[1] == 's') &&
2454 (dbp[2] == 'E' || dbp[2] == 'e') &&
2455 (dbp[3] == 'T' || dbp[3] == 't') &&
2456 (dbp[4] == '!' || dbp[4] == '!') &&
2457 (isspace (dbp[5])))
2459 while (!isspace (*dbp))
2460 dbp++;
2461 /* Skip over white space */
2462 while (isspace (*dbp))
2463 dbp++;
2464 get_scheme ();
2469 static void
2470 get_scheme ()
2472 register char *cp;
2473 char c;
2474 char nambuf[BUFSIZ];
2476 if (*dbp == 0)
2477 return;
2478 /* Go till you get to white space or a syntactic break */
2479 for (cp = dbp + 1; *cp && *cp != '(' && *cp != ')' && !isspace (*cp); cp++)
2480 continue;
2481 /* Null terminate the string there. */
2482 c = cp[0];
2483 cp[0] = 0;
2484 /* Copy the string */
2485 strcpy (nambuf, dbp);
2486 /* Unterminate the string */
2487 cp[0] = c;
2488 /* Announce the change */
2489 pfnote (nambuf, TRUE, FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
2490 pfcnt++;
2493 /* Find tags in TeX and LaTeX input files. */
2495 /* TEX_toktab is a table of TeX control sequences that define tags.
2496 Each TEX_tabent records one such control sequence.
2497 CONVERT THIS TO USE THE Stab TYPE!! */
2499 struct TEX_tabent
2501 char *name;
2502 int len;
2505 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
2507 /* Default set of control sequences to put into TEX_toktab.
2508 The value of environment var TEXTAGS is prepended to this. */
2510 static char *TEX_defenv =
2511 ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
2513 void TEX_mode ();
2514 struct TEX_tabent *TEX_decode_env ();
2515 void TEX_getit ();
2516 int TEX_Token ();
2518 static char TEX_esc = '\\';
2519 static char TEX_opgrp = '{';
2520 static char TEX_clgrp = '}';
2523 * TeX/LaTeX scanning loop.
2526 void
2527 TEX_funcs (fi)
2528 FILE *fi;
2530 char *lasthit;
2532 lineno = 0;
2533 charno = 0;
2534 pfcnt = 0;
2536 /* Select either \ or ! as escape character. */
2537 TEX_mode (fi);
2539 /* Initialize token table once from environment. */
2540 if (!TEX_toktab)
2541 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
2543 while (!feof (fi))
2545 lineno++;
2546 linecharno = charno;
2547 charno += readline (&lb, fi);
2548 dbp = lb.buffer;
2549 lasthit = dbp;
2551 while (!feof (fi))
2552 { /* Scan each line in file */
2553 lineno++;
2554 linecharno = charno;
2555 charno += readline (&lb, fi);
2556 dbp = lb.buffer;
2557 lasthit = dbp;
2558 while (dbp = index (dbp, TEX_esc)) /* Look at each escape in line */
2560 register int i;
2562 if (!*(++dbp))
2563 break;
2564 linecharno += dbp - lasthit;
2565 lasthit = dbp;
2566 i = TEX_Token (lasthit);
2567 if (0 <= i)
2569 TEX_getit (lasthit, TEX_toktab[i].len);
2570 break; /* We only save a line once */
2577 #define TEX_LESC '\\'
2578 #define TEX_SESC '!'
2579 #define TEX_cmt '%'
2581 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
2582 /* chars accordingly. */
2584 void
2585 TEX_mode (f)
2586 FILE *f;
2588 int c;
2590 while ((c = getc (f)) != EOF)
2592 /* Skip to next line if we hit the TeX comment char. */
2593 if (c == TEX_cmt)
2594 while (c != '\n')
2595 c = getc (f);
2596 else if (c == TEX_LESC || c == TEX_SESC )
2597 break;
2600 if (c == TEX_LESC)
2602 TEX_esc = TEX_LESC;
2603 TEX_opgrp = '{';
2604 TEX_clgrp = '}';
2606 else
2608 TEX_esc = TEX_SESC;
2609 TEX_opgrp = '<';
2610 TEX_clgrp = '>';
2612 rewind (f);
2615 /* Read environment and prepend it to the default string. */
2616 /* Build token table. */
2618 struct TEX_tabent *
2619 TEX_decode_env (evarname, defenv)
2620 char *evarname;
2621 char *defenv;
2623 register char *env, *p;
2624 extern char *savenstr (), *index ();
2626 struct TEX_tabent *tab;
2627 int size, i;
2629 /* Append default string to environment. */
2630 env = getenv (evarname);
2631 if (!env)
2632 env = defenv;
2633 else
2634 env = concat (env, defenv, "");
2636 /* Allocate a token table */
2637 for (size = 1, p = env; p;)
2638 if ((p = index (p, ':')) && *(++p))
2639 size++;
2640 tab = xnew (size, struct TEX_tabent);
2642 /* Unpack environment string into token table. Be careful about */
2643 /* zero-length strings (leading ':', "::" and trailing ':') */
2644 for (i = 0; *env;)
2646 p = index (env, ':');
2647 if (!p) /* End of environment string. */
2648 p = env + strlen (env);
2649 if (p - env > 0)
2650 { /* Only non-zero strings. */
2651 tab[i].name = savenstr (env, p - env);
2652 tab[i].len = strlen (tab[i].name);
2653 i++;
2655 if (*p)
2656 env = p + 1;
2657 else
2659 tab[i].name = NULL; /* Mark end of table. */
2660 tab[i].len = 0;
2661 break;
2664 return tab;
2667 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
2668 The name being defined actually starts at (NAME + LEN + 1).
2669 But we seem to include the TeX command in the tag name. */
2671 void
2672 TEX_getit (name, len)
2673 char *name;
2674 int len;
2676 char *p = name + len;
2677 char nambuf[BUFSIZ];
2679 if (*name == 0)
2680 return;
2682 /* Let tag name extend to next group close (or end of line) */
2683 while (*p && *p != TEX_clgrp)
2684 p++;
2685 (void) strncpy (nambuf, name, p - name);
2686 nambuf[p - name] = 0;
2688 pfnote (nambuf, TRUE, FALSE, lb.buffer, strlen (lb.buffer), lineno, linecharno);
2689 pfcnt++;
2692 /* If the text at CP matches one of the tag-defining TeX command names,
2693 return the index of that command in TEX_toktab.
2694 Otherwise return -1. */
2696 /* Keep the capital `T' in `Token' for dumb truncating compilers
2697 (this distinguishes it from `TEX_toktab' */
2699 TEX_Token (cp)
2700 char *cp;
2702 int i;
2704 for (i = 0; TEX_toktab[i].len > 0; i++)
2705 if (strncmp (TEX_toktab[i].name, cp, TEX_toktab[i].len) == 0)
2706 return i;
2707 return -1;
2710 /* Support for Prolog. */
2712 /* whole head (not only functor, but also arguments)
2713 is gotten in compound term. */
2715 void
2716 prolog_getit (s, lineno, linecharno)
2717 char *s;
2718 int lineno;
2719 long linecharno;
2721 char nambuf[BUFSIZ], *save_s, tmpc;
2722 int insquote, npar;
2724 save_s = s;
2725 insquote = FALSE;
2726 npar = 0;
2727 while (1)
2729 if (*s == '\0') /* syntax error. */
2730 return;
2731 else if (insquote && *s == '\'' && *(s + 1) == '\'')
2732 s += 2;
2733 else if (*s == '\'')
2735 insquote = !insquote;
2736 s++;
2738 else if (!insquote && *s == '(')
2740 npar++;
2741 s++;
2743 else if (!insquote && *s == ')')
2745 npar--;
2746 s++;
2747 if (npar == 0)
2748 break;
2749 else if (npar < 0) /* syntax error. */
2750 return;
2752 else if (!insquote && *s == '.' && (isspace (*(s + 1)) || *(s + 1) == '\0'))
2753 { /* fullstop. */
2754 if (npar != 0) /* syntax error. */
2755 return;
2756 s++;
2757 break;
2759 else
2760 s++;
2762 tmpc = *s;
2763 *s = '\0';
2764 strcpy (nambuf, save_s);
2765 *s = tmpc;
2766 pfnote (nambuf, TRUE, save_s, strlen (nambuf), lineno, linecharno);
2769 /* It is assumed that prolog predicate starts from column 0. */
2771 void
2772 prolog_funcs (fi)
2773 FILE *fi;
2775 void skip_comment (), prolog_getit ();
2777 lineno = linecharno = charno = 0;
2778 while (!feof (fi))
2780 lineno++;
2781 linecharno += charno;
2782 charno = readline (&lb, fi) + 1; /* 1 for newline. */
2783 dbp = lb.buffer;
2784 if (isspace (dbp[0])) /* not predicate header. */
2785 continue;
2786 else if (dbp[0] == '%') /* comment. */
2787 continue;
2788 else if (dbp[0] == '/' && dbp[1] == '*') /* comment. */
2789 skip_comment (&lb, fi, &lineno, &linecharno);
2790 else /* found. */
2791 prolog_getit (dbp, lineno, linecharno);
2795 void
2796 skip_comment (plb, fi, plineno, plinecharno)
2797 struct linebuffer *plb;
2798 FILE *fi;
2799 int *plineno; /* result */
2800 long *plinecharno; /* result */
2802 while (!substr ("*/", plb->buffer))
2804 (*plineno)++;
2805 *plinecharno += readline (plb, fi) + 1;
2806 } /* 1 for newline. */
2809 /* Return TRUE if 'sub' exists somewhere in 's'. */
2812 substr (sub, s)
2813 char *sub;
2814 char *s;
2816 while (*s && (s = index (s, *sub)))
2817 if (prestr (sub, s))
2818 return (TRUE);
2819 else
2820 s++;
2821 return (FALSE);
2824 /* Return TRUE if 'pre' is prefix of string 's'. */
2827 prestr (pre, s)
2828 char *pre;
2829 char *s;
2831 if (*pre == '\0')
2832 return (TRUE);
2833 else if (*pre == *s)
2834 return (prestr (pre + 1, s + 1));
2835 else
2836 return (FALSE);
2839 /* Initialize a linebuffer for use */
2841 void
2842 initbuffer (linebuffer)
2843 struct linebuffer *linebuffer;
2845 linebuffer->size = 200;
2846 linebuffer->buffer = xnew (200, char);
2850 * Read a line of text from `stream' into `linebuffer'.
2851 * Return the number of characters read from `stream',
2852 * which is the length of the line including the newline, if any.
2854 long
2855 readline (linebuffer, stream)
2856 struct linebuffer *linebuffer;
2857 register FILE *stream;
2859 char *buffer = linebuffer->buffer;
2860 register char *p = linebuffer->buffer;
2861 register char *pend;
2862 int newline; /* 1 if ended with newline, 0 if ended with EOF */
2864 pend = p + linebuffer->size; /* Separate to avoind 386/IX compiler bug. */
2866 while (1)
2868 register int c = getc (stream);
2869 if (p == pend)
2871 linebuffer->size *= 2;
2872 buffer = (char *) xrealloc (buffer, linebuffer->size);
2873 p += buffer - linebuffer->buffer;
2874 pend = buffer + linebuffer->size;
2875 linebuffer->buffer = buffer;
2877 if (c < 0 || c == '\n')
2879 *p = 0;
2880 newline = (c == '\n' ? 1 : 0);
2881 break;
2883 *p++ = c;
2886 return p - buffer + newline;
2889 char *
2890 savestr (cp)
2891 char *cp;
2893 return savenstr (cp, strlen (cp));
2896 char *
2897 savenstr (cp, len)
2898 char *cp;
2899 int len;
2901 register char *dp;
2903 dp = xnew (len + 1, char);
2904 (void) strncpy (dp, cp, len);
2905 dp[len] = '\0';
2906 return dp;
2909 #ifdef NEED_RINDEX
2911 * Return the ptr in sp at which the character c last
2912 * appears; NULL if not found
2914 * Identical to v7 rindex, included for portability.
2917 char *
2918 rindex (sp, c)
2919 register char *sp, c;
2921 register char *r;
2923 r = NULL;
2926 if (*sp == c)
2927 r = sp;
2928 } while (*sp++);
2929 return (r);
2931 #endif /* not NEED_RINDEX */
2934 #ifdef NEED_INDEX
2936 * Return the ptr in sp at which the character c first
2937 * appears; NULL if not found
2939 * Identical to v7 index, included for portability.
2942 char *
2943 index (sp, c)
2944 register char *sp, c;
2948 if (*sp == c)
2949 return (sp);
2950 } while (*sp++);
2951 return (NULL);
2954 #endif /* not NEED_INDEX */
2956 /* Print error message and exit. */
2958 /* VARARGS1 */
2959 void
2960 fatal (s1, s2)
2961 char *s1, *s2;
2963 error (s1, s2);
2964 exit (1);
2967 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
2969 /* VARARGS1 */
2970 void
2971 error (s1, s2)
2972 char *s1, *s2;
2974 fprintf (stderr, "%s: ", progname);
2975 fprintf (stderr, s1, s2);
2976 fprintf (stderr, "\n");
2979 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
2981 char *
2982 concat (s1, s2, s3)
2983 char *s1, *s2, *s3;
2985 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
2986 char *result = xnew (len1 + len2 + len3 + 1, char);
2988 (void) strcpy (result, s1);
2989 (void) strcpy (result + len1, s2);
2990 (void) strcpy (result + len1 + len2, s3);
2991 *(result + len1 + len2 + len3) = 0;
2993 return result;
2996 /* Like malloc but get fatal error if memory is exhausted. */
2998 char *
2999 xmalloc (size)
3000 int size;
3002 char *result = malloc (size);
3003 if (!result)
3004 fatal ("virtual memory exhausted", 0);
3005 return result;
3008 char *
3009 xrealloc (ptr, size)
3010 char *ptr;
3011 int size;
3013 char *result = realloc (ptr, size);
3014 if (!result)
3015 fatal ("virtual memory exhausted");
3016 return result;