1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 87, 88, 89, 93, 94, 95
3 Free Software Foundation, Inc. and Ken Arnold
4 This file is not considered part of GNU Emacs.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22 * Ctags originally by Ken Arnold.
23 * Fortran added by Jim Kleckner.
24 * Ed Pelegri-Llopart added C typedefs.
25 * Gnu Emacs TAGS format and modifications by RMS?
26 * Sam Kendall added C++.
27 * Francesco Potorti` reorganised C and C++ based on work by Joe Wells.
29 * Regexp tags by Tom Tromey.
32 * Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer.
35 char pot_etags_version
[] = "@(#) pot revision number is 11.42";
45 #include <sys/param.h>
52 #define MAXPATHLEN _MAX_PATH
57 /* On some systems, Emacs defines static as nothing for the sake
58 of unexec. We don't want that here since we don't use unexec. */
68 #include <sys/types.h>
71 #if !defined (S_ISREG) && defined (S_IFREG)
72 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
79 #endif /* ETAGS_REGEXPS */
81 /* Define CTAGS to make the program "ctags" compatible with the usual one.
82 Let it undefined to make the program "etags", which makes emacs-style
83 tag tables and tags typedefs, #defines and struct/union/enum by default. */
91 /* Exit codes for success and failure. */
101 #define C_PLPL 0x00001 /* C++ */
102 #define C_STAR 0x00003 /* C* */
103 #define YACC 0x10000 /* yacc file */
105 #define streq(s,t) (strcmp (s, t) == 0)
106 #define strneq(s,t,n) (strncmp (s, t, n) == 0)
108 #define lowcase(c) tolower ((unsigned char)c)
110 #define iswhite(arg) (_wht[arg]) /* T if char is white */
111 #define begtoken(arg) (_btk[arg]) /* T if char can start token */
112 #define intoken(arg) (_itk[arg]) /* T if char can be in token */
113 #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
116 # define absolutefn(fn) (fn[0] == '/' || (isalpha (fn[0]) && fn[1] == ':'))
118 # define absolutefn(fn) (fn[0] == '/')
123 * xnew -- allocate storage
125 * SYNOPSIS: Type *xnew (int n, Type);
127 #define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
132 { /* sorting structure */
133 char *name
; /* function or type name */
134 char *file
; /* file name */
135 logical is_func
; /* use pattern or line no */
136 logical been_warned
; /* set if noticed dup */
137 int lno
; /* line number tag is on */
138 long cno
; /* character number line starts on */
139 char *pat
; /* search pattern */
140 struct nd_st
*left
, *right
; /* left and right sons */
143 extern char *getenv ();
146 char *savenstr (), *savestr ();
147 char *etags_strchr (), *etags_strrchr ();
148 char *etags_getcwd ();
149 char *relative_filename (), *absolute_filename (), *absolute_dirname ();
150 long *xmalloc (), *xrealloc ();
152 typedef void Lang_function ();
153 #if FALSE /* many compilers barf on this */
154 Lang_function Asm_labels
;
155 Lang_function default_C_entries
;
156 Lang_function C_entries
;
157 Lang_function Cplusplus_entries
;
158 Lang_function Cstar_entries
;
159 Lang_function Fortran_functions
;
160 Lang_function Yacc_entries
;
161 Lang_function Lisp_functions
;
162 Lang_function Pascal_functions
;
163 Lang_function Prolog_functions
;
164 Lang_function Scheme_functions
;
165 Lang_function TeX_functions
;
166 Lang_function just_read_file
;
167 #else /* so let's write it this way */
170 void default_C_entries ();
171 void plain_C_entries ();
172 void Cplusplus_entries ();
173 void Cstar_entries ();
174 void Fortran_functions ();
175 void Yacc_entries ();
176 void Lisp_functions ();
177 void Pascal_functions ();
178 void Prolog_functions ();
179 void Scheme_functions ();
180 void TeX_functions ();
181 void just_read_file ();
184 logical
get_language ();
185 int total_size_of_entries ();
187 long readline_internal ();
193 void fatal (), pfatal ();
194 void find_entries ();
200 void process_file ();
205 char searchar
= '/'; /* use /.../ searches */
207 int lineno
; /* line number of current line */
208 long charno
; /* current character number */
210 long linecharno
; /* charno of start of line; not used by C,
211 but by every other language. */
213 char *curfile
; /* current input file name */
214 char *tagfile
; /* output file */
215 char *progname
; /* name this program was invoked with */
216 char *cwd
; /* current working directory */
217 char *tagfiledir
; /* directory of tagfile */
219 FILE *tagf
; /* ioptr for tags file */
220 NODE
*head
; /* the head of the binary tree of tags */
223 * A `struct linebuffer' is a structure which holds a line of text.
224 * `readline' reads a line from a stream into a linebuffer and works
225 * regardless of the length of the line.
233 struct linebuffer lb
; /* the current line */
234 struct linebuffer token_name
; /* used by C_entries as temporary area */
238 struct linebuffer lb
; /* used by C_entries instead of lb */
241 /* boolean "functions" (see init) */
242 logical _wht
[0177], _etk
[0177], _itk
[0177], _btk
[0177];
244 *white
= " \f\t\n\013", /* white chars */
245 *endtk
= " \t\n\013\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */
246 /* token starting chars */
247 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~",
248 /* valid in-token chars */
249 *intk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
251 logical append_to_tagfile
; /* -a: append to tags */
252 /* The following three default to TRUE for etags, but to FALSE for ctags. */
253 logical typedefs
; /* -t: create tags for typedefs */
254 logical typedefs_and_cplusplus
; /* -T: create tags for typedefs, level */
255 /* 0 struct/enum/union decls, and C++ */
256 /* member functions. */
257 logical constantypedefs
; /* -d: create tags for C #define and enum */
258 /* constants. Enum consts not implemented. */
259 /* -D: opposite of -d. Default under ctags. */
260 logical update
; /* -u: update tags */
261 logical vgrind_style
; /* -v: create vgrind style index output */
262 logical no_warnings
; /* -w: suppress warnings */
263 logical cxref_style
; /* -x: create cxref style output */
264 logical cplusplus
; /* .[hc] means C++, not C */
265 logical noindentypedefs
; /* -I: ignore indentation in C */
267 struct option longopts
[] =
269 { "append", no_argument
, NULL
, 'a' },
270 { "backward-search", no_argument
, NULL
, 'B' },
271 { "c++", no_argument
, NULL
, 'C' },
272 { "cxref", no_argument
, NULL
, 'x' },
273 { "defines", no_argument
, NULL
, 'd' },
274 { "help", no_argument
, NULL
, 'h' },
275 { "help", no_argument
, NULL
, 'H' },
276 { "ignore-indentation", no_argument
, NULL
, 'I' },
277 { "include", required_argument
, NULL
, 'i' },
278 { "language", required_argument
, NULL
, 'l' },
279 { "no-defines", no_argument
, NULL
, 'D' },
280 { "no-regex", no_argument
, NULL
, 'R' },
281 { "no-warn", no_argument
, NULL
, 'w' },
282 { "output", required_argument
, NULL
, 'o' },
283 { "regex", required_argument
, NULL
, 'r' },
284 { "typedefs", no_argument
, NULL
, 't' },
285 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
286 { "update", no_argument
, NULL
, 'u' },
287 { "version", no_argument
, NULL
, 'V' },
288 { "vgrind", no_argument
, NULL
, 'v' },
293 /* Structure defining a regular expression. Elements are
294 the compiled pattern, and the name string. */
297 struct re_pattern_buffer
*pattern
;
298 struct re_registers regs
;
300 logical error_signaled
;
303 /* Number of regexps found. */
304 int num_patterns
= 0;
306 /* Array of all regexps. */
307 struct pattern
*patterns
= NULL
;
308 #endif /* ETAGS_REGEXPS */
310 /* Language stuff. */
314 Lang_function
*function
;
317 /* Table of language names and corresponding functions. */
318 /* It is ok for a given function to be listed under more than one
319 name. I just didn't. */
320 /* "auto" language reverts to default behavior. */
321 struct lang_entry lang_names
[] =
323 { "asm", Asm_labels
},
324 { "c", default_C_entries
},
325 { "c++", Cplusplus_entries
},
326 { "c*", Cstar_entries
},
327 { "fortran", Fortran_functions
},
328 { "lisp", Lisp_functions
},
329 { "none", just_read_file
},
330 { "pascal", Pascal_functions
},
331 { "scheme" , Scheme_functions
},
332 { "tex", TeX_functions
},
337 /* Table of file name suffixes and corresponding language functions. */
338 struct lang_entry lang_suffixes
[] =
341 { "a", Asm_labels
}, /* Unix assembler */
342 { "asm", Asm_labels
}, /* Microcontroller assembly */
343 { "def", Asm_labels
}, /* BSO/Tasking definition includes */
344 { "inc", Asm_labels
}, /* Microcontroller include files */
345 { "ins", Asm_labels
}, /* Microcontroller include files */
347 { "sa", Asm_labels
}, /* Unix assembler */
348 { "src", Asm_labels
}, /* BSO/Tasking C compiler output */
350 /* LaTeX source code */
351 { "bib", TeX_functions
},
352 { "clo", TeX_functions
},
353 { "cls", TeX_functions
},
354 { "ltx", TeX_functions
},
355 { "sty", TeX_functions
},
356 { "TeX", TeX_functions
},
357 { "tex", TeX_functions
},
359 /* Lisp source code */
360 { "cl", Lisp_functions
},
361 { "clisp", Lisp_functions
},
362 { "el", Lisp_functions
},
363 { "l", Lisp_functions
},
364 { "lisp", Lisp_functions
},
365 { "lsp", Lisp_functions
},
366 { "ml", Lisp_functions
},
368 /* Scheme source code */
369 { "SCM", Scheme_functions
},
370 { "SM", Scheme_functions
},
371 { "oak", Scheme_functions
},
372 { "sch", Scheme_functions
},
373 { "scheme", Scheme_functions
},
374 { "scm", Scheme_functions
},
375 { "sm", Scheme_functions
},
376 { "t", Scheme_functions
},
377 /* FIXME Can't do the `SCM' or `scm' prefix with a version number */
379 /* Note that .c and .h can be considered C++, if the --c++ flag was
380 given. That is why default_C_entries is called here. */
381 { "c", default_C_entries
},
382 { "h", default_C_entries
},
385 { "pc", plain_C_entries
},
388 { "C", Cplusplus_entries
},
389 { "H", Cplusplus_entries
},
390 { "c++", Cplusplus_entries
},
391 { "cc", Cplusplus_entries
},
392 { "cpp", Cplusplus_entries
},
393 { "cxx", Cplusplus_entries
},
394 { "h++", Cplusplus_entries
},
395 { "hh", Cplusplus_entries
},
396 { "hpp", Cplusplus_entries
},
397 { "hxx", Cplusplus_entries
},
400 { "y", Yacc_entries
},
403 { "cs", Cstar_entries
},
404 { "hs", Cstar_entries
},
407 { "F", Fortran_functions
},
408 { "f", Fortran_functions
},
409 { "f90", Fortran_functions
},
410 { "for", Fortran_functions
},
412 /* Prolog source code */
413 { "prolog", Prolog_functions
},
416 { "p", Pascal_functions
},
417 { "pas", Pascal_functions
},
422 /* Non-NULL if language fixed. */
423 Lang_function
*lang_func
= NULL
;
427 print_language_names ()
429 struct lang_entry
*name
, *ext
;
431 puts ("\nThese are the currently supported languages, along with the\n\
432 default file name suffixes:");
433 for (name
= lang_names
; name
->suffix
; ++name
)
435 printf ("\t%s\t", name
->suffix
);
436 for (ext
= lang_suffixes
; ext
->suffix
; ++ext
)
437 if (name
->function
== ext
->function
)
438 printf (" .%s", ext
->suffix
);
441 puts ("Where `auto' means use default language for files based on file\n\
442 name suffix, and `none' means only do regexp processing on files.\n\
443 If no language is specified and no matching suffix is found,\n\
444 Fortran is tried first; if no tags are found, C is tried next.");
448 # define VERSION "19"
453 printf ("%s for Emacs version %s\n", (CTAGS
) ? "ctags" : "etags", VERSION
);
461 printf ("These are the options accepted by %s. You may use unambiguous\n\
462 abbreviations for the long option names. A - as file name means read\n\
463 names from stdin.\n\n", progname
);
465 puts ("-a, --append\n\
466 Append tag entries to existing tags file.");
469 puts ("-B, --backward-search\n\
470 Write the search commands for the tag entries using '?', the\n\
471 backward-search command instead of '/', the forward-search command.");
474 Treat files whose name suffix defaults to C language as C++ files.");
477 puts ("-d, --defines\n\
478 Create tag entries for constant C #defines, too.");
480 puts ("-D, --no-defines\n\
481 Don't create tag entries for constant C #defines. This makes\n\
482 the tags file smaller.");
486 puts ("-i FILE, --include=FILE\n\
487 Include a note in tag file indicating that, when searching for\n\
488 a tag, one should also consult the tags file FILE after\n\
489 checking the current file.");
490 puts ("-l LANG, --language=LANG\n\
491 Force the following files to be considered as written in the\n\
492 named language up to the next --language=LANG option.");
496 puts ("-r /REGEXP/, --regex=/REGEXP/\n\
497 Make a tag for each line matching pattern REGEXP in the\n\
498 following files. REGEXP is anchored (as if preceded by ^).\n\
499 The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
500 named tags can be created with:\n\
501 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
502 puts ("-R, --no-regex\n\
503 Don't create tags from regexps for the following files.");
504 #endif /* ETAGS_REGEXPS */
505 puts ("-o FILE, --output=FILE\n\
506 Write the tags to FILE.");
507 puts ("-I, --ignore-indentation\n\
508 Don't rely on indentation quite as much as normal. Currently,\n\
509 this means not to assume that a closing brace in the first\n\
510 column is the final brace of a function or structure\n\
511 definition in C and C++.");
515 puts ("-t, --typedefs\n\
516 Generate tag entries for C typedefs.");
517 puts ("-T, --typedefs-and-c++\n\
518 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
519 and C++ member functions.");
520 puts ("-u, --update\n\
521 Update the tag entries for the given files, leaving tag\n\
522 entries for other files in place. Currently, this is\n\
523 implemented by deleting the existing entries for the given\n\
524 files and then rewriting the new entries at the end of the\n\
525 tags file. It is often faster to simply rebuild the entire\n\
526 tag file than to use this.");
527 puts ("-v, --vgrind\n\
528 Generates an index of items intended for human consumption,\n\
529 similar to the output of vgrind. The index is sorted, and\n\
530 gives the page number of each item.");
531 puts ("-w, --no-warn\n\
532 Suppress warning messages about entries defined in multiple\n\
534 puts ("-x, --cxref\n\
535 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
536 The output uses line numbers instead of page numbers, but\n\
537 beyond that the differences are cosmetic; try both to see\n\
541 puts ("-V, --version\n\
542 Print the version of the program.\n\
544 Print this help message.");
546 print_language_names ();
559 /* This structure helps us allow mixing of --lang and filenames. */
562 enum argument_type arg_type
;
564 Lang_function
*function
;
567 #ifdef VMS /* VMS specific functions */
571 /* This is a BUG! ANY arbitrary limit is a BUG!
572 Won't someone please fix this? */
573 #define MAX_FILE_SPEC_LEN 255
576 char body
[MAX_FILE_SPEC_LEN
+ 1];
580 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
581 returning in each successive call the next filename matching the input
582 spec. The function expects that each in_spec passed
583 to it will be processed to completion; in particular, up to and
584 including the call following that in which the last matching name
585 is returned, the function ignores the value of in_spec, and will
586 only start processing a new spec with the following call.
587 If an error occurs, on return out_spec contains the value
588 of in_spec when the error occurred.
590 With each successive filename returned in out_spec, the
591 function's return value is one. When there are no more matching
592 names the function returns zero. If on the first call no file
593 matches in_spec, or there is any other error, -1 is returned.
598 #define OUTSIZE MAX_FILE_SPEC_LEN
604 static long context
= 0;
605 static struct dsc$descriptor_s o
;
606 static struct dsc$descriptor_s i
;
607 static logical pass1
= TRUE
;
614 o
.dsc$a_pointer
= (char *) out
;
615 o
.dsc$w_length
= (short)OUTSIZE
;
616 i
.dsc$a_pointer
= in
;
617 i
.dsc$w_length
= (short)strlen(in
);
618 i
.dsc$b_dtype
= DSC$K_DTYPE_T
;
619 i
.dsc$b_class
= DSC$K_CLASS_S
;
620 o
.dsc$b_dtype
= DSC$K_DTYPE_VT
;
621 o
.dsc$b_class
= DSC$K_CLASS_VS
;
623 if ((status
= lib$
find_file(&i
, &o
, &context
, 0, 0)) == RMS$_NORMAL
)
625 out
->body
[out
->curlen
] = EOS
;
628 else if (status
== RMS$_NMF
)
632 strcpy(out
->body
, in
);
635 lib$
find_file_end(&context
);
641 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
642 name of each file specified by the provided arg expanding wildcards.
645 gfnames (arg
, p_error
)
649 static vspec filename
= {MAX_FILE_SPEC_LEN
, "\0"};
651 switch (fn_exp (&filename
, arg
))
655 return filename
.body
;
661 return filename
.body
;
665 #ifndef OLD /* Newer versions of VMS do provide `system'. */
669 fprintf (stderr
, "system() function not implemented under VMS\n");
673 #define VERSION_DELIM ';'
674 char *massage_name (s
)
680 if (*s
== VERSION_DELIM
)
698 unsigned int nincluded_files
= 0;
699 char **included_files
= xnew (argc
, char *);
702 int current_arg
= 0, file_count
= 0;
703 struct linebuffer filename_lb
;
709 _fmode
= O_BINARY
; /* all of files are treated as binary files */
714 /* Allocate enough no matter what happens. Overkill, but each one
716 argbuffer
= xnew (argc
, ARGUMENT
);
719 /* Set syntax for regular expression routines. */
720 re_set_syntax (RE_SYNTAX_EMACS
);
721 #endif /* ETAGS_REGEXPS */
724 * If etags, always find typedefs and structure tags. Why not?
725 * Also default is to find macro constants.
728 typedefs
= typedefs_and_cplusplus
= constantypedefs
= TRUE
;
732 int opt
= getopt_long (argc
, argv
,
733 "-aCdDf:Il:o:r:RStTi:BuvxwVhH", longopts
, 0);
741 /* If getopt returns 0, then it has already processed a
742 long-named option. We should do nothing. */
746 /* This means that a filename has been seen. Record it. */
747 argbuffer
[current_arg
].arg_type
= at_filename
;
748 argbuffer
[current_arg
].what
= optarg
;
753 /* Common options. */
755 append_to_tagfile
= TRUE
;
761 constantypedefs
= TRUE
;
764 constantypedefs
= FALSE
;
766 case 'f': /* for compatibility with old makefiles */
770 fprintf (stderr
, "%s: -%c option may only be given once.\n",
777 case 'S': /* for backward compatibility */
778 noindentypedefs
= TRUE
;
781 if (!get_language (optarg
, &argbuffer
[current_arg
].function
))
783 fprintf (stderr
, "%s: language \"%s\" not recognized.\n",
787 argbuffer
[current_arg
].arg_type
= at_language
;
792 argbuffer
[current_arg
].arg_type
= at_regexp
;
793 argbuffer
[current_arg
].what
= optarg
;
797 argbuffer
[current_arg
].arg_type
= at_regexp
;
798 argbuffer
[current_arg
].what
= NULL
;
801 #endif /* ETAGS_REGEXPS */
813 typedefs
= typedefs_and_cplusplus
= TRUE
;
818 included_files
[nincluded_files
++] = optarg
;
843 for (; optind
< argc
; ++optind
)
845 argbuffer
[current_arg
].arg_type
= at_filename
;
846 argbuffer
[current_arg
].what
= argv
[optind
];
851 if (nincluded_files
== 0 && file_count
== 0)
853 fprintf (stderr
, "%s: No input files specified.\n", progname
);
856 fprintf (stderr
, "\tTry `%s --help' for a complete list of options.\n",
863 tagfile
= CTAGS
? "tags" : "TAGS";
865 cwd
= etags_getcwd (); /* the current working directory */
867 if (streq (tagfile
, "-"))
873 tagfiledir
= absolute_dirname (tagfile
, cwd
);
876 init (); /* set up boolean "functions" */
879 initbuffer (&token_name
);
880 initbuffer (&lbs
[0].lb
);
881 initbuffer (&lbs
[1].lb
);
882 initbuffer (&filename_lb
);
886 if (streq (tagfile
, "-"))
889 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
895 * Loop through files finding functions.
897 for (i
= 0; i
< current_arg
; ++i
)
899 switch (argbuffer
[i
].arg_type
)
902 lang_func
= argbuffer
[i
].function
;
906 add_regex (argbuffer
[i
].what
);
911 while ((this_file
= gfnames (argbuffer
[i
].what
, &got_err
)) != NULL
)
915 error ("Can't find file %s\n", this_file
);
920 this_file
= massage_name (this_file
);
923 this_file
= argbuffer
[i
].what
;
925 /* Input file named "-" means read file names from stdin
927 if (streq (this_file
, "-"))
928 while (readline_internal (&filename_lb
, stdin
) > 0)
929 process_file (filename_lb
.buffer
);
931 process_file (this_file
);
941 while (nincluded_files
-- > 0)
942 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
948 /* If CTAGS, we are here. process_file did not write the tags yet,
949 because we want them ordered. Let's do it now. */
952 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
962 for (i
= 0; i
< current_arg
; ++i
)
964 if (argbuffer
[i
].arg_type
!= at_filename
)
967 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
968 tagfile
, argbuffer
[i
].what
, tagfile
);
969 if (system (cmd
) != GOOD
)
970 fatal ("failed to execute shell command");
972 append_to_tagfile
= TRUE
;
975 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
984 sprintf (cmd
, "sort %s -o %s", tagfile
, tagfile
);
992 * Set the language, given the name.
995 get_language (language
, func
)
997 Lang_function
**func
;
999 struct lang_entry
*lang
;
1001 for (lang
= lang_names
; lang
->suffix
; ++lang
)
1003 if (streq (language
, lang
->suffix
))
1005 *func
= lang
->function
;
1015 * This routine is called on each file argument.
1021 struct stat stat_buf
;
1024 if (stat (file
, &stat_buf
) == 0 && !S_ISREG (stat_buf
.st_mode
))
1026 fprintf (stderr
, "Skipping %s: it is not a regular file.\n", file
);
1029 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
1031 fprintf (stderr
, "Skipping inclusion of %s in self.\n", file
);
1034 inf
= fopen (file
, "r");
1041 find_entries (file
, inf
);
1047 if (absolutefn (file
))
1049 /* file is an absolute filename. Canonicalise it. */
1050 filename
= absolute_filename (file
, cwd
);
1054 /* file is a filename relative to cwd. Make it relative
1055 to the directory of the tags file. */
1056 filename
= relative_filename (file
, tagfiledir
);
1058 fprintf (tagf
, "\f\n%s,%d\n", filename
, total_size_of_entries (head
));
1067 * This routine sets up the boolean pseudo-functions which work
1068 * by setting boolean flags dependent upon the corresponding character
1069 * Every char which is NOT in that string is not a white char. Therefore,
1070 * all of the array "_wht" is set to FALSE, and then the elements
1071 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1072 * of a char is TRUE if it is the string "white", else FALSE.
1080 for (i
= 0; i
< 0177; i
++)
1081 _wht
[i
] = _etk
[i
] = _itk
[i
] = _btk
[i
] = FALSE
;
1082 for (sp
= white
; *sp
; sp
++)
1084 for (sp
= endtk
; *sp
; sp
++)
1086 for (sp
= intk
; *sp
; sp
++)
1088 for (sp
= begtk
; *sp
; sp
++)
1090 _wht
[0] = _wht
['\n'];
1091 _etk
[0] = _etk
['\n'];
1092 _btk
[0] = _btk
['\n'];
1093 _itk
[0] = _itk
['\n'];
1097 * This routine opens the specified file and calls the function
1098 * which finds the function and type definitions.
1101 find_entries (file
, inf
)
1106 struct lang_entry
*lang
;
1107 NODE
*old_last_node
;
1108 extern NODE
*last_node
;
1110 /* Memory leakage here: the memory block pointed by curfile is never
1111 released. The amount of memory leaked here is the sum of the
1112 lengths of the input file names. */
1113 curfile
= savestr (file
);
1114 cp
= etags_strrchr (file
, '.');
1116 /* If user specified a language, use it. */
1117 if (lang_func
!= NULL
)
1127 for (lang
= lang_suffixes
; lang
->suffix
; ++lang
)
1129 if (streq (cp
, lang
->suffix
))
1131 lang
->function (inf
);
1139 old_last_node
= last_node
;
1140 Fortran_functions (inf
);
1142 /* No Fortran entries found. Try C. */
1143 if (old_last_node
== last_node
)
1146 default_C_entries (inf
);
1153 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
)
1154 char *name
; /* tag name, if different from definition */
1155 logical is_func
; /* tag is a function */
1156 char *linestart
; /* start of the line where tag is */
1157 int linelen
; /* length of the line where tag is */
1158 int lno
; /* line number */
1159 long cno
; /* character number */
1161 register NODE
*np
= xnew (1, NODE
);
1163 /* If ctags mode, change name "main" to M<thisfilename>. */
1164 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
1166 register char *fp
= etags_strrchr (curfile
, '/');
1167 np
->name
= concat ("M", fp
== 0 ? curfile
: fp
+ 1, "");
1168 fp
= etags_strrchr (np
->name
, '.');
1169 if (fp
&& fp
[1] != '\0' && fp
[2] == '\0')
1174 np
->been_warned
= FALSE
;
1176 np
->is_func
= is_func
;
1178 /* Our char numbers are 0-base, because of C language tradition?
1179 ctags compatibility? old versions compatibility? I don't know.
1180 Anyway, since emacs's are 1-base we espect etags.el to take care
1181 of the difference. If we wanted to have 1-based numbers, we would
1182 uncomment the +1 below. */
1183 np
->cno
= cno
/* + 1 */ ;
1184 np
->left
= np
->right
= NULL
;
1185 np
->pat
= savenstr (linestart
, ((CTAGS
&& !cxref_style
) ? 50 : linelen
));
1187 add_node (np
, &head
);
1192 * recurse on left children, iterate on right children.
1196 register NODE
*node
;
1200 register NODE
*node_right
= node
->right
;
1201 free_tree (node
->left
);
1202 if (node
->name
!= NULL
)
1205 free ((char *) node
);
1212 * Adds a node to the tree of nodes. In etags mode, we don't keep
1213 * it sorted; we just keep a linear list. In ctags mode, maintain
1214 * an ordered tree, with no attempt at balancing.
1216 * add_node is the only function allowed to add nodes, so it can
1219 NODE
*last_node
= NULL
;
1221 add_node (node
, cur_node_p
)
1222 NODE
*node
, **cur_node_p
;
1225 register NODE
*cur_node
= *cur_node_p
;
1227 if (cur_node
== NULL
)
1237 if (last_node
== NULL
)
1238 fatal ("internal error in add_node", 0);
1239 last_node
->right
= node
;
1245 dif
= strcmp (node
->name
, cur_node
->name
);
1248 * If this tag name matches an existing one, then
1249 * do not add the node, but maybe print a warning.
1253 if (streq (node
->file
, cur_node
->file
))
1257 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1258 node
->file
, lineno
, node
->name
);
1259 fprintf (stderr
, "Second entry ignored\n");
1262 else if (!cur_node
->been_warned
&& !no_warnings
)
1266 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1267 node
->file
, cur_node
->file
, node
->name
);
1268 cur_node
->been_warned
= TRUE
;
1273 /* Actually add the node */
1274 add_node (node
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1280 register NODE
*node
;
1287 /* Output subentries that precede this one */
1288 put_entries (node
->left
);
1290 /* Output this entry */
1294 if (node
->name
!= NULL
)
1295 fprintf (tagf
, "%s\177%s\001%d,%d\n",
1296 node
->pat
, node
->name
, node
->lno
, node
->cno
);
1298 fprintf (tagf
, "%s\177%d,%d\n",
1299 node
->pat
, node
->lno
, node
->cno
);
1301 else if (!cxref_style
)
1303 fprintf (tagf
, "%s\t%s\t",
1304 node
->name
, node
->file
);
1308 putc (searchar
, tagf
);
1311 for (sp
= node
->pat
; *sp
; sp
++)
1313 if (*sp
== '\\' || *sp
== searchar
)
1317 putc (searchar
, tagf
);
1320 { /* a typedef; text pattern inadequate */
1321 fprintf (tagf
, "%d", node
->lno
);
1325 else if (vgrind_style
)
1326 fprintf (stdout
, "%s %s %d\n",
1327 node
->name
, node
->file
, (node
->lno
+ 63) / 64);
1329 fprintf (stdout
, "%-16s %3d %-16s %s\n",
1330 node
->name
, node
->lno
, node
->file
, node
->pat
);
1332 /* Output subentries that follow this one */
1333 put_entries (node
->right
);
1336 /* Length of a number's decimal representation. */
1344 for (; num
; num
/= 10)
1350 * Return total number of characters that put_entries will output for
1351 * the nodes in the subtree of the specified node. Works only if
1352 * we are not ctags, but called only in that case. This count
1353 * is irrelevant with the new tags.el, but is still supplied for
1354 * backward compatibility.
1357 total_size_of_entries (node
)
1358 register NODE
*node
;
1366 for (; node
; node
= node
->right
)
1368 /* Count left subentries. */
1369 total
+= total_size_of_entries (node
->left
);
1371 /* Count this entry */
1372 total
+= strlen (node
->pat
) + 1;
1373 total
+= number_len ((long) node
->lno
) + 1 + number_len (node
->cno
) + 1;
1374 if (node
->name
!= NULL
)
1375 total
+= 1 + strlen (node
->name
); /* \001name */
1382 * The C symbol tables.
1386 st_none
, st_C_struct
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
1389 /* Feed stuff between (but not including) %[ and %] lines to:
1390 gperf -c -k1,3 -o -p -r -t
1392 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1394 class, C_PLPL, st_C_struct
1395 domain, C_STAR, st_C_struct
1396 union, 0, st_C_struct
1397 struct, 0, st_C_struct
1399 typedef, 0, st_C_typedef
1400 define, 0, st_C_define
1401 long, 0, st_C_typespec
1402 short, 0, st_C_typespec
1403 int, 0, st_C_typespec
1404 char, 0, st_C_typespec
1405 float, 0, st_C_typespec
1406 double, 0, st_C_typespec
1407 signed, 0, st_C_typespec
1408 unsigned, 0, st_C_typespec
1409 auto, 0, st_C_typespec
1410 void, 0, st_C_typespec
1411 extern, 0, st_C_typespec
1412 static, 0, st_C_typespec
1413 const, 0, st_C_typespec
1414 volatile, 0, st_C_typespec
1416 and replace lines between %< and %> with its output. */
1418 /* C code produced by gperf version 1.8.1 (K&R C version) */
1419 /* Command-line: gperf -c -k1,3 -o -p -r -t */
1422 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
1424 #define MIN_WORD_LENGTH 3
1425 #define MAX_WORD_LENGTH 8
1426 #define MIN_HASH_VALUE 10
1427 #define MAX_HASH_VALUE 62
1430 53 is the maximum key range
1438 static unsigned char hash_table
[] =
1440 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1441 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1442 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1443 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1444 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1445 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1446 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1447 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1448 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
1449 62, 62, 62, 62, 62, 62, 62, 2, 62, 7,
1450 6, 9, 15, 30, 62, 24, 62, 62, 1, 24,
1451 7, 27, 13, 62, 19, 26, 18, 27, 1, 62,
1452 62, 62, 62, 62, 62, 62, 62, 62,
1454 return len
+ hash_table
[str
[2]] + hash_table
[str
[0]];
1457 struct C_stab_entry
*
1458 in_word_set (str
, len
)
1463 static struct C_stab_entry wordlist
[] =
1465 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1467 {"volatile", 0, st_C_typespec
},
1469 {"long", 0, st_C_typespec
},
1470 {"char", 0, st_C_typespec
},
1471 {"class", C_PLPL
, st_C_struct
},
1472 {"",}, {"",}, {"",}, {"",},
1473 {"const", 0, st_C_typespec
},
1474 {"",}, {"",}, {"",}, {"",},
1475 {"auto", 0, st_C_typespec
},
1477 {"define", 0, st_C_define
},
1479 {"void", 0, st_C_typespec
},
1480 {"",}, {"",}, {"",},
1481 {"extern", 0, st_C_typespec
},
1482 {"static", 0, st_C_typespec
},
1484 {"domain", C_STAR
, st_C_struct
},
1486 {"typedef", 0, st_C_typedef
},
1487 {"double", 0, st_C_typespec
},
1488 {"enum", 0, st_C_enum
},
1489 {"",}, {"",}, {"",}, {"",},
1490 {"int", 0, st_C_typespec
},
1492 {"float", 0, st_C_typespec
},
1493 {"",}, {"",}, {"",},
1494 {"struct", 0, st_C_struct
},
1495 {"",}, {"",}, {"",}, {"",},
1496 {"union", 0, st_C_struct
},
1498 {"short", 0, st_C_typespec
},
1500 {"unsigned", 0, st_C_typespec
},
1501 {"signed", 0, st_C_typespec
},
1504 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
1506 register int key
= hash (str
, len
);
1508 if (key
<= MAX_HASH_VALUE
&& key
>= MIN_HASH_VALUE
)
1510 register char *s
= wordlist
[key
].name
;
1512 if (*s
== *str
&& strneq (str
+ 1, s
+ 1, len
- 1))
1513 return &wordlist
[key
];
1521 C_symtype(str
, len
, c_ext
)
1526 register struct C_stab_entry
*se
= in_word_set(str
, len
);
1528 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
1534 * C functions are recognized using a simple finite automaton.
1535 * funcdef is its state variable.
1539 fnone
, /* nothing seen */
1540 ftagseen
, /* function-like tag seen */
1541 fstartlist
, /* just after open parenthesis */
1542 finlist
, /* in parameter list */
1543 flistseen
, /* after parameter list */
1544 fignore
/* before open brace */
1550 * typedefs are recognized using a simple finite automaton.
1551 * typeddef is its state variable.
1555 tnone
, /* nothing seen */
1556 ttypedseen
, /* typedef keyword seen */
1557 tinbody
, /* inside typedef body */
1558 tend
, /* just before typedef tag */
1559 tignore
/* junk after typedef tag */
1565 * struct-like structures (enum, struct and union) are recognized
1566 * using another simple finite automaton. `structdef' is its state
1571 snone
, /* nothing seen yet */
1572 skeyseen
, /* struct-like keyword seen */
1573 stagseen
, /* struct-like tag seen */
1574 scolonseen
, /* colon seen after struct-like tag */
1575 sinbody
/* in struct body: recognize member func defs*/
1580 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1581 * struct tag, and structtype is the type of the preceding struct-like
1584 char *structtag
= "<uninited>";
1585 enum sym_type structtype
;
1588 * Yet another little state machine to deal with preprocessor lines.
1592 dnone
, /* nothing seen */
1593 dsharpseen
, /* '#' seen as first char on line */
1594 ddefineseen
, /* '#' and 'define' seen */
1595 dignorerest
/* ignore rest of line */
1600 * Set this to TRUE, and the next token considered is called a function.
1601 * Used only for GNU emacs's function-defining macros.
1603 logical next_token_is_func
;
1606 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
1612 * checks to see if the current token is at the start of a
1613 * function, or corresponds to a typedef, or is a struct/union/enum
1616 * *IS_FUNC gets TRUE iff the token is a function or macro with args.
1617 * C_EXT is which language we are looking at.
1619 * In the future we will need some way to adjust where the end of
1620 * the token is; for instance, implementing the C++ keyword
1621 * `operator' properly will adjust the end of the token to be after
1622 * whatever follows `operator'.
1629 * next_token_is_func IN OUT
1633 consider_token (str
, len
, c
, c_ext
, cblev
, is_func
)
1634 register char *str
; /* IN: token pointer */
1635 register int len
; /* IN: token length */
1636 register char c
; /* IN: first char after the token */
1637 int c_ext
; /* IN: C extensions mask */
1638 int cblev
; /* IN: curly brace level */
1639 logical
*is_func
; /* OUT: function found */
1641 enum sym_type toktype
= C_symtype (str
, len
, c_ext
);
1644 * Advance the definedef state machine.
1649 /* We're not on a preprocessor line. */
1652 if (toktype
== st_C_define
)
1654 definedef
= ddefineseen
;
1658 definedef
= dignorerest
;
1663 * Make a tag for any macro, unless it is a constant
1664 * and constantypedefs is FALSE.
1666 definedef
= dignorerest
;
1667 *is_func
= (c
== '(');
1668 if (!*is_func
&& !constantypedefs
)
1675 error ("internal error: definedef value.", 0);
1684 if (toktype
== st_C_typedef
)
1687 typdef
= ttypedseen
;
1703 /* Do not return here, so the structdef stuff has a chance. */
1717 * This structdef business is currently only invoked when cblev==0.
1718 * It should be recursively invoked whatever the curly brace level,
1719 * and a stack of states kept, to allow for definitions of structs
1722 * This structdef business is NOT invoked when we are ctags and the
1723 * file is plain C. This is because a struct tag may have the same
1724 * name as another tag, and this loses with ctags.
1726 * This if statement deals with the typdef state machine as
1727 * follows: if typdef==ttypedseen and token is struct/union/class/enum,
1728 * return FALSE. All the other code here is for the structdef
1735 if (typdef
== ttypedseen
1736 || (typedefs_and_cplusplus
&& cblev
== 0 && structdef
== snone
))
1738 structdef
= skeyseen
;
1739 structtype
= toktype
;
1743 if (structdef
== skeyseen
)
1745 /* Save the tag for struct/union/class, for functions that may be
1747 if (structtype
== st_C_struct
)
1748 structtag
= savenstr (str
, len
);
1750 structtag
= "<enum>";
1751 structdef
= stagseen
;
1755 /* Avoid entering funcdef stuff if typdef is going on. */
1756 if (typdef
!= tnone
)
1762 /* Detect GNU macros. */
1763 if (definedef
== dnone
)
1764 if (strneq (str
, "DEFUN", len
) /* Used in emacs */
1766 These are defined inside C functions
, so currently they
1768 || strneq (str
, "EXFUN", len
) /* Used in glibc */
1769 || strneq (str
, "DEFVAR_", 7) /* Used in emacs */
1771 || strneq (str
, "SYSCALL", len
) /* Used in glibc (mach) */
1772 || strneq (str
, "ENTRY", len
) /* Used in glibc */
1773 || strneq (str
, "PSEUDO", len
)) /* Used in glibc */
1776 next_token_is_func
= TRUE
;
1779 if (next_token_is_func
)
1781 next_token_is_func
= FALSE
;
1791 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1792 funcdef
= fnone
; /* should be useless */
1795 if (funcdef
== fnone
)
1808 * This routine finds functions, typedefs, #define's and
1809 * struct/union/enum definitions in C syntax and adds them
1823 #define current_lb_is_new (newndx == curndx)
1824 #define switch_line_buffers() (curndx = 1 - curndx)
1826 #define curlb (lbs[curndx].lb)
1827 #define othlb (lbs[1-curndx].lb)
1828 #define newlb (lbs[newndx].lb)
1829 #define curlinepos (lbs[curndx].linepos)
1830 #define othlinepos (lbs[1-curndx].linepos)
1831 #define newlinepos (lbs[newndx].linepos)
1833 #define CNL_SAVE_DEFINEDEF \
1835 curlinepos = charno; \
1837 charno += readline (&curlb, inf); \
1838 lp = curlb.buffer; \
1845 CNL_SAVE_DEFINEDEF; \
1846 if (savetok.valid) \
1849 savetok.valid = FALSE; \
1851 definedef = dnone; \
1854 #define make_tag(isfun) do \
1858 char *name = NULL; \
1860 name = savestr (token_name.buffer); \
1861 pfnote (name, isfun, tok.buffer, tok.linelen, tok.lineno, tok.linepos); \
1863 else if (DEBUG) abort (); \
1864 tok.valid = FALSE; \
1868 C_entries (c_ext
, inf
)
1869 int c_ext
; /* extension of C */
1870 FILE *inf
; /* input file */
1872 register char c
; /* latest char read; '\0' for end of line */
1873 register char *lp
; /* pointer one beyond the character `c' */
1874 int curndx
, newndx
; /* indices for current and new lb */
1875 TOKEN tok
; /* latest token read */
1876 register int tokoff
; /* offset in line of start of current token */
1877 register int toklen
; /* length of current token */
1878 int cblev
; /* current curly brace level */
1879 int parlev
; /* current parenthesis level */
1880 logical incomm
, inquote
, inchar
, quotednl
, midtoken
;
1882 TOKEN savetok
; /* token saved during preprocessor handling */
1885 curndx
= newndx
= 0;
1891 definedef
= dnone
; funcdef
= fnone
; typdef
= tnone
; structdef
= snone
;
1892 next_token_is_func
= yacc_rules
= FALSE
;
1893 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
1894 tok
.valid
= savetok
.valid
= FALSE
;
1897 cplpl
= c_ext
& C_PLPL
;
1904 /* If we're at the end of the line, the next character is a
1905 '\0'; don't skip it, because it's the thing that tells us
1906 to read the next line. */
1927 /* Newlines inside comments do not end macro definitions in
1942 /* Newlines inside strings do not end macro definitions
1943 in traditional cpp, even though compilers don't
1944 usually accept them. */
1955 /* Hmmm, something went wrong. */
1969 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1974 if (funcdef
!= finlist
&& funcdef
!= fignore
)
1984 else if (cplpl
&& *lp
== '/')
1992 if ((c_ext
& YACC
) && *lp
== '%')
1994 /* entering or exiting rules section in yacc file */
1996 definedef
= dnone
; funcdef
= fnone
;
1997 typdef
= tnone
; structdef
= snone
;
1998 next_token_is_func
= FALSE
;
1999 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
2001 yacc_rules
= !yacc_rules
;
2007 if (definedef
== dnone
)
2010 logical cpptoken
= TRUE
;
2012 /* Look back on this line. If all blanks, or nonblanks
2013 followed by an end of comment, this is a preprocessor
2015 for (cp
= newlb
.buffer
; cp
< lp
-1; cp
++)
2018 if (*cp
== '*' && *(cp
+1) == '/')
2027 definedef
= dsharpseen
;
2028 } /* if (definedef == dnone) */
2034 /* Consider token only if some complicated conditions are satisfied. */
2035 if ((definedef
!= dnone
2036 || (cblev
== 0 && structdef
!= scolonseen
)
2037 || (cblev
== 1 && cplpl
&& structdef
== sinbody
))
2038 && typdef
!= tignore
2039 && definedef
!= dignorerest
2040 && funcdef
!= finlist
)
2046 if (cplpl
&& c
== ':' && *lp
== ':' && begtoken(*(lp
+ 1)))
2049 * This handles :: in the middle, but not at the
2050 * beginning of an identifier.
2057 logical is_func
= FALSE
;
2060 || consider_token (newlb
.buffer
+ tokoff
, toklen
,
2061 c
, c_ext
, cblev
, &is_func
))
2063 if (structdef
== sinbody
2064 && definedef
== dnone
2066 /* function defined in C++ class body */
2068 int strsize
= strlen(structtag
) + 2 + toklen
+ 1;
2069 while (token_name
.size
< strsize
)
2071 token_name
.size
*= 2;
2073 = (char *) xrealloc (token_name
.buffer
,
2076 strcpy (token_name
.buffer
, structtag
);
2077 strcat (token_name
.buffer
, "::");
2078 strncat (token_name
.buffer
,
2079 newlb
.buffer
+tokoff
, toklen
);
2084 while (token_name
.size
< toklen
+ 1)
2086 token_name
.size
*= 2;
2088 = (char *) xrealloc (token_name
.buffer
,
2091 strncpy (token_name
.buffer
,
2092 newlb
.buffer
+tokoff
, toklen
);
2093 token_name
.buffer
[toklen
] = '\0';
2094 if (structdef
== stagseen
2097 && definedef
== dignorerest
)) /* macro */
2102 tok
.lineno
= lineno
;
2103 tok
.linelen
= tokoff
+ toklen
+ 1;
2104 tok
.buffer
= newlb
.buffer
;
2105 tok
.linepos
= newlinepos
;
2108 if (definedef
== dnone
2109 && (funcdef
== ftagseen
2110 || structdef
== stagseen
2113 if (current_lb_is_new
)
2114 switch_line_buffers ();
2121 } /* if (endtoken (c)) */
2122 else if (intoken (c
))
2127 } /* if (midtoken) */
2128 else if (begtoken (c
))
2146 if (structdef
== stagseen
)
2152 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
2154 tokoff
= lp
- 1 - newlb
.buffer
;
2159 } /* if (begtoken) */
2160 } /* if must look at token */
2163 /* Detect end of line, colon, comma, semicolon and various braces
2164 after having handled a token.*/
2168 if (definedef
!= dnone
)
2170 if (structdef
== stagseen
)
2171 structdef
= scolonseen
;
2188 if (definedef
!= dnone
)
2199 if (funcdef
!= fignore
)
2201 if (structdef
== stagseen
)
2205 if (definedef
!= dnone
)
2207 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2209 if (structdef
== stagseen
)
2213 if (definedef
!= dnone
)
2215 if (cblev
== 0 && typdef
== tend
)
2221 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2223 if (structdef
== stagseen
)
2227 if (definedef
!= dnone
)
2236 /* Make sure that the next char is not a '*'.
2237 This handles constructs like:
2238 typedef void OperatorFun (int fun); */
2245 } /* switch (typdef) */
2248 funcdef
= fstartlist
;
2257 if (definedef
!= dnone
)
2265 funcdef
= flistseen
;
2268 if (cblev
== 0 && typdef
== tend
)
2274 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
2278 if (definedef
!= dnone
)
2280 if (typdef
== ttypedseen
)
2284 case skeyseen
: /* unnamed struct */
2285 structtag
= "_anonymous_";
2286 structdef
= sinbody
;
2289 case scolonseen
: /* named struct */
2290 structdef
= sinbody
;
2303 /* Neutralize `extern "C" {' grot and look inside structs. */
2304 if (cblev
== 0 && structdef
== snone
&& typdef
== tnone
)
2310 if (definedef
!= dnone
)
2312 if (funcdef
== fstartlist
)
2313 funcdef
= fnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
2316 if (definedef
!= dnone
)
2318 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
2320 cblev
= 0; /* reset curly brace level if first column */
2321 parlev
= 0; /* also reset paren level, just in case... */
2327 if (typdef
== tinbody
)
2329 /* Memory leakage here: the string pointed by structtag is
2330 never released, because I fear to miss something and
2331 break things while freeing the area. The amount of
2332 memory leaked here is the sum of the lenghts of the
2334 if (structdef == sinbody)
2335 free (structtag); */
2338 structtag
= "<error>";
2342 case '#': case '+': case '-': case '~': case '&': case '%': case '/':
2343 case '|': case '^': case '!': case '<': case '>': case '.': case '?':
2344 if (definedef
!= dnone
)
2346 /* These surely cannot follow a function tag. */
2347 if (funcdef
!= finlist
&& funcdef
!= fignore
)
2351 /* If a macro spans multiple lines don't reset its state. */
2359 } /* while not eof */
2363 * Process either a C++ file or a C file depending on the setting
2367 default_C_entries (inf
)
2370 C_entries (cplusplus
? C_PLPL
: 0, inf
);
2373 /* Always do plain ANSI C. */
2375 plain_C_entries (inf
)
2381 /* Always do C++. */
2383 Cplusplus_entries (inf
)
2386 C_entries (C_PLPL
, inf
);
2394 C_entries (C_STAR
, inf
);
2397 /* Always do Yacc. */
2402 C_entries (YACC
, inf
);
2405 /* Fortran parsing */
2413 register int len
= 0;
2415 while (*cp
&& lowcase(*cp
) == lowcase(dbp
[len
]))
2417 if (*cp
== '\0' && !intoken(dbp
[len
]))
2428 while (isspace (*dbp
))
2433 while (isspace (*dbp
))
2435 if (strneq (dbp
, "(*)", 3))
2440 if (!isdigit (*dbp
))
2442 --dbp
; /* force failure */
2447 while (isdigit (*dbp
));
2456 while (isspace (*dbp
))
2461 linecharno
= charno
;
2462 charno
+= readline (&lb
, inf
);
2467 while (isspace (*dbp
))
2476 && (isalpha (*cp
) || isdigit (*cp
) || (*cp
== '_') || (*cp
== '$')));
2479 pfnote (NULL
, TRUE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2483 Fortran_functions (inf
)
2492 linecharno
= charno
;
2493 charno
+= readline (&lb
, inf
);
2496 dbp
++; /* Ratfor escape to fortran */
2497 while (isspace (*dbp
))
2501 switch (lowcase (*dbp
))
2504 if (tail ("integer"))
2512 if (tail ("logical"))
2516 if (tail ("complex") || tail ("character"))
2520 if (tail ("double"))
2522 while (isspace (*dbp
))
2526 if (tail ("precision"))
2532 while (isspace (*dbp
))
2536 switch (lowcase (*dbp
))
2539 if (tail ("function"))
2543 if (tail ("subroutine"))
2551 if (tail ("program"))
2556 if (tail ("procedure"))
2564 * Bob Weiner, Motorola Inc., 4/3/94
2565 * Unix and microcontroller assembly tag handling
2566 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
2580 linecharno
= charno
;
2581 charno
+= readline (&lb
, inf
);
2584 /* If first char is alphabetic or one of [_.$], test for colon
2585 following identifier. */
2586 if (isalpha (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2588 /* Read past label. */
2590 while (isalnum (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
2592 if (*cp
== ':' || isspace (*cp
))
2594 /* Found end of label, so copy it and add it to the table. */
2596 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2602 /* Added by Mosur Mohan, 4/22/88 */
2603 /* Pascal parsing */
2605 #define GET_NEW_LINE \
2607 linecharno = charno; lineno++; \
2608 charno += 1 + readline (&lb, inf); \
2613 * Locates tags for procedures & functions. Doesn't do any type- or
2614 * var-definitions. It does look for the keyword "extern" or
2615 * "forward" immediately following the procedure statement; if found,
2616 * the tag is skipped.
2619 Pascal_functions (inf
)
2622 struct linebuffer tline
; /* mostly copied from C_entries */
2624 int save_lineno
, save_len
;
2627 logical
/* each of these flags is TRUE iff: */
2628 incomment
, /* point is inside a comment */
2629 inquote
, /* point is inside '..' string */
2630 get_tagname
, /* point is after PROCEDURE/FUNCTION
2631 keyword, so next item = potential tag */
2632 found_tag
, /* point is after a potential tag */
2633 inparms
, /* point is within parameter-list */
2634 verify_tag
; /* point has passed the parm-list, so the
2635 next token will determine whether this
2636 is a FORWARD/EXTERN to be ignored, or
2637 whether it is a real tag */
2644 initbuffer (&tline
);
2646 incomment
= inquote
= FALSE
;
2647 found_tag
= FALSE
; /* have a proc name; check if extern */
2648 get_tagname
= FALSE
; /* have found "procedure" keyword */
2649 inparms
= FALSE
; /* found '(' after "proc" */
2650 verify_tag
= FALSE
; /* check if "extern" is ahead */
2652 /* long main loop to get next char */
2656 if (c
== '\0') /* if end of line */
2661 if (!((found_tag
&& verify_tag
) ||
2663 c
= *dbp
++; /* only if don't need *dbp pointing
2664 to the beginning of the name of
2665 the procedure or function */
2669 if (c
== '}') /* within { } comments */
2671 else if (c
== '*' && *dbp
== ')') /* within (* *) comments */
2688 inquote
= TRUE
; /* found first quote */
2690 case '{': /* found open { comment */
2694 if (*dbp
== '*') /* found open (* comment */
2699 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
2702 case ')': /* end of parms list */
2707 if (found_tag
&& !inparms
) /* end of proc or fn stmt */
2714 if (found_tag
&& verify_tag
&& (*dbp
!= ' '))
2716 /* check if this is an "extern" declaration */
2719 if (lowcase (*dbp
== 'e'))
2721 if (tail ("extern")) /* superfluous, really! */
2727 else if (lowcase (*dbp
) == 'f')
2729 if (tail ("forward")) /* check for forward reference */
2735 if (found_tag
&& verify_tag
) /* not external proc, so make tag */
2740 tline
.buffer
, save_len
, save_lineno
, save_lcno
);
2744 if (get_tagname
) /* grab name of proc or fn */
2751 /* save all values for later tagging */
2752 size
= strlen (lb
.buffer
) + 1;
2753 while (size
> tline
.size
)
2756 tline
.buffer
= (char *) xrealloc (tline
.buffer
, tline
.size
);
2758 strcpy (tline
.buffer
, lb
.buffer
);
2759 save_lineno
= lineno
;
2760 save_lcno
= linecharno
;
2762 /* grab block name */
2763 for (dbp
++; *dbp
&& (!endtoken (*dbp
)); dbp
++)
2765 save_len
= dbp
- lb
.buffer
+ 1;
2766 get_tagname
= FALSE
;
2770 /* and proceed to check for "extern" */
2772 else if (!incomment
&& !inquote
&& !found_tag
)
2774 /* check for proc/fn keywords */
2775 switch (lowcase (c
))
2778 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
2782 if (tail ("unction"))
2787 } /* while not eof */
2789 free (tline
.buffer
);
2793 * lisp tag functions
2794 * look for (def or (DEF, quote or QUOTE
2798 register char *strp
;
2800 return ((strp
[1] == 'd' || strp
[1] == 'D')
2801 && (strp
[2] == 'e' || strp
[2] == 'E')
2802 && (strp
[3] == 'f' || strp
[3] == 'F'));
2807 register char *strp
;
2809 return ((*(++strp
) == 'q' || *strp
== 'Q')
2810 && (*(++strp
) == 'u' || *strp
== 'U')
2811 && (*(++strp
) == 'o' || *strp
== 'O')
2812 && (*(++strp
) == 't' || *strp
== 'T')
2813 && (*(++strp
) == 'e' || *strp
== 'E')
2814 && isspace(*(++strp
)));
2822 if (*dbp
== '\'') /* Skip prefix quote */
2824 else if (*dbp
== '(' && L_isquote (dbp
)) /* Skip "(quote " */
2827 while (isspace(*dbp
))
2830 for (cp
= dbp
/*+1*/;
2831 *cp
&& *cp
!= '(' && *cp
!= ' ' && *cp
!= ')';
2837 pfnote (NULL
, TRUE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2841 Lisp_functions (inf
)
2850 linecharno
= charno
;
2851 charno
+= readline (&lb
, inf
);
2857 while (!isspace (*dbp
))
2859 while (isspace (*dbp
))
2865 /* Check for (foo::defmumble name-defined ... */
2868 while (*dbp
&& !isspace (*dbp
)
2869 && *dbp
!= ':' && *dbp
!= '(' && *dbp
!= ')');
2874 while (*dbp
== ':');
2876 if (L_isdef (dbp
- 1))
2878 while (!isspace (*dbp
))
2880 while (isspace (*dbp
))
2891 * Scheme tag functions
2892 * look for (def... xyzzy
2893 * look for (def... (xyzzy
2894 * look for (def ... ((...(xyzzy ....
2895 * look for (set! xyzzy
2901 Scheme_functions (inf
)
2910 linecharno
= charno
;
2911 charno
+= readline (&lb
, inf
);
2913 if (dbp
[0] == '(' &&
2914 (dbp
[1] == 'D' || dbp
[1] == 'd') &&
2915 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2916 (dbp
[3] == 'F' || dbp
[3] == 'f'))
2918 while (!isspace (*dbp
))
2920 /* Skip over open parens and white space */
2921 while (*dbp
&& (isspace (*dbp
) || *dbp
== '('))
2925 if (dbp
[0] == '(' &&
2926 (dbp
[1] == 'S' || dbp
[1] == 's') &&
2927 (dbp
[2] == 'E' || dbp
[2] == 'e') &&
2928 (dbp
[3] == 'T' || dbp
[3] == 't') &&
2929 (dbp
[4] == '!' || dbp
[4] == '!') &&
2932 while (!isspace (*dbp
))
2934 /* Skip over white space */
2935 while (isspace (*dbp
))
2949 /* Go till you get to white space or a syntactic break */
2951 *cp
&& *cp
!= '(' && *cp
!= ')' && !isspace (*cp
);
2954 pfnote (NULL
, TRUE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
2957 /* Find tags in TeX and LaTeX input files. */
2959 /* TEX_toktab is a table of TeX control sequences that define tags.
2960 Each TEX_tabent records one such control sequence.
2961 CONVERT THIS TO USE THE Stab TYPE!! */
2968 struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
2970 /* Default set of control sequences to put into TEX_toktab.
2971 The value of environment var TEXTAGS is prepended to this. */
2973 char *TEX_defenv
= "\
2974 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
2975 :part:appendix:entry:index";
2978 struct TEX_tabent
*TEX_decode_env ();
2980 #if TeX_named_tokens
2984 char TEX_esc
= '\\';
2985 char TEX_opgrp
= '{';
2986 char TEX_clgrp
= '}';
2989 * TeX/LaTeX scanning loop.
3000 /* Select either \ or ! as escape character. */
3003 /* Initialize token table once from environment. */
3005 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
3008 { /* Scan each line in file */
3010 linecharno
= charno
;
3011 charno
+= readline (&lb
, inf
);
3014 while (dbp
= etags_strchr (dbp
, TEX_esc
)) /* Look at each esc in line */
3020 linecharno
+= dbp
- lasthit
;
3022 i
= TEX_Token (lasthit
);
3026 lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
3027 #if TeX_named_tokens
3028 TEX_getit (lasthit
, TEX_toktab
[i
].len
);
3030 break; /* We only save a line once */
3036 #define TEX_LESC '\\'
3037 #define TEX_SESC '!'
3040 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
3041 chars accordingly. */
3048 while ((c
= getc (inf
)) != EOF
)
3050 /* Skip to next line if we hit the TeX comment char. */
3054 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
3073 /* Read environment and prepend it to the default string.
3074 Build token table. */
3076 TEX_decode_env (evarname
, defenv
)
3080 register char *env
, *p
;
3082 struct TEX_tabent
*tab
;
3085 /* Append default string to environment. */
3086 env
= getenv (evarname
);
3090 env
= concat (env
, defenv
, "");
3092 /* Allocate a token table */
3093 for (size
= 1, p
= env
; p
;)
3094 if ((p
= etags_strchr (p
, ':')) && *(++p
))
3096 /* Add 1 to leave room for null terminator. */
3097 tab
= xnew (size
+ 1, struct TEX_tabent
);
3099 /* Unpack environment string into token table. Be careful about */
3100 /* zero-length strings (leading ':', "::" and trailing ':') */
3103 p
= etags_strchr (env
, ':');
3104 if (!p
) /* End of environment string. */
3105 p
= env
+ strlen (env
);
3107 { /* Only non-zero strings. */
3108 tab
[i
].name
= savenstr (env
, p
- env
);
3109 tab
[i
].len
= strlen (tab
[i
].name
);
3116 tab
[i
].name
= NULL
; /* Mark end of table. */
3124 #if TeX_named_tokens
3125 /* Record a tag defined by a TeX command of length LEN and starting at NAME.
3126 The name being defined actually starts at (NAME + LEN + 1).
3127 But we seem to include the TeX command in the tag name. */
3129 TEX_getit (name
, len
)
3133 char *p
= name
+ len
;
3138 /* Let tag name extend to next group close (or end of line) */
3139 while (*p
&& *p
!= TEX_clgrp
)
3141 pfnote (savenstr (name
, p
-name
), TRUE
,
3142 lb
.buffer
, strlen (lb
.buffer
), lineno
, linecharno
);
3146 /* If the text at CP matches one of the tag-defining TeX command names,
3147 return the pointer to the first occurrence of that command in TEX_toktab.
3148 Otherwise return -1.
3149 Keep the capital `T' in `Token' for dumb truncating compilers
3150 (this distinguishes it from `TEX_toktab' */
3157 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
3158 if (strneq (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
))
3163 /* Support for Prolog. */
3165 /* Whole head (not only functor, but also arguments)
3166 is gotten in compound term. */
3179 if (s
[0] == '\0') /* syntax error. */
3181 else if (insquote
&& s
[0] == '\'' && s
[1] == '\'')
3183 else if (s
[0] == '\'')
3185 insquote
= !insquote
;
3188 else if (!insquote
&& s
[0] == '(')
3193 else if (!insquote
&& s
[0] == ')')
3199 else if (npar
< 0) /* syntax error. */
3202 else if (!insquote
&& s
[0] == '.'
3203 && (isspace (s
[1]) || s
[1] == '\0'))
3205 if (npar
!= 0) /* syntax error. */
3213 pfnote (NULL
, TRUE
, save_s
, s
-save_s
, lineno
, linecharno
);
3216 /* It is assumed that prolog predicate starts from column 0. */
3218 Prolog_functions (inf
)
3221 void skip_comment (), prolog_getit ();
3223 lineno
= linecharno
= charno
= 0;
3227 linecharno
+= charno
;
3228 charno
= readline (&lb
, inf
) + 1; /* 1 for newline. */
3230 if (isspace (dbp
[0])) /* not predicate header. */
3232 else if (dbp
[0] == '%') /* comment. */
3234 else if (dbp
[0] == '/' && dbp
[1] == '*') /* comment. */
3235 skip_comment (&lb
, inf
, &lineno
, &linecharno
);
3242 skip_comment (plb
, inf
, plineno
, plinecharno
)
3243 struct linebuffer
*plb
;
3245 int *plineno
; /* result */
3246 long *plinecharno
; /* result */
3252 for (cp
= plb
->buffer
; *cp
!= '\0'; cp
++)
3253 if (cp
[0] == '*' && cp
[1] == '/')
3256 *plinecharno
+= readline (plb
, inf
) + 1; /* 1 for newline. */
3261 #ifdef ETAGS_REGEXPS
3262 /* Take a string like "/blah/" and turn it into "blah", making sure
3263 that the first and last characters are the same, and handling
3264 quoted separator characters. Actually, stops on the occurence of
3265 an unquoted separator. Also turns "\t" into a Tab character.
3266 Returns pointer to terminating separator. Works in place. Null
3267 terminates name string. */
3269 scan_separators (name
)
3273 char *copyto
= name
;
3274 logical quoted
= FALSE
;
3276 for (++name
; *name
!= '\0'; ++name
)
3282 else if (*name
== sep
)
3286 /* Something else is quoted, so preserve the quote. */
3292 else if (*name
== '\\')
3294 else if (*name
== sep
)
3300 /* Terminate copied string. */
3305 /* Turn a name, which is an ed-style (but Emacs syntax) regular
3306 expression, into a real regular expression by compiling it. */
3308 add_regex (regexp_pattern
)
3309 char *regexp_pattern
;
3313 struct re_pattern_buffer
*patbuf
;
3315 if (regexp_pattern
== NULL
)
3317 /* Remove existing regexps. */
3323 if (regexp_pattern
[0] == '\0')
3325 error ("missing regexp", 0);
3328 if (regexp_pattern
[strlen(regexp_pattern
)-1] != regexp_pattern
[0])
3330 error ("%s: unterminated regexp", regexp_pattern
);
3333 name
= scan_separators (regexp_pattern
);
3334 if (regexp_pattern
[0] == '\0')
3336 error ("null regexp", 0);
3339 (void) scan_separators (name
);
3341 patbuf
= xnew (1, struct re_pattern_buffer
);
3342 patbuf
->translate
= NULL
;
3343 patbuf
->fastmap
= NULL
;
3344 patbuf
->buffer
= NULL
;
3345 patbuf
->allocated
= 0;
3347 err
= re_compile_pattern (regexp_pattern
, strlen (regexp_pattern
), patbuf
);
3350 error ("%s while compiling pattern", err
);
3355 if (num_patterns
== 1)
3356 patterns
= xnew (1, struct pattern
);
3358 patterns
= ((struct pattern
*)
3360 (num_patterns
* sizeof (struct pattern
))));
3361 patterns
[num_patterns
- 1].pattern
= patbuf
;
3362 patterns
[num_patterns
- 1].name_pattern
= savestr (name
);
3363 patterns
[num_patterns
- 1].error_signaled
= FALSE
;
3367 * Do the substitutions indicated by the regular expression and
3371 substitute (in
, out
, regs
)
3373 struct re_registers
*regs
;
3375 char *result
= NULL
, *t
;
3378 /* Pass 1: figure out how much size to allocate. */
3379 for (t
= out
; *t
; ++t
)
3386 fprintf (stderr
, "%s: pattern subtitution ends prematurely\n",
3393 size
+= regs
->end
[dig
] - regs
->start
[dig
];
3398 /* Allocate space and do the substitutions. */
3399 result
= xnew (size
+ 1, char);
3408 /* Using "dig2" satisfies my debugger. Bleah. */
3409 int dig2
= *out
- '0';
3410 strncpy (result
+ size
, in
+ regs
->start
[dig2
],
3411 regs
->end
[dig2
] - regs
->start
[dig2
]);
3412 size
+= regs
->end
[dig2
] - regs
->start
[dig2
];
3415 result
[size
++] = *out
;
3418 result
[size
++] = *out
;
3420 result
[size
] = '\0';
3425 #endif /* ETAGS_REGEXPS */
3426 /* Initialize a linebuffer for use */
3428 initbuffer (linebuffer
)
3429 struct linebuffer
*linebuffer
;
3431 linebuffer
->size
= 200;
3432 linebuffer
->buffer
= xnew (200, char);
3436 * Read a line of text from `stream' into `linebuffer'.
3437 * Return the number of characters read from `stream',
3438 * which is the length of the line including the newline, if any.
3441 readline_internal (linebuffer
, stream
)
3442 struct linebuffer
*linebuffer
;
3443 register FILE *stream
;
3445 char *buffer
= linebuffer
->buffer
;
3446 register char *p
= linebuffer
->buffer
;
3447 register char *pend
;
3450 pend
= p
+ linebuffer
->size
; /* Separate to avoid 386/IX compiler bug. */
3454 register int c
= getc (stream
);
3457 linebuffer
->size
*= 2;
3458 buffer
= (char *) xrealloc (buffer
, linebuffer
->size
);
3459 p
+= buffer
- linebuffer
->buffer
;
3460 pend
= buffer
+ linebuffer
->size
;
3461 linebuffer
->buffer
= buffer
;
3470 if (p
> buffer
&& p
[-1] == '\r')
3485 return p
- buffer
+ chars_deleted
;
3489 * Like readline_internal, above, but try to match the input
3490 * line against any existing regular expressions.
3493 readline (linebuffer
, stream
)
3494 struct linebuffer
*linebuffer
;
3497 /* Read new line. */
3499 long result
= readline_internal (linebuffer
, stream
);
3501 #ifdef ETAGS_REGEXPS
3502 /* Match against all listed patterns. */
3503 for (i
= 0; i
< num_patterns
; ++i
)
3505 int match
= re_match (patterns
[i
].pattern
, linebuffer
->buffer
,
3506 (int)result
, 0, &patterns
[i
].regs
);
3511 if (!patterns
[i
].error_signaled
)
3513 error ("error while matching pattern %d", i
);
3514 patterns
[i
].error_signaled
= TRUE
;
3521 /* Match occurred. Construct a tag. */
3522 if (patterns
[i
].name_pattern
[0] != '\0')
3524 /* Make a named tag. */
3525 char *name
= substitute (linebuffer
->buffer
,
3526 patterns
[i
].name_pattern
,
3530 linebuffer
->buffer
, match
, lineno
, linecharno
);
3534 /* Make an unnamed tag. */
3536 linebuffer
->buffer
, match
, lineno
, linecharno
);
3541 #endif /* ETAGS_REGEXPS */
3547 * Read a file, but do no processing. This is used to do regexp
3548 * matching on files that have no language defined.
3551 just_read_file (inf
)
3557 linecharno
= charno
;
3558 charno
+= readline (&lb
, inf
) + 1;
3564 * Return a pointer to a space of size strlen(cp)+1 allocated
3565 * with xnew where the string CP has been copied.
3571 return savenstr (cp
, strlen (cp
));
3575 * Return a pointer to a space of size LEN+1 allocated with xnew where
3576 * the string CP has been copied for at most the first LEN characters.
3585 dp
= xnew (len
+ 1, char);
3586 strncpy (dp
, cp
, len
);
3592 * Return the ptr in sp at which the character c last
3593 * appears; NULL if not found
3595 * Identical to System V strrchr, included for portability.
3598 etags_strrchr (sp
, c
)
3599 register char *sp
, c
;
3614 * Return the ptr in sp at which the character c first
3615 * appears; NULL if not found
3617 * Identical to System V strchr, included for portability.
3620 etags_strchr (sp
, c
)
3621 register char *sp
, c
;
3631 /* Print error message and exit. */
3648 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
3653 fprintf (stderr
, "%s: ", progname
);
3654 fprintf (stderr
, s1
, s2
);
3655 fprintf (stderr
, "\n");
3658 /* Return a newly-allocated string whose contents
3659 concatenate those of s1, s2, s3. */
3664 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
3665 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
3667 strcpy (result
, s1
);
3668 strcpy (result
+ len1
, s2
);
3669 strcpy (result
+ len1
+ len2
, s3
);
3670 result
[len1
+ len2
+ len3
] = '\0';
3675 /* Does the same work as the system V getcwd, but does not need to
3676 guess the buffer size in advance. */
3681 char *p
, path
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
3689 *p
++ = lowcase (*p
);
3691 return strdup (path
);
3692 #else /* not DOS_NT */
3695 char *path
= xnew (bufsize
, char);
3697 while (getcwd (path
, bufsize
) == NULL
)
3699 if (errno
!= ERANGE
)
3702 path
= xnew (bufsize
, char);
3706 #else /* not DOS_NT and not HAVE_GETCWD */
3707 struct linebuffer path
;
3711 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
3712 if (pipe
== NULL
|| readline_internal (&path
, pipe
) == 0)
3717 #endif /* not HAVE_GETCWD */
3718 #endif /* not DOS_NT */
3721 /* Return a newly allocated string containing the filename
3722 of FILE relative to the absolute directory DIR (which
3723 should end with a slash). */
3725 relative_filename (file
, dir
)
3728 char *fp
, *dp
, *abs
, *res
;
3730 /* Find the common root of file and dir. */
3731 abs
= absolute_filename (file
, cwd
);
3734 while (*fp
++ == *dp
++)
3743 /* Build a sequence of "../" strings for the resulting relative filename. */
3744 for (dp
= etags_strchr (dp
+ 1, '/'), res
= "";
3746 dp
= etags_strchr (dp
+ 1, '/'))
3748 res
= concat (res
, "../", "");
3751 /* Add the filename relative to the common root of file and dir. */
3752 res
= concat (res
, fp
+ 1, "");
3758 /* Return a newly allocated string containing the
3759 absolute filename of FILE given CWD (which should
3760 end with a slash). */
3762 absolute_filename (file
, cwd
)
3765 char *slashp
, *cp
, *res
;
3767 if (absolutefn (file
))
3768 res
= concat (file
, "", "");
3770 res
= concat (cwd
, file
, "");
3772 /* Delete the "/dirname/.." and "/." substrings. */
3773 slashp
= etags_strchr (res
, '/');
3774 while (slashp
!= NULL
&& slashp
[0] != '\0')
3776 if (slashp
[1] == '.')
3778 if (slashp
[2] == '.'
3779 && (slashp
[3] == '/' || slashp
[3] == '\0'))
3784 while (cp
>= res
&& *cp
!= '/');
3787 strcpy (cp
, slashp
+ 3);
3789 else /* else (cp == res) */
3791 if (slashp
[3] != '\0')
3792 strcpy (cp
, slashp
+ 4);
3799 else if (slashp
[2] == '/' || slashp
[2] == '\0')
3801 strcpy (slashp
, slashp
+ 2);
3806 slashp
= etags_strchr (slashp
+ 1, '/');
3812 /* Return a newly allocated string containing the absolute
3813 filename of dir where FILE resides given CWD (which should
3814 end with a slash). */
3816 absolute_dirname (file
, cwd
)
3822 slashp
= etags_strrchr (file
, '/');
3827 res
= absolute_filename (file
, cwd
);
3833 /* Like malloc but get fatal error if memory is exhausted. */
3838 long *result
= (long *) malloc (size
);
3840 fatal ("virtual memory exhausted", 0);
3845 xrealloc (ptr
, size
)
3849 long *result
= (long *) realloc (ptr
, size
);
3851 fatal ("virtual memory exhausted");