1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984,87,88,89,93,94 Free Software Foundation, Inc. and Ken Arnold
3 This file is not considered part of GNU Emacs.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21 * Ctags originally by Ken Arnold.
22 * Fortran added by Jim Kleckner.
23 * Ed Pelegri-Llopart added C typedefs.
24 * Gnu Emacs TAGS format and modifications by RMS?
25 * Sam Kendall added C++.
26 * Francesco Potorti` reorganised C and C++ based on work by Joe Wells.
28 * Regexp tags by Tom Tromey.
31 * Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer.
34 char pot_etags_version
[] = "@(#) pot revision number is 11.14";
38 #include <sys/param.h>
45 #define MAXPATHLEN _MAX_PATH
50 /* On some systems, Emacs defines static as nothing for the sake
51 of unexec. We don't want that here since we don't use unexec. */
61 #include <sys/types.h>
64 #if !defined (S_ISREG) && defined (S_IFREG)
65 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
72 #endif /* ETAGS_REGEXPS */
74 extern char *getenv ();
76 /* Define CTAGS to make the program "ctags" compatible with the usual one.
77 Let it undefined to make the program "etags", which makes emacs-style
78 tag tables and tags typedefs, #defines and struct/union/enum by default. */
86 /* Exit codes for success and failure. */
96 * The FILEPOS abstract type, which represents a position in a file,
97 * plus the following accessor functions:
99 * long GET_CHARNO (pos)
100 * returns absolute char number.
101 * void SET_FILEPOS (pos, fp, charno)
102 * FILE *fp; long charno;
103 * sets `pos' from the current file
104 * position of `fp' and from `charno',
105 * which must be the absolute character
106 * number corresponding to the current
109 * The `pos' parameter is an lvalue expression of type FILEPOS.
110 * Parameters to the accessor functions are evaluated 0 or more times,
111 * and so must have no side effects.
113 * FILEPOS objects can also be assigned and passed to and from
114 * functions in the normal C manner.
116 * Implementation notes: the `+ 0' is to enforce rvalue-ness.
122 /* real implementation */
123 typedef long FILEPOS
;
124 #define GET_CHARNO(pos) ((pos) + 0)
125 #define SET_FILEPOS(pos,fp,cno) ((void) ((pos) = (cno)))
131 /* debugging implementation */
137 #define GET_CHARNO(pos) ((pos).charno + 0)
138 #define SET_FILEPOS(pos,fp,cno) \
139 ((void) ((pos).charno = (cno), \
140 (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \
144 #define streq(s,t) (strcmp (s, t) == 0)
145 #define strneq(s,t,n) (strncmp (s, t, n) == 0)
150 #define iswhite(arg) (_wht[arg]) /* T if char is white */
151 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
152 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
153 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
155 #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2))
160 { /* sorting structure */
161 char *name
; /* function or type name */
162 char *file
; /* file name */
163 logical is_func
; /* use pattern or line no */
164 logical named
; /* list name separately */
165 logical been_warned
; /* set if noticed dup */
166 int lno
; /* line number tag is on */
167 long cno
; /* character number line starts on */
168 char *pat
; /* search pattern */
169 struct nd_st
*left
, *right
; /* left and right sons */
172 typedef struct nd_st NODE
;
174 /* boolean "functions" (see init) */
175 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
177 char *cwd
; /* current working directory */
178 char *tagfiledir
; /* directory of tagfile */
181 char *savenstr (), *savestr ();
182 char *etags_strchr (), *etags_strrchr ();
183 char *etags_getcwd ();
184 char *relative_filename (), *absolute_filename (), *absolute_dirname ();
185 char *xmalloc (), *xrealloc ();
187 typedef void Lang_function ();
188 #if FALSE /* many compilers barf on this */
189 Lang_function Asm_labels
;
190 Lang_function default_C_entries
;
191 Lang_function C_entries
;
192 Lang_function Cplusplus_entries
;
193 Lang_function Cstar_entries
;
194 Lang_function Fortran_functions
;
195 Lang_function Yacc_entries
;
196 Lang_function Lisp_functions
;
197 Lang_function Pascal_functions
;
198 Lang_function Prolog_functions
;
199 Lang_function Scheme_functions
;
200 Lang_function TeX_functions
;
201 Lang_function just_read_file
;
202 #else /* so let's write it this way */
204 void default_C_entries ();
206 void Cplusplus_entries ();
207 void Cstar_entries ();
208 void Fortran_functions ();
209 void Yacc_entries ();
210 void Lisp_functions ();
211 void Pascal_functions ();
212 void Prolog_functions ();
213 void Scheme_functions ();
214 void TeX_functions ();
215 void just_read_file ();
218 logical
get_language ();
219 int total_size_of_entries ();
221 long readline_internal ();
227 void fatal (), pfatal ();
228 logical
find_entries ();
234 void process_file ();
240 * xnew -- allocate storage
243 * Type *xnew (int n, Type);
245 #define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
248 * Symbol table types.
252 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
269 #define C_PLPL 0x00001 /* C++ */
270 #define C_STAR 0x00003 /* C* */
271 #define YACC 0x10000 /* yacc file */
273 char searchar
= '/'; /* use /.../ searches */
275 LINENO lineno
; /* line number of current line */
276 long charno
; /* current character number */
278 long linecharno
; /* charno of start of line; not used by C, but
279 * by every other language.
282 char *curfile
, /* current input file name */
283 *tagfile
, /* output file */
284 *white
= " \f\t\n\013", /* white chars */
285 *endtk
= " \t\n\013\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
286 /* token starting chars */
287 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
288 /* valid in-token chars */
289 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
291 int append_to_tagfile
; /* -a: append to tags */
292 /* The following three default to 1 for etags, but to 0 for ctags. */
293 int typedefs
; /* -t: create tags for typedefs */
294 int typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
295 /* 0 struct/enum/union decls, and C++ */
296 /* member functions. */
297 int constantypedefs
; /* -d: create tags for C #define and enum */
298 /* constants. Enum consts not implemented. */
299 /* -D: opposite of -d. Default under ctags. */
300 int update
; /* -u: update tags */
301 int vgrind_style
; /* -v: create vgrind style index output */
302 int no_warnings
; /* -w: suppress warnings */
303 int cxref_style
; /* -x: create cxref style output */
304 int cplusplus
; /* .[hc] means C++, not C */
305 int noindentypedefs
; /* -S: ignore indentation in C */
307 /* Name this program was invoked with. */
310 struct option longopts
[] =
312 { "append", no_argument
, NULL
, 'a' },
313 { "backward-search", no_argument
, NULL
, 'B' },
314 { "c++", no_argument
, NULL
, 'C' },
315 { "cxref", no_argument
, NULL
, 'x' },
316 { "defines", no_argument
, NULL
, 'd' },
317 { "help", no_argument
, NULL
, 'h' },
318 { "help", no_argument
, NULL
, 'H' },
319 { "ignore-indentation", no_argument
, NULL
, 'S' },
320 { "include", required_argument
, NULL
, 'i' },
321 { "language", required_argument
, NULL
, 'l' },
322 { "no-defines", no_argument
, NULL
, 'D' },
323 { "no-regex", no_argument
, NULL
, 'R' },
324 { "no-warn", no_argument
, NULL
, 'w' },
325 { "output", required_argument
, NULL
, 'o' },
326 { "regex", required_argument
, NULL
, 'r' },
327 { "typedefs", no_argument
, NULL
, 't' },
328 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
329 { "update", no_argument
, NULL
, 'u' },
330 { "version", no_argument
, NULL
, 'V' },
331 { "vgrind", no_argument
, NULL
, 'v' },
335 FILE *tagf
; /* ioptr for tags file */
336 NODE
*head
; /* the head of the binary tree of tags */
337 logical permit_duplicates
= TRUE
; /* allow duplicate tags */
340 * A `struct linebuffer' is a structure which holds a line of text.
341 * `readline' reads a line from a stream into a linebuffer and works
342 * regardless of the length of the line.
350 struct linebuffer lb
; /* the current line */
351 struct linebuffer filename_lb
; /* used to read in filenames */
355 struct linebuffer lb
; /* used by C_entries instead of lb */
359 /* Structure defining a regular expression. Elements are
360 the compiled pattern, and the name string. */
363 struct re_pattern_buffer
*pattern
;
364 struct re_registers regs
;
366 logical error_signaled
;
369 /* Number of regexps found. */
370 int num_patterns
= 0;
372 /* Array of all regexps. */
373 struct pattern
*patterns
= NULL
;
374 #endif /* ETAGS_REGEXPS */
376 /* Language stuff. */
380 Lang_function
*function
;
383 /* Table of language names and corresponding functions. */
384 /* It is ok for a given function to be listed under more than one
385 name. I just didn't. */
386 /* "auto" language reverts to default behavior. */
387 struct lang_entry lang_names
[] =
389 { "asm", Asm_labels
},
390 { "c", default_C_entries
},
391 { "c++", Cplusplus_entries
},
392 { "c*", Cstar_entries
},
393 { "fortran", Fortran_functions
},
394 { "lisp", Lisp_functions
},
395 { "none", just_read_file
},
396 { "pascal", Pascal_functions
},
397 { "scheme" , Scheme_functions
},
398 { "tex", TeX_functions
},
403 /* Table of file extensions and corresponding language functions. */
404 struct lang_entry lang_extensions
[] =
406 /* Assume that ".s" or ".a" is assembly code. -wolfgang.
408 { "a", Asm_labels
}, /* Unix assembler */
409 { "asm", Asm_labels
}, /* Microcontroller assembly */
410 { "def", Asm_labels
}, /* BSO/Tasking definition includes */
411 { "inc", Asm_labels
}, /* Microcontroller include files */
412 { "ins", Asm_labels
}, /* Microcontroller include files */
414 { "sa", Asm_labels
}, /* Unix assembler */
415 { "src", Asm_labels
}, /* BSO/Tasking C compiler output */
417 /* .aux, .bbl, .clo, .cls, .dtx or .tex implies LaTeX source code. */
418 { "aux", TeX_functions
},
419 { "bbl", TeX_functions
},
420 { "clo", TeX_functions
},
421 { "cls", TeX_functions
},
422 { "dtx", TeX_functions
},
423 { "sty", TeX_functions
},
424 { "tex", TeX_functions
},
426 /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
427 { "cl", Lisp_functions
},
428 { "clisp", Lisp_functions
},
429 { "el", Lisp_functions
},
430 { "l", Lisp_functions
},
431 { "lisp", Lisp_functions
},
432 { "lsp", Lisp_functions
},
434 /* .scm or .sm or .scheme implies scheme source code */
435 { "SCM", Scheme_functions
},
436 { "SM", Scheme_functions
},
437 { "oak", Scheme_functions
},
438 { "sch", Scheme_functions
},
439 { "scheme", Scheme_functions
},
440 { "scm", Scheme_functions
},
441 { "sm", Scheme_functions
},
442 { "t", Scheme_functions
},
443 /* FIXME Can't do the `SCM' or `scm' prefix with a version number */
445 /* Note that ".c" and ".h" can be considered C++, if the --c++
446 flag was given. That is why default_C_entries is called here. */
447 { "c", default_C_entries
},
448 { "h", default_C_entries
},
450 /* .C or .H or .cpp or .cxx or .hxx or .hh or .cc or .cpp: a C++ file */
451 { "C", Cplusplus_entries
},
452 { "H", Cplusplus_entries
},
453 { "cc", Cplusplus_entries
},
454 { "cpp", Cplusplus_entries
},
455 { "cxx", Cplusplus_entries
},
456 { "hh", Cplusplus_entries
},
457 { "hxx", Cplusplus_entries
},
459 /* .y: a yacc file */
460 { "y", Yacc_entries
},
462 /* .cs or .hs: a C* file */
463 { "cs", Cstar_entries
},
464 { "hs", Cstar_entries
},
466 /* .f and .for are FORTRAN. */
467 { "F", Fortran_functions
},
468 { "f", Fortran_functions
},
469 { "for", Fortran_functions
},
471 /* .pl implies prolog source code */
472 { "pl", Prolog_functions
},
474 /* .p or .pas: a Pascal file */
475 { "p", Pascal_functions
},
476 { "pas", Pascal_functions
},
481 /* Non-NULL if language fixed. */
482 Lang_function
*lang_func
= NULL
;
486 print_language_names ()
488 struct lang_entry
*name
, *ext
;
490 puts ("\nThese are the currently supported languages, along with the\n\
491 default extensions for files:");
492 for (name
= lang_names
; name
->extension
; ++name
)
494 printf ("\t%s\t", name
->extension
);
495 for (ext
= lang_extensions
; ext
->extension
; ++ext
)
496 if (name
->function
== ext
->function
)
497 printf (" .%s", ext
->extension
);
500 puts ("Where `auto' means use default language for files based on filename\n\
501 extension, and `none' means only do regexp processing on files.\n\
502 If no language is specified and no extension is found for some file,\n\
503 Fortran is tried first; if no tags are found, C is tried next.");
510 printf ("%s for Emacs version %s.\n", (CTAGS
) ? "CTAGS" : "ETAGS", VERSION
);
512 printf ("%s for Emacs version 19.\n", (CTAGS
) ? "CTAGS" : "ETAGS");
521 printf ("These are the options accepted by %s. You may use unambiguous\n\
522 abbreviations for the long option names. A - as file name means read\n\
523 names from stdin.\n\n", progname
);
525 puts ("-a, --append\n\
526 Append tag entries to existing tags file.");
529 puts ("-B, --backward-search\n\
530 Write the search commands for the tag entries using '?', the\n\
531 backward-search command instead of '/', the forward-search command.");
534 Treat files whose extension defaults to C language as C++ files.");
537 puts ("-d, --defines\n\
538 Create tag entries for constant C #defines, too.");
540 puts ("-D, --no-defines\n\
541 Don't create tag entries for constant C #defines. This makes\n\
542 the tags file smaller.");
546 puts ("-i FILE, --include=FILE\n\
547 Include a note in tag file indicating that, when searching for\n\
548 a tag, one should also consult the tags file FILE after\n\
549 checking the current file.");
550 puts ("-l LANG, --language=LANG\n\
551 Force the following files to be considered as written in the\n\
552 named language up to the next --language=LANG option.");
556 puts ("-r /REGEXP/, --regex=/REGEXP/\n\
557 Make a tag for each line matching pattern REGEXP in the\n\
558 following files. REGEXP is anchored (as if preceded by ^).\n\
559 The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
560 named tags can be created with:\n\
561 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
562 puts ("-R, --no-regex\n\
563 Don't create tags from regexps for the following files.");
564 #endif /* ETAGS_REGEXPS */
565 puts ("-o FILE, --output=FILE\n\
566 Write the tags to FILE.");
567 puts ("-S, --ignore-indentation\n\
568 Don't rely on indentation quite as much as normal. Currently,\n\
569 this means not to assume that a closing brace in the first\n\
570 column is the final brace of a function or structure\n\
571 definition in C and C++.");
575 puts ("-t, --typedefs\n\
576 Generate tag entries for C typedefs.");
577 puts ("-T, --typedefs-and-c++\n\
578 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
579 and C++ member functions.");
580 puts ("-u, --update\n\
581 Update the tag entries for the given files, leaving tag\n\
582 entries for other files in place. Currently, this is\n\
583 implemented by deleting the existing entries for the given\n\
584 files and then rewriting the new entries at the end of the\n\
585 tags file. It is often faster to simply rebuild the entire\n\
586 tag file than to use this.");
587 puts ("-v, --vgrind\n\
588 Generates an index of items intended for human consumption,\n\
589 similar to the output of vgrind. The index is sorted, and\n\
590 gives the page number of each item.");
591 puts ("-w, --no-warn\n\
592 Suppress warning messages about entries defined in multiple\n\
594 puts ("-x, --cxref\n\
595 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
596 The output uses line numbers instead of page numbers, but\n\
597 beyond that the differences are cosmetic; try both to see\n\
601 puts ("-V, --version\n\
602 Print the version of the program.\n\
604 Print this help message.");
606 print_language_names ();
619 /* This structure helps us allow mixing of --lang and filenames. */
622 enum argument_type arg_type
;
624 Lang_function
*function
;
627 #ifdef VMS /* VMS specific functions */
631 /* This is a BUG! ANY arbitrary limit is a BUG!
632 Won't someone please fix this? */
633 #define MAX_FILE_SPEC_LEN 255
636 char body
[MAX_FILE_SPEC_LEN
+ 1];
640 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
641 returning in each successive call the next filename matching the input
642 spec. The function expects that each in_spec passed
643 to it will be processed to completion; in particular, up to and
644 including the call following that in which the last matching name
645 is returned, the function ignores the value of in_spec, and will
646 only start processing a new spec with the following call.
647 If an error occurs, on return out_spec contains the value
648 of in_spec when the error occurred.
650 With each successive filename returned in out_spec, the
651 function's return value is one. When there are no more matching
652 names the function returns zero. If on the first call no file
653 matches in_spec, or there is any other error, -1 is returned.
658 #define OUTSIZE MAX_FILE_SPEC_LEN
664 static long context
= 0;
665 static struct dsc$descriptor_s o
;
666 static struct dsc$descriptor_s i
;
667 static logical pass1
= TRUE
;
674 o
.dsc$a_pointer
= (char *) out
;
675 o
.dsc$w_length
= (short)OUTSIZE
;
676 i
.dsc$a_pointer
= in
;
677 i
.dsc$w_length
= (short)strlen(in
);
678 i
.dsc$b_dtype
= DSC$K_DTYPE_T
;
679 i
.dsc$b_class
= DSC$K_CLASS_S
;
680 o
.dsc$b_dtype
= DSC$K_DTYPE_VT
;
681 o
.dsc$b_class
= DSC$K_CLASS_VS
;
683 if ((status
= lib$
find_file(&i
, &o
, &context
, 0, 0)) == RMS$_NORMAL
)
685 out
->body
[out
->curlen
] = EOS
;
688 else if (status
== RMS$_NMF
)
692 strcpy(out
->body
, in
);
695 lib$
find_file_end(&context
);
701 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
702 name of each file specified by the provided arg expanding wildcards.
705 gfnames (arg
, p_error
)
709 static vspec filename
= {MAX_FILE_SPEC_LEN
, "\0"};
711 switch (fn_exp (&filename
, arg
))
715 return filename
.body
;
721 return filename
.body
;
725 #ifndef OLD /* Newer versions of VMS do provide `system'. */
729 fprintf (stderr
, "system() function not implemented under VMS\n");
733 #define VERSION_DELIM ';'
734 char *massage_name (s
)
740 if (*s
== VERSION_DELIM
)
759 unsigned int nincluded_files
= 0;
760 char **included_files
= xnew (argc
, char *);
763 int current_arg
= 0, file_count
= 0;
769 _fmode
= O_BINARY
; /* all of files are treated as binary files */
774 /* Allocate enough no matter what happens. Overkill, but each one
776 argbuffer
= xnew (argc
, ARGUMENT
);
779 /* Set syntax for regular expression routines. */
780 re_set_syntax (RE_SYNTAX_EMACS
);
781 #endif /* ETAGS_REGEXPS */
784 * If etags, always find typedefs and structure tags. Why not?
785 * Also default is to find macro constants.
788 typedefs
= typedefs_and_cplusplus
= constantypedefs
= 1;
792 int opt
= getopt_long (argc
, argv
,
793 "-aCdDf:l:o:r:RStTi:BuvxwVhH", longopts
, 0);
801 /* If getopt returns 0, then it has already processed a
802 long-named option. We should do nothing. */
806 /* This means that a filename has been seen. Record it. */
807 argbuffer
[current_arg
].arg_type
= at_filename
;
808 argbuffer
[current_arg
].what
= optarg
;
813 /* Common options. */
826 case 'f': /* for compatibility with old makefiles */
831 "%s: -%c flag may only be given once.\n", progname
, opt
);
837 if (!get_language (optarg
, &argbuffer
[current_arg
].function
))
839 fprintf (stderr
, "%s: language \"%s\" not recognized.\n",
843 argbuffer
[current_arg
].arg_type
= at_language
;
848 argbuffer
[current_arg
].arg_type
= at_regexp
;
849 argbuffer
[current_arg
].what
= optarg
;
853 argbuffer
[current_arg
].arg_type
= at_regexp
;
854 argbuffer
[current_arg
].what
= NULL
;
857 #endif /* ETAGS_REGEXPS */
873 typedefs_and_cplusplus
++;
878 included_files
[nincluded_files
++] = optarg
;
900 "%s: -%c flag not recognised.\n", progname
, opt
);
905 for (; optind
< argc
; ++optind
)
907 argbuffer
[current_arg
].arg_type
= at_filename
;
908 argbuffer
[current_arg
].what
= argv
[optind
];
913 if (nincluded_files
== 0 && file_count
== 0)
915 fprintf (stderr
, "%s: No input files specified.\n", progname
);
918 fprintf (stderr
, "%s: Try `%s --help' for a complete list of options.\n",
925 tagfile
= CTAGS
? "tags" : "TAGS";
927 cwd
= etags_getcwd (); /* the current working directory */
929 if (streq (tagfile
, "-"))
935 tagfiledir
= absolute_dirname (tagfile
, cwd
);
938 init (); /* set up boolean "functions" */
941 initbuffer (&lbs
[0].lb
);
942 initbuffer (&lbs
[1].lb
);
943 initbuffer (&filename_lb
);
947 if (streq (tagfile
, "-"))
950 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
956 * Loop through files finding functions.
958 for (i
= 0; i
< current_arg
; ++i
)
960 switch (argbuffer
[i
].arg_type
)
963 lang_func
= argbuffer
[i
].function
;
967 add_regex (argbuffer
[i
].what
);
972 while ((this_file
= gfnames (argbuffer
[i
].what
, &got_err
)) != NULL
)
976 error ("Can't find file %s\n", this_file
);
981 this_file
= massage_name (this_file
);
984 this_file
= argbuffer
[i
].what
;
986 /* Input file named "-" means read file names from stdin
988 if (streq (this_file
, "-"))
990 while (!feof (stdin
))
992 /* Use readline_internal so that regexp matching */
993 /* is not done on filenames. */
994 (void) readline_internal (&filename_lb
, stdin
);
995 if (strlen (filename_lb
.buffer
) > 0)
996 process_file (filename_lb
.buffer
);
1000 process_file (this_file
);
1010 while (nincluded_files
-- > 0)
1011 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
1013 (void) fclose (tagf
);
1024 for (i
= 0; i
< current_arg
; ++i
)
1026 if (argbuffer
[i
].arg_type
== at_language
)
1029 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1030 tagfile
, argbuffer
[i
].what
, tagfile
);
1031 (void) system (cmd
);
1033 append_to_tagfile
++;
1035 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1042 (void) fclose (tagf
);
1045 sprintf (cmd
, "sort %s -o %s", tagfile
, tagfile
);
1046 (void) system (cmd
);
1053 * Set the language, given the name.
1056 get_language (language
, func
)
1058 Lang_function
**func
;
1060 struct lang_entry
*lang
;
1062 for (lang
= lang_names
; lang
->extension
; ++lang
)
1064 if (streq (language
, lang
->extension
))
1066 *func
= lang
->function
;
1076 * This routine is called on each file argument.
1082 struct stat stat_buf
;
1084 if (stat (file
, &stat_buf
) == 0 && !S_ISREG (stat_buf
.st_mode
))
1086 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
1089 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
1091 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
1094 if (!find_entries (file
))
1104 /* file is an absolute filename. Canonicalise it. */
1105 filename
= absolute_filename (file
, cwd
);
1109 /* file is a filename relative to cwd. Make it relative
1110 to the directory of the tags file. */
1111 filename
= relative_filename (file
, tagfiledir
);
1113 fprintf (tagf
, "\f\n%s,%d\n", filename
, total_size_of_entries (head
));
1121 * This routine sets up the boolean pseudo-functions which work
1122 * by setting boolean flags dependent upon the corresponding character
1123 * Every char which is NOT in that string is not a white char. Therefore,
1124 * all of the array "_wht" is set to FALSE, and then the elements
1125 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1126 * of a char is TRUE if it is the string "white", else FALSE.
1134 for (i
= 0; i
< 0177; i
++)
1135 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
1136 for (sp
= white
; *sp
; sp
++)
1138 for (sp
= endtk
; *sp
; sp
++)
1140 for (sp
= intk
; *sp
; sp
++)
1142 for (sp
= begtk
; *sp
; sp
++)
1144 _wht
[0] = _wht
['\n'];
1145 _etk
[0] = _etk
['\n'];
1146 _btk
[0] = _btk
['\n'];
1147 _itk
[0] = _itk
['\n'];
1151 * This routine opens the specified file and calls the function
1152 * which finds the function and type definitions.
1160 struct lang_entry
*lang
;
1161 NODE
*old_last_node
;
1162 extern NODE
*last_node
;
1164 inf
= fopen (file
, "r");
1170 curfile
= savestr (file
);
1171 cp
= etags_strrchr (file
, '.');
1173 /* If user specified a language, use it. */
1174 if (lang_func
!= NULL
)
1184 for (lang
= lang_extensions
; lang
->extension
; ++lang
)
1186 if (streq (cp
, lang
->extension
))
1188 lang
->function (inf
);
1196 old_last_node
= last_node
;
1197 Fortran_functions (inf
);
1199 /* No Fortran entries found. Try C. */
1200 if (old_last_node
== last_node
)
1201 default_C_entries (inf
);
1207 /* Should take a TOKEN* instead!! */
1209 pfnote (name
, is_func
, named
, linestart
, linelen
, lno
, cno
)
1210 char *name
; /* tag name */
1211 logical is_func
; /* function or type name? */
1212 logical named
; /* tag different from text of definition? */
1223 np
= xnew (1, NODE
);
1228 /* It's okay to output early in etags -- it only disrupts the
1229 * character count of the tag entries, which is no longer used
1230 * by tags.el anyway.
1232 error ("too many entries to sort", 0);
1237 np
= xnew (1, NODE
);
1239 /* If ctags mode, change name "main" to M<thisfilename>. */
1240 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
1242 fp
= etags_strrchr (curfile
, '/');
1243 name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
1244 fp
= etags_strrchr (name
, '.');
1245 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
1249 np
->name
= savestr (name
);
1251 np
->is_func
= is_func
;
1254 /* Our char numbers are 0-base, because of C language tradition?
1255 ctags compatibility? old versions compatibility? I don't know.
1256 Anyway, since emacs's are 1-base we espect etags.el to take care
1257 of the difference. If we wanted to have 1-based numbers, we would
1258 uncomment the +1 below. */
1259 np
->cno
= cno
/* + 1 */ ;
1260 np
->left
= np
->right
= 0;
1263 c
= linestart
[linelen
];
1264 linestart
[linelen
] = 0;
1266 else if (cxref_style
== 0)
1268 sprintf (tem
, strlen (linestart
) < 50 ? "%s$" : "%.50s", linestart
);
1271 np
->pat
= savestr (linestart
);
1274 linestart
[linelen
] = c
;
1277 add_node (np
, &head
);
1282 * recurse on left children, iterate on right children.
1286 register NODE
*node
;
1290 register NODE
*node_right
= node
->right
;
1291 free_tree (node
->left
);
1294 free ((char *) node
);
1301 * Adds a node to the tree of nodes. In etags mode, we don't keep
1302 * it sorted; we just keep a linear list. In ctags mode, maintain
1303 * an ordered tree, with no attempt at balancing.
1305 * add_node is the only function allowed to add nodes, so it can
1308 NODE
*last_node
= NULL
;
1310 add_node (node
, cur_node_p
)
1311 NODE
*node
, **cur_node_p
;
1314 register NODE
*cur_node
= *cur_node_p
;
1316 if (cur_node
== NULL
)
1326 if (last_node
== NULL
)
1327 fatal ("internal error in add_node", 0);
1328 last_node
->right
= node
;
1334 dif
= strcmp (node
->name
, cur_node
->name
);
1337 * If this tag name matches an existing one, then
1338 * do not add the node, but maybe print a warning.
1342 if (node
->file
== cur_node
->file
)
1346 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1347 node
->file
, lineno
, node
->name
);
1348 fprintf (stderr
, "Second entry ignored\n");
1352 if (!cur_node
->been_warned
&& !no_warnings
)
1355 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1356 node
->file
, cur_node
->file
, node
->name
);
1358 cur_node
->been_warned
= TRUE
;
1362 /* Maybe refuse to add duplicate nodes. */
1363 if (!permit_duplicates
)
1365 if (streq (node
->name
, cur_node
->name
)
1366 && streq (node
->file
, cur_node
->file
))
1370 /* Actually add the node */
1371 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1377 register NODE
*node
;
1384 /* Output subentries that precede this one */
1385 put_entries (node
->left
);
1387 /* Output this entry */
1393 fprintf (tagf
, "%s\177%s\001%d,%d\n",
1394 node
->pat
, node
->name
,
1395 node
->lno
, node
->cno
);
1399 fprintf (tagf
, "%s\177%d,%d\n",
1401 node
->lno
, node
->cno
);
1404 else if (!cxref_style
)
1406 fprintf (tagf
, "%s\t%s\t",
1407 node
->name
, node
->file
);
1411 putc (searchar
, tagf
);
1414 for (sp
= node
->pat
; *sp
; sp
++)
1416 if (*sp
== '\\' || *sp
== searchar
)
1420 putc (searchar
, tagf
);
1423 { /* a typedef; text pattern inadequate */
1424 fprintf (tagf
, "%d", node
->lno
);
1428 else if (vgrind_style
)
1429 fprintf (stdout
, "%s %s %d\n",
1430 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1432 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1433 node
->name
, node
->lno
, node
->file
, node
->pat
);
1435 /* Output subentries that follow this one */
1436 put_entries (node
->right
);
1439 /* Length of a number's decimal representation. */
1447 for (; num
; num
/= 10)
1453 * Return total number of characters that put_entries will output for
1454 * the nodes in the subtree of the specified node. Works only if
1455 * we are not ctags, but called only in that case. This count
1456 * is irrelevant with the new tags.el, but is still supplied for
1457 * backward compatibility.
1460 total_size_of_entries (node
)
1461 register NODE
*node
;
1469 for (; node
; node
= node
->right
)
1471 /* Count left subentries. */
1472 total
+= total_size_of_entries (node
->left
);
1474 /* Count this entry */
1475 total
+= strlen (node
->pat
) + 1;
1476 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1478 total
+= 1 + strlen (node
->name
); /* \001name */
1485 * The C symbol tables.
1488 /* Feed stuff between (but not including) %[ and %] lines to:
1489 gperf -c -k1,3 -o -p -r -t
1491 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1493 class, C_PLPL, st_C_struct
1494 domain, C_STAR, st_C_struct
1495 union, 0, st_C_struct
1496 struct, 0, st_C_struct
1498 typedef, 0, st_C_typedef
1499 define, 0, st_C_define
1500 long, 0, st_C_typespec
1501 short, 0, st_C_typespec
1502 int, 0, st_C_typespec
1503 char, 0, st_C_typespec
1504 float, 0, st_C_typespec
1505 double, 0, st_C_typespec
1506 signed, 0, st_C_typespec
1507 unsigned, 0, st_C_typespec
1508 auto, 0, st_C_typespec
1509 void, 0, st_C_typespec
1510 extern, 0, st_C_typespec
1511 static, 0, st_C_typespec
1512 const, 0, st_C_typespec
1513 volatile, 0, st_C_typespec
1515 and replace lines between %< and %> with its output. */
1517 /* C code produced by gperf version 1.8.1 (K&R C version) */
1518 /* Command-line: gperf -c -k1,3 -o -p -r -t */
1521 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
1523 #define MIN_WORD_LENGTH 3
1524 #define MAX_WORD_LENGTH 8
1525 #define MIN_HASH_VALUE 10
1526 #define MAX_HASH_VALUE 62
1529 53 is the maximum key range
1537 static unsigned char hash_table
[] =
1539 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1540 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1541 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1542 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1543 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1544 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1545 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1546 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1547 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1548 62, 62, 62, 62, 62, 62, 62, 2, 62, 7,
1549 6, 9, 15, 30, 62, 24, 62, 62, 1, 24,
1550 7, 27, 13, 62, 19, 26, 18, 27, 1, 62,
1551 62, 62, 62, 62, 62, 62, 62, 62,
1553 return len
+ hash_table
[str
[2]] + hash_table
[str
[0]];
1556 struct C_stab_entry
*
1557 in_word_set (str
, len
)
1562 static struct C_stab_entry wordlist
[] =
1564 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1566 {"volatile", 0, st_C_typespec
},
1568 {"long", 0, st_C_typespec
},
1569 {"char", 0, st_C_typespec
},
1570 {"class", C_PLPL
, st_C_struct
},
1571 {"",}, {"",}, {"",}, {"",},
1572 {"const", 0, st_C_typespec
},
1573 {"",}, {"",}, {"",}, {"",},
1574 {"auto", 0, st_C_typespec
},
1576 {"define", 0, st_C_define
},
1578 {"void", 0, st_C_typespec
},
1579 {"",}, {"",}, {"",},
1580 {"extern", 0, st_C_typespec
},
1581 {"static", 0, st_C_typespec
},
1583 {"domain", C_STAR
, st_C_struct
},
1585 {"typedef", 0, st_C_typedef
},
1586 {"double", 0, st_C_typespec
},
1587 {"enum", 0, st_C_enum
},
1588 {"",}, {"",}, {"",}, {"",},
1589 {"int", 0, st_C_typespec
},
1591 {"float", 0, st_C_typespec
},
1592 {"",}, {"",}, {"",},
1593 {"struct", 0, st_C_struct
},
1594 {"",}, {"",}, {"",}, {"",},
1595 {"union", 0, st_C_struct
},
1597 {"short", 0, st_C_typespec
},
1599 {"unsigned", 0, st_C_typespec
},
1600 {"signed", 0, st_C_typespec
},
1603 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
1605 register int key
= hash (str
, len
);
1607 if (key
<= MAX_HASH_VALUE
&& key
>= MIN_HASH_VALUE
)
1609 register char *s
= wordlist
[key
].name
;
1611 if (*s
== *str
&& strneq (str
+ 1, s
+ 1, len
- 1))
1612 return &wordlist
[key
];
1620 C_symtype(str
, len
, c_ext
)
1625 register struct C_stab_entry
*se
= in_word_set(str
, len
);
1627 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
1633 * C functions are recognized using a simple finite automaton.
1634 * funcdef is its state variable.
1638 fnone
, /* nothing seen */
1639 ftagseen
, /* function-like tag seen */
1640 fstartlist
, /* just after open parenthesis */
1641 finlist
, /* in parameter list */
1642 flistseen
, /* after parameter list */
1643 fignore
/* before open brace */
1649 * typedefs are recognized using a simple finite automaton.
1650 * typeddef is its state variable.
1654 tnone
, /* nothing seen */
1655 ttypedseen
, /* typedef keyword seen */
1656 tinbody
, /* inside typedef body */
1657 tend
, /* just before typedef tag */
1658 tignore
/* junk after typedef tag */
1664 * struct-like structures (enum, struct and union) are recognized
1665 * using another simple finite automaton. `structdef' is its state
1670 snone
, /* nothing seen yet */
1671 skeyseen
, /* struct-like keyword seen */
1672 stagseen
, /* struct-like tag seen */
1673 scolonseen
, /* colon seen after struct-like tag */
1674 sinbody
/* in struct body: recognize member func defs*/
1679 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1680 * struct tag, and structtype is the type of the preceding struct-like
1683 char structtag
[BUFSIZ
];
1684 enum sym_type structtype
;
1687 * Yet another little state machine to deal with preprocessor lines.
1691 dnone
, /* nothing seen */
1692 dsharpseen
, /* '#' seen as first char on line */
1693 ddefineseen
, /* '#' and 'define' seen */
1694 dignorerest
/* ignore rest of line */
1699 * Set this to TRUE, and the next token considered is called a function.
1700 * Used only for GNU emacs's function-defining macros.
1702 logical next_token_is_func
;
1705 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1711 * checks to see if the current token is at the start of a
1712 * function, or corresponds to a typedef, or is a struct/union/enum
1715 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1716 * C_EXT is which language we are looking at.
1718 * In the future we will need some way to adjust where the end of
1719 * the token is; for instance, implementing the C++ keyword
1720 * `operator' properly will adjust the end of the token to be after
1721 * whatever follows `operator'.
1728 * next_token_is_func IN OUT
1732 consider_token (c
, tokp
, c_ext
, cblev
, is_func
)
1733 register char c
; /* IN: first char after the token */
1734 register TOKEN
*tokp
; /* IN: token pointer */
1735 int c_ext
; /* IN: C extensions mask */
1736 int cblev
; /* IN: curly brace level */
1737 logical
*is_func
; /* OUT: function found */
1739 enum sym_type toktype
= C_symtype(tokp
->p
, tokp
->len
, c_ext
);
1742 * Advance the definedef state machine.
1747 /* We're not on a preprocessor line. */
1750 if (toktype
== st_C_define
)
1752 definedef
= ddefineseen
;
1756 definedef
= dignorerest
;
1761 * Make a tag for any macro, unless it is a constant
1762 * and constantypedefs is FALSE.
1764 definedef
= dignorerest
;
1765 *is_func
= (c
== '(');
1766 if (!*is_func
&& !constantypedefs
)
1773 error ("internal error: definedef value.", 0);
1782 if (toktype
== st_C_typedef
)
1785 typdef
= ttypedseen
;
1801 /* Do not return here, so the structdef stuff has a chance. */
1815 * This structdef business is currently only invoked when cblev==0.
1816 * It should be recursively invoked whatever the curly brace level,
1817 * and a stack of states kept, to allow for definitions of structs
1820 * This structdef business is NOT invoked when we are ctags and the
1821 * file is plain C. This is because a struct tag may have the same
1822 * name as another tag, and this loses with ctags.
1824 * This if statement deals with the typdef state machine as
1825 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1826 * return FALSE. All the other code here is for the structdef
1833 if (typdef
== ttypedseen
1834 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1836 structdef
= skeyseen
;
1837 structtype
= toktype
;
1841 if (structdef
== skeyseen
)
1843 if (structtype
== st_C_struct
)
1845 strncpy (structtag
, tokp
->p
, tokp
->len
);
1846 structtag
[tokp
->len
] = '\0'; /* for struct/union/class */
1850 structtag
[0] = '\0'; /* for enum (why is it treated differently?) */
1852 structdef
= stagseen
;
1856 /* Avoid entering funcdef stuff if typdef is going on. */
1857 if (typdef
!= tnone
)
1863 /* Detect GNU macros. */
1864 if (definedef
== dnone
)
1865 if (strneq (tokp
->p
, "DEFUN", 5) /* Used in emacs */
1867 These are defined inside C functions
, so currently they
1869 || strneq (tokp
->p
, "EXFUN", 5) /* Used in glibc */
1870 || strneq (tokp
->p
, "DEFVAR_", 7) /* Used in emacs */
1872 || strneq (tokp
->p
, "SYSCALL", 7) /* Used in glibc (mach) */
1873 || strneq (tokp
->p
, "ENTRY", 5) /* Used in glibc */
1874 || strneq (tokp
->p
, "PSEUDO", 6)) /* Used in glibc */
1877 next_token_is_func
= TRUE
;
1880 if (next_token_is_func
)
1882 next_token_is_func
= FALSE
;
1892 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1893 funcdef
= fnone
; /* should be useless */
1896 if (funcdef
== fnone
)
1909 * This routine finds functions, typedefs, #define's and
1910 * struct/union/enum definitions in C syntax and adds them
1914 #define curlb (lbs[curndx].lb)
1915 #define othlb (lbs[1-curndx].lb)
1916 #define newlb (lbs[newndx].lb)
1917 #define curlinepos (lbs[curndx].linepos)
1918 #define othlinepos (lbs[1-curndx].linepos)
1919 #define newlinepos (lbs[newndx].linepos)
1921 /* Save and restore token state. This is used when preprocessor defines
1922 are handled, to avoid disturbing active function/typedef/struct states. */
1923 #define TOKEN_SAVED_P (savetok.lineno > 0)
1924 #define SAVE_TOKEN (savetok = tok, savetok.p = (char *) tokoff, \
1925 savetok.len = toklen, strcpy(savenameb, nameb))
1926 #define RESTORE_TOKEN (tok = savetok, tokoff = (int) tok.p, \
1927 toklen = tok.len, strcpy(nameb, savenameb), \
1930 #define CNL_SAVE_DEFINEDEF \
1932 SET_FILEPOS (curlinepos, inf, charno); \
1934 charno += readline (&curlb, inf); \
1935 lp = curlb.buffer; \
1942 CNL_SAVE_DEFINEDEF; \
1943 if (TOKEN_SAVED_P) \
1945 definedef = dnone; \
1948 #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (nameb, isfun, tok.named, \
1949 newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos))
1950 #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (nameb, isfun, tok.named, \
1951 othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos))
1954 C_entries (c_ext
, inf
)
1955 int c_ext
; /* extension of C */
1956 FILE *inf
; /* input file */
1958 register char c
; /* latest char read; '\0' for end of line */
1959 register char *lp
; /* pointer one beyond the character `c' */
1960 int curndx
, newndx
; /* indices for current and new lb */
1961 TOKEN tok
; /* latest token read for funcdef & structdef */
1962 char nameb
[BUFSIZ
]; /* latest token name for funcdef & structdef */
1963 register int tokoff
; /* offset in line of start of latest token */
1964 register int toklen
; /* length of latest token */
1965 int cblev
; /* current curly brace level */
1966 int parlev
; /* current parenthesis level */
1967 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1969 TOKEN savetok
; /* saved token during preprocessor handling */
1970 char savenameb
[BUFSIZ
]; /* ouch! */
1973 curndx
= newndx
= 0;
1979 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1980 next_token_is_func
= yacc_rules
= FALSE
;
1981 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1984 cplpl
= c_ext
& C_PLPL
;
1991 /* If we're at the end of the line, the next character is a
1992 '\0'; don't skip it, because it's the thing that tells us
1993 to read the next line. */
2014 /* Newlines inside comments do not end macro definitions in
2029 /* Newlines inside strings do not end macro definitions
2030 in traditional cpp, even though compilers don't
2031 usually accept them. */
2042 /* Hmmm, something went wrong. */
2056 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2061 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2071 else if (cplpl
&& *lp
== '/')
2079 if ((c_ext
& YACC
) && *lp
== '%')
2081 /* entering or exiting rules section in yacc file */
2083 definedef
= dnone
; funcdef
= fnone
;
2084 typdef
= tnone
; structdef
= snone
;
2085 next_token_is_func
= FALSE
;
2086 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
2088 yacc_rules
= !yacc_rules
;
2094 if (definedef
== dnone
)
2097 logical cpptoken
= TRUE
;
2099 /* Look back on this line. If all blanks, or nonblanks
2100 followed by an end of comment, this is a preprocessor
2102 for (cp
= newlb
.buffer
; cp
< lp
-1; cp
++)
2105 if (*cp
== '*' && *(cp
+1) == '/')
2114 definedef
= dsharpseen
;
2115 } /* if (definedef == dnone) */
2121 /* Consider token only if some complicated conditions are satisfied. */
2122 if ((definedef
!= dnone
2123 || (cblev
== 0 && structdef
!= scolonseen
)
2124 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
2125 && typdef
!= tignore
2126 && definedef
!= dignorerest
2127 && funcdef
!= finlist
)
2133 if (cplpl
&& c
== ':' && *lp
== ':' && begtoken(*(lp
+ 1)))
2136 * This handles :: in the middle, but not at the
2137 * beginning of an identifier.
2144 logical is_func
= FALSE
;
2146 tok
.lineno
= lineno
;
2147 tok
.p
= newlb
.buffer
+ tokoff
;
2151 || consider_token (c
, &tok
, c_ext
, cblev
, &is_func
))
2153 if (structdef
== sinbody
2154 && definedef
== dnone
2156 /* function defined in C++ class body */
2158 sprintf (nameb
, "%s::%.*s",
2159 ((structtag
[0] == '\0')
2160 ? "_anonymous_" : structtag
),
2166 sprintf (nameb
, "%.*s", tok
.len
, tok
.p
);
2169 if (structdef
== stagseen
2172 && definedef
== dignorerest
)) /* macro */
2175 if (definedef
== dnone
2176 && (funcdef
== ftagseen
2177 || structdef
== stagseen
2180 if (newndx
== curndx
)
2181 curndx
= 1 - curndx
; /* switch line buffers */
2184 MAKE_TAG_FROM_NEW_LB (is_func
);
2188 } /* if (endtoken (c)) */
2189 else if (intoken (c
))
2194 } /* if (midtoken) */
2195 else if (begtoken (c
))
2206 MAKE_TAG_FROM_OTH_LB (TRUE
);
2213 if (structdef
== stagseen
)
2217 /* Take a quick peek ahead for a define directive,
2218 so we can avoid saving the token when not absolutely
2219 necessary. [This is a speed hack.] */
2220 if (c
== 'd' && strneq (lp
, "efine", 5)
2221 && iswhite (*(lp
+ 5)))
2224 definedef
= ddefineseen
;
2228 definedef
= dignorerest
;
2231 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
2233 tokoff
= lp
- 1 - newlb
.buffer
;
2239 } /* if must look at token */
2242 /* Detect end of line, colon, comma, semicolon and various braces
2243 after having handled a token.*/
2247 if (definedef
!= dnone
)
2249 if (structdef
== stagseen
)
2250 structdef
= scolonseen
;
2257 MAKE_TAG_FROM_OTH_LB (FALSE
);
2267 if (definedef
!= dnone
)
2273 MAKE_TAG_FROM_OTH_LB (FALSE
);
2278 if (funcdef
!= fignore
)
2280 if (structdef
== stagseen
)
2284 if (definedef
!= dnone
)
2286 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2288 if (structdef
== stagseen
)
2292 if (definedef
!= dnone
)
2294 if (cblev
== 0 && typdef
== tend
)
2297 MAKE_TAG_FROM_OTH_LB (FALSE
);
2300 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2302 if (structdef
== stagseen
)
2306 if (definedef
!= dnone
)
2315 /* Make sure that the next char is not a '*'.
2316 This handles constructs like:
2317 typedef void OperatorFun (int fun); */
2321 MAKE_TAG_FROM_OTH_LB (FALSE
);
2324 } /* switch (typdef) */
2327 funcdef
= fstartlist
;
2336 if (definedef
!= dnone
)
2344 funcdef
= flistseen
;
2347 if (cblev
== 0 && typdef
== tend
)
2350 MAKE_TAG_FROM_OTH_LB (FALSE
);
2353 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
2357 if (definedef
!= dnone
)
2359 if (typdef
== ttypedseen
)
2363 case skeyseen
: /* unnamed struct */
2364 structtag
[0] = '\0';
2365 structdef
= sinbody
;
2368 case scolonseen
: /* named struct */
2369 structdef
= sinbody
;
2370 MAKE_TAG_FROM_OTH_LB (FALSE
);
2376 MAKE_TAG_FROM_OTH_LB (TRUE
);
2382 /* Neutralize `extern "C" {' grot and look inside structs. */
2383 if (cblev
== 0 && structdef
== snone
&& typdef
== tnone
)
2389 if (definedef
!= dnone
)
2391 if (funcdef
== fstartlist
)
2392 funcdef
= fnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
2395 if (definedef
!= dnone
)
2397 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
2399 cblev
= 0; /* reset curly brace level if first column */
2400 parlev
= 0; /* also reset paren level, just in case... */
2406 if (typdef
== tinbody
)
2409 strcpy (structtag
, "<error 2>");
2413 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
2414 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
2415 if (definedef
!= dnone
)
2417 /* These surely cannot follow a function tag. */
2418 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2422 /* If a macro spans multiple lines don't reset its state. */
2430 } /* while not eof */
2434 * Process either a C++ file or a C file depending on the setting
2438 default_C_entries (inf
)
2441 C_entries (cplusplus
? C_PLPL
: 0, inf
);
2444 /* Always do C++. */
2446 Cplusplus_entries (inf
)
2449 C_entries (C_PLPL
, inf
);
2457 C_entries (C_STAR
, inf
);
2460 /* Always do Yacc. */
2465 C_entries (YACC
, inf
);
2468 /* Fortran parsing */
2477 register int len
= 0;
2479 while (*cp
&& (*cp
| ' ') == (dbp
[len
] | ' '))
2492 while (isspace (*dbp
))
2497 while (isspace (*dbp
))
2501 if (!isdigit (*dbp
))
2503 --dbp
; /* force failure */
2508 while (isdigit (*dbp
));
2517 char nambuf
[BUFSIZ
];
2519 while (isspace (*dbp
))
2524 linecharno
= charno
;
2525 charno
+= readline (&lb
, inf
);
2530 while (isspace (*dbp
))
2539 && (isalpha (*cp
) || isdigit (*cp
) || (*cp
== '_') || (*cp
== '$')));
2544 strcpy (nambuf
, dbp
);
2546 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2547 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2552 Fortran_functions (inf
)
2562 linecharno
= charno
;
2563 charno
+= readline (&lb
, inf
);
2566 dbp
++; /* Ratfor escape to fortran */
2567 while (isspace (*dbp
))
2574 if (tail ("integer"))
2582 if (tail ("logical"))
2586 if (tail ("complex") || tail ("character"))
2590 if (tail ("double"))
2592 while (isspace (*dbp
))
2596 if (tail ("precision"))
2602 while (isspace (*dbp
))
2609 if (tail ("function"))
2613 if (tail ("subroutine"))
2621 if (tail ("program"))
2626 if (tail ("procedure"))
2634 * Bob Weiner, Motorola Inc., 4/3/94
2635 * Unix and microcontroller assembly tag handling
2636 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
2642 char nambuf
[BUFSIZ
];
2653 linecharno
= charno
;
2654 charno
+= readline (&lb
, inf
);
2657 /* If first char is alphabetic or one of [_.$], test for colon
2658 following identifier. */
2659 if (isalpha (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2661 /* Read past label. */
2663 while (isalnum (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2665 if (*cp
== ':' || isspace (*cp
))
2667 /* Found end of label, so copy it and add it to the table. */
2670 strcpy (nambuf
, lb
.buffer
);
2672 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2673 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2680 /* Added by Mosur Mohan, 4/22/88 */
2681 /* Pascal parsing */
2683 #define GET_NEW_LINE \
2685 linecharno = charno; lineno++; \
2686 charno += 1 + readline (&lb, inf); \
2691 * Locates tags for procedures & functions. Doesn't do any type- or
2692 * var-definitions. It does look for the keyword "extern" or
2693 * "forward" immediately following the procedure statement; if found,
2694 * the tag is skipped.
2697 Pascal_functions (inf
)
2700 struct linebuffer tline
; /* mostly copied from C_entries */
2704 char nambuf
[BUFSIZ
];
2706 logical
/* each of these flags is TRUE iff: */
2707 incomment
, /* point is inside a comment */
2708 inquote
, /* point is inside '..' string */
2709 get_tagname
, /* point is after PROCEDURE/FUNCTION */
2710 /* keyword, so next item = potential tag */
2711 found_tag
, /* point is after a potential tag */
2712 inparms
, /* point is within parameter-list */
2713 verify_tag
; /* point has passed the parm-list, so the */
2714 /* next token will determine whether */
2715 /* this is a FORWARD/EXTERN to be */
2716 /* ignored, or whether it is a real tag */
2722 initbuffer (&tline
);
2724 incomment
= inquote
= FALSE
;
2725 found_tag
= FALSE
; /* have a proc name; check if extern */
2726 get_tagname
= FALSE
; /* have found "procedure" keyword */
2727 inparms
= FALSE
; /* found '(' after "proc" */
2728 verify_tag
= FALSE
; /* check if "extern" is ahead */
2730 /* long main loop to get next char */
2734 if (c
== 0) /* if end of line */
2739 if (!((found_tag
&& verify_tag
) ||
2741 c
= *dbp
++; /* only if don't need *dbp pointing */
2742 /* to the beginning of the name of */
2743 /* the procedure or function */
2747 if (c
== '}') /* within { - } comments */
2749 else if (c
== '*' && dbp
[1] == ')') /* within (* - *) comments */
2766 inquote
= TRUE
; /* found first quote */
2768 case '{': /* found open-{-comment */
2772 if (*dbp
== '*') /* found open-(*-comment */
2777 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2780 case ')': /* end of parms list */
2785 if ((found_tag
) && (!inparms
)) /* end of proc or fn stmt */
2792 if ((found_tag
) && (verify_tag
) && (*dbp
!= ' '))
2794 /* check if this is an "extern" declaration */
2797 if ((*dbp
== 'e') || (*dbp
== 'E'))
2799 if (tail ("extern")) /* superfluous, really! */
2805 else if ((*dbp
== 'f') || (*dbp
== 'F'))
2807 if (tail ("forward")) /* check for forward reference */
2813 if ((found_tag
) && (verify_tag
)) /* not external proc, so make tag */
2817 pfnote (nambuf
, TRUE
, FALSE
,
2818 tline
.buffer
, cp
- tline
.buffer
+ 1,
2819 save_lineno
, save_lcno
);
2823 if (get_tagname
) /* grab name of proc or fn */
2828 /* save all values for later tagging */
2829 tline
.size
= lb
.size
;
2830 strcpy (tline
.buffer
, lb
.buffer
);
2831 save_lineno
= lineno
;
2832 save_lcno
= linecharno
;
2834 /* grab block name */
2835 for (cp
= dbp
+ 1; *cp
&& (!endtoken (*cp
)); cp
++)
2839 strcpy (nambuf
, dbp
);
2841 dbp
= cp
; /* restore dbp to e-o-token */
2842 get_tagname
= FALSE
;
2846 /* and proceed to check for "extern" */
2848 if (!incomment
&& !inquote
&& !found_tag
&& !get_tagname
)
2850 /* check for proc/fn keywords */
2854 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2858 if (tail ("unction"))
2863 } /* while not eof */
2867 * lisp tag functions
2868 * just look for (def or (DEF
2873 register char *tokp
;
2875 return ((tokp
[1] == 'd' || tokp
[1] == 'D')
2876 && (tokp
[2] == 'e' || tokp
[2] == 'E')
2877 && (tokp
[3] == 'f' || tokp
[3] == 'F'));
2882 register char *tokp
;
2884 return ((*(++tokp
) == 'q' || *tokp
== 'Q')
2885 && (*(++tokp
) == 'u' || *tokp
== 'U')
2886 && (*(++tokp
) == 'o' || *tokp
== 'O')
2887 && (*(++tokp
) == 't' || *tokp
== 'T')
2888 && (*(++tokp
) == 'e' || *tokp
== 'E')
2889 && isspace(*(++tokp
)));
2897 char nambuf
[BUFSIZ
];
2899 if (*dbp
== '\'') /* Skip prefix quote */
2901 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2904 while (isspace(*dbp
))
2907 for (cp
= dbp
/*+1*/; *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')'; cp
++)
2914 strcpy (nambuf
, dbp
);
2916 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
,
2917 cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2922 Lisp_functions (inf
)
2932 linecharno
= charno
;
2933 charno
+= readline (&lb
, inf
);
2939 while (!isspace (*dbp
))
2941 while (isspace (*dbp
))
2947 /* Check for (foo::defmumble name-defined ... */
2950 while (*dbp
&& !isspace (*dbp
)
2951 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2956 while (*dbp
== ':');
2958 if (L_isdef (dbp
- 1))
2960 while (!isspace (*dbp
))
2962 while (isspace (*dbp
))
2973 * Scheme tag functions
2974 * look for (def... xyzzy
2975 * look for (def... (xyzzy
2976 * look for (def ... ((...(xyzzy ....
2977 * look for (set! xyzzy
2983 Scheme_functions (inf
)
2993 linecharno
= charno
;
2994 charno
+= readline (&lb
, inf
);
2996 if (dbp
[0] == '(' &&
2997 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2998 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2999 (dbp
[3] == 'F' || dbp
[3] == 'f'))
3001 while (!isspace (*dbp
))
3003 /* Skip over open parens and white space */
3004 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
3008 if (dbp
[0] == '(' &&
3009 (dbp
[1] == 'S' || dbp
[1] == 's') &&
3010 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
3011 (dbp
[3] == 'T' || dbp
[3] == 't') &&
3012 (dbp
[4] == '!' || dbp
[4] == '!') &&
3015 while (!isspace (*dbp
))
3017 /* Skip over white space */
3018 while (isspace (*dbp
))
3030 char nambuf
[BUFSIZ
];
3034 /* Go till you get to white space or a syntactic break */
3035 for (cp
= dbp
+ 1; *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
); cp
++)
3037 /* Null terminate the string there. */
3040 /* Copy the string */
3041 strcpy (nambuf
, dbp
);
3042 /* Unterminate the string */
3044 /* Announce the change */
3045 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
3049 /* Find tags in TeX and LaTeX input files. */
3051 /* TEX_toktab is a table of TeX control sequences that define tags.
3052 Each TEX_tabent records one such control sequence.
3053 CONVERT THIS TO USE THE Stab TYPE!! */
3060 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
3062 /* Default set of control sequences to put into TEX_toktab.
3063 The value of environment var TEXTAGS is prepended to this. */
3065 char *TEX_defenv
= "\
3066 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
3069 struct TEX_tabent
*TEX_decode_env ();
3073 char TEX_esc
= '\\';
3074 char TEX_opgrp
= '{';
3075 char TEX_clgrp
= '}';
3078 * TeX/LaTeX scanning loop.
3090 /* Select either \ or ! as escape character. */
3093 /* Initialize token table once from environment. */
3095 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
3098 { /* Scan each line in file */
3100 linecharno
= charno
;
3101 charno
+= readline (&lb
, inf
);
3104 while (dbp
= etags_strchr (dbp
, TEX_esc
)) /* Look at each esc in line */
3110 linecharno
+= dbp
- lasthit
;
3112 i
= TEX_Token (lasthit
);
3115 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
3116 break; /* We only save a line once */
3122 #define TEX_LESC '\\'
3123 #define TEX_SESC '!'
3126 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
3127 chars accordingly. */
3134 while ((c
= getc (inf
)) != EOF
)
3136 /* Skip to next line if we hit the TeX comment char. */
3140 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
3159 /* Read environment and prepend it to the default string.
3160 Build token table. */
3162 TEX_decode_env (evarname
, defenv
)
3166 register char *env
, *p
;
3168 struct TEX_tabent
*tab
;
3171 /* Append default string to environment. */
3172 env
= getenv (evarname
);
3176 env
= concat (env
, defenv
, "");
3178 /* Allocate a token table */
3179 for (size
= 1, p
= env
; p
;)
3180 if ((p
= etags_strchr (p
, ':')) && *(++p
))
3182 /* Add 1 to leave room for null terminator. */
3183 tab
= xnew (size
+ 1, struct TEX_tabent
);
3185 /* Unpack environment string into token table. Be careful about */
3186 /* zero-length strings (leading ':', "::" and trailing ':') */
3189 p
= etags_strchr (env
, ':');
3190 if (!p
) /* End of environment string. */
3191 p
= env
+ strlen (env
);
3193 { /* Only non-zero strings. */
3194 tab
[i
].name
= savenstr (env
, p
- env
);
3195 tab
[i
].len
= strlen (tab
[i
].name
);
3202 tab
[i
].name
= NULL
; /* Mark end of table. */
3210 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
3211 The name being defined actually starts at (NAME + LEN + 1).
3212 But we seem to include the TeX command in the tag name. */
3214 TEX_getit (name
, len
)
3218 char *p
= name
+ len
;
3219 char nambuf
[BUFSIZ
];
3224 /* Let tag name extend to next group close (or end of line) */
3225 while (*p
&& *p
!= TEX_clgrp
)
3227 strncpy (nambuf
, name
, p
- name
);
3228 nambuf
[p
- name
] = 0;
3230 pfnote (nambuf
, TRUE
, FALSE
, lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
3234 /* If the text at CP matches one of the tag-defining TeX command names,
3235 return the pointer to the first occurrence of that command in TEX_toktab.
3236 Otherwise return -1.
3237 Keep the capital `T' in `Token' for dumb truncating compilers
3238 (this distinguishes it from `TEX_toktab' */
3245 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
3246 if (strneq (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
))
3251 /* Support for Prolog. */
3253 /* Whole head (not only functor, but also arguments)
3254 is gotten in compound term. */
3259 char nambuf
[BUFSIZ
], *save_s
, tmpc
;
3267 if (*s
== '\0') /* syntax error. */
3269 else if (insquote
&& *s
== '\'' && *(s
+ 1) == '\'')
3271 else if (*s
== '\'')
3273 insquote
= !insquote
;
3276 else if (!insquote
&& *s
== '(')
3281 else if (!insquote
&& *s
== ')')
3287 else if (npar
< 0) /* syntax error. */
3290 else if (!insquote
&& *s
== '.' && (isspace (*(s
+ 1)) || *(s
+ 1) == '\0'))
3292 if (npar
!= 0) /* syntax error. */
3302 strcpy (nambuf
, save_s
);
3304 pfnote (nambuf
, TRUE
, FALSE
, save_s
, strlen (nambuf
), lineno
, linecharno
);
3307 /* It is assumed that prolog predicate starts from column 0. */
3309 Prolog_functions (inf
)
3312 void skip_comment (), prolog_getit ();
3314 lineno
= linecharno
= charno
= 0;
3318 linecharno
+= charno
;
3319 charno
= readline (&lb
, inf
) + 1; /* 1 for newline. */
3321 if (isspace (dbp
[0])) /* not predicate header. */
3323 else if (dbp
[0] == '%') /* comment. */
3325 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
3326 skip_comment (&lb
, inf
, &lineno
, &linecharno
);
3333 skip_comment (plb
, inf
, plineno
, plinecharno
)
3334 struct linebuffer
*plb
;
3336 int *plineno
; /* result */
3337 long *plinecharno
; /* result */
3343 for (cp
= plb
->buffer
; *cp
!= '\0'; cp
++)
3344 if (cp
[0] == '*' && cp
[1] == '/')
3347 *plinecharno
+= readline (plb
, inf
) + 1; /* 1 for newline. */
3352 #ifdef ETAGS_REGEXPS
3353 /* Take a string like "/blah/" and turn it into "blah", making sure
3354 that the first and last characters are the same, and handling
3355 quoted separator characters. Actually, stops on the occurence of
3356 an unquoted separator. Also turns "\t" into a Tab character.
3357 Returns pointer to terminating separator. Works in place. Null
3358 terminates name string. */
3360 scan_separators (name
)
3364 char *copyto
= name
;
3365 logical quoted
= FALSE
;
3367 for (++name
; *name
!= '\0'; ++name
)
3373 else if (*name
== sep
)
3377 /* Something else is quoted, so preserve the quote. */
3383 else if (*name
== '\\')
3385 else if (*name
== sep
)
3391 /* Terminate copied string. */
3396 /* Turn a name, which is an ed-style (but Emacs syntax) regular
3397 expression, into a real regular expression by compiling it. */
3399 add_regex (regexp_pattern
)
3400 char *regexp_pattern
;
3404 struct re_pattern_buffer
*patbuf
;
3406 if (regexp_pattern
== NULL
)
3408 /* Remove existing regexps. */
3414 if (regexp_pattern
[0] == '\0')
3416 error ("missing regexp", 0);
3419 if (regexp_pattern
[strlen(regexp_pattern
)-1] != regexp_pattern
[0])
3421 error ("%s: unterminated regexp", regexp_pattern
);
3424 name
= scan_separators (regexp_pattern
);
3425 if (regexp_pattern
[0] == '\0')
3427 error ("null regexp", 0);
3430 (void) scan_separators (name
);
3432 patbuf
= xnew (1, struct re_pattern_buffer
);
3433 patbuf
->translate
= NULL
;
3434 patbuf
->fastmap
= NULL
;
3435 patbuf
->buffer
= NULL
;
3436 patbuf
->allocated
= 0;
3438 err
= re_compile_pattern (regexp_pattern
, strlen (regexp_pattern
), patbuf
);
3441 error ("%s while compiling pattern", err
);
3446 if (num_patterns
== 1)
3447 patterns
= xnew (1, struct pattern
);
3449 patterns
= ((struct pattern
*)
3451 (num_patterns
* sizeof (struct pattern
))));
3452 patterns
[num_patterns
- 1].pattern
= patbuf
;
3453 patterns
[num_patterns
- 1].name_pattern
= savestr (name
);
3454 patterns
[num_patterns
- 1].error_signaled
= FALSE
;
3458 * Do the subtitutions indicated by the regular expression and
3462 substitute (in
, out
, regs
)
3464 struct re_registers
*regs
;
3466 char *result
= NULL
, *t
;
3469 /* Pass 1: figure out how much size to allocate. */
3470 for (t
= out
; *t
; ++t
)
3477 fprintf (stderr
, "%s: pattern subtitution ends prematurely\n",
3484 size
+= regs
->end
[dig
] - regs
->start
[dig
];
3489 /* Allocate space and do the substitutions. */
3490 result
= xnew (size
+ 1, char);
3499 /* Using "dig2" satisfies my debugger. Bleah. */
3500 int dig2
= *out
- '0';
3501 strncpy (result
+ size
, in
+ regs
->start
[dig2
],
3502 regs
->end
[dig2
] - regs
->start
[dig2
]);
3503 size
+= regs
->end
[dig2
] - regs
->start
[dig2
];
3510 result
[size
++] = '\t';
3516 result
[size
++] = *out
;
3522 result
[size
++] = *out
;
3524 result
[size
] = '\0';
3529 #endif /* ETAGS_REGEXPS */
3530 /* Initialize a linebuffer for use */
3532 initbuffer (linebuffer
)
3533 struct linebuffer
*linebuffer
;
3535 linebuffer
->size
= 200;
3536 linebuffer
->buffer
= xnew (200, char);
3540 * Read a line of text from `stream' into `linebuffer'.
3541 * Return the number of characters read from `stream',
3542 * which is the length of the line including the newline, if any.
3545 readline_internal (linebuffer
, stream
)
3546 struct linebuffer
*linebuffer
;
3547 register FILE *stream
;
3549 char *buffer
= linebuffer
->buffer
;
3550 register char *p
= linebuffer
->buffer
;
3551 register char *pend
;
3554 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
3558 register int c
= getc (stream
);
3561 linebuffer
->size
*= 2;
3562 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
3563 p
+= buffer
- linebuffer
->buffer
;
3564 pend
= buffer
+ linebuffer
->size
;
3565 linebuffer
->buffer
= buffer
;
3574 if (p
[-1] == '\r' && p
> buffer
)
3589 return p
- buffer
+ chars_deleted
;
3593 * Like readline_internal, above, but try to match the input
3594 * line against any existing regular expressions.
3597 readline (linebuffer
, stream
)
3598 struct linebuffer
*linebuffer
;
3601 /* Read new line. */
3603 long result
= readline_internal (linebuffer
, stream
);
3605 #ifdef ETAGS_REGEXPS
3606 /* Match against all listed patterns. */
3607 for (i
= 0; i
< num_patterns
; ++i
)
3609 int match
= re_match (patterns
[i
].pattern
, linebuffer
->buffer
,
3610 (int)result
, 0, &patterns
[i
].regs
);
3615 if (!patterns
[i
].error_signaled
)
3617 error ("error while matching pattern %d", i
);
3618 patterns
[i
].error_signaled
= TRUE
;
3625 /* Match occurred. Construct a tag. */
3626 if (patterns
[i
].name_pattern
[0] != '\0')
3628 /* Make a named tag. */
3629 char *name
= substitute (linebuffer
->buffer
,
3630 patterns
[i
].name_pattern
,
3633 pfnote (name
, TRUE
, TRUE
, linebuffer
->buffer
,
3634 match
, lineno
, linecharno
);
3638 /* Make an unnamed tag. */
3639 pfnote (NULL
, TRUE
, FALSE
, linebuffer
->buffer
,
3640 match
, lineno
, linecharno
);
3645 #endif /* ETAGS_REGEXPS */
3651 * Read a file, but do no processing. This is used to do regexp
3652 * matching on files that have no language defined.
3655 just_read_file (inf
)
3661 linecharno
= charno
;
3662 charno
+= readline (&lb
, inf
) + 1;
3671 return savenstr (cp
, strlen (cp
));
3681 dp
= xnew (len
+ 1, char);
3682 strncpy (dp
, cp
, len
);
3688 * Return the ptr in sp at which the character c last
3689 * appears; NULL if not found
3691 * Identical to System V strrchr, included for portability.
3694 etags_strrchr (sp
, c
)
3695 register char *sp
, c
;
3710 * Return the ptr in sp at which the character c first
3711 * appears; NULL if not found
3713 * Identical to System V strchr, included for portability.
3716 etags_strchr (sp
, c
)
3717 register char *sp
, c
;
3727 /* Print error message and exit. */
3744 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3749 fprintf (stderr
, "%s: ", progname
);
3750 fprintf (stderr
, s1
, s2
);
3751 fprintf (stderr
, "\n");
3754 /* Return a newly-allocated string whose contents
3755 concatenate those of s1, s2, s3. */
3760 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3761 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3763 strcpy (result
, s1
);
3764 strcpy (result
+ len1
, s2
);
3765 strcpy (result
+ len1
+ len2
, s3
);
3766 result
[len1
+ len2
+ len3
] = '\0';
3771 /* Does the same work as the system V getcwd, but does not need to
3772 guess buffer size in advance. */
3777 char *p
, path
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
3785 *p
++ = tolower (*p
);
3787 return strdup (path
);
3789 #elif HAVE_GETCWD /* not DOS_NT */
3792 char *path
= xnew (bufsize
, char);
3794 while (getcwd (path
, bufsize
) == NULL
)
3796 if (errno
!= ERANGE
)
3799 path
= xnew (bufsize
, char);
3804 #else /* not DOS_NT and not HAVE_GETCWD */
3806 struct linebuffer path
;
3810 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
3811 if (pipe
== NULL
|| readline_internal (&path
, pipe
) == 0)
3817 #endif /* not DOS_NT and not HAVE_GETCWD */
3819 /* Return a newly allocated string containing the filename
3820 of FILE relative to the absolute directory DIR (which
3821 should end with a slash). */
3823 relative_filename (file
, dir
)
3826 char *fp
, *dp
, *res
;
3828 /* Find the common root of file and dir. */
3829 fp
= absolute_filename (file
, cwd
);
3831 while (*fp
++ == *dp
++)
3840 /* Build a sequence of "../" strings for the resulting relative filename. */
3841 for (dp
= etags_strchr (dp
+ 1, '/'), res
= "";
3843 dp
= etags_strchr (dp
+ 1, '/'))
3845 res
= concat (res
, "../", "");
3848 /* Add the filename relative to the common root of file and dir. */
3849 res
= concat (res
, fp
+ 1, "");
3851 return res
; /* temporary stub */
3854 /* Return a newly allocated string containing the
3855 absolute filename of FILE given CWD (which should
3856 end with a slash). */
3858 absolute_filename (file
, cwd
)
3861 char *slashp
, *cp
, *res
;
3864 res
= concat (file
, "", "");
3866 res
= concat (cwd
, file
, "");
3868 /* Delete the "/dirname/.." and "/." substrings. */
3869 slashp
= etags_strchr (res
, '/');
3870 while (slashp
!= NULL
&& slashp
[0] != '\0')
3872 if (slashp
[1] == '.')
3874 if (slashp
[2] == '.'
3875 && (slashp
[3] == '/' || slashp
[3] == '\0'))
3880 while (cp
>= res
&& *cp
!= '/');
3883 strcpy (cp
, slashp
+ 3);
3885 else /* else (cp == res) */
3887 if (slashp
[3] != '\0')
3888 strcpy (cp
, slashp
+ 4);
3895 else if (slashp
[2] == '/' || slashp
[2] == '\0')
3897 strcpy (slashp
, slashp
+ 2);
3902 slashp
= etags_strchr (slashp
+ 1, '/');
3908 /* Return a newly allocated string containing the absolute
3909 filename of dir where FILE resides given CWD (which should
3910 end with a slash). */
3912 absolute_dirname (file
, cwd
)
3918 slashp
= etags_strrchr (file
, '/');
3923 res
= absolute_filename (file
, cwd
);
3929 /* Like malloc but get fatal error if memory is exhausted. */
3934 char *result
= (char *) malloc (size
);
3936 fatal ("virtual memory exhausted", 0);
3941 xrealloc (ptr
, size
)
3945 char *result
= (char *) realloc (ptr
, size
);
3947 fatal ("virtual memory exhausted");