1 /* Tags file maker to go with GNU Emacs -*- coding: latin-1 -*-
2 Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2001, 2002
3 Free Software Foundation, Inc. and Ken Arnold
5 This file is not considered part of GNU Emacs.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 * Ctags originally by Ken Arnold.
24 * Fortran added by Jim Kleckner.
25 * Ed Pelegri-Llopart added C typedefs.
26 * Gnu Emacs TAGS format and modifications by RMS?
27 * 1989 Sam Kendall added C++.
28 * 1992 Joseph B. Wells improved C and C++ parsing.
29 * 1993 Francesco Potortì reorganised C and C++.
30 * 1994 Regexp tags by Tom Tromey.
31 * 2001 Nested classes by Francesco Potortì (concept by Mykola Dzyuba).
32 * 2002 #line directives by Francesco Potortì.
34 * Francesco Potortì <pot@gnu.org> has maintained it since 1993.
37 char pot_etags_version
[] = "@(#) pot revision number is 16.10";
47 # define NDEBUG /* disable assert */
52 /* On some systems, Emacs defines static as nothing for the sake
53 of unexec. We don't want that here since we don't use unexec. */
55 # define ETAGS_REGEXPS /* use the regexp features */
56 # define LONG_OPTIONS /* accept long options */
57 # ifndef PTR /* for Xemacs */
60 # ifndef __P /* for Xemacs */
61 # define __P(args) args
64 # if defined(__STDC__) && (__STDC__ || defined(__SUNPRO_C))
65 # define __P(args) args /* use prototypes */
66 # define PTR void * /* for generic pointers */
68 # define __P(args) () /* no prototypes */
69 # define const /* remove const for old compilers' sake */
70 # define PTR long * /* don't use void* */
72 #endif /* !HAVE_CONFIG_H */
75 # define _GNU_SOURCE 1 /* enables some compiler checks on GNU */
78 /* WIN32_NATIVE is for Xemacs.
79 MSDOS, WINDOWSNT, DOS_NT are for Emacs. */
84 #endif /* WIN32_NATIVE */
90 # include <sys/param.h>
92 # ifndef HAVE_CONFIG_H
94 # include <sys/config.h>
106 # define MAXPATHLEN _MAX_PATH
112 # endif /* undef HAVE_GETCWD */
113 #else /* !WINDOWSNT */
118 extern char *getenv ();
120 #endif /* !WINDOWSNT */
125 # if defined (HAVE_GETCWD) && !defined (WINDOWSNT)
126 extern char *getcwd (char *buf
, size_t size
);
128 #endif /* HAVE_UNISTD_H */
136 #include <sys/types.h>
137 #include <sys/stat.h>
141 # undef assert /* some systems have a buggy assert.h */
142 # define assert(x) ((void) 0)
145 #if !defined (S_ISREG) && defined (S_IFREG)
146 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
152 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
154 extern int optind
, opterr
;
155 #endif /* LONG_OPTIONS */
158 # ifndef HAVE_CONFIG_H /* this is a standalone compilation */
159 # ifdef __CYGWIN__ /* compiling on Cygwin */
161 the regex
.h distributed with Cygwin is
not compatible with etags
, alas
!
162 If you want regular expression support
, you should
delete this notice
and
163 arrange to use the GNU regex
.h
and regex
.c
.
167 #endif /* ETAGS_REGEXPS */
169 /* Define CTAGS to make the program "ctags" compatible with the usual one.
170 Leave it undefined to make the program "etags", which makes emacs-style
171 tag tables and tags typedefs, #defines and struct/union/enum by default. */
179 /* Exit codes for success and failure. */
188 #define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t))
189 #define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
191 #define CHARS 256 /* 2^sizeof(char) */
192 #define CHAR(x) ((unsigned int)(x) & (CHARS - 1))
193 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */
194 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
195 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
196 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
197 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
199 #define ISALNUM(c) isalnum (CHAR(c))
200 #define ISALPHA(c) isalpha (CHAR(c))
201 #define ISDIGIT(c) isdigit (CHAR(c))
202 #define ISLOWER(c) islower (CHAR(c))
204 #define lowcase(c) tolower (CHAR(c))
205 #define upcase(c) toupper (CHAR(c))
209 * xnew, xrnew -- allocate, reallocate storage
211 * SYNOPSIS: Type *xnew (int n, Type);
212 * void xrnew (OldPointer, int n, Type);
215 # include "chkmalloc.h"
216 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
217 (n) * sizeof (Type)))
218 # define xrnew(op,n,Type) ((op) = (Type *) trace_realloc (__FILE__, __LINE__, \
219 (char *) (op), (n) * sizeof (Type)))
221 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
222 # define xrnew(op,n,Type) ((op) = (Type *) xrealloc ( \
223 (char *) (op), (n) * sizeof (Type)))
228 typedef void Lang_function
__P((FILE *));
232 char *suffix
; /* file name suffix for this compressor */
233 char *command
; /* takes one arg and decompresses to stdout */
238 char *name
; /* language name */
239 bool metasource
; /* source used to generate other sources */
240 Lang_function
*function
; /* parse function */
241 char **filenames
; /* names of this language's files */
242 char **suffixes
; /* name suffixes of this language's files */
243 char **interpreters
; /* interpreters for this language */
248 struct fdesc
*next
; /* for the linked list */
249 char *infname
; /* uncompressed input file name */
250 char *infabsname
; /* absolute uncompressed input file name */
251 char *infabsdir
; /* absolute dir of input file */
252 char *taggedfname
; /* file name to write in tagfile */
253 language
*lang
; /* language of file */
254 char *prop
; /* file properties to write in tagfile */
255 bool usecharno
; /* etags tags shall contain char number */
258 typedef struct node_st
259 { /* sorting structure */
260 struct node_st
*left
, *right
; /* left and right sons */
261 fdesc
*fdp
; /* description of file to whom tag belongs */
262 char *name
; /* tag name */
263 char *pat
; /* search pattern */
264 bool valid
; /* write this tag on the tag file */
265 bool is_func
; /* function tag: use pattern in CTAGS mode */
266 bool been_warned
; /* warning already given for duplicated tag */
267 int lno
; /* line number tag is on */
268 long cno
; /* character number line starts on */
272 * A `linebuffer' is a structure which holds a line of text.
273 * `readline_internal' reads a line from a stream into a linebuffer
274 * and works regardless of the length of the line.
275 * SIZE is the size of BUFFER, LEN is the length of the string in
276 * BUFFER after readline reads it.
285 /* Used to support mixing of --lang and file names. */
289 at_language
, /* a language specification */
290 at_regexp
, /* a regular expression */
291 at_icregexp
, /* same, but with case ignored */
292 at_filename
, /* a file name */
293 at_stdin
/* read from stdin here */
294 } arg_type
; /* argument type */
295 language
*lang
; /* language associated with the argument */
296 char *what
; /* the argument itself */
300 /* Structure defining a regular expression. */
301 typedef struct pattern
303 struct pattern
*p_next
;
306 struct re_pattern_buffer
*pat
;
307 struct re_registers regs
;
312 #endif /* ETAGS_REGEXPS */
315 /* Many compilers barf on this:
316 Lang_function Ada_funcs;
317 so let's write it this way */
318 static void Ada_funcs
__P((FILE *));
319 static void Asm_labels
__P((FILE *));
320 static void C_entries
__P((int c_ext
, FILE *));
321 static void default_C_entries
__P((FILE *));
322 static void plain_C_entries
__P((FILE *));
323 static void Cjava_entries
__P((FILE *));
324 static void Cobol_paragraphs
__P((FILE *));
325 static void Cplusplus_entries
__P((FILE *));
326 static void Cstar_entries
__P((FILE *));
327 static void Erlang_functions
__P((FILE *));
328 static void Fortran_functions
__P((FILE *));
329 static void Yacc_entries
__P((FILE *));
330 static void Lisp_functions
__P((FILE *));
331 static void Makefile_targets
__P((FILE *));
332 static void Pascal_functions
__P((FILE *));
333 static void Perl_functions
__P((FILE *));
334 static void PHP_functions
__P((FILE *));
335 static void Postscript_functions
__P((FILE *));
336 static void Prolog_functions
__P((FILE *));
337 static void Python_functions
__P((FILE *));
338 static void Scheme_functions
__P((FILE *));
339 static void TeX_commands
__P((FILE *));
340 static void Texinfo_nodes
__P((FILE *));
341 static void just_read_file
__P((FILE *));
343 static void print_language_names
__P((void));
344 static void print_version
__P((void));
345 static void print_help
__P((void));
346 int main
__P((int, char **));
348 static compressor
*get_compressor_from_suffix
__P((char *, char **));
349 static language
*get_language_from_langname
__P((const char *));
350 static language
*get_language_from_interpreter
__P((char *));
351 static language
*get_language_from_filename
__P((char *, bool));
352 static void readline
__P((linebuffer
*, FILE *));
353 static long readline_internal
__P((linebuffer
*, FILE *));
354 static bool nocase_tail
__P((char *));
355 static char *get_tag
__P((char *));
358 static void analyse_regex
__P((char *, bool));
359 static void add_regex
__P((char *, bool, language
*));
360 static void free_patterns
__P((void));
361 #endif /* ETAGS_REGEXPS */
362 static void error
__P((const char *, const char *));
363 static void suggest_asking_for_help
__P((void));
364 void fatal
__P((char *, char *));
365 static void pfatal
__P((char *));
366 static void add_node
__P((node
*, node
**));
368 static void init
__P((void));
369 static void initbuffer
__P((linebuffer
*));
370 static void process_file_name
__P((char *, language
*));
371 static void process_file
__P((FILE *, char *, language
*));
372 static void find_entries
__P((FILE *));
373 static void free_tree
__P((node
*));
374 static void free_fdesc
__P((fdesc
*));
375 static void pfnote
__P((char *, bool, char *, int, int, long));
376 static void new_pfnote
__P((char *, int, bool, char *, int, int, long));
377 static void invalidate_nodes
__P((fdesc
*, node
**));
378 static void put_entries
__P((node
*));
380 static char *concat
__P((char *, char *, char *));
381 static char *skip_spaces
__P((char *));
382 static char *skip_non_spaces
__P((char *));
383 static char *savenstr
__P((char *, int));
384 static char *savestr
__P((char *));
385 static char *etags_strchr
__P((const char *, int));
386 static char *etags_strrchr
__P((const char *, int));
387 static bool strcaseeq
__P((const char *, const char *));
388 static char *etags_getcwd
__P((void));
389 static char *relative_filename
__P((char *, char *));
390 static char *absolute_filename
__P((char *, char *));
391 static char *absolute_dirname
__P((char *, char *));
392 static bool filename_is_absolute
__P((char *f
));
393 static void canonicalize_filename
__P((char *));
394 static void linebuffer_setlen
__P((linebuffer
*, int));
395 static PTR xmalloc
__P((unsigned int));
396 static PTR xrealloc
__P((char *, unsigned int));
399 static char searchar
= '/'; /* use /.../ searches */
401 static char *tagfile
; /* output file */
402 static char *progname
; /* name this program was invoked with */
403 static char *cwd
; /* current working directory */
404 static char *tagfiledir
; /* directory of tagfile */
405 static FILE *tagf
; /* ioptr for tags file */
407 static fdesc
*fdhead
; /* head of file description list */
408 static fdesc
*curfdp
; /* current file description */
409 static int lineno
; /* line number of current line */
410 static long charno
; /* current character number */
411 static long linecharno
; /* charno of start of current line */
412 static char *dbp
; /* pointer to start of current tag */
414 static const int invalidcharno
= -1;
416 static node
*nodehead
; /* the head of the binary tree of tags */
417 static node
*last_node
; /* the last node created */
419 static linebuffer lb
; /* the current line */
421 /* boolean "functions" (see init) */
422 static bool _wht
[CHARS
], _nin
[CHARS
], _itk
[CHARS
], _btk
[CHARS
], _etk
[CHARS
];
425 *white
= " \f\t\n\r\v",
427 *nonam
= " \f\t\n\r()=,;",
428 /* token ending chars */
429 *endtk
= " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
430 /* token starting chars */
431 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
432 /* valid in-token chars */
433 *midtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
435 static bool append_to_tagfile
; /* -a: append to tags */
436 /* The next four default to TRUE for etags, but to FALSE for ctags. */
437 static bool typedefs
; /* -t: create tags for C and Ada typedefs */
438 static bool typedefs_or_cplusplus
; /* -T: create tags for C typedefs, level */
439 /* 0 struct/enum/union decls, and C++ */
440 /* member functions. */
441 static bool constantypedefs
; /* -d: create tags for C #define, enum */
442 /* constants and variables. */
443 /* -D: opposite of -d. Default under ctags. */
444 static bool globals
; /* create tags for global variables */
445 static bool declarations
; /* --declarations: tag them and extern in C&Co*/
446 static bool members
; /* create tags for C member variables */
447 static bool no_line_directive
; /* ignore #line directives (undocumented) */
448 static bool update
; /* -u: update tags */
449 static bool vgrind_style
; /* -v: create vgrind style index output */
450 static bool no_warnings
; /* -w: suppress warnings */
451 static bool cxref_style
; /* -x: create cxref style output */
452 static bool cplusplus
; /* .[hc] means C++, not C */
453 static bool noindentypedefs
; /* -I: ignore indentation in C */
454 static bool packages_only
; /* --packages-only: in Ada, only tag packages*/
456 #define STDIN 0x1001 /* returned by getopt_long on --parse-stdin */
457 static bool parsing_stdin
; /* --parse-stdin used */
460 /* List of all regexps. */
461 static pattern
*p_head
;
463 /* How many characters in the character set. (From regex.c.) */
464 #define CHAR_SET_SIZE 256
465 /* Translation table for case-insensitive matching. */
466 static char lc_trans
[CHAR_SET_SIZE
];
467 #endif /* ETAGS_REGEXPS */
470 static struct option longopts
[] =
472 { "packages-only", no_argument
, &packages_only
, TRUE
},
473 { "c++", no_argument
, NULL
, 'C' },
474 { "declarations", no_argument
, &declarations
, TRUE
},
475 { "no-line-directive", no_argument
, &no_line_directive
, TRUE
},
476 { "help", no_argument
, NULL
, 'h' },
477 { "help", no_argument
, NULL
, 'H' },
478 { "ignore-indentation", no_argument
, NULL
, 'I' },
479 { "language", required_argument
, NULL
, 'l' },
480 { "members", no_argument
, &members
, TRUE
},
481 { "no-members", no_argument
, &members
, FALSE
},
482 { "output", required_argument
, NULL
, 'o' },
484 { "regex", required_argument
, NULL
, 'r' },
485 { "no-regex", no_argument
, NULL
, 'R' },
486 { "ignore-case-regex", required_argument
, NULL
, 'c' },
487 #endif /* ETAGS_REGEXPS */
488 { "parse-stdin", required_argument
, NULL
, STDIN
},
489 { "version", no_argument
, NULL
, 'V' },
491 #if CTAGS /* Etags options */
492 { "backward-search", no_argument
, NULL
, 'B' },
493 { "cxref", no_argument
, NULL
, 'x' },
494 { "defines", no_argument
, NULL
, 'd' },
495 { "globals", no_argument
, &globals
, TRUE
},
496 { "typedefs", no_argument
, NULL
, 't' },
497 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
498 { "update", no_argument
, NULL
, 'u' },
499 { "vgrind", no_argument
, NULL
, 'v' },
500 { "no-warn", no_argument
, NULL
, 'w' },
502 #else /* Ctags options */
503 { "append", no_argument
, NULL
, 'a' },
504 { "no-defines", no_argument
, NULL
, 'D' },
505 { "no-globals", no_argument
, &globals
, FALSE
},
506 { "include", required_argument
, NULL
, 'i' },
510 #endif /* LONG_OPTIONS */
512 static compressor compressors
[] =
514 { "z", "gzip -d -c"},
515 { "Z", "gzip -d -c"},
516 { "gz", "gzip -d -c"},
517 { "GZ", "gzip -d -c"},
518 { "bz2", "bzip2 -d -c" },
527 static char *Ada_suffixes
[] =
528 { "ads", "adb", "ada", NULL
};
531 static char *Asm_suffixes
[] =
532 { "a", /* Unix assembler */
533 "asm", /* Microcontroller assembly */
534 "def", /* BSO/Tasking definition includes */
535 "inc", /* Microcontroller include files */
536 "ins", /* Microcontroller include files */
537 "s", "sa", /* Unix assembler */
538 "S", /* cpp-processed Unix assembler */
539 "src", /* BSO/Tasking C compiler output */
543 /* Note that .c and .h can be considered C++, if the --c++ flag was
544 given, or if the `class' keyowrd is met inside the file.
545 That is why default_C_entries is called for these. */
546 static char *default_C_suffixes
[] =
549 static char *Cplusplus_suffixes
[] =
550 { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
551 "M", /* Objective C++ */
552 "pdb", /* Postscript with C syntax */
555 static char *Cjava_suffixes
[] =
558 static char *Cobol_suffixes
[] =
559 { "COB", "cob", NULL
};
561 static char *Cstar_suffixes
[] =
562 { "cs", "hs", NULL
};
564 static char *Erlang_suffixes
[] =
565 { "erl", "hrl", NULL
};
567 static char *Fortran_suffixes
[] =
568 { "F", "f", "f90", "for", NULL
};
570 static char *Lisp_suffixes
[] =
571 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL
};
573 static char *Makefile_filenames
[] =
574 { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL
};
576 static char *Pascal_suffixes
[] =
577 { "p", "pas", NULL
};
579 static char *Perl_suffixes
[] =
580 { "pl", "pm", NULL
};
582 static char *Perl_interpreters
[] =
583 { "perl", "@PERL@", NULL
};
585 static char *PHP_suffixes
[] =
586 { "php", "php3", "php4", NULL
};
588 static char *plain_C_suffixes
[] =
589 { "lm", /* Objective lex file */
590 "m", /* Objective C file */
591 "pc", /* Pro*C file */
594 static char *Postscript_suffixes
[] =
595 { "ps", "psw", NULL
}; /* .psw is for PSWrap */
597 static char *Prolog_suffixes
[] =
600 static char *Python_suffixes
[] =
603 /* Can't do the `SCM' or `scm' prefix with a version number. */
604 static char *Scheme_suffixes
[] =
605 { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL
};
607 static char *TeX_suffixes
[] =
608 { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL
};
610 static char *Texinfo_suffixes
[] =
611 { "texi", "texinfo", "txi", NULL
};
613 static char *Yacc_suffixes
[] =
614 { "y", "y++", "ym", "yxx", "yy", NULL
}; /* .ym is Objective yacc file */
617 * Table of languages.
619 * It is ok for a given function to be listed under more than one
620 * name. I just didn't.
623 static language lang_names
[] =
625 { "ada", FALSE
, Ada_funcs
, NULL
, Ada_suffixes
, NULL
},
626 { "asm", FALSE
, Asm_labels
, NULL
, Asm_suffixes
, NULL
},
627 { "c", FALSE
, default_C_entries
, NULL
, default_C_suffixes
, NULL
},
628 { "c++", FALSE
, Cplusplus_entries
, NULL
, Cplusplus_suffixes
, NULL
},
629 { "c*", FALSE
, Cstar_entries
, NULL
, Cstar_suffixes
, NULL
},
630 { "cobol", FALSE
, Cobol_paragraphs
, NULL
, Cobol_suffixes
, NULL
},
631 { "erlang", FALSE
, Erlang_functions
, NULL
, Erlang_suffixes
, NULL
},
632 { "fortran", FALSE
, Fortran_functions
, NULL
, Fortran_suffixes
, NULL
},
633 { "java", FALSE
, Cjava_entries
, NULL
, Cjava_suffixes
, NULL
},
634 { "lisp", FALSE
, Lisp_functions
, NULL
, Lisp_suffixes
, NULL
},
635 { "makefile", FALSE
, Makefile_targets
, Makefile_filenames
, NULL
, NULL
},
636 { "pascal", FALSE
, Pascal_functions
, NULL
, Pascal_suffixes
, NULL
},
637 { "perl", FALSE
, Perl_functions
,NULL
, Perl_suffixes
, Perl_interpreters
},
638 { "php", FALSE
, PHP_functions
, NULL
, PHP_suffixes
, NULL
},
639 { "postscript",FALSE
, Postscript_functions
,NULL
, Postscript_suffixes
, NULL
},
640 { "proc", FALSE
, plain_C_entries
, NULL
, plain_C_suffixes
, NULL
},
641 { "prolog", FALSE
, Prolog_functions
, NULL
, Prolog_suffixes
, NULL
},
642 { "python", FALSE
, Python_functions
, NULL
, Python_suffixes
, NULL
},
643 { "scheme", FALSE
, Scheme_functions
, NULL
, Scheme_suffixes
, NULL
},
644 { "tex", FALSE
, TeX_commands
, NULL
, TeX_suffixes
, NULL
},
645 { "texinfo", FALSE
, Texinfo_nodes
, NULL
, Texinfo_suffixes
, NULL
},
646 { "yacc", TRUE
, Yacc_entries
, NULL
, Yacc_suffixes
, NULL
},
647 { "auto", FALSE
, NULL
}, /* default guessing scheme */
648 { "none", FALSE
, just_read_file
}, /* regexp matching only */
649 { NULL
, FALSE
, NULL
} /* end of list */
654 print_language_names ()
659 puts ("\nThese are the currently supported languages, along with the\n\
660 default file names and dot suffixes:");
661 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
663 printf (" %-*s", 10, lang
->name
);
664 if (lang
->filenames
!= NULL
)
665 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
666 printf (" %s", *name
);
667 if (lang
->suffixes
!= NULL
)
668 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
669 printf (" .%s", *ext
);
672 puts ("Where `auto' means use default language for files based on file\n\
673 name suffix, and `none' means only do regexp processing on files.\n\
674 If no language is specified and no matching suffix is found,\n\
675 the first line of the file is read for a sharp-bang (#!) sequence\n\
676 followed by the name of an interpreter. If no such sequence is found,\n\
677 Fortran is tried first; if no tags are found, C is tried next.\n\
678 When parsing any C file, a \"class\" keyword switches to C++.\n\
679 Compressed files are supported using gzip and bzip2.");
683 # define EMACS_NAME "GNU Emacs"
686 # define VERSION "21"
691 printf ("%s (%s %s)\n", (CTAGS
) ? "ctags" : "etags", EMACS_NAME
, VERSION
);
692 puts ("Copyright (C) 2002 Free Software Foundation, Inc. and Ken Arnold");
693 puts ("This program is distributed under the same terms as Emacs");
701 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
703 These are the options accepted by %s.\n", progname
, progname
);
705 puts ("You may use unambiguous abbreviations for the long option names.");
707 puts ("Long option names do not work with this executable, as it is not\n\
708 linked with GNU getopt.");
709 #endif /* LONG_OPTIONS */
710 puts (" A - as file name means read names from stdin (one per line).\n\
711 Absolute names are stored in the output file as they are.\n\
712 Relative ones are stored relative to the output file's directory.\n");
715 puts ("-a, --append\n\
716 Append tag entries to existing tags file.");
718 puts ("--packages-only\n\
719 For Ada files, only generate tags for packages.");
722 puts ("-B, --backward-search\n\
723 Write the search commands for the tag entries using '?', the\n\
724 backward-search command instead of '/', the forward-search command.");
726 /* This option is mostly obsolete, because etags can now automatically
727 detect C++. Retained for backward compatibility and for debugging and
728 experimentation. In principle, we could want to tag as C++ even
729 before any "class" keyword.
731 Treat files whose name suffix defaults to C language as C++ files.");
734 puts ("--declarations\n\
735 In C and derived languages, create tags for function declarations,");
737 puts ("\tand create tags for extern variables if --globals is used.");
740 ("\tand create tags for extern variables unless --no-globals is used.");
743 puts ("-d, --defines\n\
744 Create tag entries for C #define constants and enum constants, too.");
746 puts ("-D, --no-defines\n\
747 Don't create tag entries for C #define constants and enum constants.\n\
748 This makes the tags file smaller.");
751 puts ("-i FILE, --include=FILE\n\
752 Include a note in tag file indicating that, when searching for\n\
753 a tag, one should also consult the tags file FILE after\n\
754 checking the current file.");
756 puts ("-l LANG, --language=LANG\n\
757 Force the following files to be considered as written in the\n\
758 named language up to the next --language=LANG option.");
762 Create tag entries for global variables in some languages.");
764 puts ("--no-globals\n\
765 Do not create tag entries for global variables in some\n\
766 languages. This makes the tags file smaller.");
768 Create tag entries for member variables in C and derived languages.");
771 puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
772 Make a tag for each line matching pattern REGEXP in the following\n\
773 files. {LANGUAGE}/REGEXP/ uses REGEXP for LANGUAGE files only.\n\
774 regexfile is a file containing one REGEXP per line.\n\
775 REGEXP is anchored (as if preceded by ^).\n\
776 The form /REGEXP/NAME/ creates a named tag.\n\
777 For example Tcl named tags can be created with:\n\
778 --regex=\"/proc[ \\t]+\\([^ \\t]+\\)/\\1/.\"");
779 puts ("-c /REGEXP/, --ignore-case-regex=/REGEXP/ or --ignore-case-regex=@regexfile\n\
780 Like -r, --regex but ignore case when matching expressions.");
781 puts ("-R, --no-regex\n\
782 Don't create tags from regexps for the following files.");
783 #endif /* ETAGS_REGEXPS */
784 puts ("-I, --ignore-indentation\n\
785 Don't rely on indentation quite as much as normal. Currently,\n\
786 this means not to assume that a closing brace in the first\n\
787 column is the final brace of a function or structure\n\
788 definition in C and C++.");
789 puts ("-o FILE, --output=FILE\n\
790 Write the tags to FILE.");
791 puts ("--parse-stdin=NAME\n\
792 Read from standard input and record tags as belonging to file NAME.");
796 puts ("-t, --typedefs\n\
797 Generate tag entries for C and Ada typedefs.");
798 puts ("-T, --typedefs-and-c++\n\
799 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
800 and C++ member functions.");
804 puts ("-u, --update\n\
805 Update the tag entries for the given files, leaving tag\n\
806 entries for other files in place. Currently, this is\n\
807 implemented by deleting the existing entries for the given\n\
808 files and then rewriting the new entries at the end of the\n\
809 tags file. It is often faster to simply rebuild the entire\n\
810 tag file than to use this.");
814 puts ("-v, --vgrind\n\
815 Generates an index of items intended for human consumption,\n\
816 similar to the output of vgrind. The index is sorted, and\n\
817 gives the page number of each item.");
818 puts ("-w, --no-warn\n\
819 Suppress warning messages about entries defined in multiple\n\
821 puts ("-x, --cxref\n\
822 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
823 The output uses line numbers instead of page numbers, but\n\
824 beyond that the differences are cosmetic; try both to see\n\
828 puts ("-V, --version\n\
829 Print the version of the program.\n\
831 Print this help message.");
833 print_language_names ();
836 puts ("Report bugs to bug-gnu-emacs@gnu.org");
842 #ifdef VMS /* VMS specific functions */
846 /* This is a BUG! ANY arbitrary limit is a BUG!
847 Won't someone please fix this? */
848 #define MAX_FILE_SPEC_LEN 255
851 char body
[MAX_FILE_SPEC_LEN
+ 1];
855 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
856 returning in each successive call the next file name matching the input
857 spec. The function expects that each in_spec passed
858 to it will be processed to completion; in particular, up to and
859 including the call following that in which the last matching name
860 is returned, the function ignores the value of in_spec, and will
861 only start processing a new spec with the following call.
862 If an error occurs, on return out_spec contains the value
863 of in_spec when the error occurred.
865 With each successive file name returned in out_spec, the
866 function's return value is one. When there are no more matching
867 names the function returns zero. If on the first call no file
868 matches in_spec, or there is any other error, -1 is returned.
873 #define OUTSIZE MAX_FILE_SPEC_LEN
879 static long context
= 0;
880 static struct dsc$descriptor_s o
;
881 static struct dsc$descriptor_s i
;
882 static bool pass1
= TRUE
;
889 o
.dsc$a_pointer
= (char *) out
;
890 o
.dsc$w_length
= (short)OUTSIZE
;
891 i
.dsc$a_pointer
= in
;
892 i
.dsc$w_length
= (short)strlen(in
);
893 i
.dsc$b_dtype
= DSC$K_DTYPE_T
;
894 i
.dsc$b_class
= DSC$K_CLASS_S
;
895 o
.dsc$b_dtype
= DSC$K_DTYPE_VT
;
896 o
.dsc$b_class
= DSC$K_CLASS_VS
;
898 if ((status
= lib$
find_file(&i
, &o
, &context
, 0, 0)) == RMS$_NORMAL
)
900 out
->body
[out
->curlen
] = EOS
;
903 else if (status
== RMS$_NMF
)
907 strcpy(out
->body
, in
);
910 lib$
find_file_end(&context
);
916 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
917 name of each file specified by the provided arg expanding wildcards.
920 gfnames (arg
, p_error
)
924 static vspec filename
= {MAX_FILE_SPEC_LEN
, "\0"};
926 switch (fn_exp (&filename
, arg
))
930 return filename
.body
;
936 return filename
.body
;
940 #ifndef OLD /* Newer versions of VMS do provide `system'. */
944 error ("%s", "system() function not implemented under VMS");
948 #define VERSION_DELIM ';'
949 char *massage_name (s
)
955 if (*s
== VERSION_DELIM
)
973 unsigned int nincluded_files
;
974 char **included_files
;
976 int current_arg
, file_count
;
977 linebuffer filename_lb
;
986 _fmode
= O_BINARY
; /* all of files are treated as binary files */
991 included_files
= xnew (argc
, char *);
995 /* Allocate enough no matter what happens. Overkill, but each one
997 argbuffer
= xnew (argc
, argument
);
1000 /* Set syntax for regular expression routines. */
1001 re_set_syntax (RE_SYNTAX_EMACS
| RE_INTERVALS
);
1002 /* Translation table for case-insensitive search. */
1003 for (i
= 0; i
< CHAR_SET_SIZE
; i
++)
1004 lc_trans
[i
] = lowcase (i
);
1005 #endif /* ETAGS_REGEXPS */
1008 * If etags, always find typedefs and structure tags. Why not?
1009 * Also default to find macro constants, enum constants and
1014 typedefs
= typedefs_or_cplusplus
= constantypedefs
= TRUE
;
1019 #ifdef ETAGS_REGEXPS
1020 optstring
= "-r:Rc:";
1021 #endif /* ETAGS_REGEXPS */
1022 #ifndef LONG_OPTIONS
1023 optstring
= optstring
+ 1;
1024 #endif /* LONG_OPTIONS */
1025 optstring
= concat (optstring
,
1027 (CTAGS
) ? "BxdtTuvw" : "aDi:");
1029 while ((opt
= getopt_long (argc
, argv
, optstring
, longopts
, 0)) != EOF
)
1033 /* If getopt returns 0, then it has already processed a
1034 long-named option. We should do nothing. */
1038 /* This means that a file name has been seen. Record it. */
1039 argbuffer
[current_arg
].arg_type
= at_filename
;
1040 argbuffer
[current_arg
].what
= optarg
;
1046 /* Parse standard input. Idea by Vivek <vivek@etla.org>. */
1047 argbuffer
[current_arg
].arg_type
= at_stdin
;
1048 argbuffer
[current_arg
].what
= optarg
;
1052 fatal ("cannot parse standard input more than once", (char *)NULL
);
1053 parsing_stdin
= TRUE
;
1056 /* Common options. */
1057 case 'C': cplusplus
= TRUE
; break;
1058 case 'f': /* for compatibility with old makefiles */
1062 error ("-o option may only be given once.", (char *)NULL
);
1063 suggest_asking_for_help ();
1068 case 'S': /* for backward compatibility */
1069 noindentypedefs
= TRUE
;
1073 language
*lang
= get_language_from_langname (optarg
);
1076 argbuffer
[current_arg
].lang
= lang
;
1077 argbuffer
[current_arg
].arg_type
= at_language
;
1083 argbuffer
[current_arg
].arg_type
= at_regexp
;
1084 argbuffer
[current_arg
].what
= optarg
;
1088 argbuffer
[current_arg
].arg_type
= at_regexp
;
1089 argbuffer
[current_arg
].what
= NULL
;
1093 argbuffer
[current_arg
].arg_type
= at_icregexp
;
1094 argbuffer
[current_arg
].what
= optarg
;
1106 case 'a': append_to_tagfile
= TRUE
; break;
1107 case 'D': constantypedefs
= FALSE
; break;
1108 case 'i': included_files
[nincluded_files
++] = optarg
; break;
1110 /* Ctags options. */
1111 case 'B': searchar
= '?'; break;
1112 case 'd': constantypedefs
= TRUE
; break;
1113 case 't': typedefs
= TRUE
; break;
1114 case 'T': typedefs
= typedefs_or_cplusplus
= TRUE
; break;
1115 case 'u': update
= TRUE
; break;
1116 case 'v': vgrind_style
= TRUE
; /*FALLTHRU*/
1117 case 'x': cxref_style
= TRUE
; break;
1118 case 'w': no_warnings
= TRUE
; break;
1120 suggest_asking_for_help ();
1123 for (; optind
< argc
; ++optind
)
1125 argbuffer
[current_arg
].arg_type
= at_filename
;
1126 argbuffer
[current_arg
].what
= argv
[optind
];
1131 if (nincluded_files
== 0 && file_count
== 0)
1133 error ("no input files specified.", (char *)NULL
);
1134 suggest_asking_for_help ();
1137 if (tagfile
== NULL
)
1138 tagfile
= CTAGS
? "tags" : "TAGS";
1139 cwd
= etags_getcwd (); /* the current working directory */
1140 if (cwd
[strlen (cwd
) - 1] != '/')
1143 cwd
= concat (oldcwd
, "/", "");
1146 if (streq (tagfile
, "-"))
1149 tagfiledir
= absolute_dirname (tagfile
, cwd
);
1151 init (); /* set up boolean "functions" */
1154 initbuffer (&filename_lb
);
1158 if (streq (tagfile
, "-"))
1162 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1163 doesn't take effect until after `stdout' is already open). */
1164 if (!isatty (fileno (stdout
)))
1165 setmode (fileno (stdout
), O_BINARY
);
1169 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1175 * Loop through files finding functions.
1177 for (i
= 0; i
< current_arg
; ++i
)
1179 static language
*lang
; /* non-NULL if language is forced */
1182 switch (argbuffer
[i
].arg_type
)
1185 lang
= argbuffer
[i
].lang
;
1187 #ifdef ETAGS_REGEXPS
1189 analyse_regex (argbuffer
[i
].what
, FALSE
);
1192 analyse_regex (argbuffer
[i
].what
, TRUE
);
1197 while ((this_file
= gfnames (argbuffer
[i
].what
, &got_err
)) != NULL
)
1201 error ("can't find file %s\n", this_file
);
1206 this_file
= massage_name (this_file
);
1209 this_file
= argbuffer
[i
].what
;
1211 /* Input file named "-" means read file names from stdin
1212 (one per line) and use them. */
1213 if (streq (this_file
, "-"))
1216 fatal ("cannot parse standard input AND read file names from it",
1218 while (readline_internal (&filename_lb
, stdin
) > 0)
1219 process_file_name (filename_lb
.buffer
, lang
);
1222 process_file_name (this_file
, lang
);
1228 this_file
= argbuffer
[i
].what
;
1229 process_file (stdin
, this_file
, lang
);
1234 #ifdef ETAGS_REGEXPS
1236 #endif /* ETAGS_REGEXPS */
1238 if (!CTAGS
|| cxref_style
)
1240 put_entries (nodehead
);
1241 free_tree (nodehead
);
1244 while (nincluded_files
-- > 0)
1245 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
1247 if (fclose (tagf
) == EOF
)
1255 for (i
= 0; i
< current_arg
; ++i
)
1257 switch (argbuffer
[i
].arg_type
)
1263 continue; /* the for loop */
1266 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1267 tagfile
, argbuffer
[i
].what
, tagfile
);
1268 if (system (cmd
) != GOOD
)
1269 fatal ("failed to execute shell command", (char *)NULL
);
1271 append_to_tagfile
= TRUE
;
1274 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1277 put_entries (nodehead
);
1278 free_tree (nodehead
);
1280 if (fclose (tagf
) == EOF
)
1285 char cmd
[2*BUFSIZ
+10];
1286 sprintf (cmd
, "sort -o %.*s %.*s", BUFSIZ
, tagfile
, BUFSIZ
, tagfile
);
1287 exit (system (cmd
));
1294 * Return a compressor given the file name. If EXTPTR is non-zero,
1295 * return a pointer into FILE where the compressor-specific
1296 * extension begins. If no compressor is found, NULL is returned
1297 * and EXTPTR is not significant.
1298 * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca> (1998)
1301 get_compressor_from_suffix (file
, extptr
)
1306 char *slash
, *suffix
;
1308 /* This relies on FN to be after canonicalize_filename,
1309 so we don't need to consider backslashes on DOS_NT. */
1310 slash
= etags_strrchr (file
, '/');
1311 suffix
= etags_strrchr (file
, '.');
1312 if (suffix
== NULL
|| suffix
< slash
)
1317 /* Let those poor souls who live with DOS 8+3 file name limits get
1318 some solace by treating foo.cgz as if it were foo.c.gz, etc.
1319 Only the first do loop is run if not MSDOS */
1322 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1323 if (streq (compr
->suffix
, suffix
))
1326 break; /* do it only once: not really a loop */
1329 } while (*suffix
!= '\0');
1336 * Return a language given the name.
1339 get_language_from_langname (name
)
1345 error ("empty language name", (char *)NULL
);
1348 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1349 if (streq (name
, lang
->name
))
1351 error ("unknown language \"%s\"", name
);
1359 * Return a language given the interpreter name.
1362 get_language_from_interpreter (interpreter
)
1368 if (interpreter
== NULL
)
1370 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1371 if (lang
->interpreters
!= NULL
)
1372 for (iname
= lang
->interpreters
; *iname
!= NULL
; iname
++)
1373 if (streq (*iname
, interpreter
))
1382 * Return a language given the file name.
1385 get_language_from_filename (file
, case_sensitive
)
1387 bool case_sensitive
;
1390 char **name
, **ext
, *suffix
;
1392 /* Try whole file name first. */
1393 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1394 if (lang
->filenames
!= NULL
)
1395 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
1396 if ((case_sensitive
)
1397 ? streq (*name
, file
)
1398 : strcaseeq (*name
, file
))
1401 /* If not found, try suffix after last dot. */
1402 suffix
= etags_strrchr (file
, '.');
1406 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1407 if (lang
->suffixes
!= NULL
)
1408 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
1409 if ((case_sensitive
)
1410 ? streq (*ext
, suffix
)
1411 : strcaseeq (*ext
, suffix
))
1418 * This routine is called on each file argument.
1421 process_file_name (file
, lang
)
1425 struct stat stat_buf
;
1429 char *compressed_name
, *uncompressed_name
;
1430 char *ext
, *real_name
;
1433 canonicalize_filename (file
);
1434 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
1436 error ("skipping inclusion of %s in self.", file
);
1439 if ((compr
= get_compressor_from_suffix (file
, &ext
)) == NULL
)
1441 compressed_name
= NULL
;
1442 real_name
= uncompressed_name
= savestr (file
);
1446 real_name
= compressed_name
= savestr (file
);
1447 uncompressed_name
= savenstr (file
, ext
- file
);
1450 /* If the canonicalized uncompressed name
1451 has already been dealt with, skip it silently. */
1452 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
1454 assert (fdp
->infname
!= NULL
);
1455 if (streq (uncompressed_name
, fdp
->infname
))
1459 if (stat (real_name
, &stat_buf
) != 0)
1461 /* Reset real_name and try with a different name. */
1463 if (compressed_name
!= NULL
) /* try with the given suffix */
1465 if (stat (uncompressed_name
, &stat_buf
) == 0)
1466 real_name
= uncompressed_name
;
1468 else /* try all possible suffixes */
1470 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1472 compressed_name
= concat (file
, ".", compr
->suffix
);
1473 if (stat (compressed_name
, &stat_buf
) != 0)
1477 char *suf
= compressed_name
+ strlen (file
);
1478 size_t suflen
= strlen (compr
->suffix
) + 1;
1479 for ( ; suf
[1]; suf
++, suflen
--)
1481 memmove (suf
, suf
+ 1, suflen
);
1482 if (stat (compressed_name
, &stat_buf
) == 0)
1484 real_name
= compressed_name
;
1488 if (real_name
!= NULL
)
1491 free (compressed_name
);
1492 compressed_name
= NULL
;
1496 real_name
= compressed_name
;
1501 if (real_name
== NULL
)
1506 } /* try with a different name */
1508 if (!S_ISREG (stat_buf
.st_mode
))
1510 error ("skipping %s: it is not a regular file.", real_name
);
1513 if (real_name
== compressed_name
)
1515 char *cmd
= concat (compr
->command
, " ", real_name
);
1516 inf
= (FILE *) popen (cmd
, "r");
1520 inf
= fopen (real_name
, "r");
1527 process_file (inf
, uncompressed_name
, lang
);
1529 if (real_name
== compressed_name
)
1530 retval
= pclose (inf
);
1532 retval
= fclose (inf
);
1537 if (compressed_name
) free (compressed_name
);
1538 if (uncompressed_name
) free (uncompressed_name
);
1545 process_file (fh
, fn
, lang
)
1550 static const fdesc emptyfdesc
;
1553 /* Create a new input file description entry. */
1554 fdp
= xnew (1, fdesc
);
1557 fdp
->infname
= savestr (fn
);
1559 fdp
->infabsname
= absolute_filename (fn
, cwd
);
1560 fdp
->infabsdir
= absolute_dirname (fn
, cwd
);
1561 if (filename_is_absolute (fn
))
1563 /* An absolute file name. Canonicalize it. */
1564 fdp
->taggedfname
= absolute_filename (fn
, NULL
);
1568 /* A file name relative to cwd. Make it relative
1569 to the directory of the tags file. */
1570 fdp
->taggedfname
= relative_filename (fn
, tagfiledir
);
1572 fdp
->usecharno
= TRUE
; /* use char position when making tags */
1576 curfdp
= fdhead
; /* the current file description */
1580 /* If not Ctags, and if this is not metasource and if it contained no #line
1581 directives, we can write the tags and free all nodes pointing to
1584 && curfdp
->usecharno
/* no #line directives in this file */
1585 && !curfdp
->lang
->metasource
)
1589 /* Look for the head of the sublist relative to this file. See add_node
1590 for the structure of the node tree. */
1592 for (np
= nodehead
; np
!= NULL
; prev
= np
, np
= np
->left
)
1593 if (np
->fdp
== curfdp
)
1596 /* If we generated tags for this file, write and delete them. */
1599 /* This is the head of the last sublist, if any. The following
1600 instructions depend on this being true. */
1601 assert (np
->left
== NULL
);
1603 assert (fdhead
== curfdp
);
1604 assert (last_node
->fdp
== curfdp
);
1605 put_entries (np
); /* write tags for file curfdp->taggedfname */
1606 free_tree (np
); /* remove the written nodes */
1608 nodehead
= NULL
; /* no nodes left */
1610 prev
->left
= NULL
; /* delete the pointer to the sublist */
1616 * This routine sets up the boolean pseudo-functions which work
1617 * by setting boolean flags dependent upon the corresponding character.
1618 * Every char which is NOT in that string is not a white char. Therefore,
1619 * all of the array "_wht" is set to FALSE, and then the elements
1620 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1621 * of a char is TRUE if it is the string "white", else FALSE.
1629 for (i
= 0; i
< CHARS
; i
++)
1630 iswhite(i
) = notinname(i
) = begtoken(i
) = intoken(i
) = endtoken(i
) = FALSE
;
1631 for (sp
= white
; *sp
!= '\0'; sp
++) iswhite (*sp
) = TRUE
;
1632 for (sp
= nonam
; *sp
!= '\0'; sp
++) notinname (*sp
) = TRUE
;
1633 notinname('\0') = notinname('\n');
1634 for (sp
= begtk
; *sp
!= '\0'; sp
++) begtoken (*sp
) = TRUE
;
1635 begtoken('\0') = begtoken('\n');
1636 for (sp
= midtk
; *sp
!= '\0'; sp
++) intoken (*sp
) = TRUE
;
1637 intoken('\0') = intoken('\n');
1638 for (sp
= endtk
; *sp
!= '\0'; sp
++) endtoken (*sp
) = TRUE
;
1639 endtoken('\0') = endtoken('\n');
1643 * This routine opens the specified file and calls the function
1644 * which finds the function and type definitions.
1651 node
*old_last_node
;
1652 language
*lang
= curfdp
->lang
;
1653 Lang_function
*parser
= NULL
;
1655 /* If user specified a language, use it. */
1656 if (lang
!= NULL
&& lang
->function
!= NULL
)
1658 parser
= lang
->function
;
1661 /* Else try to guess the language given the file name. */
1664 lang
= get_language_from_filename (curfdp
->infname
, TRUE
);
1665 if (lang
!= NULL
&& lang
->function
!= NULL
)
1667 curfdp
->lang
= lang
;
1668 parser
= lang
->function
;
1672 /* Else look for sharp-bang as the first two characters. */
1674 && readline_internal (&lb
, inf
) > 0
1676 && lb
.buffer
[0] == '#'
1677 && lb
.buffer
[1] == '!')
1681 /* Set lp to point at the first char after the last slash in the
1682 line or, if no slashes, at the first nonblank. Then set cp to
1683 the first successive blank and terminate the string. */
1684 lp
= etags_strrchr (lb
.buffer
+2, '/');
1688 lp
= skip_spaces (lb
.buffer
+ 2);
1689 cp
= skip_non_spaces (lp
);
1692 if (strlen (lp
) > 0)
1694 lang
= get_language_from_interpreter (lp
);
1695 if (lang
!= NULL
&& lang
->function
!= NULL
)
1697 curfdp
->lang
= lang
;
1698 parser
= lang
->function
;
1703 /* We rewind here, even if inf may be a pipe. We fail if the
1704 length of the first line is longer than the pipe block size,
1705 which is unlikely. */
1708 /* Else try to guess the language given the case insensitive file name. */
1711 lang
= get_language_from_filename (curfdp
->infname
, FALSE
);
1712 if (lang
!= NULL
&& lang
->function
!= NULL
)
1714 curfdp
->lang
= lang
;
1715 parser
= lang
->function
;
1719 if (!no_line_directive
1720 && curfdp
->lang
!= NULL
&& curfdp
->lang
->metasource
)
1721 /* It may be that this is a bingo.y file, and we already parsed a bingo.c
1722 file, or anyway we parsed a file that is automatically generated from
1723 this one. If this is the case, the bingo.c file contained #line
1724 directives that generated tags pointing to this file. Let's delete
1725 them all before parsing this file, which is the real source. */
1727 fdesc
**fdpp
= &fdhead
;
1728 while (*fdpp
!= NULL
)
1730 && streq ((*fdpp
)->taggedfname
, curfdp
->taggedfname
))
1731 /* We found one of those! We must delete both the file description
1732 and all tags referring to it. */
1734 fdesc
*badfdp
= *fdpp
;
1738 "Removing references to \"%s\" obtained from \"%s\"\n",
1739 badfdp
->taggedfname
, badfdp
->infname
);
1741 /* Delete the tags referring to badfdp. */
1742 invalidate_nodes (badfdp
, &nodehead
);
1744 *fdpp
= badfdp
->next
; /* remove the bad description from the list */
1745 free_fdesc (badfdp
);
1748 fdpp
= &(*fdpp
)->next
; /* advance the list pointer */
1753 /* Generic initialisations before reading from file. */
1754 lineno
= 0; /* reset global line number */
1755 charno
= 0; /* reset global char number */
1756 linecharno
= 0; /* reset global char number of line start */
1762 /* Else try Fortran. */
1763 old_last_node
= last_node
;
1764 curfdp
->lang
= get_language_from_langname ("fortran");
1767 if (old_last_node
== last_node
)
1768 /* No Fortran entries found. Try C. */
1770 /* We do not tag if rewind fails.
1771 Only the file name will be recorded in the tags file. */
1773 curfdp
->lang
= get_language_from_langname (cplusplus
? "c++" : "c");
1782 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
)
1783 char *name
; /* tag name, or NULL if unnamed */
1784 bool is_func
; /* tag is a function */
1785 char *linestart
; /* start of the line where tag is */
1786 int linelen
; /* length of the line where tag is */
1787 int lno
; /* line number */
1788 long cno
; /* character number */
1792 if (CTAGS
&& name
== NULL
)
1795 np
= xnew (1, node
);
1797 /* If ctags mode, change name "main" to M<thisfilename>. */
1798 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
1800 register char *fp
= etags_strrchr (curfdp
->taggedfname
, '/');
1801 np
->name
= concat ("M", fp
== NULL
? curfdp
->taggedfname
: fp
+ 1, "");
1802 fp
= etags_strrchr (np
->name
, '.');
1803 if (fp
!= NULL
&& fp
[1] != '\0' && fp
[2] == '\0')
1809 np
->been_warned
= FALSE
;
1811 np
->is_func
= is_func
;
1813 if (np
->fdp
->usecharno
)
1814 /* Our char numbers are 0-base, because of C language tradition?
1815 ctags compatibility? old versions compatibility? I don't know.
1816 Anyway, since emacs's are 1-base we expect etags.el to take care
1817 of the difference. If we wanted to have 1-based numbers, we would
1818 uncomment the +1 below. */
1819 np
->cno
= cno
/* + 1 */ ;
1821 np
->cno
= invalidcharno
;
1822 np
->left
= np
->right
= NULL
;
1823 if (CTAGS
&& !cxref_style
)
1825 if (strlen (linestart
) < 50)
1826 np
->pat
= concat (linestart
, "$", "");
1828 np
->pat
= savenstr (linestart
, 50);
1831 np
->pat
= savenstr (linestart
, linelen
);
1833 add_node (np
, &nodehead
);
1837 * TAGS format specification
1838 * Idea by Sam Kendall <kendall@mv.mv.com> (1997)
1840 * pfnote should emit the optimized form [unnamed tag] only if:
1841 * 1. name does not contain any of the characters " \t\r\n(),;";
1842 * 2. linestart contains name as either a rightmost, or rightmost but
1843 * one character, substring;
1844 * 3. the character, if any, immediately before name in linestart must
1845 * be one of the characters " \t(),;";
1846 * 4. the character, if any, immediately after name in linestart must
1847 * also be one of the characters " \t(),;".
1849 * The real implementation uses the notinname() macro, which recognises
1850 * characters slightly different from " \t\r\n(),;". See the variable
1853 #define traditional_tag_style TRUE
1855 new_pfnote (name
, namelen
, is_func
, linestart
, linelen
, lno
, cno
)
1856 char *name
; /* tag name, or NULL if unnamed */
1857 int namelen
; /* tag length */
1858 bool is_func
; /* tag is a function */
1859 char *linestart
; /* start of the line where tag is */
1860 int linelen
; /* length of the line where tag is */
1861 int lno
; /* line number */
1862 long cno
; /* character number */
1870 for (cp
= name
; !notinname (*cp
); cp
++)
1872 if (*cp
== '\0') /* rule #1 */
1874 cp
= linestart
+ linelen
- namelen
;
1875 if (notinname (linestart
[linelen
-1]))
1876 cp
-= 1; /* rule #4 */
1877 if (cp
>= linestart
/* rule #2 */
1879 || notinname (cp
[-1])) /* rule #3 */
1880 && strneq (name
, cp
, namelen
)) /* rule #2 */
1881 named
= FALSE
; /* use unnamed tag */
1886 name
= savenstr (name
, namelen
);
1889 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
);
1894 * recurse on left children, iterate on right children.
1902 register node
*node_right
= np
->right
;
1903 free_tree (np
->left
);
1904 if (np
->name
!= NULL
)
1914 * delete a file description
1918 register fdesc
*fdp
;
1920 if (fdp
->infname
!= NULL
) free (fdp
->infname
);
1921 if (fdp
->infabsname
!= NULL
) free (fdp
->infabsname
);
1922 if (fdp
->infabsdir
!= NULL
) free (fdp
->infabsdir
);
1923 if (fdp
->taggedfname
!= NULL
) free (fdp
->taggedfname
);
1924 if (fdp
->prop
!= NULL
) free (fdp
->prop
);
1930 * Adds a node to the tree of nodes. In etags mode, sort by file
1931 * name. In ctags mode, sort by tag name. Make no attempt at
1934 * add_node is the only function allowed to add nodes, so it can
1938 add_node (np
, cur_node_p
)
1939 node
*np
, **cur_node_p
;
1942 register node
*cur_node
= *cur_node_p
;
1944 if (cur_node
== NULL
)
1954 /* For each file name, tags are in a linked sublist on the right
1955 pointer. The first tags of different files are a linked list
1956 on the left pointer. last_node points to the end of the last
1958 if (last_node
!= NULL
&& last_node
->fdp
== np
->fdp
)
1960 /* Let's use the same sublist as the last added node. */
1961 assert (last_node
->right
== NULL
);
1962 last_node
->right
= np
;
1965 else if (cur_node
->fdp
== np
->fdp
)
1967 /* Scanning the list we found the head of a sublist which is
1968 good for us. Let's scan this sublist. */
1969 add_node (np
, &cur_node
->right
);
1972 /* The head of this sublist is not good for us. Let's try the
1974 add_node (np
, &cur_node
->left
);
1975 } /* if ETAGS mode */
1980 dif
= strcmp (np
->name
, cur_node
->name
);
1983 * If this tag name matches an existing one, then
1984 * do not add the node, but maybe print a warning.
1988 if (np
->fdp
== cur_node
->fdp
)
1992 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1993 np
->fdp
->infname
, lineno
, np
->name
);
1994 fprintf (stderr
, "Second entry ignored\n");
1997 else if (!cur_node
->been_warned
&& !no_warnings
)
2001 "Duplicate entry in files %s and %s: %s (Warning only)\n",
2002 np
->fdp
->infname
, cur_node
->fdp
->infname
, np
->name
);
2003 cur_node
->been_warned
= TRUE
;
2008 /* Actually add the node */
2009 add_node (np
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
2010 } /* if CTAGS mode */
2014 * invalidate_nodes ()
2015 * Scan the node tree and invalidate all nodes pointing to the
2016 * given file description (CTAGS case) or free them (ETAGS case).
2019 invalidate_nodes (badfdp
, npp
)
2030 if (np
->left
!= NULL
)
2031 invalidate_nodes (badfdp
, &np
->left
);
2032 if (np
->fdp
== badfdp
)
2034 if (np
->right
!= NULL
)
2035 invalidate_nodes (badfdp
, &np
->right
);
2039 node
**next
= &np
->left
;
2040 if (np
->fdp
== badfdp
)
2042 *npp
= *next
; /* detach the sublist from the list */
2043 np
->left
= NULL
; /* isolate it */
2044 free_tree (np
); /* free it */
2046 invalidate_nodes (badfdp
, next
);
2051 static int total_size_of_entries
__P((node
*));
2052 static int number_len
__P((long));
2054 /* Length of a non-negative number's decimal representation. */
2060 while ((num
/= 10) > 0)
2066 * Return total number of characters that put_entries will output for
2067 * the nodes in the linked list at the right of the specified node.
2068 * This count is irrelevant with etags.el since emacs 19.34 at least,
2069 * but is still supplied for backward compatibility.
2072 total_size_of_entries (np
)
2075 register int total
= 0;
2077 for (; np
!= NULL
; np
= np
->right
)
2079 total
+= strlen (np
->pat
) + 1; /* pat\177 */
2080 if (np
->name
!= NULL
)
2081 total
+= strlen (np
->name
) + 1; /* name\001 */
2082 total
+= number_len ((long) np
->lno
) + 1; /* lno, */
2083 if (np
->cno
!= invalidcharno
) /* cno */
2084 total
+= number_len (np
->cno
);
2085 total
+= 1; /* newline */
2096 static fdesc
*fdp
= NULL
;
2101 /* Output subentries that precede this one */
2103 put_entries (np
->left
);
2105 /* Output this entry */
2114 fprintf (tagf
, "\f\n%s,%d\n",
2115 fdp
->taggedfname
, total_size_of_entries (np
));
2117 fputs (np
->pat
, tagf
);
2118 fputc ('\177', tagf
);
2119 if (np
->name
!= NULL
)
2121 fputs (np
->name
, tagf
);
2122 fputc ('\001', tagf
);
2124 fprintf (tagf
, "%d,", np
->lno
);
2125 if (np
->cno
!= invalidcharno
)
2126 fprintf (tagf
, "%ld", np
->cno
);
2132 if (np
->name
== NULL
)
2133 error ("internal error: NULL name in ctags mode.", (char *)NULL
);
2138 fprintf (stdout
, "%s %s %d\n",
2139 np
->name
, np
->fdp
->taggedfname
, (np
->lno
+ 63) / 64);
2141 fprintf (stdout
, "%-16s %3d %-16s %s\n",
2142 np
->name
, np
->lno
, np
->fdp
->taggedfname
, np
->pat
);
2146 fprintf (tagf
, "%s\t%s\t", np
->name
, np
->fdp
->taggedfname
);
2149 { /* function or #define macro with args */
2150 putc (searchar
, tagf
);
2153 for (sp
= np
->pat
; *sp
; sp
++)
2155 if (*sp
== '\\' || *sp
== searchar
)
2159 putc (searchar
, tagf
);
2162 { /* anything else; text pattern inadequate */
2163 fprintf (tagf
, "%d", np
->lno
);
2168 } /* if this node contains a valid tag */
2170 /* Output subentries that follow this one */
2171 put_entries (np
->right
);
2173 put_entries (np
->left
);
2178 #define C_EXT 0x00fff /* C extensions */
2179 #define C_PLAIN 0x00000 /* C */
2180 #define C_PLPL 0x00001 /* C++ */
2181 #define C_STAR 0x00003 /* C* */
2182 #define C_JAVA 0x00005 /* JAVA */
2183 #define C_AUTO 0x01000 /* C, but switch to C++ if `class' is met */
2184 #define YACC 0x10000 /* yacc file */
2187 * The C symbol tables.
2192 st_C_objprot
, st_C_objimpl
, st_C_objend
,
2197 st_C_class
, st_C_template
,
2198 st_C_struct
, st_C_extern
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
2201 static unsigned int hash
__P((const char *, unsigned int));
2202 static struct C_stab_entry
* in_word_set
__P((const char *, unsigned int));
2203 static enum sym_type C_symtype
__P((char *, int, int));
2205 /* Feed stuff between (but not including) %[ and %] lines to:
2206 gperf -c -k 1,3 -o -p -r -t
2208 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
2212 while, 0, st_C_ignore
2213 switch, 0, st_C_ignore
2214 return, 0, st_C_ignore
2215 @interface, 0, st_C_objprot
2216 @protocol, 0, st_C_objprot
2217 @implementation,0, st_C_objimpl
2218 @end, 0, st_C_objend
2219 import, C_JAVA, st_C_ignore
2220 package, C_JAVA, st_C_ignore
2221 friend, C_PLPL, st_C_ignore
2222 extends, C_JAVA, st_C_javastruct
2223 implements, C_JAVA, st_C_javastruct
2224 interface, C_JAVA, st_C_struct
2225 class, 0, st_C_class
2226 namespace, C_PLPL, st_C_struct
2227 domain, C_STAR, st_C_struct
2228 union, 0, st_C_struct
2229 struct, 0, st_C_struct
2230 extern, 0, st_C_extern
2232 typedef, 0, st_C_typedef
2233 define, 0, st_C_define
2234 operator, C_PLPL, st_C_operator
2235 template, 0, st_C_template
2236 bool, C_PLPL, st_C_typespec
2237 long, 0, st_C_typespec
2238 short, 0, st_C_typespec
2239 int, 0, st_C_typespec
2240 char, 0, st_C_typespec
2241 float, 0, st_C_typespec
2242 double, 0, st_C_typespec
2243 signed, 0, st_C_typespec
2244 unsigned, 0, st_C_typespec
2245 auto, 0, st_C_typespec
2246 void, 0, st_C_typespec
2247 static, 0, st_C_typespec
2248 const, 0, st_C_typespec
2249 volatile, 0, st_C_typespec
2250 explicit, C_PLPL, st_C_typespec
2251 mutable, C_PLPL, st_C_typespec
2252 typename, C_PLPL, st_C_typespec
2253 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
2254 DEFUN, 0, st_C_gnumacro
2255 SYSCALL, 0, st_C_gnumacro
2256 ENTRY, 0, st_C_gnumacro
2257 PSEUDO, 0, st_C_gnumacro
2258 # These are defined inside C functions, so currently they are not met.
2259 # EXFUN used in glibc, DEFVAR_* in emacs.
2260 #EXFUN, 0, st_C_gnumacro
2261 #DEFVAR_, 0, st_C_gnumacro
2263 and replace lines between %< and %> with its output,
2264 then make in_word_set and C_stab_entry static. */
2266 /* C code produced by gperf version 2.7.1 (19981006 egcs) */
2267 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
2268 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
2270 #define TOTAL_KEYWORDS 47
2271 #define MIN_WORD_LENGTH 2
2272 #define MAX_WORD_LENGTH 15
2273 #define MIN_HASH_VALUE 18
2274 #define MAX_HASH_VALUE 138
2275 /* maximum key range = 121, duplicates = 0 */
2282 register const char *str
;
2283 register unsigned int len
;
2285 static unsigned char asso_values
[] =
2287 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2288 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2289 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2290 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2291 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2292 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2293 139, 139, 139, 139, 63, 139, 139, 139, 33, 44,
2294 62, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2295 42, 139, 139, 12, 32, 139, 139, 139, 139, 139,
2296 139, 139, 139, 139, 139, 139, 139, 34, 59, 37,
2297 24, 58, 33, 3, 139, 16, 139, 139, 42, 60,
2298 18, 11, 39, 139, 23, 57, 4, 63, 6, 20,
2299 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2300 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2301 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2302 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2303 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2304 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2305 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2306 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2307 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2308 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2309 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2310 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2311 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2312 139, 139, 139, 139, 139, 139
2314 register int hval
= len
;
2320 hval
+= asso_values
[(unsigned char)str
[2]];
2323 hval
+= asso_values
[(unsigned char)str
[0]];
2332 static struct C_stab_entry
*
2333 in_word_set (str
, len
)
2334 register const char *str
;
2335 register unsigned int len
;
2337 static struct C_stab_entry wordlist
[] =
2339 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2340 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2341 {"if", 0, st_C_ignore
},
2342 {""}, {""}, {""}, {""},
2343 {"int", 0, st_C_typespec
},
2345 {"void", 0, st_C_typespec
},
2347 {"interface", C_JAVA
, st_C_struct
},
2349 {"SYSCALL", 0, st_C_gnumacro
},
2351 {"return", 0, st_C_ignore
},
2352 {""}, {""}, {""}, {""}, {""}, {""}, {""},
2353 {"while", 0, st_C_ignore
},
2354 {"auto", 0, st_C_typespec
},
2355 {""}, {""}, {""}, {""}, {""}, {""},
2356 {"float", 0, st_C_typespec
},
2357 {"typedef", 0, st_C_typedef
},
2358 {"typename", C_PLPL
, st_C_typespec
},
2360 {"friend", C_PLPL
, st_C_ignore
},
2361 {"volatile", 0, st_C_typespec
},
2363 {"for", 0, st_C_ignore
},
2364 {"const", 0, st_C_typespec
},
2365 {"import", C_JAVA
, st_C_ignore
},
2367 {"define", 0, st_C_define
},
2368 {"long", 0, st_C_typespec
},
2369 {"implements", C_JAVA
, st_C_javastruct
},
2370 {"signed", 0, st_C_typespec
},
2372 {"extern", 0, st_C_extern
},
2373 {"extends", C_JAVA
, st_C_javastruct
},
2375 {"mutable", C_PLPL
, st_C_typespec
},
2376 {"template", 0, st_C_template
},
2377 {"short", 0, st_C_typespec
},
2378 {"bool", C_PLPL
, st_C_typespec
},
2379 {"char", 0, st_C_typespec
},
2380 {"class", 0, st_C_class
},
2381 {"operator", C_PLPL
, st_C_operator
},
2383 {"switch", 0, st_C_ignore
},
2385 {"ENTRY", 0, st_C_gnumacro
},
2387 {"package", C_JAVA
, st_C_ignore
},
2388 {"union", 0, st_C_struct
},
2389 {"@end", 0, st_C_objend
},
2390 {"struct", 0, st_C_struct
},
2391 {"namespace", C_PLPL
, st_C_struct
},
2393 {"domain", C_STAR
, st_C_struct
},
2394 {"@interface", 0, st_C_objprot
},
2395 {"PSEUDO", 0, st_C_gnumacro
},
2396 {"double", 0, st_C_typespec
},
2398 {"@protocol", 0, st_C_objprot
},
2400 {"static", 0, st_C_typespec
},
2402 {"DEFUN", 0, st_C_gnumacro
},
2403 {""}, {""}, {""}, {""},
2404 {"explicit", C_PLPL
, st_C_typespec
},
2405 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2406 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2408 {"enum", 0, st_C_enum
},
2410 {"unsigned", 0, st_C_typespec
},
2411 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2412 {"@implementation",0, st_C_objimpl
}
2415 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
2417 register int key
= hash (str
, len
);
2419 if (key
<= MAX_HASH_VALUE
&& key
>= 0)
2421 register const char *s
= wordlist
[key
].name
;
2423 if (*str
== *s
&& !strncmp (str
+ 1, s
+ 1, len
- 1))
2424 return &wordlist
[key
];
2431 static enum sym_type
2432 C_symtype (str
, len
, c_ext
)
2437 register struct C_stab_entry
*se
= in_word_set (str
, len
);
2439 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
2446 * C functions and variables are recognized using a simple
2447 * finite automaton. fvdef is its state variable.
2451 fvnone
, /* nothing seen */
2452 fdefunkey
, /* Emacs DEFUN keyword seen */
2453 fdefunname
, /* Emacs DEFUN name seen */
2454 foperator
, /* func: operator keyword seen (cplpl) */
2455 fvnameseen
, /* function or variable name seen */
2456 fstartlist
, /* func: just after open parenthesis */
2457 finlist
, /* func: in parameter list */
2458 flistseen
, /* func: after parameter list */
2459 fignore
, /* func: before open brace */
2460 vignore
/* var-like: ignore until ';' */
2463 static bool fvextern
; /* func or var: extern keyword seen; */
2466 * typedefs are recognized using a simple finite automaton.
2467 * typdef is its state variable.
2471 tnone
, /* nothing seen */
2472 tkeyseen
, /* typedef keyword seen */
2473 ttypeseen
, /* defined type seen */
2474 tinbody
, /* inside typedef body */
2475 tend
, /* just before typedef tag */
2476 tignore
/* junk after typedef tag */
2480 * struct-like structures (enum, struct and union) are recognized
2481 * using another simple finite automaton. `structdef' is its state
2486 snone
, /* nothing seen yet,
2487 or in struct body if cblev > 0 */
2488 skeyseen
, /* struct-like keyword seen */
2489 stagseen
, /* struct-like tag seen */
2490 sintemplate
, /* inside template (ignore) */
2491 scolonseen
/* colon seen after struct-like tag */
2495 * When objdef is different from onone, objtag is the name of the class.
2497 static char *objtag
= "<uninited>";
2500 * Yet another little state machine to deal with preprocessor lines.
2504 dnone
, /* nothing seen */
2505 dsharpseen
, /* '#' seen as first char on line */
2506 ddefineseen
, /* '#' and 'define' seen */
2507 dignorerest
/* ignore rest of line */
2511 * State machine for Objective C protocols and implementations.
2512 * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995)
2516 onone
, /* nothing seen */
2517 oprotocol
, /* @interface or @protocol seen */
2518 oimplementation
, /* @implementations seen */
2519 otagseen
, /* class name seen */
2520 oparenseen
, /* parenthesis before category seen */
2521 ocatseen
, /* category name seen */
2522 oinbody
, /* in @implementation body */
2523 omethodsign
, /* in @implementation body, after +/- */
2524 omethodtag
, /* after method name */
2525 omethodcolon
, /* after method colon */
2526 omethodparm
, /* after method parameter */
2527 oignore
/* wait for @end */
2532 * Use this structure to keep info about the token read, and how it
2533 * should be tagged. Used by the make_C_tag function to build a tag.
2544 } token
; /* latest token read */
2545 static linebuffer token_name
; /* its name */
2548 * Variables and functions for dealing with nested structures.
2549 * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001)
2551 static void pushclass_above
__P((int, char *, int));
2552 static void popclass_above
__P((int));
2553 static void write_classname
__P((linebuffer
*, char *qualifier
));
2556 char **cname
; /* nested class names */
2557 int *cblev
; /* nested class curly brace level */
2558 int nl
; /* class nesting level (elements used) */
2559 int size
; /* length of the array */
2560 } cstack
; /* stack for nested declaration tags */
2561 /* Current struct nesting depth (namespace, class, struct, union, enum). */
2562 #define nestlev (cstack.nl)
2563 /* After struct keyword or in struct body, not inside an nested function. */
2564 #define instruct (structdef == snone && nestlev > 0 \
2565 && cblev == cstack.cblev[nestlev-1] + 1)
2568 pushclass_above (cblev
, str
, len
)
2575 popclass_above (cblev
);
2577 if (nl
>= cstack
.size
)
2579 int size
= cstack
.size
*= 2;
2580 xrnew (cstack
.cname
, size
, char *);
2581 xrnew (cstack
.cblev
, size
, int);
2583 assert (nl
== 0 || cstack
.cblev
[nl
-1] < cblev
);
2584 cstack
.cname
[nl
] = (str
== NULL
) ? NULL
: savenstr (str
, len
);
2585 cstack
.cblev
[nl
] = cblev
;
2590 popclass_above (cblev
)
2595 for (nl
= cstack
.nl
- 1;
2596 nl
>= 0 && cstack
.cblev
[nl
] >= cblev
;
2599 if (cstack
.cname
[nl
] != NULL
)
2600 free (cstack
.cname
[nl
]);
2606 write_classname (cn
, qualifier
)
2611 int qlen
= strlen (qualifier
);
2613 if (cstack
.nl
== 0 || cstack
.cname
[0] == NULL
)
2617 cn
->buffer
[0] = '\0';
2621 len
= strlen (cstack
.cname
[0]);
2622 linebuffer_setlen (cn
, len
);
2623 strcpy (cn
->buffer
, cstack
.cname
[0]);
2625 for (i
= 1; i
< cstack
.nl
; i
++)
2630 s
= cstack
.cname
[i
];
2635 linebuffer_setlen (cn
, len
);
2636 strncat (cn
->buffer
, qualifier
, qlen
);
2637 strncat (cn
->buffer
, s
, slen
);
2642 static bool consider_token
__P((char *, int, int, int *, int, int, bool *));
2643 static void make_C_tag
__P((bool));
2647 * checks to see if the current token is at the start of a
2648 * function or variable, or corresponds to a typedef, or
2649 * is a struct/union/enum tag, or #define, or an enum constant.
2651 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2652 * with args. C_EXTP points to which language we are looking at.
2663 consider_token (str
, len
, c
, c_extp
, cblev
, parlev
, is_func_or_var
)
2664 register char *str
; /* IN: token pointer */
2665 register int len
; /* IN: token length */
2666 register int c
; /* IN: first char after the token */
2667 int *c_extp
; /* IN, OUT: C extensions mask */
2668 int cblev
; /* IN: curly brace level */
2669 int parlev
; /* IN: parenthesis level */
2670 bool *is_func_or_var
; /* OUT: function or variable found */
2672 /* When structdef is stagseen, scolonseen, or snone with cblev > 0,
2673 structtype is the type of the preceding struct-like keyword, and
2674 structcblev is the curly brace level where it has been seen. */
2675 static enum sym_type structtype
;
2676 static int structcblev
;
2677 static enum sym_type toktype
;
2680 toktype
= C_symtype (str
, len
, *c_extp
);
2683 * Advance the definedef state machine.
2688 /* We're not on a preprocessor line. */
2689 if (toktype
== st_C_gnumacro
)
2696 if (toktype
== st_C_define
)
2698 definedef
= ddefineseen
;
2702 definedef
= dignorerest
;
2707 * Make a tag for any macro, unless it is a constant
2708 * and constantypedefs is FALSE.
2710 definedef
= dignorerest
;
2711 *is_func_or_var
= (c
== '(');
2712 if (!*is_func_or_var
&& !constantypedefs
)
2719 error ("internal error: definedef value.", (char *)NULL
);
2728 if (toktype
== st_C_typedef
)
2750 if (structdef
== snone
&& fvdef
== fvnone
)
2769 * This structdef business is NOT invoked when we are ctags and the
2770 * file is plain C. This is because a struct tag may have the same
2771 * name as another tag, and this loses with ctags.
2775 case st_C_javastruct
:
2776 if (structdef
== stagseen
)
2777 structdef
= scolonseen
;
2782 && (*c_extp
& C_AUTO
) /* automatic detection of C++ language */
2783 && definedef
== dnone
&& structdef
== snone
2784 && typdef
== tnone
&& fvdef
== fvnone
)
2785 *c_extp
= (*c_extp
| C_PLPL
) & ~C_AUTO
;
2786 if (toktype
== st_C_template
)
2793 && (typdef
== tkeyseen
2794 || (typedefs_or_cplusplus
&& structdef
== snone
)))
2796 structdef
= skeyseen
;
2797 structtype
= toktype
;
2798 structcblev
= cblev
;
2803 if (structdef
== skeyseen
)
2805 structdef
= stagseen
;
2809 if (typdef
!= tnone
)
2812 /* Detect Objective C constructs. */
2822 objdef
= oimplementation
;
2826 case oimplementation
:
2827 /* Save the class tag for functions or variables defined inside. */
2828 objtag
= savenstr (str
, len
);
2832 /* Save the class tag for categories. */
2833 objtag
= savenstr (str
, len
);
2835 *is_func_or_var
= TRUE
;
2839 *is_func_or_var
= TRUE
;
2846 objdef
= omethodtag
;
2847 linebuffer_setlen (&token_name
, len
);
2848 strncpy (token_name
.buffer
, str
, len
);
2849 token_name
.buffer
[len
] = '\0';
2855 objdef
= omethodparm
;
2860 objdef
= omethodtag
;
2861 linebuffer_setlen (&token_name
, token_name
.len
+ len
);
2862 strncat (token_name
.buffer
, str
, len
);
2867 if (toktype
== st_C_objend
)
2869 /* Memory leakage here: the string pointed by objtag is
2870 never released, because many tests would be needed to
2871 avoid breaking on incorrect input code. The amount of
2872 memory leaked here is the sum of the lengths of the
2880 /* A function, variable or enum constant? */
2887 if (fvdef
!= finlist
&& fvdef
!= fignore
&& fvdef
!= vignore
)
2888 fvdef
= fvnone
; /* should be useless */
2896 *is_func_or_var
= TRUE
;
2900 && structdef
== snone
2901 && structtype
== st_C_enum
&& cblev
> structcblev
)
2902 return TRUE
; /* enum constant */
2908 fvdef
= fdefunname
; /* GNU macro */
2909 *is_func_or_var
= TRUE
;
2912 if ((strneq (str
, "asm", 3) && endtoken (str
[3]))
2913 || (strneq (str
, "__asm__", 7) && endtoken (str
[7])))
2918 if ((*c_extp
& C_PLPL
) && strneq (str
+len
-10, "::operator", 10))
2921 *is_func_or_var
= TRUE
;
2924 if (cblev
> 0 && !instruct
)
2926 fvdef
= fvnameseen
; /* function or variable */
2927 *is_func_or_var
= TRUE
;
2938 * C_entries often keeps pointers to tokens or lines which are older than
2939 * the line currently read. By keeping two line buffers, and switching
2940 * them at end of line, it is possible to use those pointers.
2948 #define current_lb_is_new (newndx == curndx)
2949 #define switch_line_buffers() (curndx = 1 - curndx)
2951 #define curlb (lbs[curndx].lb)
2952 #define newlb (lbs[newndx].lb)
2953 #define curlinepos (lbs[curndx].linepos)
2954 #define newlinepos (lbs[newndx].linepos)
2956 #define CNL_SAVE_DEFINEDEF() \
2958 curlinepos = charno; \
2959 readline (&curlb, inf); \
2960 lp = curlb.buffer; \
2967 CNL_SAVE_DEFINEDEF(); \
2968 if (savetoken.valid) \
2970 token = savetoken; \
2971 savetoken.valid = FALSE; \
2973 definedef = dnone; \
2981 /* This function should never be called when token.valid is FALSE, but
2982 we must protect against invalid input or internal errors. */
2983 if (DEBUG
|| token
.valid
)
2985 if (traditional_tag_style
)
2987 /* This was the original code. Now we call new_pfnote instead,
2988 which uses the new method for naming tags (see new_pfnote). */
2991 if (CTAGS
|| token
.named
)
2992 name
= savestr (token_name
.buffer
);
2993 if (DEBUG
&& !token
.valid
)
2996 name
= concat (name
, "##invalid##", "");
2998 name
= savestr ("##invalid##");
3000 pfnote (name
, isfun
, token
.line
,
3001 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
3004 new_pfnote (token_name
.buffer
, token_name
.len
, isfun
, token
.line
,
3005 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
3006 token
.valid
= FALSE
;
3013 * This routine finds functions, variables, typedefs,
3014 * #define's, enum constants and struct/union/enum definitions in
3015 * C syntax and adds them to the list.
3018 C_entries (c_ext
, inf
)
3019 int c_ext
; /* extension of C */
3020 FILE *inf
; /* input file */
3022 register char c
; /* latest char read; '\0' for end of line */
3023 register char *lp
; /* pointer one beyond the character `c' */
3024 int curndx
, newndx
; /* indices for current and new lb */
3025 register int tokoff
; /* offset in line of start of current token */
3026 register int toklen
; /* length of current token */
3027 char *qualifier
; /* string used to qualify names */
3028 int qlen
; /* length of qualifier */
3029 int cblev
; /* current curly brace level */
3030 int parlev
; /* current parenthesis level */
3031 int typdefcblev
; /* cblev where a typedef struct body begun */
3032 bool incomm
, inquote
, inchar
, quotednl
, midtoken
;
3034 bool yacc_rules
; /* in the rules part of a yacc file */
3035 struct tok savetoken
; /* token saved during preprocessor handling */
3038 initbuffer (&token_name
);
3039 initbuffer (&lbs
[0].lb
);
3040 initbuffer (&lbs
[1].lb
);
3041 if (cstack
.size
== 0)
3043 cstack
.size
= (DEBUG
) ? 1 : 4;
3045 cstack
.cname
= xnew (cstack
.size
, char *);
3046 cstack
.cblev
= xnew (cstack
.size
, int);
3049 tokoff
= toklen
= typdefcblev
= 0; /* keep compiler quiet */
3050 curndx
= newndx
= 0;
3054 fvdef
= fvnone
; fvextern
= FALSE
; typdef
= tnone
;
3055 structdef
= snone
; definedef
= dnone
; objdef
= onone
;
3057 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3058 token
.valid
= savetoken
.valid
= FALSE
;
3061 cplpl
= (c_ext
& C_PLPL
) == C_PLPL
;
3062 cjava
= (c_ext
& C_JAVA
) == C_JAVA
;
3064 { qualifier
= "."; qlen
= 1; }
3066 { qualifier
= "::"; qlen
= 2; }
3074 /* If we're at the end of the line, the next character is a
3075 '\0'; don't skip it, because it's the thing that tells us
3076 to read the next line. */
3097 /* Newlines inside comments do not end macro definitions in
3099 CNL_SAVE_DEFINEDEF ();
3112 /* Newlines inside strings do not end macro definitions
3113 in traditional cpp, even though compilers don't
3114 usually accept them. */
3115 CNL_SAVE_DEFINEDEF ();
3125 /* Hmmm, something went wrong. */
3154 if (fvdef
!= finlist
&& fvdef
!= fignore
&& fvdef
!=vignore
)
3167 else if (/* cplpl && */ *lp
== '/')
3175 if ((c_ext
& YACC
) && *lp
== '%')
3177 /* Entering or exiting rules section in yacc file. */
3179 definedef
= dnone
; fvdef
= fvnone
; fvextern
= FALSE
;
3180 typdef
= tnone
; structdef
= snone
;
3181 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3183 yacc_rules
= !yacc_rules
;
3189 if (definedef
== dnone
)
3192 bool cpptoken
= TRUE
;
3194 /* Look back on this line. If all blanks, or nonblanks
3195 followed by an end of comment, this is a preprocessor
3197 for (cp
= newlb
.buffer
; cp
< lp
-1; cp
++)
3200 if (*cp
== '*' && *(cp
+1) == '/')
3209 definedef
= dsharpseen
;
3210 } /* if (definedef == dnone) */
3216 /* Consider token only if some involved conditions are satisfied. */
3217 if (typdef
!= tignore
3218 && definedef
!= dignorerest
3220 && structdef
!= sintemplate
3221 && (definedef
!= dnone
3222 || structdef
!= scolonseen
))
3228 if (c
== ':' && cplpl
&& *lp
== ':' && begtoken (lp
[1]))
3231 * This handles :: in the middle, but not at the
3232 * beginning of an identifier. Also, space-separated
3233 * :: is not recognised.
3238 goto still_in_token
;
3242 bool funorvar
= FALSE
;
3245 || consider_token (newlb
.buffer
+ tokoff
, toklen
, c
,
3246 &c_ext
, cblev
, parlev
, &funorvar
))
3248 if (fvdef
== foperator
)
3251 lp
= skip_spaces (lp
-1);
3255 && !iswhite (*lp
) && *lp
!= '(')
3258 toklen
+= lp
- oldlp
;
3260 token
.named
= FALSE
;
3261 if ((c_ext
& C_EXT
) /* not pure C */
3262 && nestlev
> 0 && definedef
== dnone
)
3263 /* in struct body */
3265 write_classname (&token_name
, qualifier
);
3266 linebuffer_setlen (&token_name
,
3267 token_name
.len
+qlen
+toklen
);
3268 strcat (token_name
.buffer
, qualifier
);
3269 strncat (token_name
.buffer
,
3270 newlb
.buffer
+ tokoff
, toklen
);
3273 else if (objdef
== ocatseen
)
3274 /* Objective C category */
3276 int len
= strlen (objtag
) + 2 + toklen
;
3277 linebuffer_setlen (&token_name
, len
);
3278 strcpy (token_name
.buffer
, objtag
);
3279 strcat (token_name
.buffer
, "(");
3280 strncat (token_name
.buffer
,
3281 newlb
.buffer
+ tokoff
, toklen
);
3282 strcat (token_name
.buffer
, ")");
3285 else if (objdef
== omethodtag
3286 || objdef
== omethodparm
)
3287 /* Objective C method */
3291 else if (fvdef
== fdefunname
)
3292 /* GNU DEFUN and similar macros */
3294 bool defun
= (newlb
.buffer
[tokoff
] == 'F');
3298 /* Rewrite the tag so that emacs lisp DEFUNs
3299 can be found by their elisp name */
3306 linebuffer_setlen (&token_name
, len
);
3307 strncpy (token_name
.buffer
,
3308 newlb
.buffer
+ off
, len
);
3309 token_name
.buffer
[len
] = '\0';
3312 if (token_name
.buffer
[len
] == '_')
3313 token_name
.buffer
[len
] = '-';
3314 token
.named
= defun
;
3318 linebuffer_setlen (&token_name
, toklen
);
3319 strncpy (token_name
.buffer
,
3320 newlb
.buffer
+ tokoff
, toklen
);
3321 token_name
.buffer
[toklen
] = '\0';
3322 /* Name macros and members. */
3323 token
.named
= (structdef
== stagseen
3324 || typdef
== ttypeseen
3327 && definedef
== dignorerest
)
3329 && definedef
== dnone
3330 && structdef
== snone
3333 token
.lineno
= lineno
;
3334 token
.offset
= tokoff
;
3335 token
.length
= toklen
;
3336 token
.line
= newlb
.buffer
;
3337 token
.linepos
= newlinepos
;
3340 if (definedef
== dnone
3341 && (fvdef
== fvnameseen
3342 || fvdef
== foperator
3343 || structdef
== stagseen
3345 || typdef
== ttypeseen
3346 || objdef
!= onone
))
3348 if (current_lb_is_new
)
3349 switch_line_buffers ();
3351 else if (definedef
!= dnone
3352 || fvdef
== fdefunname
3354 make_C_tag (funorvar
);
3358 } /* if (endtoken (c)) */
3359 else if (intoken (c
))
3365 } /* if (midtoken) */
3366 else if (begtoken (c
))
3377 make_C_tag (TRUE
); /* a function */
3384 if (structdef
== stagseen
&& !cjava
)
3386 popclass_above (cblev
);
3394 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
3396 tokoff
= lp
- 1 - newlb
.buffer
;
3401 } /* if (begtoken) */
3402 } /* if must look at token */
3405 /* Detect end of line, colon, comma, semicolon and various braces
3406 after having handled a token.*/
3410 if (yacc_rules
&& token
.offset
== 0 && token
.valid
)
3412 make_C_tag (FALSE
); /* a yacc function */
3415 if (definedef
!= dnone
)
3421 make_C_tag (TRUE
); /* an Objective C class */
3425 objdef
= omethodcolon
;
3426 linebuffer_setlen (&token_name
, token_name
.len
+ 1);
3427 strcat (token_name
.buffer
, ":");
3430 if (structdef
== stagseen
)
3431 structdef
= scolonseen
;
3434 if (definedef
!= dnone
)
3440 make_C_tag (FALSE
); /* a typedef */
3450 if (typdef
== tignore
)
3454 if ((globals
&& cblev
== 0 && (!fvextern
|| declarations
))
3455 || (members
&& instruct
))
3456 make_C_tag (FALSE
); /* a variable */
3459 token
.valid
= FALSE
;
3462 if ((declarations
&& typdef
== tnone
&& !instruct
)
3463 || (members
&& typdef
!= tignore
&& instruct
))
3464 make_C_tag (TRUE
); /* a function declaration */
3470 && structdef
== stagseen
&& (c_ext
& C_PLPL
))
3471 make_C_tag (FALSE
); /* forward declaration */
3473 /* The following instruction invalidates the token.
3474 Probably the token should be invalidated in all other
3475 cases where some state machine is reset prematurely. */
3476 token
.valid
= FALSE
;
3477 } /* switch (fvdef) */
3483 if (structdef
== stagseen
)
3487 if (definedef
!= dnone
)
3493 make_C_tag (TRUE
); /* an Objective C method */
3509 case fvnameseen
: /* a variable */
3510 if ((globals
&& cblev
== 0 && (!fvextern
|| declarations
))
3511 || (members
&& instruct
))
3514 case flistseen
: /* a function */
3515 if ((declarations
&& typdef
== tnone
&& !instruct
)
3516 || (members
&& typdef
!= tignore
&& instruct
))
3518 make_C_tag (TRUE
); /* a function declaration */
3521 else if (!declarations
)
3523 token
.valid
= FALSE
;
3528 if (structdef
== stagseen
)
3532 if (definedef
!= dnone
)
3534 if (structdef
== stagseen
)
3541 make_C_tag (FALSE
); /* a typedef */
3553 if ((members
&& cblev
== 1)
3554 || (globals
&& cblev
== 0
3555 && (!fvextern
|| declarations
)))
3556 make_C_tag (FALSE
); /* a variable */
3565 if (definedef
!= dnone
)
3567 if (objdef
== otagseen
&& parlev
== 0)
3568 objdef
= oparenseen
;
3572 if (typdef
== ttypeseen
3576 /* This handles constructs like:
3577 typedef void OperatorFun (int fun); */
3594 if (definedef
!= dnone
)
3596 if (objdef
== ocatseen
&& parlev
== 1)
3598 make_C_tag (TRUE
); /* an Objective C category */
3612 || typdef
== ttypeseen
))
3615 make_C_tag (FALSE
); /* a typedef */
3618 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
3622 if (definedef
!= dnone
)
3624 if (typdef
== ttypeseen
)
3626 /* Whenever typdef is set to tinbody (currently only
3627 here), typdefcblev should be set to cblev. */
3629 typdefcblev
= cblev
;
3634 make_C_tag (TRUE
); /* a function */
3643 make_C_tag (TRUE
); /* an Objective C class */
3648 make_C_tag (TRUE
); /* an Objective C method */
3652 /* Neutralize `extern "C" {' grot. */
3653 if (cblev
== 0 && structdef
== snone
&& nestlev
== 0
3661 case skeyseen
: /* unnamed struct */
3662 pushclass_above (cblev
, NULL
, 0);
3665 case stagseen
: /* named struct or enum */
3666 case scolonseen
: /* a class */
3667 pushclass_above (cblev
, token
.line
+token
.offset
, token
.length
);
3669 make_C_tag (FALSE
); /* a struct or enum */
3675 if (definedef
!= dnone
)
3677 if (fvdef
== fstartlist
)
3678 fvdef
= fvnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
3681 if (definedef
!= dnone
)
3683 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
3685 cblev
= 0; /* reset curly brace level if first column */
3686 parlev
= 0; /* also reset paren level, just in case... */
3690 popclass_above (cblev
);
3692 /* Only if typdef == tinbody is typdefcblev significant. */
3693 if (typdef
== tinbody
&& cblev
<= typdefcblev
)
3695 assert (cblev
== typdefcblev
);
3700 if (definedef
!= dnone
)
3710 if ((members
&& cblev
== 1)
3711 || (globals
&& cblev
== 0 && (!fvextern
|| declarations
)))
3712 make_C_tag (FALSE
); /* a variable */
3719 if (cplpl
&& structdef
== stagseen
)
3721 structdef
= sintemplate
;
3726 if (structdef
== sintemplate
)
3728 structdef
= stagseen
;
3734 if (objdef
== oinbody
&& cblev
== 0)
3736 objdef
= omethodsign
;
3741 case '#': case '~': case '&': case '%': case '/': case '|':
3742 case '^': case '!': case '.': case '?': case ']':
3743 if (definedef
!= dnone
)
3745 /* These surely cannot follow a function tag in C. */
3758 if (objdef
== otagseen
)
3760 make_C_tag (TRUE
); /* an Objective C class */
3763 /* If a macro spans multiple lines don't reset its state. */
3765 CNL_SAVE_DEFINEDEF ();
3771 } /* while not eof */
3773 free (token_name
.buffer
);
3774 free (lbs
[0].lb
.buffer
);
3775 free (lbs
[1].lb
.buffer
);
3779 * Process either a C++ file or a C file depending on the setting
3783 default_C_entries (inf
)
3786 C_entries (cplusplus
? C_PLPL
: C_AUTO
, inf
);
3789 /* Always do plain C. */
3791 plain_C_entries (inf
)
3797 /* Always do C++. */
3799 Cplusplus_entries (inf
)
3802 C_entries (C_PLPL
, inf
);
3805 /* Always do Java. */
3810 C_entries (C_JAVA
, inf
);
3818 C_entries (C_STAR
, inf
);
3821 /* Always do Yacc. */
3826 C_entries (YACC
, inf
);
3830 /* Useful macros. */
3831 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3832 for (; /* loop initialization */ \
3833 !feof (file_pointer) /* loop test */ \
3834 && (char_pointer = lb.buffer, /* instructions at start of loop */ \
3835 readline (&line_buffer, file_pointer), \
3838 #define LOOKING_AT(cp, keyword) /* keyword is a constant string */ \
3839 (strneq ((cp), keyword, sizeof(keyword)-1) /* cp points at keyword */ \
3840 && notinname ((cp)[sizeof(keyword)-1]) /* end of keyword */ \
3841 && ((cp) = skip_spaces((cp)+sizeof(keyword)-1))) /* skip spaces */
3844 * Read a file, but do no processing. This is used to do regexp
3845 * matching on files that have no language defined.
3848 just_read_file (inf
)
3851 register char *dummy
;
3853 LOOP_ON_INPUT_LINES (inf
, lb
, dummy
)
3858 /* Fortran parsing */
3860 static void F_takeprec
__P((void));
3861 static void F_getit
__P((FILE *));
3866 dbp
= skip_spaces (dbp
);
3870 dbp
= skip_spaces (dbp
);
3871 if (strneq (dbp
, "(*)", 3))
3876 if (!ISDIGIT (*dbp
))
3878 --dbp
; /* force failure */
3883 while (ISDIGIT (*dbp
));
3892 dbp
= skip_spaces (dbp
);
3895 readline (&lb
, inf
);
3900 dbp
= skip_spaces (dbp
);
3902 if (!ISALPHA (*dbp
) && *dbp
!= '_' && *dbp
!= '$')
3904 for (cp
= dbp
+ 1; *cp
!= '\0' && intoken (*cp
); cp
++)
3906 pfnote (savenstr (dbp
, cp
-dbp
), TRUE
,
3907 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
3912 Fortran_functions (inf
)
3915 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
3918 dbp
++; /* Ratfor escape to fortran */
3919 dbp
= skip_spaces (dbp
);
3922 switch (lowcase (*dbp
))
3925 if (nocase_tail ("integer"))
3929 if (nocase_tail ("real"))
3933 if (nocase_tail ("logical"))
3937 if (nocase_tail ("complex") || nocase_tail ("character"))
3941 if (nocase_tail ("double"))
3943 dbp
= skip_spaces (dbp
);
3946 if (nocase_tail ("precision"))
3952 dbp
= skip_spaces (dbp
);
3955 switch (lowcase (*dbp
))
3958 if (nocase_tail ("function"))
3962 if (nocase_tail ("subroutine"))
3966 if (nocase_tail ("entry"))
3970 if (nocase_tail ("blockdata") || nocase_tail ("block data"))
3972 dbp
= skip_spaces (dbp
);
3973 if (*dbp
== '\0') /* assume un-named */
3974 pfnote (savestr ("blockdata"), TRUE
,
3975 lb
.buffer
, dbp
- lb
.buffer
, lineno
, linecharno
);
3977 F_getit (inf
); /* look for name */
3988 * Philippe Waroquiers <philippe.waroquiers@eurocontrol.be> (1998)
3991 static void Ada_getit
__P((FILE *, char *));
3993 /* Once we are positioned after an "interesting" keyword, let's get
3994 the real tag value necessary. */
3996 Ada_getit (inf
, name_qualifier
)
3998 char *name_qualifier
;
4006 dbp
= skip_spaces (dbp
);
4008 || (dbp
[0] == '-' && dbp
[1] == '-'))
4010 readline (&lb
, inf
);
4013 switch (lowcase(*dbp
))
4016 if (nocase_tail ("body"))
4018 /* Skipping body of procedure body or package body or ....
4019 resetting qualifier to body instead of spec. */
4020 name_qualifier
= "/b";
4025 /* Skipping type of task type or protected type ... */
4026 if (nocase_tail ("type"))
4033 for (cp
= dbp
; *cp
!= '\0' && *cp
!= '"'; cp
++)
4038 dbp
= skip_spaces (dbp
);
4041 && (ISALPHA (*cp
) || ISDIGIT (*cp
) || *cp
== '_' || *cp
== '.'));
4049 name
= concat (dbp
, name_qualifier
, "");
4051 pfnote (name
, TRUE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4062 bool inquote
= FALSE
;
4064 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4066 while (*dbp
!= '\0')
4068 /* Skip a string i.e. "abcd". */
4069 if (inquote
|| (*dbp
== '"'))
4071 dbp
= etags_strchr ((inquote
) ? dbp
: dbp
+1, '"');
4076 continue; /* advance char */
4081 break; /* advance line */
4085 /* Skip comments. */
4086 if (dbp
[0] == '-' && dbp
[1] == '-')
4087 break; /* advance line */
4089 /* Skip character enclosed in single quote i.e. 'a'
4090 and skip single quote starting an attribute i.e. 'Image. */
4099 /* Search for beginning of a token. */
4100 if (!begtoken (*dbp
))
4103 continue; /* advance char */
4106 /* We are at the beginning of a token. */
4107 switch (lowcase(*dbp
))
4110 if (!packages_only
&& nocase_tail ("function"))
4111 Ada_getit (inf
, "/f");
4113 break; /* from switch */
4114 continue; /* advance char */
4116 if (!packages_only
&& nocase_tail ("procedure"))
4117 Ada_getit (inf
, "/p");
4118 else if (nocase_tail ("package"))
4119 Ada_getit (inf
, "/s");
4120 else if (nocase_tail ("protected")) /* protected type */
4121 Ada_getit (inf
, "/t");
4123 break; /* from switch */
4124 continue; /* advance char */
4126 if (!packages_only
&& nocase_tail ("task"))
4127 Ada_getit (inf
, "/k");
4128 else if (typedefs
&& !packages_only
&& nocase_tail ("type"))
4130 Ada_getit (inf
, "/t");
4131 while (*dbp
!= '\0')
4135 break; /* from switch */
4136 continue; /* advance char */
4139 /* Look for the end of the token. */
4140 while (!endtoken (*dbp
))
4143 } /* advance char */
4144 } /* advance line */
4149 * Unix and microcontroller assembly tag handling
4150 * Labels: /^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]/
4151 * Idea by Bob Weiner, Motorola Inc. (1994)
4159 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4161 /* If first char is alphabetic or one of [_.$], test for colon
4162 following identifier. */
4163 if (ISALPHA (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4165 /* Read past label. */
4167 while (ISALNUM (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4169 if (*cp
== ':' || iswhite (*cp
))
4171 /* Found end of label, so copy it and add it to the table. */
4172 pfnote (savenstr(lb
.buffer
, cp
-lb
.buffer
), TRUE
,
4173 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4182 * Perl sub names: /^sub[ \t\n]+[^ \t\n{]+/
4183 * Perl variable names: /^(my|local).../
4184 * Original code by Bart Robinson <lomew@cs.utah.edu> (1995)
4185 * Additions by Michael Ernst <mernst@alum.mit.edu> (1997)
4186 * Ideas by Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE> (2001)
4189 Perl_functions (inf
)
4192 char *package
= savestr ("main"); /* current package name */
4195 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4199 if (LOOKING_AT (cp
, "package"))
4202 package
= get_tag (cp
);
4203 if (package
== NULL
) /* can't parse package name */
4204 package
= savestr ("");
4206 package
= savestr(package
); /* make a copy */
4208 else if (LOOKING_AT (cp
, "sub"))
4210 char *name
, *fullname
, *pos
;
4213 while (!notinname (*cp
))
4217 name
= savenstr (sp
, cp
-sp
);
4218 if ((pos
= etags_strchr (name
, ':')) != NULL
&& pos
[1] == ':')
4221 fullname
= concat (package
, "::", name
);
4222 pfnote (fullname
, TRUE
,
4223 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4224 if (name
!= fullname
)
4227 else if (globals
/* only if tagging global vars is enabled */
4228 && (LOOKING_AT (cp
, "my") || LOOKING_AT (cp
, "local")))
4230 /* After "my" or "local", but before any following paren or space. */
4231 char *varname
= NULL
;
4233 if (*cp
== '$' || *cp
== '@' || *cp
== '%')
4235 char* varstart
= ++cp
;
4236 while (ISALNUM (*cp
) || *cp
== '_')
4238 varname
= savenstr (varstart
, cp
-varstart
);
4242 /* Should be examining a variable list at this point;
4243 could insist on seeing an open parenthesis. */
4244 while (*cp
!= '\0' && *cp
!= ';' && *cp
!= '=' && *cp
!= ')')
4248 /* Perhaps I should back cp up one character, so the TAGS table
4249 doesn't mention (and so depend upon) the following char. */
4250 pfnote (varname
, FALSE
,
4251 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4259 * Look for /^[\t]*def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
4260 * Idea by Eric S. Raymond <esr@thyrsus.com> (1997)
4261 * More ideas by seb bacon <seb@jamkit.com> (2002)
4264 Python_functions (inf
)
4269 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4271 cp
= skip_spaces (cp
);
4272 if (LOOKING_AT (cp
, "def") || LOOKING_AT (cp
, "class"))
4275 while (!notinname (*cp
) && *cp
!= ':')
4277 pfnote (savenstr (name
, cp
-name
), TRUE
,
4278 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4287 * - /^[ \t]*function[ \t\n]+[^ \t\n(]+/
4288 * - /^[ \t]*class[ \t\n]+[^ \t\n]+/
4289 * - /^[ \t]*define\(\"[^\"]+/
4290 * Only with --members:
4291 * - /^[ \t]*var[ \t\n]+\$[^ \t\n=;]/
4292 * Idea by Diez B. Roggisch (2001)
4298 register char *cp
, *name
;
4299 bool search_identifier
= FALSE
;
4301 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4303 cp
= skip_spaces (cp
);
4305 if (search_identifier
4308 while (!notinname (*cp
))
4310 pfnote (savenstr (name
, cp
-name
), TRUE
,
4311 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4312 search_identifier
= FALSE
;
4314 else if (LOOKING_AT (cp
, "function"))
4317 cp
= skip_spaces (cp
+1);
4321 while (!notinname (*cp
))
4323 pfnote (savenstr (name
, cp
-name
), TRUE
,
4324 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4327 search_identifier
= TRUE
;
4329 else if (LOOKING_AT (cp
, "class"))
4334 while (*cp
!= '\0' && !iswhite (*cp
))
4336 pfnote (savenstr (name
, cp
-name
), FALSE
,
4337 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4340 search_identifier
= TRUE
;
4342 else if (strneq (cp
, "define", 6)
4343 && (cp
= skip_spaces (cp
+6))
4345 && (*cp
== '"' || *cp
== '\''))
4349 while (*cp
!= quote
&& *cp
!= '\0')
4351 pfnote (savenstr (name
, cp
-name
), FALSE
,
4352 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4355 && LOOKING_AT (cp
, "var")
4359 while (!notinname(*cp
))
4361 pfnote (savenstr (name
, cp
-name
), FALSE
,
4362 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4369 * Cobol tag functions
4370 * We could look for anything that could be a paragraph name.
4371 * i.e. anything that starts in column 8 is one word and ends in a full stop.
4372 * Idea by Corny de Souza (1993)
4375 Cobol_paragraphs (inf
)
4378 register char *bp
, *ep
;
4380 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4386 /* If eoln, compiler option or comment ignore whole line. */
4387 if (bp
[-1] != ' ' || !ISALNUM (bp
[0]))
4390 for (ep
= bp
; ISALNUM (*ep
) || *ep
== '-'; ep
++)
4393 pfnote (savenstr (bp
, ep
-bp
), TRUE
,
4394 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
4401 * Idea by Assar Westerlund <assar@sics.se> (2001)
4404 Makefile_targets (inf
)
4409 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4411 if (*bp
== '\t' || *bp
== '#')
4413 while (*bp
!= '\0' && *bp
!= '=' && *bp
!= ':')
4416 pfnote (savenstr (lb
.buffer
, bp
- lb
.buffer
), TRUE
,
4417 lb
.buffer
, bp
- lb
.buffer
+ 1, lineno
, linecharno
);
4424 * Original code by Mosur K. Mohan (1989)
4426 * Locates tags for procedures & functions. Doesn't do any type- or
4427 * var-definitions. It does look for the keyword "extern" or
4428 * "forward" immediately following the procedure statement; if found,
4429 * the tag is skipped.
4432 Pascal_functions (inf
)
4435 linebuffer tline
; /* mostly copied from C_entries */
4437 int save_lineno
, save_len
;
4438 char c
, *cp
, *namebuf
;
4440 bool /* each of these flags is TRUE iff: */
4441 incomment
, /* point is inside a comment */
4442 inquote
, /* point is inside '..' string */
4443 get_tagname
, /* point is after PROCEDURE/FUNCTION
4444 keyword, so next item = potential tag */
4445 found_tag
, /* point is after a potential tag */
4446 inparms
, /* point is within parameter-list */
4447 verify_tag
; /* point has passed the parm-list, so the
4448 next token will determine whether this
4449 is a FORWARD/EXTERN to be ignored, or
4450 whether it is a real tag */
4452 save_lcno
= save_lineno
= save_len
= 0; /* keep compiler quiet */
4453 namebuf
= NULL
; /* keep compiler quiet */
4456 initbuffer (&tline
);
4458 incomment
= inquote
= FALSE
;
4459 found_tag
= FALSE
; /* have a proc name; check if extern */
4460 get_tagname
= FALSE
; /* have found "procedure" keyword */
4461 inparms
= FALSE
; /* found '(' after "proc" */
4462 verify_tag
= FALSE
; /* check if "extern" is ahead */
4465 while (!feof (inf
)) /* long main loop to get next char */
4468 if (c
== '\0') /* if end of line */
4470 readline (&lb
, inf
);
4474 if (!((found_tag
&& verify_tag
)
4476 c
= *dbp
++; /* only if don't need *dbp pointing
4477 to the beginning of the name of
4478 the procedure or function */
4482 if (c
== '}') /* within { } comments */
4484 else if (c
== '*' && *dbp
== ')') /* within (* *) comments */
4501 inquote
= TRUE
; /* found first quote */
4503 case '{': /* found open { comment */
4507 if (*dbp
== '*') /* found open (* comment */
4512 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
4515 case ')': /* end of parms list */
4520 if (found_tag
&& !inparms
) /* end of proc or fn stmt */
4527 if (found_tag
&& verify_tag
&& (*dbp
!= ' '))
4529 /* check if this is an "extern" declaration */
4532 if (lowcase (*dbp
== 'e'))
4534 if (nocase_tail ("extern")) /* superfluous, really! */
4540 else if (lowcase (*dbp
) == 'f')
4542 if (nocase_tail ("forward")) /* check for forward reference */
4548 if (found_tag
&& verify_tag
) /* not external proc, so make tag */
4552 pfnote (namebuf
, TRUE
,
4553 tline
.buffer
, save_len
, save_lineno
, save_lcno
);
4557 if (get_tagname
) /* grab name of proc or fn */
4562 /* save all values for later tagging */
4563 linebuffer_setlen (&tline
, lb
.len
);
4564 strcpy (tline
.buffer
, lb
.buffer
);
4565 save_lineno
= lineno
;
4566 save_lcno
= linecharno
;
4568 /* grab block name */
4569 for (cp
= dbp
+ 1; *cp
!= '\0' && !endtoken (*cp
); cp
++)
4571 namebuf
= savenstr (dbp
, cp
-dbp
);
4572 dbp
= cp
; /* set dbp to e-o-token */
4573 save_len
= dbp
- lb
.buffer
+ 1;
4574 get_tagname
= FALSE
;
4578 /* and proceed to check for "extern" */
4580 else if (!incomment
&& !inquote
&& !found_tag
)
4582 /* check for proc/fn keywords */
4583 switch (lowcase (c
))
4586 if (nocase_tail ("rocedure")) /* c = 'p', dbp has advanced */
4590 if (nocase_tail ("unction"))
4595 } /* while not eof */
4597 free (tline
.buffer
);
4602 * Lisp tag functions
4603 * look for (def or (DEF, quote or QUOTE
4606 static void L_getit
__P((void));
4611 if (*dbp
== '\'') /* Skip prefix quote */
4613 else if (*dbp
== '(')
4616 /* Try to skip "(quote " */
4617 if (!LOOKING_AT (dbp
, "quote") && !LOOKING_AT (dbp
, "QUOTE"))
4618 /* Ok, then skip "(" before name in (defstruct (foo)) */
4619 dbp
= skip_spaces (dbp
);
4625 Lisp_functions (inf
)
4628 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4633 if (strneq (dbp
+1, "def", 3) || strneq (dbp
+1, "DEF", 3))
4635 dbp
= skip_non_spaces (dbp
);
4636 dbp
= skip_spaces (dbp
);
4641 /* Check for (foo::defmumble name-defined ... */
4644 while (!notinname (*dbp
) && *dbp
!= ':');
4649 while (*dbp
== ':');
4651 if (strneq (dbp
, "def", 3) || strneq (dbp
, "DEF", 3))
4653 dbp
= skip_non_spaces (dbp
);
4654 dbp
= skip_spaces (dbp
);
4664 * Postscript tag functions
4665 * Just look for lines where the first character is '/'
4666 * Also look at "defineps" for PSWrap
4668 * Richard Mlynarik <mly@adoc.xerox.com> (1997)
4669 * Masatake Yamato <masata-y@is.aist-nara.ac.jp> (1999)
4672 Postscript_functions (inf
)
4675 register char *bp
, *ep
;
4677 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4682 *ep
!= '\0' && *ep
!= ' ' && *ep
!= '{';
4685 pfnote (savenstr (bp
, ep
-bp
), TRUE
,
4686 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
4688 else if (LOOKING_AT (bp
, "defineps"))
4695 * Scheme tag functions
4696 * look for (def... xyzzy
4698 * (def ... ((...(xyzzy ....
4700 * Original code by Ken Haase (1985?)
4704 Scheme_functions (inf
)
4709 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4711 if (strneq (bp
, "(def", 4) || strneq (bp
, "(DEF", 4))
4713 bp
= skip_non_spaces (bp
+4);
4714 /* Skip over open parens and white space */
4715 while (notinname (*bp
))
4719 if (LOOKING_AT (bp
, "(SET!") || LOOKING_AT (bp
, "(set!"))
4725 /* Find tags in TeX and LaTeX input files. */
4727 /* TEX_toktab is a table of TeX control sequences that define tags.
4728 * Each entry records one such control sequence.
4730 * Original code from who knows whom.
4732 * Stefan Monnier (2002)
4735 static linebuffer
*TEX_toktab
= NULL
; /* Table with tag tokens */
4737 /* Default set of control sequences to put into TEX_toktab.
4738 The value of environment var TEXTAGS is prepended to this. */
4739 static char *TEX_defenv
= "\
4740 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4741 :part:appendix:entry:index:def\
4742 :newcommand:renewcommand:newenvironment:renewenvironment";
4744 static void TEX_mode
__P((FILE *));
4745 static void TEX_decode_env
__P((char *, char *));
4747 static char TEX_esc
= '\\';
4748 static char TEX_opgrp
= '{';
4749 static char TEX_clgrp
= '}';
4752 * TeX/LaTeX scanning loop.
4761 /* Select either \ or ! as escape character. */
4764 /* Initialize token table once from environment. */
4765 if (TEX_toktab
== NULL
)
4766 TEX_decode_env ("TEXTAGS", TEX_defenv
);
4768 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4770 /* Look at each TEX keyword in line. */
4773 /* Look for a TEX escape. */
4774 while (*cp
++ != TEX_esc
)
4775 if (cp
[-1] == '\0' || cp
[-1] == '%')
4778 for (key
= TEX_toktab
; key
->buffer
!= NULL
; key
++)
4779 if (strneq (cp
, key
->buffer
, key
->len
))
4786 cp
= skip_spaces (cp
+ key
->len
);
4787 if (*cp
== TEX_opgrp
)
4793 (!iswhite (*p
) && *p
!= '#' &&
4794 *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
);
4797 name
= savenstr (cp
, p
-cp
);
4799 if (!opgrp
|| *p
== TEX_clgrp
)
4801 while (*p
!= '\0' && *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
)
4803 linelen
= p
- lb
.buffer
+ 1;
4805 pfnote (name
, TRUE
, lb
.buffer
, linelen
, lineno
, linecharno
);
4806 goto tex_next_line
; /* We only tag a line once */
4814 #define TEX_LESC '\\'
4815 #define TEX_SESC '!'
4817 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4818 chars accordingly. */
4825 while ((c
= getc (inf
)) != EOF
)
4827 /* Skip to next line if we hit the TeX comment char. */
4831 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
4847 /* If the input file is compressed, inf is a pipe, and rewind may fail.
4848 No attempt is made to correct the situation. */
4852 /* Read environment and prepend it to the default string.
4853 Build token table. */
4855 TEX_decode_env (evarname
, defenv
)
4859 register char *env
, *p
;
4862 /* Append default string to environment. */
4863 env
= getenv (evarname
);
4869 env
= concat (oldenv
, defenv
, "");
4872 /* Allocate a token table */
4873 for (len
= 1, p
= env
; p
;)
4874 if ((p
= etags_strchr (p
, ':')) && *++p
!= '\0')
4876 TEX_toktab
= xnew (len
, linebuffer
);
4878 /* Unpack environment string into token table. Be careful about */
4879 /* zero-length strings (leading ':', "::" and trailing ':') */
4880 for (i
= 0; *env
!= '\0';)
4882 p
= etags_strchr (env
, ':');
4883 if (!p
) /* End of environment string. */
4884 p
= env
+ strlen (env
);
4886 { /* Only non-zero strings. */
4887 TEX_toktab
[i
].buffer
= savenstr (env
, p
- env
);
4888 TEX_toktab
[i
].len
= p
- env
;
4895 TEX_toktab
[i
].buffer
= NULL
; /* Mark end of table. */
4896 TEX_toktab
[i
].len
= 0;
4903 /* Texinfo support. Dave Love, Mar. 2000. */
4909 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4910 if (LOOKING_AT (cp
, "@node"))
4913 while (*cp
!= '\0' && *cp
!= ',')
4915 pfnote (savenstr (start
, cp
- start
), TRUE
,
4916 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4924 * Assumes that the predicate or rule starts at column 0.
4925 * Only the first clause of a predicate or rule is added.
4926 * Original code by Sunichirou Sugou (1989)
4927 * Rewritten by Anders Lindgren (1996)
4929 static int prolog_pr
__P((char *, char *));
4930 static void prolog_skip_comment
__P((linebuffer
*, FILE *));
4931 static int prolog_atom
__P((char *, int));
4934 Prolog_functions (inf
)
4945 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4947 if (cp
[0] == '\0') /* Empty line */
4949 else if (iswhite (cp
[0])) /* Not a predicate */
4951 else if (cp
[0] == '/' && cp
[1] == '*') /* comment. */
4952 prolog_skip_comment (&lb
, inf
);
4953 else if ((len
= prolog_pr (cp
, last
)) > 0)
4955 /* Predicate or rule. Store the function name so that we
4956 only generate a tag for the first clause. */
4958 last
= xnew(len
+ 1, char);
4959 else if (len
+ 1 > allocated
)
4960 xrnew (last
, len
+ 1, char);
4961 allocated
= len
+ 1;
4962 strncpy (last
, cp
, len
);
4970 prolog_skip_comment (plb
, inf
)
4978 for (cp
= plb
->buffer
; *cp
!= '\0'; cp
++)
4979 if (cp
[0] == '*' && cp
[1] == '/')
4981 readline (plb
, inf
);
4987 * A predicate or rule definition is added if it matches:
4988 * <beginning of line><Prolog Atom><whitespace>(
4989 * or <beginning of line><Prolog Atom><whitespace>:-
4991 * It is added to the tags database if it doesn't match the
4992 * name of the previous clause header.
4994 * Return the size of the name of the predicate or rule, or 0 if no
5000 char *last
; /* Name of last clause. */
5005 pos
= prolog_atom (s
, 0);
5010 pos
= skip_spaces (s
+ pos
) - s
;
5013 || (s
[pos
] == '(' && (pos
+= 1))
5014 || (s
[pos
] == ':' && s
[pos
+ 1] == '-' && (pos
+= 2)))
5015 && (last
== NULL
/* save only the first clause */
5016 || len
!= strlen (last
)
5017 || !strneq (s
, last
, len
)))
5019 pfnote (savenstr (s
, len
), TRUE
, s
, pos
, lineno
, linecharno
);
5027 * Consume a Prolog atom.
5028 * Return the number of bytes consumed, or -1 if there was an error.
5030 * A prolog atom, in this context, could be one of:
5031 * - An alphanumeric sequence, starting with a lower case letter.
5032 * - A quoted arbitrary string. Single quotes can escape themselves.
5033 * Backslash quotes everything.
5036 prolog_atom (s
, pos
)
5044 if (ISLOWER(s
[pos
]) || (s
[pos
] == '_'))
5046 /* The atom is unquoted. */
5048 while (ISALNUM(s
[pos
]) || (s
[pos
] == '_'))
5052 return pos
- origpos
;
5054 else if (s
[pos
] == '\'')
5065 pos
++; /* A double quote */
5067 else if (s
[pos
] == '\0')
5068 /* Multiline quoted atoms are ignored. */
5070 else if (s
[pos
] == '\\')
5072 if (s
[pos
+1] == '\0')
5079 return pos
- origpos
;
5087 * Support for Erlang
5089 * Generates tags for functions, defines, and records.
5090 * Assumes that Erlang functions start at column 0.
5091 * Original code by Anders Lindgren (1996)
5093 static int erlang_func
__P((char *, char *));
5094 static void erlang_attribute
__P((char *));
5095 static int erlang_atom
__P((char *, int));
5098 Erlang_functions (inf
)
5109 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5111 if (cp
[0] == '\0') /* Empty line */
5113 else if (iswhite (cp
[0])) /* Not function nor attribute */
5115 else if (cp
[0] == '%') /* comment */
5117 else if (cp
[0] == '"') /* Sometimes, strings start in column one */
5119 else if (cp
[0] == '-') /* attribute, e.g. "-define" */
5121 erlang_attribute (cp
);
5124 else if ((len
= erlang_func (cp
, last
)) > 0)
5127 * Function. Store the function name so that we only
5128 * generates a tag for the first clause.
5131 last
= xnew (len
+ 1, char);
5132 else if (len
+ 1 > allocated
)
5133 xrnew (last
, len
+ 1, char);
5134 allocated
= len
+ 1;
5135 strncpy (last
, cp
, len
);
5143 * A function definition is added if it matches:
5144 * <beginning of line><Erlang Atom><whitespace>(
5146 * It is added to the tags database if it doesn't match the
5147 * name of the previous clause header.
5149 * Return the size of the name of the function, or 0 if no function
5153 erlang_func (s
, last
)
5155 char *last
; /* Name of last clause. */
5160 pos
= erlang_atom (s
, 0);
5165 pos
= skip_spaces (s
+ pos
) - s
;
5167 /* Save only the first clause. */
5170 || len
!= (int)strlen (last
)
5171 || !strneq (s
, last
, len
)))
5173 pfnote (savenstr (s
, len
), TRUE
, s
, pos
, lineno
, linecharno
);
5182 * Handle attributes. Currently, tags are generated for defines
5185 * They are on the form:
5186 * -define(foo, bar).
5187 * -define(Foo(M, N), M+N).
5188 * -record(graph, {vtab = notable, cyclic = true}).
5191 erlang_attribute (s
)
5197 if (LOOKING_AT (s
, "-define") || LOOKING_AT (s
, "-record"))
5199 if (s
[pos
++] == '(')
5201 pos
= skip_spaces (s
+ pos
) - s
;
5202 len
= erlang_atom (s
, pos
);
5204 pfnote (savenstr (& s
[pos
], len
), TRUE
,
5205 s
, pos
+ len
, lineno
, linecharno
);
5213 * Consume an Erlang atom (or variable).
5214 * Return the number of bytes consumed, or -1 if there was an error.
5217 erlang_atom (s
, pos
)
5225 if (ISALPHA (s
[pos
]) || s
[pos
] == '_')
5227 /* The atom is unquoted. */
5229 while (ISALNUM (s
[pos
]) || s
[pos
] == '_')
5231 return pos
- origpos
;
5233 else if (s
[pos
] == '\'')
5244 else if (s
[pos
] == '\0')
5245 /* Multiline quoted atoms are ignored. */
5247 else if (s
[pos
] == '\\')
5249 if (s
[pos
+1] == '\0')
5256 return pos
- origpos
;
5263 #ifdef ETAGS_REGEXPS
5265 static char *scan_separators
__P((char *));
5266 static void analyse_regex
__P((char *, bool));
5267 static void add_regex
__P((char *, bool, language
*));
5268 static char *substitute
__P((char *, char *, struct re_registers
*));
5270 /* Take a string like "/blah/" and turn it into "blah", making sure
5271 that the first and last characters are the same, and handling
5272 quoted separator characters. Actually, stops on the occurrence of
5273 an unquoted separator. Also turns "\t" into a Tab character, and
5274 similarly for all character escape sequences supported by Gcc.
5275 Returns pointer to terminating separator. Works in place. Null
5276 terminates name string. */
5278 scan_separators (name
)
5282 char *copyto
= name
;
5283 bool quoted
= FALSE
;
5285 for (++name
; *name
!= '\0'; ++name
)
5291 case 'a': *copyto
++ = '\007'; break;
5292 case 'b': *copyto
++ = '\b'; break;
5293 case 'd': *copyto
++ = 0177; break;
5294 case 'e': *copyto
++ = 033; break;
5295 case 'f': *copyto
++ = '\f'; break;
5296 case 'n': *copyto
++ = '\n'; break;
5297 case 'r': *copyto
++ = '\r'; break;
5298 case 't': *copyto
++ = '\t'; break;
5299 case 'v': *copyto
++ = '\v'; break;
5305 /* Something else is quoted, so preserve the quote. */
5313 else if (*name
== '\\')
5315 else if (*name
== sep
)
5321 /* Terminate copied string. */
5326 /* Look at the argument of --regex or --no-regex and do the right
5327 thing. Same for each line of a regexp file. */
5329 analyse_regex (regex_arg
, ignore_case
)
5333 if (regex_arg
== NULL
)
5335 free_patterns (); /* --no-regex: remove existing regexps */
5339 /* A real --regexp option or a line in a regexp file. */
5340 switch (regex_arg
[0])
5342 /* Comments in regexp file or null arg to --regex. */
5348 /* Read a regex file. This is recursive and may result in a
5349 loop, which will stop when the file descriptors are exhausted. */
5353 linebuffer regexbuf
;
5354 char *regexfile
= regex_arg
+ 1;
5356 /* regexfile is a file containing regexps, one per line. */
5357 regexfp
= fopen (regexfile
, "r");
5358 if (regexfp
== NULL
)
5363 initbuffer (®exbuf
);
5364 while (readline_internal (®exbuf
, regexfp
) > 0)
5365 analyse_regex (regexbuf
.buffer
, ignore_case
);
5366 free (regexbuf
.buffer
);
5371 /* Regexp to be used for a specific language only. */
5375 char *lang_name
= regex_arg
+ 1;
5378 for (cp
= lang_name
; *cp
!= '}'; cp
++)
5381 error ("unterminated language name in regex: %s", regex_arg
);
5385 lang
= get_language_from_langname (lang_name
);
5388 add_regex (cp
+ 1, ignore_case
, lang
);
5392 /* Regexp to be used for any language. */
5394 add_regex (regex_arg
, ignore_case
, NULL
);
5399 /* Turn a name, which is an ed-style (but Emacs syntax) regular
5400 expression, into a real regular expression by compiling it. */
5402 add_regex (regexp_pattern
, ignore_case
, lang
)
5403 char *regexp_pattern
;
5407 static struct re_pattern_buffer zeropattern
;
5410 struct re_pattern_buffer
*patbuf
;
5414 if (regexp_pattern
[strlen(regexp_pattern
)-1] != regexp_pattern
[0])
5416 error ("%s: unterminated regexp", regexp_pattern
);
5419 name
= scan_separators (regexp_pattern
);
5420 if (regexp_pattern
[0] == '\0')
5422 error ("null regexp", (char *)NULL
);
5425 (void) scan_separators (name
);
5427 patbuf
= xnew (1, struct re_pattern_buffer
);
5428 *patbuf
= zeropattern
;
5430 patbuf
->translate
= lc_trans
; /* translation table to fold case */
5432 err
= re_compile_pattern (regexp_pattern
, strlen (regexp_pattern
), patbuf
);
5435 error ("%s while compiling pattern", err
);
5440 p_head
= xnew (1, pattern
);
5441 p_head
->regex
= savestr (regexp_pattern
);
5442 p_head
->p_next
= pp
;
5443 p_head
->lang
= lang
;
5444 p_head
->pat
= patbuf
;
5445 p_head
->name_pattern
= savestr (name
);
5446 p_head
->error_signaled
= FALSE
;
5447 p_head
->ignore_case
= ignore_case
;
5451 * Do the substitutions indicated by the regular expression and
5455 substitute (in
, out
, regs
)
5457 struct re_registers
*regs
;
5460 int size
, dig
, diglen
;
5463 size
= strlen (out
);
5465 /* Pass 1: figure out how much to allocate by finding all \N strings. */
5466 if (out
[size
- 1] == '\\')
5467 fatal ("pattern error in \"%s\"", out
);
5468 for (t
= etags_strchr (out
, '\\');
5470 t
= etags_strchr (t
+ 2, '\\'))
5474 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
5480 /* Allocate space and do the substitutions. */
5481 result
= xnew (size
+ 1, char);
5483 for (t
= result
; *out
!= '\0'; out
++)
5484 if (*out
== '\\' && ISDIGIT (*++out
))
5487 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
5488 strncpy (t
, in
+ regs
->start
[dig
], diglen
);
5495 assert (t
<= result
+ size
&& t
- result
== (int)strlen (result
));
5500 /* Deallocate all patterns. */
5505 while (p_head
!= NULL
)
5507 pp
= p_head
->p_next
;
5508 free (p_head
->regex
);
5509 free (p_head
->name_pattern
);
5515 #endif /* ETAGS_REGEXPS */
5522 register int len
= 0;
5524 while (*cp
!= '\0' && lowcase (*cp
) == lowcase (dbp
[len
]))
5526 if (*cp
== '\0' && !intoken (dbp
[len
]))
5538 register char *cp
, *name
;
5542 /* Go till you get to white space or a syntactic break */
5543 for (cp
= bp
+ 1; !notinname (*cp
); cp
++)
5545 name
= savenstr (bp
, cp
-bp
);
5547 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
5551 /* Initialize a linebuffer for use */
5556 lbp
->size
= (DEBUG
) ? 3 : 200;
5557 lbp
->buffer
= xnew (lbp
->size
, char);
5558 lbp
->buffer
[0] = '\0';
5563 * Read a line of text from `stream' into `lbp', excluding the
5564 * newline or CR-NL, if any. Return the number of characters read from
5565 * `stream', which is the length of the line including the newline.
5567 * On DOS or Windows we do not count the CR character, if any, before the
5568 * NL, in the returned length; this mirrors the behavior of emacs on those
5569 * platforms (for text files, it translates CR-NL to NL as it reads in the
5573 readline_internal (lbp
, stream
)
5575 register FILE *stream
;
5577 char *buffer
= lbp
->buffer
;
5578 register char *p
= lbp
->buffer
;
5579 register char *pend
;
5582 pend
= p
+ lbp
->size
; /* Separate to avoid 386/IX compiler bug. */
5586 register int c
= getc (stream
);
5589 /* We're at the end of linebuffer: expand it. */
5591 xrnew (buffer
, lbp
->size
, char);
5592 p
+= buffer
- lbp
->buffer
;
5593 pend
= buffer
+ lbp
->size
;
5594 lbp
->buffer
= buffer
;
5604 if (p
> buffer
&& p
[-1] == '\r')
5608 /* Assume CRLF->LF translation will be performed by Emacs
5609 when loading this file, so CRs won't appear in the buffer.
5610 It would be cleaner to compensate within Emacs;
5611 however, Emacs does not know how many CRs were deleted
5612 before any given point in the file. */
5627 lbp
->len
= p
- buffer
;
5629 return lbp
->len
+ chars_deleted
;
5633 * Like readline_internal, above, but in addition try to match the
5634 * input line against relevant regular expressions.
5637 readline (lbp
, stream
)
5643 linecharno
= charno
; /* update global char number of line start */
5644 result
= readline_internal (lbp
, stream
); /* read line */
5645 lineno
+= 1; /* increment global line number */
5646 charno
+= result
; /* increment global char number */
5648 /* Honour #line directives. */
5649 if (!no_line_directive
)
5651 static bool discard_until_line_directive
;
5653 /* Check whether this is a #line directive. */
5654 if (result
> 12 && strneq (lbp
->buffer
, "#line ", 6))
5658 if (DEBUG
) start
= 0; /* shut up the compiler */
5659 if (sscanf (lbp
->buffer
, "#line %d \"%n", &lno
, &start
) == 1)
5661 char *endp
= lbp
->buffer
+ start
;
5664 while ((endp
= etags_strchr (endp
, '"')) != NULL
5665 && endp
[-1] == '\\')
5668 /* Ok, this is a real #line directive. Let's deal with it. */
5670 char *taggedabsname
; /* absolute name of original file */
5671 char *taggedfname
; /* name of original file as given */
5672 char *name
; /* temp var */
5674 discard_until_line_directive
= FALSE
; /* found it */
5675 name
= lbp
->buffer
+ start
;
5677 canonicalize_filename (name
); /* for DOS */
5678 taggedabsname
= absolute_filename (name
, curfdp
->infabsdir
);
5679 if (filename_is_absolute (name
)
5680 || filename_is_absolute (curfdp
->infname
))
5681 taggedfname
= savestr (taggedabsname
);
5683 taggedfname
= relative_filename (taggedabsname
,tagfiledir
);
5685 if (streq (curfdp
->taggedfname
, taggedfname
))
5686 /* The #line directive is only a line number change. We
5687 deal with this afterwards. */
5690 /* The tags following this #line directive should be
5691 attributed to taggedfname. In order to do this, set
5692 curfdp accordingly. */
5694 fdesc
*fdp
; /* file description pointer */
5696 /* Go look for a file description already set up for the
5697 file indicated in the #line directive. If there is
5698 one, use it from now until the next #line
5700 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
5701 if (streq (fdp
->infname
, curfdp
->infname
)
5702 && streq (fdp
->taggedfname
, taggedfname
))
5703 /* If we remove the second test above (after the &&)
5704 then all entries pertaining to the same file are
5705 coalesced in the tags file. If we use it, then
5706 entries pertaining to the same file but generated
5707 from different files (via #line directives) will
5708 go into separate sections in the tags file. These
5709 alternatives look equivalent. The first one
5710 destroys some apparently useless information. */
5716 /* Else, if we already tagged the real file, skip all
5717 input lines until the next #line directive. */
5718 if (fdp
== NULL
) /* not found */
5719 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
5720 if (streq (fdp
->infabsname
, taggedabsname
))
5722 discard_until_line_directive
= TRUE
;
5726 /* Else create a new file description and use that from
5727 now on, until the next #line directive. */
5728 if (fdp
== NULL
) /* not found */
5731 fdhead
= xnew (1, fdesc
);
5732 *fdhead
= *curfdp
; /* copy curr. file description */
5734 fdhead
->infname
= savestr (curfdp
->infname
);
5735 fdhead
->infabsname
= savestr (curfdp
->infabsname
);
5736 fdhead
->infabsdir
= savestr (curfdp
->infabsdir
);
5737 fdhead
->taggedfname
= taggedfname
;
5738 fdhead
->usecharno
= FALSE
;
5742 free (taggedabsname
);
5744 readline (lbp
, stream
);
5746 } /* if a real #line directive */
5747 } /* if #line is followed by a a number */
5748 } /* if line begins with "#line " */
5750 /* If we are here, no #line directive was found. */
5751 if (discard_until_line_directive
)
5755 /* Do a tail recursion on ourselves, thus discarding the contents
5756 of the line buffer. */
5757 readline (lbp
, stream
);
5761 discard_until_line_directive
= FALSE
;
5764 } /* if #line directives should be considered */
5766 #ifdef ETAGS_REGEXPS
5771 /* Match against relevant patterns. */
5773 for (pp
= p_head
; pp
!= NULL
; pp
= pp
->p_next
)
5775 /* Only use generic regexps or those for the current language. */
5776 if (pp
->lang
!= NULL
&& pp
->lang
!= fdhead
->lang
)
5779 match
= re_match (pp
->pat
, lbp
->buffer
, lbp
->len
, 0, &pp
->regs
);
5784 if (!pp
->error_signaled
)
5786 error ("error while matching \"%s\"", pp
->regex
);
5787 pp
->error_signaled
= TRUE
;
5794 /* Match occurred. Construct a tag. */
5795 if (pp
->name_pattern
[0] != '\0')
5797 /* Make a named tag. */
5798 char *name
= substitute (lbp
->buffer
,
5799 pp
->name_pattern
, &pp
->regs
);
5801 pfnote (name
, TRUE
, lbp
->buffer
, match
, lineno
, linecharno
);
5805 /* Make an unnamed tag. */
5806 pfnote ((char *)NULL
, TRUE
,
5807 lbp
->buffer
, match
, lineno
, linecharno
);
5813 #endif /* ETAGS_REGEXPS */
5818 * Return a pointer to a space of size strlen(cp)+1 allocated
5819 * with xnew where the string CP has been copied.
5825 return savenstr (cp
, strlen (cp
));
5829 * Return a pointer to a space of size LEN+1 allocated with xnew where
5830 * the string CP has been copied for at most the first LEN characters.
5839 dp
= xnew (len
+ 1, char);
5840 strncpy (dp
, cp
, len
);
5846 * Return the ptr in sp at which the character c last
5847 * appears; NULL if not found
5849 * Identical to POSIX strrchr, included for portability.
5852 etags_strrchr (sp
, c
)
5853 register const char *sp
;
5856 register const char *r
;
5868 * Return the ptr in sp at which the character c first
5869 * appears; NULL if not found
5871 * Identical to POSIX strchr, included for portability.
5874 etags_strchr (sp
, c
)
5875 register const char *sp
;
5887 * Return TRUE if the two strings are equal, ignoring case for alphabetic
5890 * Analogous to BSD's strcasecmp, included for portability.
5894 register const char *s1
;
5895 register const char *s2
;
5898 && (ISALPHA (*s1
) && ISALPHA (*s2
)
5899 ? lowcase (*s1
) == lowcase (*s2
)
5903 return (*s1
== *s2
);
5906 /* Skip spaces, return new pointer. */
5911 while (iswhite (*cp
))
5916 /* Skip non spaces, return new pointer. */
5918 skip_non_spaces (cp
)
5921 while (*cp
!= '\0' && !iswhite (*cp
))
5926 /* Print error message and exit. */
5944 suggest_asking_for_help ()
5946 fprintf (stderr
, "\tTry `%s %s' for a complete list of options.\n",
5957 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
5960 const char *s1
, *s2
;
5962 fprintf (stderr
, "%s: ", progname
);
5963 fprintf (stderr
, s1
, s2
);
5964 fprintf (stderr
, "\n");
5967 /* Return a newly-allocated string whose contents
5968 concatenate those of s1, s2, s3. */
5973 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
5974 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
5976 strcpy (result
, s1
);
5977 strcpy (result
+ len1
, s2
);
5978 strcpy (result
+ len1
+ len2
, s3
);
5979 result
[len1
+ len2
+ len3
] = '\0';
5985 /* Does the same work as the system V getcwd, but does not need to
5986 guess the buffer size in advance. */
5992 char *path
= xnew (bufsize
, char);
5994 while (getcwd (path
, bufsize
) == NULL
)
5996 if (errno
!= ERANGE
)
6000 path
= xnew (bufsize
, char);
6003 canonicalize_filename (path
);
6006 #else /* not HAVE_GETCWD */
6009 char *p
, path
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
6013 for (p
= path
; *p
!= '\0'; p
++)
6019 return strdup (path
);
6020 #else /* not MSDOS */
6025 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
6026 if (pipe
== NULL
|| readline_internal (&path
, pipe
) == 0)
6031 #endif /* not MSDOS */
6032 #endif /* not HAVE_GETCWD */
6035 /* Return a newly allocated string containing the file name of FILE
6036 relative to the absolute directory DIR (which should end with a slash). */
6038 relative_filename (file
, dir
)
6041 char *fp
, *dp
, *afn
, *res
;
6044 /* Find the common root of file and dir (with a trailing slash). */
6045 afn
= absolute_filename (file
, cwd
);
6048 while (*fp
++ == *dp
++)
6050 fp
--, dp
--; /* back to the first differing char */
6052 if (fp
== afn
&& afn
[0] != '/') /* cannot build a relative name */
6055 do /* look at the equal chars until '/' */
6059 /* Build a sequence of "../" strings for the resulting relative file name. */
6061 while ((dp
= etags_strchr (dp
+ 1, '/')) != NULL
)
6063 res
= xnew (3*i
+ strlen (fp
+ 1) + 1, char);
6066 strcat (res
, "../");
6068 /* Add the file name relative to the common root of file and dir. */
6069 strcat (res
, fp
+ 1);
6075 /* Return a newly allocated string containing the absolute file name
6076 of FILE given DIR (which should end with a slash). */
6078 absolute_filename (file
, dir
)
6081 char *slashp
, *cp
, *res
;
6083 if (filename_is_absolute (file
))
6084 res
= savestr (file
);
6086 /* We don't support non-absolute file names with a drive
6087 letter, like `d:NAME' (it's too much hassle). */
6088 else if (file
[1] == ':')
6089 fatal ("%s: relative file names with drive letters not supported", file
);
6092 res
= concat (dir
, file
, "");
6094 /* Delete the "/dirname/.." and "/." substrings. */
6095 slashp
= etags_strchr (res
, '/');
6096 while (slashp
!= NULL
&& slashp
[0] != '\0')
6098 if (slashp
[1] == '.')
6100 if (slashp
[2] == '.'
6101 && (slashp
[3] == '/' || slashp
[3] == '\0'))
6106 while (cp
>= res
&& !filename_is_absolute (cp
));
6108 cp
= slashp
; /* the absolute name begins with "/.." */
6110 /* Under MSDOS and NT we get `d:/NAME' as absolute
6111 file name, so the luser could say `d:/../NAME'.
6112 We silently treat this as `d:/NAME'. */
6113 else if (cp
[0] != '/')
6116 strcpy (cp
, slashp
+ 3);
6120 else if (slashp
[2] == '/' || slashp
[2] == '\0')
6122 strcpy (slashp
, slashp
+ 2);
6127 slashp
= etags_strchr (slashp
+ 1, '/');
6131 return savestr ("/");
6136 /* Return a newly allocated string containing the absolute
6137 file name of dir where FILE resides given DIR (which should
6138 end with a slash). */
6140 absolute_dirname (file
, dir
)
6146 canonicalize_filename (file
);
6147 slashp
= etags_strrchr (file
, '/');
6149 return savestr (dir
);
6152 res
= absolute_filename (file
, dir
);
6158 /* Whether the argument string is an absolute file name. The argument
6159 string must have been canonicalized with canonicalize_filename. */
6161 filename_is_absolute (fn
)
6164 return (fn
[0] == '/'
6166 || (ISALPHA(fn
[0]) && fn
[1] == ':' && fn
[2] == '/')
6171 /* Translate backslashes into slashes. Works in place. */
6173 canonicalize_filename (fn
)
6177 /* Canonicalize drive letter case. */
6178 if (fn
[0] != '\0' && fn
[1] == ':' && ISLOWER (fn
[0]))
6179 fn
[0] = upcase (fn
[0]);
6180 /* Convert backslashes to slashes. */
6181 for (; *fn
!= '\0'; fn
++)
6186 fn
= NULL
; /* shut up the compiler */
6190 /* Set the minimum size of a string contained in a linebuffer. */
6192 linebuffer_setlen (lbp
, toksize
)
6196 while (lbp
->size
<= toksize
)
6199 xrnew (lbp
->buffer
, lbp
->size
, char);
6204 /* Like malloc but get fatal error if memory is exhausted. */
6209 PTR result
= (PTR
) malloc (size
);
6211 fatal ("virtual memory exhausted", (char *)NULL
);
6216 xrealloc (ptr
, size
)
6220 PTR result
= (PTR
) realloc (ptr
, size
);
6222 fatal ("virtual memory exhausted", (char *)NULL
);
6228 * c-indentation-style: gnu
6229 * indent-tabs-mode: t
6232 * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node")