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ì (ideas by Mykola Dzyuba).
33 * Francesco Potortì <pot@gnu.org> has maintained it since 1993.
36 char pot_etags_version
[] = "@(#) pot revision number is 15.16";
46 # define NDEBUG /* disable assert */
51 /* On some systems, Emacs defines static as nothing for the sake
52 of unexec. We don't want that here since we don't use unexec. */
54 # define ETAGS_REGEXPS /* use the regexp features */
55 # define LONG_OPTIONS /* accept long options */
56 # ifndef PTR /* for Xemacs */
59 # ifndef __P /* for Xemacs */
60 # define __P(args) args
63 # if defined(__STDC__) && (__STDC__ || defined(__SUNPRO_C))
64 # define __P(args) args /* use prototypes */
65 # define PTR void * /* for generic pointers */
67 # define __P(args) () /* no prototypes */
68 # define const /* remove const for old compilers' sake */
69 # define PTR long * /* don't use void* */
71 #endif /* !HAVE_CONFIG_H */
74 # define _GNU_SOURCE 1 /* enables some compiler checks on GNU */
77 /* WIN32_NATIVE is for Xemacs.
78 MSDOS, WINDOWSNT, DOS_NT are for Emacs. */
83 #endif /* WIN32_NATIVE */
89 # include <sys/param.h>
91 # ifndef HAVE_CONFIG_H
93 # include <sys/config.h>
105 # define MAXPATHLEN _MAX_PATH
111 # endif /* undef HAVE_GETCWD */
112 #else /* !WINDOWSNT */
117 extern char *getenv ();
119 #endif /* !WINDOWSNT */
124 # if defined (HAVE_GETCWD) && !defined (WINDOWSNT)
125 extern char *getcwd (char *buf
, size_t size
);
127 #endif /* HAVE_UNISTD_H */
135 #include <sys/types.h>
136 #include <sys/stat.h>
140 # undef assert /* some systems have a buggy assert.h */
141 # define assert(x) ((void) 0)
144 #if !defined (S_ISREG) && defined (S_IFREG)
145 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
151 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
153 extern int optind
, opterr
;
154 #endif /* LONG_OPTIONS */
157 # ifndef HAVE_CONFIG_H /* this is a standalone compilation */
158 # ifdef __CYGWIN__ /* compiling on Cygwin */
160 the regex
.h distributed with Cygwin is
not compatible with etags
, alas
!
161 If you want regular expression support
, you should
delete this notice
and
162 arrange to use the GNU regex
.h
and regex
.c
.
166 #endif /* ETAGS_REGEXPS */
168 /* Define CTAGS to make the program "ctags" compatible with the usual one.
169 Leave it undefined to make the program "etags", which makes emacs-style
170 tag tables and tags typedefs, #defines and struct/union/enum by default. */
178 /* Exit codes for success and failure. */
187 #define streq(s,t) (assert((s)!=NULL || (t)!=NULL), !strcmp (s, t))
188 #define strneq(s,t,n) (assert((s)!=NULL || (t)!=NULL), !strncmp (s, t, n))
190 #define CHARS 256 /* 2^sizeof(char) */
191 #define CHAR(x) ((unsigned int)(x) & (CHARS - 1))
192 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */
193 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
194 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
195 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
196 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
198 #define ISALNUM(c) isalnum (CHAR(c))
199 #define ISALPHA(c) isalpha (CHAR(c))
200 #define ISDIGIT(c) isdigit (CHAR(c))
201 #define ISLOWER(c) islower (CHAR(c))
203 #define lowcase(c) tolower (CHAR(c))
204 #define upcase(c) toupper (CHAR(c))
208 * xnew, xrnew -- allocate, reallocate storage
210 * SYNOPSIS: Type *xnew (int n, Type);
211 * void xrnew (OldPointer, int n, Type);
214 # include "chkmalloc.h"
215 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
216 (n) * sizeof (Type)))
217 # define xrnew(op,n,Type) ((op) = (Type *) trace_realloc (__FILE__, __LINE__, \
218 (char *) (op), (n) * sizeof (Type)))
220 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
221 # define xrnew(op,n,Type) ((op) = (Type *) xrealloc ( \
222 (char *) (op), (n) * sizeof (Type)))
227 typedef void Lang_function
__P((FILE *));
231 char *suffix
; /* file name suffix for this compressor */
232 char *command
; /* takes one arg and decompresses to stdout */
237 char *name
; /* language name */
238 bool metasource
; /* source used to generate other sources */
239 Lang_function
*function
; /* parse function */
240 char **filenames
; /* names of this language's files */
241 char **suffixes
; /* name suffixes of this language's files */
242 char **interpreters
; /* interpreters for this language */
247 struct fdesc
*next
; /* for the linked list */
248 char *infname
; /* uncompressed input file name */
249 char *infabsname
; /* absolute uncompressed input file name */
250 char *infabsdir
; /* absolute dir of input file */
251 char *taggedfname
; /* file name to write in tagfile */
252 language
*lang
; /* language of file */
253 char *prop
; /* file properties to write in tagfile */
254 bool usecharno
; /* etags tags shall contain char number */
257 typedef struct node_st
258 { /* sorting structure */
259 struct node_st
*left
, *right
; /* left and right sons */
260 fdesc
*fdp
; /* description of file to whom tag belongs */
261 char *name
; /* tag name */
262 char *pat
; /* search pattern */
263 bool valid
; /* write this tag on the tag file */
264 bool is_func
; /* function tag: use pattern in CTAGS mode */
265 bool been_warned
; /* warning already given for duplicated tag */
266 int lno
; /* line number tag is on */
267 long cno
; /* character number line starts on */
271 * A `linebuffer' is a structure which holds a line of text.
272 * `readline_internal' reads a line from a stream into a linebuffer
273 * and works regardless of the length of the line.
274 * SIZE is the size of BUFFER, LEN is the length of the string in
275 * BUFFER after readline reads it.
284 /* Used to support mixing of --lang and file names. */
288 at_language
, /* a language specification */
289 at_regexp
, /* a regular expression */
290 at_icregexp
, /* same, but with case ignored */
291 at_filename
/* a file name */
292 } arg_type
; /* argument type */
293 language
*lang
; /* language associated with the argument */
294 char *what
; /* the argument itself */
298 /* Structure defining a regular expression. */
299 typedef struct pattern
301 struct pattern
*p_next
;
304 struct re_pattern_buffer
*pat
;
305 struct re_registers regs
;
310 #endif /* ETAGS_REGEXPS */
313 /* Many compilers barf on this:
314 Lang_function Ada_funcs;
315 so let's write it this way */
316 static void Ada_funcs
__P((FILE *));
317 static void Asm_labels
__P((FILE *));
318 static void C_entries
__P((int c_ext
, FILE *));
319 static void default_C_entries
__P((FILE *));
320 static void plain_C_entries
__P((FILE *));
321 static void Cjava_entries
__P((FILE *));
322 static void Cobol_paragraphs
__P((FILE *));
323 static void Cplusplus_entries
__P((FILE *));
324 static void Cstar_entries
__P((FILE *));
325 static void Erlang_functions
__P((FILE *));
326 static void Fortran_functions
__P((FILE *));
327 static void Yacc_entries
__P((FILE *));
328 static void Lisp_functions
__P((FILE *));
329 static void Makefile_targets
__P((FILE *));
330 static void Pascal_functions
__P((FILE *));
331 static void Perl_functions
__P((FILE *));
332 static void PHP_functions
__P((FILE *));
333 static void Postscript_functions
__P((FILE *));
334 static void Prolog_functions
__P((FILE *));
335 static void Python_functions
__P((FILE *));
336 static void Scheme_functions
__P((FILE *));
337 static void TeX_commands
__P((FILE *));
338 static void Texinfo_nodes
__P((FILE *));
339 static void just_read_file
__P((FILE *));
341 static void print_language_names
__P((void));
342 static void print_version
__P((void));
343 static void print_help
__P((void));
344 int main
__P((int, char **));
346 static compressor
*get_compressor_from_suffix
__P((char *, char **));
347 static language
*get_language_from_langname
__P((const char *));
348 static language
*get_language_from_interpreter
__P((char *));
349 static language
*get_language_from_filename
__P((char *, bool));
350 static long readline
__P((linebuffer
*, FILE *));
351 static long readline_internal
__P((linebuffer
*, FILE *));
352 static bool nocase_tail
__P((char *));
353 static char *get_tag
__P((char *));
356 static void analyse_regex
__P((char *, bool));
357 static void add_regex
__P((char *, bool, language
*));
358 static void free_patterns
__P((void));
359 #endif /* ETAGS_REGEXPS */
360 static void error
__P((const char *, const char *));
361 static void suggest_asking_for_help
__P((void));
362 void fatal
__P((char *, char *));
363 static void pfatal
__P((char *));
364 static void add_node
__P((node
*, node
**));
366 static void init
__P((void));
367 static void initbuffer
__P((linebuffer
*));
368 static void process_file
__P((char *, language
*));
369 static void find_entries
__P((FILE *));
370 static void free_tree
__P((node
*));
371 static void free_fdesc
__P((fdesc
*));
372 static void pfnote
__P((char *, bool, char *, int, int, long));
373 static void new_pfnote
__P((char *, int, bool, char *, int, int, long));
374 static void invalidate_nodes
__P((fdesc
*, node
**));
375 static void put_entries
__P((node
*));
377 static char *concat
__P((char *, char *, char *));
378 static char *skip_spaces
__P((char *));
379 static char *skip_non_spaces
__P((char *));
380 static char *savenstr
__P((char *, int));
381 static char *savestr
__P((char *));
382 static char *etags_strchr
__P((const char *, int));
383 static char *etags_strrchr
__P((const char *, int));
384 static bool strcaseeq
__P((const char *, const char *));
385 static char *etags_getcwd
__P((void));
386 static char *relative_filename
__P((char *, char *));
387 static char *absolute_filename
__P((char *, char *));
388 static char *absolute_dirname
__P((char *, char *));
389 static bool filename_is_absolute
__P((char *f
));
390 static void canonicalize_filename
__P((char *));
391 static void linebuffer_setlen
__P((linebuffer
*, int));
392 static PTR xmalloc
__P((unsigned int));
393 static PTR xrealloc
__P((char *, unsigned int));
396 static char searchar
= '/'; /* use /.../ searches */
398 static char *tagfile
; /* output file */
399 static char *progname
; /* name this program was invoked with */
400 static char *cwd
; /* current working directory */
401 static char *tagfiledir
; /* directory of tagfile */
402 static FILE *tagf
; /* ioptr for tags file */
404 static fdesc
*fdhead
; /* head of file description list */
405 static fdesc
*curfdp
; /* current file description */
406 static int lineno
; /* line number of current line */
407 static long charno
; /* current character number */
408 static long linecharno
; /* charno of start of current line */
409 static char *dbp
; /* pointer to start of current tag */
411 static const int invalidcharno
= -1;
413 static node
*nodehead
; /* the head of the binary tree of tags */
414 static node
*last_node
; /* the last node created */
416 static linebuffer lb
; /* the current line */
418 /* boolean "functions" (see init) */
419 static bool _wht
[CHARS
], _nin
[CHARS
], _itk
[CHARS
], _btk
[CHARS
], _etk
[CHARS
];
422 *white
= " \f\t\n\r\v",
424 *nonam
= " \f\t\n\r()=,;",
425 /* token ending chars */
426 *endtk
= " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
427 /* token starting chars */
428 *begtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
429 /* valid in-token chars */
430 *midtk
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
432 static bool append_to_tagfile
; /* -a: append to tags */
433 /* The next four default to TRUE for etags, but to FALSE for ctags. */
434 static bool typedefs
; /* -t: create tags for C and Ada typedefs */
435 static bool typedefs_or_cplusplus
; /* -T: create tags for C typedefs, level */
436 /* 0 struct/enum/union decls, and C++ */
437 /* member functions. */
438 static bool constantypedefs
; /* -d: create tags for C #define, enum */
439 /* constants and variables. */
440 /* -D: opposite of -d. Default under ctags. */
441 static bool globals
; /* create tags for global variables */
442 static bool declarations
; /* --declarations: tag them and extern in C&Co*/
443 static bool members
; /* create tags for C member variables */
444 static bool no_line_directive
; /* ignore #line directives */
445 static bool update
; /* -u: update tags */
446 static bool vgrind_style
; /* -v: create vgrind style index output */
447 static bool no_warnings
; /* -w: suppress warnings */
448 static bool cxref_style
; /* -x: create cxref style output */
449 static bool cplusplus
; /* .[hc] means C++, not C */
450 static bool noindentypedefs
; /* -I: ignore indentation in C */
451 static bool packages_only
; /* --packages-only: in Ada, only tag packages*/
454 /* List of all regexps. */
455 static pattern
*p_head
;
457 /* How many characters in the character set. (From regex.c.) */
458 #define CHAR_SET_SIZE 256
459 /* Translation table for case-insensitive matching. */
460 static char lc_trans
[CHAR_SET_SIZE
];
461 #endif /* ETAGS_REGEXPS */
464 static struct option longopts
[] =
466 { "packages-only", no_argument
, &packages_only
, TRUE
},
467 { "c++", no_argument
, NULL
, 'C' },
468 { "declarations", no_argument
, &declarations
, TRUE
},
469 { "no-line-directive", no_argument
, &no_line_directive
, TRUE
},
470 { "help", no_argument
, NULL
, 'h' },
471 { "help", no_argument
, NULL
, 'H' },
472 { "ignore-indentation", no_argument
, NULL
, 'I' },
473 { "language", required_argument
, NULL
, 'l' },
474 { "members", no_argument
, &members
, TRUE
},
475 { "no-members", no_argument
, &members
, FALSE
},
476 { "output", required_argument
, NULL
, 'o' },
478 { "regex", required_argument
, NULL
, 'r' },
479 { "no-regex", no_argument
, NULL
, 'R' },
480 { "ignore-case-regex", required_argument
, NULL
, 'c' },
481 #endif /* ETAGS_REGEXPS */
482 { "version", no_argument
, NULL
, 'V' },
484 #if CTAGS /* Etags options */
485 { "backward-search", no_argument
, NULL
, 'B' },
486 { "cxref", no_argument
, NULL
, 'x' },
487 { "defines", no_argument
, NULL
, 'd' },
488 { "globals", no_argument
, &globals
, TRUE
},
489 { "typedefs", no_argument
, NULL
, 't' },
490 { "typedefs-and-c++", no_argument
, NULL
, 'T' },
491 { "update", no_argument
, NULL
, 'u' },
492 { "vgrind", no_argument
, NULL
, 'v' },
493 { "no-warn", no_argument
, NULL
, 'w' },
495 #else /* Ctags options */
496 { "append", no_argument
, NULL
, 'a' },
497 { "no-defines", no_argument
, NULL
, 'D' },
498 { "no-globals", no_argument
, &globals
, FALSE
},
499 { "include", required_argument
, NULL
, 'i' },
503 #endif /* LONG_OPTIONS */
505 static compressor compressors
[] =
507 { "z", "gzip -d -c"},
508 { "Z", "gzip -d -c"},
509 { "gz", "gzip -d -c"},
510 { "GZ", "gzip -d -c"},
511 { "bz2", "bzip2 -d -c" },
520 static char *Ada_suffixes
[] =
521 { "ads", "adb", "ada", NULL
};
524 static char *Asm_suffixes
[] =
525 { "a", /* Unix assembler */
526 "asm", /* Microcontroller assembly */
527 "def", /* BSO/Tasking definition includes */
528 "inc", /* Microcontroller include files */
529 "ins", /* Microcontroller include files */
530 "s", "sa", /* Unix assembler */
531 "S", /* cpp-processed Unix assembler */
532 "src", /* BSO/Tasking C compiler output */
536 /* Note that .c and .h can be considered C++, if the --c++ flag was
537 given, or if the `class' keyowrd is met inside the file.
538 That is why default_C_entries is called for these. */
539 static char *default_C_suffixes
[] =
542 static char *Cplusplus_suffixes
[] =
543 { "C", "c++", "cc", "cpp", "cxx", "H", "h++", "hh", "hpp", "hxx",
544 "M", /* Objective C++ */
545 "pdb", /* Postscript with C syntax */
548 static char *Cjava_suffixes
[] =
551 static char *Cobol_suffixes
[] =
552 { "COB", "cob", NULL
};
554 static char *Cstar_suffixes
[] =
555 { "cs", "hs", NULL
};
557 static char *Erlang_suffixes
[] =
558 { "erl", "hrl", NULL
};
560 static char *Fortran_suffixes
[] =
561 { "F", "f", "f90", "for", NULL
};
563 static char *Lisp_suffixes
[] =
564 { "cl", "clisp", "el", "l", "lisp", "LSP", "lsp", "ml", NULL
};
566 static char *Makefile_filenames
[] =
567 { "Makefile", "makefile", "GNUMakefile", "Makefile.in", "Makefile.am", NULL
};
569 static char *Pascal_suffixes
[] =
570 { "p", "pas", NULL
};
572 static char *Perl_suffixes
[] =
573 { "pl", "pm", NULL
};
575 static char *Perl_interpreters
[] =
576 { "perl", "@PERL@", NULL
};
578 static char *PHP_suffixes
[] =
579 { "php", "php3", "php4", NULL
};
581 static char *plain_C_suffixes
[] =
582 { "lm", /* Objective lex file */
583 "m", /* Objective C file */
584 "pc", /* Pro*C file */
587 static char *Postscript_suffixes
[] =
588 { "ps", "psw", NULL
}; /* .psw is for PSWrap */
590 static char *Prolog_suffixes
[] =
593 static char *Python_suffixes
[] =
596 /* Can't do the `SCM' or `scm' prefix with a version number. */
597 static char *Scheme_suffixes
[] =
598 { "oak", "sch", "scheme", "SCM", "scm", "SM", "sm", "ss", "t", NULL
};
600 static char *TeX_suffixes
[] =
601 { "bib", "clo", "cls", "ltx", "sty", "TeX", "tex", NULL
};
603 static char *Texinfo_suffixes
[] =
604 { "texi", "texinfo", "txi", NULL
};
606 static char *Yacc_suffixes
[] =
607 { "y", "y++", "ym", "yxx", "yy", NULL
}; /* .ym is Objective yacc file */
610 * Table of languages.
612 * It is ok for a given function to be listed under more than one
613 * name. I just didn't.
616 static language lang_names
[] =
618 { "ada", FALSE
, Ada_funcs
, NULL
, Ada_suffixes
, NULL
},
619 { "asm", FALSE
, Asm_labels
, NULL
, Asm_suffixes
, NULL
},
620 { "c", FALSE
, default_C_entries
, NULL
, default_C_suffixes
, NULL
},
621 { "c++", FALSE
, Cplusplus_entries
, NULL
, Cplusplus_suffixes
, NULL
},
622 { "c*", FALSE
, Cstar_entries
, NULL
, Cstar_suffixes
, NULL
},
623 { "cobol", FALSE
, Cobol_paragraphs
, NULL
, Cobol_suffixes
, NULL
},
624 { "erlang", FALSE
, Erlang_functions
, NULL
, Erlang_suffixes
, NULL
},
625 { "fortran", FALSE
, Fortran_functions
, NULL
, Fortran_suffixes
, NULL
},
626 { "java", FALSE
, Cjava_entries
, NULL
, Cjava_suffixes
, NULL
},
627 { "lisp", FALSE
, Lisp_functions
, NULL
, Lisp_suffixes
, NULL
},
628 { "makefile", FALSE
, Makefile_targets
, Makefile_filenames
, NULL
, NULL
},
629 { "pascal", FALSE
, Pascal_functions
, NULL
, Pascal_suffixes
, NULL
},
630 { "perl", FALSE
, Perl_functions
,NULL
, Perl_suffixes
, Perl_interpreters
},
631 { "php", FALSE
, PHP_functions
, NULL
, PHP_suffixes
, NULL
},
632 { "postscript",FALSE
, Postscript_functions
,NULL
, Postscript_suffixes
, NULL
},
633 { "proc", FALSE
, plain_C_entries
, NULL
, plain_C_suffixes
, NULL
},
634 { "prolog", FALSE
, Prolog_functions
, NULL
, Prolog_suffixes
, NULL
},
635 { "python", FALSE
, Python_functions
, NULL
, Python_suffixes
, NULL
},
636 { "scheme", FALSE
, Scheme_functions
, NULL
, Scheme_suffixes
, NULL
},
637 { "tex", FALSE
, TeX_commands
, NULL
, TeX_suffixes
, NULL
},
638 { "texinfo", FALSE
, Texinfo_nodes
, NULL
, Texinfo_suffixes
, NULL
},
639 { "yacc", TRUE
, Yacc_entries
, NULL
, Yacc_suffixes
, NULL
},
640 { "auto", FALSE
, NULL
}, /* default guessing scheme */
641 { "none", FALSE
, just_read_file
}, /* regexp matching only */
642 { NULL
, FALSE
, NULL
} /* end of list */
647 print_language_names ()
652 puts ("\nThese are the currently supported languages, along with the\n\
653 default file names and dot suffixes:");
654 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
656 printf (" %-*s", 10, lang
->name
);
657 if (lang
->filenames
!= NULL
)
658 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
659 printf (" %s", *name
);
660 if (lang
->suffixes
!= NULL
)
661 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
662 printf (" .%s", *ext
);
665 puts ("Where `auto' means use default language for files based on file\n\
666 name suffix, and `none' means only do regexp processing on files.\n\
667 If no language is specified and no matching suffix is found,\n\
668 the first line of the file is read for a sharp-bang (#!) sequence\n\
669 followed by the name of an interpreter. If no such sequence is found,\n\
670 Fortran is tried first; if no tags are found, C is tried next.\n\
671 When parsing any C file, a \"class\" keyword switches to C++.\n\
672 Compressed files are supported using gzip and bzip2.");
676 # define EMACS_NAME "GNU Emacs"
679 # define VERSION "21"
684 printf ("%s (%s %s)\n", (CTAGS
) ? "ctags" : "etags", EMACS_NAME
, VERSION
);
685 puts ("Copyright (C) 2002 Free Software Foundation, Inc. and Ken Arnold");
686 puts ("This program is distributed under the same terms as Emacs");
694 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
696 These are the options accepted by %s.\n", progname
, progname
);
698 puts ("You may use unambiguous abbreviations for the long option names.");
700 puts ("Long option names do not work with this executable, as it is not\n\
701 linked with GNU getopt.");
702 #endif /* LONG_OPTIONS */
703 puts (" A - as file name means read names from stdin (one per line).\n\
704 Absolute names are stored in the output file as they are.\n\
705 Relative ones are stored relative to the output file's directory.\n");
708 puts ("-a, --append\n\
709 Append tag entries to existing tags file.");
711 puts ("--packages-only\n\
712 For Ada files, only generate tags for packages.");
715 puts ("-B, --backward-search\n\
716 Write the search commands for the tag entries using '?', the\n\
717 backward-search command instead of '/', the forward-search command.");
719 /* This option is mostly obsolete, because etags can now automatically
720 detect C++. Retained for backward compatibility and for debugging and
721 experimentation. In principle, we could want to tag as C++ even
722 before any "class" keyword.
724 Treat files whose name suffix defaults to C language as C++ files.");
727 puts ("--declarations\n\
728 In C and derived languages, create tags for function declarations,");
730 puts ("\tand create tags for extern variables if --globals is used.");
733 ("\tand create tags for extern variables unless --no-globals is used.");
736 puts ("-d, --defines\n\
737 Create tag entries for C #define constants and enum constants, too.");
739 puts ("-D, --no-defines\n\
740 Don't create tag entries for C #define constants and enum constants.\n\
741 This makes the tags file smaller.");
744 puts ("-i FILE, --include=FILE\n\
745 Include a note in tag file indicating that, when searching for\n\
746 a tag, one should also consult the tags file FILE after\n\
747 checking the current file.");
749 puts ("-l LANG, --language=LANG\n\
750 Force the following files to be considered as written in the\n\
751 named language up to the next --language=LANG option.");
755 Create tag entries for global variables in some languages.");
757 puts ("--no-globals\n\
758 Do not create tag entries for global variables in some\n\
759 languages. This makes the tags file smaller.");
761 Create tag entries for member variables in C and derived languages.");
764 puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
765 Make a tag for each line matching pattern REGEXP in the following\n\
766 files. {LANGUAGE}/REGEXP/ uses REGEXP for LANGUAGE files only.\n\
767 regexfile is a file containing one REGEXP per line.\n\
768 REGEXP is anchored (as if preceded by ^).\n\
769 The form /REGEXP/NAME/ creates a named tag.\n\
770 For example Tcl named tags can be created with:\n\
771 --regex=\"/proc[ \\t]+\\([^ \\t]+\\)/\\1/.\"");
772 puts ("-c /REGEXP/, --ignore-case-regex=/REGEXP/ or --ignore-case-regex=@regexfile\n\
773 Like -r, --regex but ignore case when matching expressions.");
774 puts ("-R, --no-regex\n\
775 Don't create tags from regexps for the following files.");
776 #endif /* ETAGS_REGEXPS */
777 puts ("-o FILE, --output=FILE\n\
778 Write the tags to FILE.");
779 puts ("-I, --ignore-indentation\n\
780 Don't rely on indentation quite as much as normal. Currently,\n\
781 this means not to assume that a closing brace in the first\n\
782 column is the final brace of a function or structure\n\
783 definition in C and C++.");
787 puts ("-t, --typedefs\n\
788 Generate tag entries for C and Ada typedefs.");
789 puts ("-T, --typedefs-and-c++\n\
790 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
791 and C++ member functions.");
795 puts ("-u, --update\n\
796 Update the tag entries for the given files, leaving tag\n\
797 entries for other files in place. Currently, this is\n\
798 implemented by deleting the existing entries for the given\n\
799 files and then rewriting the new entries at the end of the\n\
800 tags file. It is often faster to simply rebuild the entire\n\
801 tag file than to use this.");
805 puts ("-v, --vgrind\n\
806 Generates an index of items intended for human consumption,\n\
807 similar to the output of vgrind. The index is sorted, and\n\
808 gives the page number of each item.");
809 puts ("-w, --no-warn\n\
810 Suppress warning messages about entries defined in multiple\n\
812 puts ("-x, --cxref\n\
813 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
814 The output uses line numbers instead of page numbers, but\n\
815 beyond that the differences are cosmetic; try both to see\n\
819 puts ("-V, --version\n\
820 Print the version of the program.\n\
822 Print this help message.");
824 print_language_names ();
827 puts ("Report bugs to bug-gnu-emacs@gnu.org");
833 #ifdef VMS /* VMS specific functions */
837 /* This is a BUG! ANY arbitrary limit is a BUG!
838 Won't someone please fix this? */
839 #define MAX_FILE_SPEC_LEN 255
842 char body
[MAX_FILE_SPEC_LEN
+ 1];
846 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
847 returning in each successive call the next file name matching the input
848 spec. The function expects that each in_spec passed
849 to it will be processed to completion; in particular, up to and
850 including the call following that in which the last matching name
851 is returned, the function ignores the value of in_spec, and will
852 only start processing a new spec with the following call.
853 If an error occurs, on return out_spec contains the value
854 of in_spec when the error occurred.
856 With each successive file name returned in out_spec, the
857 function's return value is one. When there are no more matching
858 names the function returns zero. If on the first call no file
859 matches in_spec, or there is any other error, -1 is returned.
864 #define OUTSIZE MAX_FILE_SPEC_LEN
870 static long context
= 0;
871 static struct dsc$descriptor_s o
;
872 static struct dsc$descriptor_s i
;
873 static bool pass1
= TRUE
;
880 o
.dsc$a_pointer
= (char *) out
;
881 o
.dsc$w_length
= (short)OUTSIZE
;
882 i
.dsc$a_pointer
= in
;
883 i
.dsc$w_length
= (short)strlen(in
);
884 i
.dsc$b_dtype
= DSC$K_DTYPE_T
;
885 i
.dsc$b_class
= DSC$K_CLASS_S
;
886 o
.dsc$b_dtype
= DSC$K_DTYPE_VT
;
887 o
.dsc$b_class
= DSC$K_CLASS_VS
;
889 if ((status
= lib$
find_file(&i
, &o
, &context
, 0, 0)) == RMS$_NORMAL
)
891 out
->body
[out
->curlen
] = EOS
;
894 else if (status
== RMS$_NMF
)
898 strcpy(out
->body
, in
);
901 lib$
find_file_end(&context
);
907 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
908 name of each file specified by the provided arg expanding wildcards.
911 gfnames (arg
, p_error
)
915 static vspec filename
= {MAX_FILE_SPEC_LEN
, "\0"};
917 switch (fn_exp (&filename
, arg
))
921 return filename
.body
;
927 return filename
.body
;
931 #ifndef OLD /* Newer versions of VMS do provide `system'. */
935 error ("%s", "system() function not implemented under VMS");
939 #define VERSION_DELIM ';'
940 char *massage_name (s
)
946 if (*s
== VERSION_DELIM
)
964 unsigned int nincluded_files
;
965 char **included_files
;
967 int current_arg
, file_count
;
968 linebuffer filename_lb
;
974 _fmode
= O_BINARY
; /* all of files are treated as binary files */
979 included_files
= xnew (argc
, char *);
983 /* Allocate enough no matter what happens. Overkill, but each one
985 argbuffer
= xnew (argc
, argument
);
988 /* Set syntax for regular expression routines. */
989 re_set_syntax (RE_SYNTAX_EMACS
| RE_INTERVALS
);
990 /* Translation table for case-insensitive search. */
991 for (i
= 0; i
< CHAR_SET_SIZE
; i
++)
992 lc_trans
[i
] = lowcase (i
);
993 #endif /* ETAGS_REGEXPS */
996 * If etags, always find typedefs and structure tags. Why not?
997 * Also default to find macro constants, enum constants and
1002 typedefs
= typedefs_or_cplusplus
= constantypedefs
= TRUE
;
1009 char *optstring
= "-";
1011 #ifdef ETAGS_REGEXPS
1012 optstring
= "-r:Rc:";
1013 #endif /* ETAGS_REGEXPS */
1015 #ifndef LONG_OPTIONS
1016 optstring
= optstring
+ 1;
1017 #endif /* LONG_OPTIONS */
1019 optstring
= concat (optstring
,
1021 (CTAGS
) ? "BxdtTuvw" : "aDi:");
1023 opt
= getopt_long (argc
, argv
, optstring
, longopts
, 0);
1030 /* If getopt returns 0, then it has already processed a
1031 long-named option. We should do nothing. */
1035 /* This means that a file name has been seen. Record it. */
1036 argbuffer
[current_arg
].arg_type
= at_filename
;
1037 argbuffer
[current_arg
].what
= optarg
;
1042 /* Common options. */
1043 case 'C': cplusplus
= TRUE
; break;
1044 case 'f': /* for compatibility with old makefiles */
1048 error ("-o option may only be given once.", (char *)NULL
);
1049 suggest_asking_for_help ();
1054 case 'S': /* for backward compatibility */
1055 noindentypedefs
= TRUE
;
1059 language
*lang
= get_language_from_langname (optarg
);
1062 argbuffer
[current_arg
].lang
= lang
;
1063 argbuffer
[current_arg
].arg_type
= at_language
;
1069 argbuffer
[current_arg
].arg_type
= at_regexp
;
1070 argbuffer
[current_arg
].what
= optarg
;
1074 argbuffer
[current_arg
].arg_type
= at_regexp
;
1075 argbuffer
[current_arg
].what
= NULL
;
1079 argbuffer
[current_arg
].arg_type
= at_icregexp
;
1080 argbuffer
[current_arg
].what
= optarg
;
1092 case 'a': append_to_tagfile
= TRUE
; break;
1093 case 'D': constantypedefs
= FALSE
; break;
1094 case 'i': included_files
[nincluded_files
++] = optarg
; break;
1096 /* Ctags options. */
1097 case 'B': searchar
= '?'; break;
1098 case 'd': constantypedefs
= TRUE
; break;
1099 case 't': typedefs
= TRUE
; break;
1100 case 'T': typedefs
= typedefs_or_cplusplus
= TRUE
; break;
1101 case 'u': update
= TRUE
; break;
1102 case 'v': vgrind_style
= TRUE
; /*FALLTHRU*/
1103 case 'x': cxref_style
= TRUE
; break;
1104 case 'w': no_warnings
= TRUE
; break;
1106 suggest_asking_for_help ();
1110 for (; optind
< argc
; ++optind
)
1112 argbuffer
[current_arg
].arg_type
= at_filename
;
1113 argbuffer
[current_arg
].what
= argv
[optind
];
1118 if (nincluded_files
== 0 && file_count
== 0)
1120 error ("no input files specified.", (char *)NULL
);
1121 suggest_asking_for_help ();
1124 if (tagfile
== NULL
)
1125 tagfile
= CTAGS
? "tags" : "TAGS";
1126 cwd
= etags_getcwd (); /* the current working directory */
1127 if (cwd
[strlen (cwd
) - 1] != '/')
1130 cwd
= concat (oldcwd
, "/", "");
1133 if (streq (tagfile
, "-"))
1136 tagfiledir
= absolute_dirname (tagfile
, cwd
);
1138 init (); /* set up boolean "functions" */
1141 initbuffer (&filename_lb
);
1145 if (streq (tagfile
, "-"))
1149 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1150 doesn't take effect until after `stdout' is already open). */
1151 if (!isatty (fileno (stdout
)))
1152 setmode (fileno (stdout
), O_BINARY
);
1156 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1162 * Loop through files finding functions.
1164 for (i
= 0; i
< current_arg
; ++i
)
1166 static language
*lang
; /* non-NULL if language is forced */
1169 switch (argbuffer
[i
].arg_type
)
1172 lang
= argbuffer
[i
].lang
;
1174 #ifdef ETAGS_REGEXPS
1176 analyse_regex (argbuffer
[i
].what
, FALSE
);
1179 analyse_regex (argbuffer
[i
].what
, TRUE
);
1184 while ((this_file
= gfnames (argbuffer
[i
].what
, &got_err
)) != NULL
)
1188 error ("can't find file %s\n", this_file
);
1193 this_file
= massage_name (this_file
);
1196 this_file
= argbuffer
[i
].what
;
1198 /* Input file named "-" means read file names from stdin
1199 (one per line) and use them. */
1200 if (streq (this_file
, "-"))
1201 while (readline_internal (&filename_lb
, stdin
) > 0)
1202 process_file (filename_lb
.buffer
, lang
);
1204 process_file (this_file
, lang
);
1212 #ifdef ETAGS_REGEXPS
1214 #endif /* ETAGS_REGEXPS */
1216 if (!CTAGS
|| cxref_style
)
1218 put_entries (nodehead
);
1219 free_tree (nodehead
);
1222 while (nincluded_files
-- > 0)
1223 fprintf (tagf
, "\f\n%s,include\n", *included_files
++);
1225 if (fclose (tagf
) == EOF
)
1233 for (i
= 0; i
< current_arg
; ++i
)
1235 if (argbuffer
[i
].arg_type
!= at_filename
)
1238 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1239 tagfile
, argbuffer
[i
].what
, tagfile
);
1240 if (system (cmd
) != GOOD
)
1241 fatal ("failed to execute shell command", (char *)NULL
);
1243 append_to_tagfile
= TRUE
;
1246 tagf
= fopen (tagfile
, append_to_tagfile
? "a" : "w");
1249 put_entries (nodehead
);
1250 free_tree (nodehead
);
1252 if (fclose (tagf
) == EOF
)
1258 sprintf (cmd
, "sort %s -o %s", tagfile
, tagfile
);
1259 exit (system (cmd
));
1266 * Return a compressor given the file name. If EXTPTR is non-zero,
1267 * return a pointer into FILE where the compressor-specific
1268 * extension begins. If no compressor is found, NULL is returned
1269 * and EXTPTR is not significant.
1270 * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca> (1998)
1273 get_compressor_from_suffix (file
, extptr
)
1278 char *slash
, *suffix
;
1280 /* This relies on FN to be after canonicalize_filename,
1281 so we don't need to consider backslashes on DOS_NT. */
1282 slash
= etags_strrchr (file
, '/');
1283 suffix
= etags_strrchr (file
, '.');
1284 if (suffix
== NULL
|| suffix
< slash
)
1289 /* Let those poor souls who live with DOS 8+3 file name limits get
1290 some solace by treating foo.cgz as if it were foo.c.gz, etc.
1291 Only the first do loop is run if not MSDOS */
1294 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1295 if (streq (compr
->suffix
, suffix
))
1298 break; /* do it only once: not really a loop */
1301 } while (*suffix
!= '\0');
1308 * Return a language given the name.
1311 get_language_from_langname (name
)
1317 error ("empty language name", (char *)NULL
);
1320 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1321 if (streq (name
, lang
->name
))
1323 error ("unknown language \"%s\"", name
);
1331 * Return a language given the interpreter name.
1334 get_language_from_interpreter (interpreter
)
1340 if (interpreter
== NULL
)
1342 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1343 if (lang
->interpreters
!= NULL
)
1344 for (iname
= lang
->interpreters
; *iname
!= NULL
; iname
++)
1345 if (streq (*iname
, interpreter
))
1354 * Return a language given the file name.
1357 get_language_from_filename (file
, case_sensitive
)
1359 bool case_sensitive
;
1362 char **name
, **ext
, *suffix
;
1364 /* Try whole file name first. */
1365 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1366 if (lang
->filenames
!= NULL
)
1367 for (name
= lang
->filenames
; *name
!= NULL
; name
++)
1368 if ((case_sensitive
)
1369 ? streq (*name
, file
)
1370 : strcaseeq (*name
, file
))
1373 /* If not found, try suffix after last dot. */
1374 suffix
= etags_strrchr (file
, '.');
1378 for (lang
= lang_names
; lang
->name
!= NULL
; lang
++)
1379 if (lang
->suffixes
!= NULL
)
1380 for (ext
= lang
->suffixes
; *ext
!= NULL
; ext
++)
1381 if ((case_sensitive
)
1382 ? streq (*ext
, suffix
)
1383 : strcaseeq (*ext
, suffix
))
1390 * This routine is called on each file argument.
1393 process_file (file
, lang
)
1397 struct stat stat_buf
;
1399 static const fdesc emptyfdesc
;
1402 char *compressed_name
, *uncompressed_name
;
1403 char *ext
, *real_name
;
1407 canonicalize_filename (file
);
1408 if (streq (file
, tagfile
) && !streq (tagfile
, "-"))
1410 error ("skipping inclusion of %s in self.", file
);
1413 if ((compr
= get_compressor_from_suffix (file
, &ext
)) == NULL
)
1415 compressed_name
= NULL
;
1416 real_name
= uncompressed_name
= savestr (file
);
1420 real_name
= compressed_name
= savestr (file
);
1421 uncompressed_name
= savenstr (file
, ext
- file
);
1424 /* If the canonicalized uncompressed name
1425 has already been dealt with, skip it silently. */
1426 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
1428 assert (fdp
->infname
!= NULL
);
1429 if (streq (uncompressed_name
, fdp
->infname
))
1433 if (stat (real_name
, &stat_buf
) != 0)
1435 /* Reset real_name and try with a different name. */
1437 if (compressed_name
!= NULL
) /* try with the given suffix */
1439 if (stat (uncompressed_name
, &stat_buf
) == 0)
1440 real_name
= uncompressed_name
;
1442 else /* try all possible suffixes */
1444 for (compr
= compressors
; compr
->suffix
!= NULL
; compr
++)
1446 compressed_name
= concat (file
, ".", compr
->suffix
);
1447 if (stat (compressed_name
, &stat_buf
) != 0)
1451 char *suf
= compressed_name
+ strlen (file
);
1452 size_t suflen
= strlen (compr
->suffix
) + 1;
1453 for ( ; suf
[1]; suf
++, suflen
--)
1455 memmove (suf
, suf
+ 1, suflen
);
1456 if (stat (compressed_name
, &stat_buf
) == 0)
1458 real_name
= compressed_name
;
1462 if (real_name
!= NULL
)
1465 free (compressed_name
);
1466 compressed_name
= NULL
;
1470 real_name
= compressed_name
;
1475 if (real_name
== NULL
)
1480 } /* try with a different name */
1482 if (!S_ISREG (stat_buf
.st_mode
))
1484 error ("skipping %s: it is not a regular file.", real_name
);
1487 if (real_name
== compressed_name
)
1489 char *cmd
= concat (compr
->command
, " ", real_name
);
1490 inf
= (FILE *) popen (cmd
, "r");
1494 inf
= fopen (real_name
, "r");
1501 /* Create a new input file description entry. */
1502 fdp
= xnew (1, fdesc
);
1505 fdp
->infname
= savestr (uncompressed_name
);
1507 fdp
->infabsname
= absolute_filename (uncompressed_name
, cwd
);
1508 fdp
->infabsdir
= absolute_dirname (uncompressed_name
, cwd
);
1509 if (filename_is_absolute (uncompressed_name
))
1511 /* file is an absolute file name. Canonicalize it. */
1512 fdp
->taggedfname
= absolute_filename (uncompressed_name
, NULL
);
1516 /* file is a file name relative to cwd. Make it relative
1517 to the directory of the tags file. */
1518 fdp
->taggedfname
= relative_filename (uncompressed_name
, tagfiledir
);
1520 fdp
->usecharno
= TRUE
; /* use char position when making tags */
1524 curfdp
= fdhead
; /* the current file description */
1528 if (real_name
== compressed_name
)
1529 retval
= pclose (inf
);
1531 retval
= fclose (inf
);
1535 /* If not Ctags, and if this is not metasource and if it contained no #line
1536 directives, we can write the tags and free all nodes pointing to
1539 && curfdp
->usecharno
/* no #line directives in this file */
1540 && !curfdp
->lang
->metasource
)
1544 /* Look for the head of the sublist relative to this file. See add_node
1545 for the structure of the node tree. */
1547 for (np
= nodehead
; np
!= NULL
; prev
= np
, np
= np
->left
)
1548 if (np
->fdp
== curfdp
)
1551 /* If we generated tags for this file, write and delete them. */
1554 /* This is the head of the last sublist, if any. The following
1555 instructions depend on this being true. */
1556 assert (np
->left
== NULL
);
1558 assert (fdhead
== curfdp
);
1559 assert (last_node
->fdp
== curfdp
);
1560 put_entries (np
); /* write tags for file curfdp->taggedfname */
1561 free_tree (np
); /* remove the written nodes */
1563 nodehead
= NULL
; /* no nodes left */
1565 prev
->left
= NULL
; /* delete the pointer to the sublist */
1570 if (compressed_name
) free (compressed_name
);
1571 if (uncompressed_name
) free (uncompressed_name
);
1578 * This routine sets up the boolean pseudo-functions which work
1579 * by setting boolean flags dependent upon the corresponding character.
1580 * Every char which is NOT in that string is not a white char. Therefore,
1581 * all of the array "_wht" is set to FALSE, and then the elements
1582 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1583 * of a char is TRUE if it is the string "white", else FALSE.
1591 for (i
= 0; i
< CHARS
; i
++)
1592 iswhite(i
) = notinname(i
) = begtoken(i
) = intoken(i
) = endtoken(i
) = FALSE
;
1593 for (sp
= white
; *sp
!= '\0'; sp
++) iswhite (*sp
) = TRUE
;
1594 for (sp
= nonam
; *sp
!= '\0'; sp
++) notinname (*sp
) = TRUE
;
1595 notinname('\0') = notinname('\n');
1596 for (sp
= begtk
; *sp
!= '\0'; sp
++) begtoken (*sp
) = TRUE
;
1597 begtoken('\0') = begtoken('\n');
1598 for (sp
= midtk
; *sp
!= '\0'; sp
++) intoken (*sp
) = TRUE
;
1599 intoken('\0') = intoken('\n');
1600 for (sp
= endtk
; *sp
!= '\0'; sp
++) endtoken (*sp
) = TRUE
;
1601 endtoken('\0') = endtoken('\n');
1605 * This routine opens the specified file and calls the function
1606 * which finds the function and type definitions.
1613 node
*old_last_node
;
1614 language
*lang
= curfdp
->lang
;
1615 Lang_function
*parser
= NULL
;
1617 /* If user specified a language, use it. */
1618 if (lang
!= NULL
&& lang
->function
!= NULL
)
1620 parser
= lang
->function
;
1623 /* Else try to guess the language given the file name. */
1626 lang
= get_language_from_filename (curfdp
->infname
, TRUE
);
1627 if (lang
!= NULL
&& lang
->function
!= NULL
)
1629 curfdp
->lang
= lang
;
1630 parser
= lang
->function
;
1634 /* Else look for sharp-bang as the first two characters. */
1636 && readline_internal (&lb
, inf
) > 0
1638 && lb
.buffer
[0] == '#'
1639 && lb
.buffer
[1] == '!')
1643 /* Set lp to point at the first char after the last slash in the
1644 line or, if no slashes, at the first nonblank. Then set cp to
1645 the first successive blank and terminate the string. */
1646 lp
= etags_strrchr (lb
.buffer
+2, '/');
1650 lp
= skip_spaces (lb
.buffer
+ 2);
1651 cp
= skip_non_spaces (lp
);
1654 if (strlen (lp
) > 0)
1656 lang
= get_language_from_interpreter (lp
);
1657 if (lang
!= NULL
&& lang
->function
!= NULL
)
1659 curfdp
->lang
= lang
;
1660 parser
= lang
->function
;
1665 /* We rewind here, even if inf may be a pipe. We fail if the
1666 length of the first line is longer than the pipe block size,
1667 which is unlikely. */
1671 /* Else try to guess the language given the case insensitive file name. */
1674 lang
= get_language_from_filename (curfdp
->infname
, FALSE
);
1675 if (lang
!= NULL
&& lang
->function
!= NULL
)
1677 curfdp
->lang
= lang
;
1678 parser
= lang
->function
;
1682 if (!no_line_directive
1683 && curfdp
->lang
!= NULL
&& curfdp
->lang
->metasource
)
1684 /* It may be that this is a bingo.y file, and we already parsed a bingo.c
1685 file, or anyway we parsed a file that is automatically generated from
1686 this one. If this is the case, the bingo.c file contained #line
1687 directives that generated tags pointing to this file. Let's delete
1688 them all before parsing this file, which is the real source. */
1690 fdesc
**fdpp
= &fdhead
;
1691 while (*fdpp
!= NULL
)
1693 && streq ((*fdpp
)->taggedfname
, curfdp
->taggedfname
))
1694 /* We found one of those! We must delete both the file description
1695 and all tags referring to it. */
1697 fdesc
*badfdp
= *fdpp
;
1701 "Removing references to \"%s\" obtained from \"%s\"\n",
1702 badfdp
->taggedfname
, badfdp
->infname
);
1704 /* Delete the tags referring to badfdp. */
1705 invalidate_nodes (badfdp
, &nodehead
);
1707 *fdpp
= badfdp
->next
; /* remove the bad description from the list */
1708 free_fdesc (badfdp
);
1711 fdpp
= &(*fdpp
)->next
; /* advance the list pointer */
1720 /* Else try Fortran. */
1721 old_last_node
= last_node
;
1722 curfdp
->lang
= get_language_from_langname ("fortran");
1723 Fortran_functions (inf
);
1725 if (old_last_node
== last_node
)
1726 /* No Fortran entries found. Try C. */
1728 /* We do not tag if rewind fails.
1729 Only the file name will be recorded in the tags file. */
1731 curfdp
->lang
= get_language_from_langname (cplusplus
? "c++" : "c");
1732 default_C_entries (inf
);
1740 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
)
1741 char *name
; /* tag name, or NULL if unnamed */
1742 bool is_func
; /* tag is a function */
1743 char *linestart
; /* start of the line where tag is */
1744 int linelen
; /* length of the line where tag is */
1745 int lno
; /* line number */
1746 long cno
; /* character number */
1750 if (CTAGS
&& name
== NULL
)
1753 np
= xnew (1, node
);
1755 /* If ctags mode, change name "main" to M<thisfilename>. */
1756 if (CTAGS
&& !cxref_style
&& streq (name
, "main"))
1758 register char *fp
= etags_strrchr (curfdp
->taggedfname
, '/');
1759 np
->name
= concat ("M", fp
== NULL
? curfdp
->taggedfname
: fp
+ 1, "");
1760 fp
= etags_strrchr (np
->name
, '.');
1761 if (fp
!= NULL
&& fp
[1] != '\0' && fp
[2] == '\0')
1767 np
->been_warned
= FALSE
;
1769 np
->is_func
= is_func
;
1771 if (np
->fdp
->usecharno
)
1772 /* Our char numbers are 0-base, because of C language tradition?
1773 ctags compatibility? old versions compatibility? I don't know.
1774 Anyway, since emacs's are 1-base we expect etags.el to take care
1775 of the difference. If we wanted to have 1-based numbers, we would
1776 uncomment the +1 below. */
1777 np
->cno
= cno
/* + 1 */ ;
1779 np
->cno
= invalidcharno
;
1780 np
->left
= np
->right
= NULL
;
1781 if (CTAGS
&& !cxref_style
)
1783 if (strlen (linestart
) < 50)
1784 np
->pat
= concat (linestart
, "$", "");
1786 np
->pat
= savenstr (linestart
, 50);
1789 np
->pat
= savenstr (linestart
, linelen
);
1791 add_node (np
, &nodehead
);
1795 * TAGS format specification
1796 * Idea by Sam Kendall <kendall@mv.mv.com> (1997)
1798 * pfnote should emit the optimized form [unnamed tag] only if:
1799 * 1. name does not contain any of the characters " \t\r\n(),;";
1800 * 2. linestart contains name as either a rightmost, or rightmost but
1801 * one character, substring;
1802 * 3. the character, if any, immediately before name in linestart must
1803 * be one of the characters " \t(),;";
1804 * 4. the character, if any, immediately after name in linestart must
1805 * also be one of the characters " \t(),;".
1807 * The real implementation uses the notinname() macro, which recognises
1808 * characters slightly different from " \t\r\n(),;". See the variable
1811 #define traditional_tag_style TRUE
1813 new_pfnote (name
, namelen
, is_func
, linestart
, linelen
, lno
, cno
)
1814 char *name
; /* tag name, or NULL if unnamed */
1815 int namelen
; /* tag length */
1816 bool is_func
; /* tag is a function */
1817 char *linestart
; /* start of the line where tag is */
1818 int linelen
; /* length of the line where tag is */
1819 int lno
; /* line number */
1820 long cno
; /* character number */
1828 for (cp
= name
; !notinname (*cp
); cp
++)
1830 if (*cp
== '\0') /* rule #1 */
1832 cp
= linestart
+ linelen
- namelen
;
1833 if (notinname (linestart
[linelen
-1]))
1834 cp
-= 1; /* rule #4 */
1835 if (cp
>= linestart
/* rule #2 */
1837 || notinname (cp
[-1])) /* rule #3 */
1838 && strneq (name
, cp
, namelen
)) /* rule #2 */
1839 named
= FALSE
; /* use unnamed tag */
1844 name
= savenstr (name
, namelen
);
1847 pfnote (name
, is_func
, linestart
, linelen
, lno
, cno
);
1852 * recurse on left children, iterate on right children.
1860 register node
*node_right
= np
->right
;
1861 free_tree (np
->left
);
1862 if (np
->name
!= NULL
)
1872 * delete a file description
1876 register fdesc
*fdp
;
1878 if (fdp
->infname
!= NULL
) free (fdp
->infname
);
1879 if (fdp
->infabsname
!= NULL
) free (fdp
->infabsname
);
1880 if (fdp
->infabsdir
!= NULL
) free (fdp
->infabsdir
);
1881 if (fdp
->taggedfname
!= NULL
) free (fdp
->taggedfname
);
1882 if (fdp
->prop
!= NULL
) free (fdp
->prop
);
1888 * Adds a node to the tree of nodes. In etags mode, sort by file
1889 * name. In ctags mode, sort by tag name. Make no attempt at
1892 * add_node is the only function allowed to add nodes, so it can
1896 add_node (np
, cur_node_p
)
1897 node
*np
, **cur_node_p
;
1900 register node
*cur_node
= *cur_node_p
;
1902 if (cur_node
== NULL
)
1912 /* For each file name, tags are in a linked sublist on the right
1913 pointer. The first tags of different files are a linked list
1914 on the left pointer. last_node points to the end of the last
1916 if (last_node
!= NULL
&& last_node
->fdp
== np
->fdp
)
1918 /* Let's use the same sublist as the last added node. */
1919 assert (last_node
->right
== NULL
);
1920 last_node
->right
= np
;
1923 else if (cur_node
->fdp
== np
->fdp
)
1925 /* Scanning the list we found the head of a sublist which is
1926 good for us. Let's scan this sublist. */
1927 add_node (np
, &cur_node
->right
);
1930 /* The head of this sublist is not good for us. Let's try the
1932 add_node (np
, &cur_node
->left
);
1933 } /* if ETAGS mode */
1938 dif
= strcmp (np
->name
, cur_node
->name
);
1941 * If this tag name matches an existing one, then
1942 * do not add the node, but maybe print a warning.
1946 if (np
->fdp
== cur_node
->fdp
)
1950 fprintf (stderr
, "Duplicate entry in file %s, line %d: %s\n",
1951 np
->fdp
->infname
, lineno
, np
->name
);
1952 fprintf (stderr
, "Second entry ignored\n");
1955 else if (!cur_node
->been_warned
&& !no_warnings
)
1959 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1960 np
->fdp
->infname
, cur_node
->fdp
->infname
, np
->name
);
1961 cur_node
->been_warned
= TRUE
;
1966 /* Actually add the node */
1967 add_node (np
, dif
< 0 ? &cur_node
->left
: &cur_node
->right
);
1968 } /* if CTAGS mode */
1972 * invalidate_nodes ()
1973 * Scan the node tree and invalidate all nodes pointing to the
1974 * given file description (CTAGS case) or free them (ETAGS case).
1977 invalidate_nodes (badfdp
, npp
)
1988 if (np
->left
!= NULL
)
1989 invalidate_nodes (badfdp
, &np
->left
);
1990 if (np
->fdp
== badfdp
)
1992 if (np
->right
!= NULL
)
1993 invalidate_nodes (badfdp
, &np
->right
);
1997 node
**next
= &np
->left
;
1998 if (np
->fdp
== badfdp
)
2000 *npp
= *next
; /* detach the sublist from the list */
2001 np
->left
= NULL
; /* isolate it */
2002 free_tree (np
); /* free it */
2004 invalidate_nodes (badfdp
, next
);
2009 static int total_size_of_entries
__P((node
*));
2010 static int number_len
__P((long));
2012 /* Length of a non-negative number's decimal representation. */
2018 while ((num
/= 10) > 0)
2024 * Return total number of characters that put_entries will output for
2025 * the nodes in the linked list at the right of the specified node.
2026 * This count is irrelevant with etags.el since emacs 19.34 at least,
2027 * but is still supplied for backward compatibility.
2030 total_size_of_entries (np
)
2033 register int total
= 0;
2035 for (; np
!= NULL
; np
= np
->right
)
2037 total
+= strlen (np
->pat
) + 1; /* pat\177 */
2038 if (np
->name
!= NULL
)
2039 total
+= strlen (np
->name
) + 1; /* name\001 */
2040 total
+= number_len ((long) np
->lno
) + 1; /* lno, */
2041 if (np
->cno
!= invalidcharno
) /* cno */
2042 total
+= number_len (np
->cno
);
2043 total
+= 1; /* newline */
2054 static fdesc
*fdp
= NULL
;
2059 /* Output subentries that precede this one */
2061 put_entries (np
->left
);
2063 /* Output this entry */
2072 fprintf (tagf
, "\f\n%s,%d\n",
2073 fdp
->taggedfname
, total_size_of_entries (np
));
2075 fputs (np
->pat
, tagf
);
2076 fputc ('\177', tagf
);
2077 if (np
->name
!= NULL
)
2079 fputs (np
->name
, tagf
);
2080 fputc ('\001', tagf
);
2082 fprintf (tagf
, "%d,", np
->lno
);
2083 if (np
->cno
!= invalidcharno
)
2084 fprintf (tagf
, "%ld", np
->cno
);
2090 if (np
->name
== NULL
)
2091 error ("internal error: NULL name in ctags mode.", (char *)NULL
);
2096 fprintf (stdout
, "%s %s %d\n",
2097 np
->name
, np
->fdp
->taggedfname
, (np
->lno
+ 63) / 64);
2099 fprintf (stdout
, "%-16s %3d %-16s %s\n",
2100 np
->name
, np
->lno
, np
->fdp
->taggedfname
, np
->pat
);
2104 fprintf (tagf
, "%s\t%s\t", np
->name
, np
->fdp
->taggedfname
);
2107 { /* function or #define macro with args */
2108 putc (searchar
, tagf
);
2111 for (sp
= np
->pat
; *sp
; sp
++)
2113 if (*sp
== '\\' || *sp
== searchar
)
2117 putc (searchar
, tagf
);
2120 { /* anything else; text pattern inadequate */
2121 fprintf (tagf
, "%d", np
->lno
);
2126 } /* if this node contains a valid tag */
2128 /* Output subentries that follow this one */
2129 put_entries (np
->right
);
2131 put_entries (np
->left
);
2136 #define C_EXT 0x00fff /* C extensions */
2137 #define C_PLAIN 0x00000 /* C */
2138 #define C_PLPL 0x00001 /* C++ */
2139 #define C_STAR 0x00003 /* C* */
2140 #define C_JAVA 0x00005 /* JAVA */
2141 #define C_AUTO 0x01000 /* C, but switch to C++ if `class' is met */
2142 #define YACC 0x10000 /* yacc file */
2145 * The C symbol tables.
2150 st_C_objprot
, st_C_objimpl
, st_C_objend
,
2155 st_C_class
, st_C_template
,
2156 st_C_struct
, st_C_extern
, st_C_enum
, st_C_define
, st_C_typedef
, st_C_typespec
2159 static unsigned int hash
__P((const char *, unsigned int));
2160 static struct C_stab_entry
* in_word_set
__P((const char *, unsigned int));
2161 static enum sym_type C_symtype
__P((char *, int, int));
2163 /* Feed stuff between (but not including) %[ and %] lines to:
2164 gperf -c -k 1,3 -o -p -r -t
2166 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
2170 while, 0, st_C_ignore
2171 switch, 0, st_C_ignore
2172 return, 0, st_C_ignore
2173 @interface, 0, st_C_objprot
2174 @protocol, 0, st_C_objprot
2175 @implementation,0, st_C_objimpl
2176 @end, 0, st_C_objend
2177 import, C_JAVA, st_C_ignore
2178 package, C_JAVA, st_C_ignore
2179 friend, C_PLPL, st_C_ignore
2180 extends, C_JAVA, st_C_javastruct
2181 implements, C_JAVA, st_C_javastruct
2182 interface, C_JAVA, st_C_struct
2183 class, 0, st_C_class
2184 namespace, C_PLPL, st_C_struct
2185 domain, C_STAR, st_C_struct
2186 union, 0, st_C_struct
2187 struct, 0, st_C_struct
2188 extern, 0, st_C_extern
2190 typedef, 0, st_C_typedef
2191 define, 0, st_C_define
2192 operator, C_PLPL, st_C_operator
2193 template, 0, st_C_template
2194 bool, C_PLPL, st_C_typespec
2195 long, 0, st_C_typespec
2196 short, 0, st_C_typespec
2197 int, 0, st_C_typespec
2198 char, 0, st_C_typespec
2199 float, 0, st_C_typespec
2200 double, 0, st_C_typespec
2201 signed, 0, st_C_typespec
2202 unsigned, 0, st_C_typespec
2203 auto, 0, st_C_typespec
2204 void, 0, st_C_typespec
2205 static, 0, st_C_typespec
2206 const, 0, st_C_typespec
2207 volatile, 0, st_C_typespec
2208 explicit, C_PLPL, st_C_typespec
2209 mutable, C_PLPL, st_C_typespec
2210 typename, C_PLPL, st_C_typespec
2211 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
2212 DEFUN, 0, st_C_gnumacro
2213 SYSCALL, 0, st_C_gnumacro
2214 ENTRY, 0, st_C_gnumacro
2215 PSEUDO, 0, st_C_gnumacro
2216 # These are defined inside C functions, so currently they are not met.
2217 # EXFUN used in glibc, DEFVAR_* in emacs.
2218 #EXFUN, 0, st_C_gnumacro
2219 #DEFVAR_, 0, st_C_gnumacro
2221 and replace lines between %< and %> with its output,
2222 then make in_word_set and C_stab_entry static. */
2224 /* C code produced by gperf version 2.7.1 (19981006 egcs) */
2225 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
2226 struct C_stab_entry
{ char *name
; int c_ext
; enum sym_type type
; };
2228 #define TOTAL_KEYWORDS 47
2229 #define MIN_WORD_LENGTH 2
2230 #define MAX_WORD_LENGTH 15
2231 #define MIN_HASH_VALUE 18
2232 #define MAX_HASH_VALUE 138
2233 /* maximum key range = 121, duplicates = 0 */
2240 register const char *str
;
2241 register unsigned int len
;
2243 static unsigned char asso_values
[] =
2245 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2246 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2247 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2248 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2249 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2250 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2251 139, 139, 139, 139, 63, 139, 139, 139, 33, 44,
2252 62, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2253 42, 139, 139, 12, 32, 139, 139, 139, 139, 139,
2254 139, 139, 139, 139, 139, 139, 139, 34, 59, 37,
2255 24, 58, 33, 3, 139, 16, 139, 139, 42, 60,
2256 18, 11, 39, 139, 23, 57, 4, 63, 6, 20,
2257 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2258 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2259 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2260 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2261 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2262 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2263 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2264 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2265 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2266 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2267 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2268 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2269 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
2270 139, 139, 139, 139, 139, 139
2272 register int hval
= len
;
2278 hval
+= asso_values
[(unsigned char)str
[2]];
2281 hval
+= asso_values
[(unsigned char)str
[0]];
2290 static struct C_stab_entry
*
2291 in_word_set (str
, len
)
2292 register const char *str
;
2293 register unsigned int len
;
2295 static struct C_stab_entry wordlist
[] =
2297 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2298 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2299 {"if", 0, st_C_ignore
},
2300 {""}, {""}, {""}, {""},
2301 {"int", 0, st_C_typespec
},
2303 {"void", 0, st_C_typespec
},
2305 {"interface", C_JAVA
, st_C_struct
},
2307 {"SYSCALL", 0, st_C_gnumacro
},
2309 {"return", 0, st_C_ignore
},
2310 {""}, {""}, {""}, {""}, {""}, {""}, {""},
2311 {"while", 0, st_C_ignore
},
2312 {"auto", 0, st_C_typespec
},
2313 {""}, {""}, {""}, {""}, {""}, {""},
2314 {"float", 0, st_C_typespec
},
2315 {"typedef", 0, st_C_typedef
},
2316 {"typename", C_PLPL
, st_C_typespec
},
2318 {"friend", C_PLPL
, st_C_ignore
},
2319 {"volatile", 0, st_C_typespec
},
2321 {"for", 0, st_C_ignore
},
2322 {"const", 0, st_C_typespec
},
2323 {"import", C_JAVA
, st_C_ignore
},
2325 {"define", 0, st_C_define
},
2326 {"long", 0, st_C_typespec
},
2327 {"implements", C_JAVA
, st_C_javastruct
},
2328 {"signed", 0, st_C_typespec
},
2330 {"extern", 0, st_C_extern
},
2331 {"extends", C_JAVA
, st_C_javastruct
},
2333 {"mutable", C_PLPL
, st_C_typespec
},
2334 {"template", 0, st_C_template
},
2335 {"short", 0, st_C_typespec
},
2336 {"bool", C_PLPL
, st_C_typespec
},
2337 {"char", 0, st_C_typespec
},
2338 {"class", 0, st_C_class
},
2339 {"operator", C_PLPL
, st_C_operator
},
2341 {"switch", 0, st_C_ignore
},
2343 {"ENTRY", 0, st_C_gnumacro
},
2345 {"package", C_JAVA
, st_C_ignore
},
2346 {"union", 0, st_C_struct
},
2347 {"@end", 0, st_C_objend
},
2348 {"struct", 0, st_C_struct
},
2349 {"namespace", C_PLPL
, st_C_struct
},
2351 {"domain", C_STAR
, st_C_struct
},
2352 {"@interface", 0, st_C_objprot
},
2353 {"PSEUDO", 0, st_C_gnumacro
},
2354 {"double", 0, st_C_typespec
},
2356 {"@protocol", 0, st_C_objprot
},
2358 {"static", 0, st_C_typespec
},
2360 {"DEFUN", 0, st_C_gnumacro
},
2361 {""}, {""}, {""}, {""},
2362 {"explicit", C_PLPL
, st_C_typespec
},
2363 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2364 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2366 {"enum", 0, st_C_enum
},
2368 {"unsigned", 0, st_C_typespec
},
2369 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
2370 {"@implementation",0, st_C_objimpl
}
2373 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
2375 register int key
= hash (str
, len
);
2377 if (key
<= MAX_HASH_VALUE
&& key
>= 0)
2379 register const char *s
= wordlist
[key
].name
;
2381 if (*str
== *s
&& !strncmp (str
+ 1, s
+ 1, len
- 1))
2382 return &wordlist
[key
];
2389 static enum sym_type
2390 C_symtype (str
, len
, c_ext
)
2395 register struct C_stab_entry
*se
= in_word_set (str
, len
);
2397 if (se
== NULL
|| (se
->c_ext
&& !(c_ext
& se
->c_ext
)))
2404 * C functions and variables are recognized using a simple
2405 * finite automaton. fvdef is its state variable.
2409 fvnone
, /* nothing seen */
2410 fdefunkey
, /* Emacs DEFUN keyword seen */
2411 fdefunname
, /* Emacs DEFUN name seen */
2412 foperator
, /* func: operator keyword seen (cplpl) */
2413 fvnameseen
, /* function or variable name seen */
2414 fstartlist
, /* func: just after open parenthesis */
2415 finlist
, /* func: in parameter list */
2416 flistseen
, /* func: after parameter list */
2417 fignore
, /* func: before open brace */
2418 vignore
/* var-like: ignore until ';' */
2421 static bool fvextern
; /* func or var: extern keyword seen; */
2424 * typedefs are recognized using a simple finite automaton.
2425 * typdef is its state variable.
2429 tnone
, /* nothing seen */
2430 tkeyseen
, /* typedef keyword seen */
2431 ttypeseen
, /* defined type seen */
2432 tinbody
, /* inside typedef body */
2433 tend
, /* just before typedef tag */
2434 tignore
/* junk after typedef tag */
2438 * struct-like structures (enum, struct and union) are recognized
2439 * using another simple finite automaton. `structdef' is its state
2444 snone
, /* nothing seen yet,
2445 or in struct body if cblev > 0 */
2446 skeyseen
, /* struct-like keyword seen */
2447 stagseen
, /* struct-like tag seen */
2448 sintemplate
, /* inside template (ignore) */
2449 scolonseen
/* colon seen after struct-like tag */
2453 * When objdef is different from onone, objtag is the name of the class.
2455 static char *objtag
= "<uninited>";
2458 * Yet another little state machine to deal with preprocessor lines.
2462 dnone
, /* nothing seen */
2463 dsharpseen
, /* '#' seen as first char on line */
2464 ddefineseen
, /* '#' and 'define' seen */
2465 dignorerest
/* ignore rest of line */
2469 * State machine for Objective C protocols and implementations.
2470 * Idea by Tom R.Hageman <tom@basil.icce.rug.nl> (1995)
2474 onone
, /* nothing seen */
2475 oprotocol
, /* @interface or @protocol seen */
2476 oimplementation
, /* @implementations seen */
2477 otagseen
, /* class name seen */
2478 oparenseen
, /* parenthesis before category seen */
2479 ocatseen
, /* category name seen */
2480 oinbody
, /* in @implementation body */
2481 omethodsign
, /* in @implementation body, after +/- */
2482 omethodtag
, /* after method name */
2483 omethodcolon
, /* after method colon */
2484 omethodparm
, /* after method parameter */
2485 oignore
/* wait for @end */
2490 * Use this structure to keep info about the token read, and how it
2491 * should be tagged. Used by the make_C_tag function to build a tag.
2502 } token
; /* latest token read */
2503 static linebuffer token_name
; /* its name */
2506 * Variables and functions for dealing with nested structures.
2507 * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001)
2509 static void pushclass_above
__P((int, char *, int));
2510 static void popclass_above
__P((int));
2511 static void write_classname
__P((linebuffer
*, char *qualifier
));
2514 char **cname
; /* nested class names */
2515 int *cblev
; /* nested class curly brace level */
2516 int nl
; /* class nesting level (elements used) */
2517 int size
; /* length of the array */
2518 } cstack
; /* stack for nested declaration tags */
2519 /* Current struct nesting depth (namespace, class, struct, union, enum). */
2520 #define nestlev (cstack.nl)
2521 /* After struct keyword or in struct body, not inside an nested function. */
2522 #define instruct (structdef == snone && nestlev > 0 \
2523 && cblev == cstack.cblev[nestlev-1] + 1)
2526 pushclass_above (cblev
, str
, len
)
2533 popclass_above (cblev
);
2535 if (nl
>= cstack
.size
)
2537 int size
= cstack
.size
*= 2;
2538 xrnew (cstack
.cname
, size
, char *);
2539 xrnew (cstack
.cblev
, size
, int);
2541 assert (nl
== 0 || cstack
.cblev
[nl
-1] < cblev
);
2542 cstack
.cname
[nl
] = (str
== NULL
) ? NULL
: savenstr (str
, len
);
2543 cstack
.cblev
[nl
] = cblev
;
2548 popclass_above (cblev
)
2553 for (nl
= cstack
.nl
- 1;
2554 nl
>= 0 && cstack
.cblev
[nl
] >= cblev
;
2557 if (cstack
.cname
[nl
] != NULL
)
2558 free (cstack
.cname
[nl
]);
2564 write_classname (cn
, qualifier
)
2569 int qlen
= strlen (qualifier
);
2571 if (cstack
.nl
== 0 || cstack
.cname
[0] == NULL
)
2575 cn
->buffer
[0] = '\0';
2579 len
= strlen (cstack
.cname
[0]);
2580 linebuffer_setlen (cn
, len
);
2581 strcpy (cn
->buffer
, cstack
.cname
[0]);
2583 for (i
= 1; i
< cstack
.nl
; i
++)
2588 s
= cstack
.cname
[i
];
2593 linebuffer_setlen (cn
, len
);
2594 strncat (cn
->buffer
, qualifier
, qlen
);
2595 strncat (cn
->buffer
, s
, slen
);
2600 static bool consider_token
__P((char *, int, int, int *, int, int, bool *));
2601 static void make_C_tag
__P((bool));
2605 * checks to see if the current token is at the start of a
2606 * function or variable, or corresponds to a typedef, or
2607 * is a struct/union/enum tag, or #define, or an enum constant.
2609 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2610 * with args. C_EXTP points to which language we are looking at.
2621 consider_token (str
, len
, c
, c_extp
, cblev
, parlev
, is_func_or_var
)
2622 register char *str
; /* IN: token pointer */
2623 register int len
; /* IN: token length */
2624 register int c
; /* IN: first char after the token */
2625 int *c_extp
; /* IN, OUT: C extensions mask */
2626 int cblev
; /* IN: curly brace level */
2627 int parlev
; /* IN: parenthesis level */
2628 bool *is_func_or_var
; /* OUT: function or variable found */
2630 /* When structdef is stagseen, scolonseen, or snone with cblev > 0,
2631 structtype is the type of the preceding struct-like keyword, and
2632 structcblev is the curly brace level where it has been seen. */
2633 static enum sym_type structtype
;
2634 static int structcblev
;
2635 static enum sym_type toktype
;
2638 toktype
= C_symtype (str
, len
, *c_extp
);
2641 * Advance the definedef state machine.
2646 /* We're not on a preprocessor line. */
2647 if (toktype
== st_C_gnumacro
)
2654 if (toktype
== st_C_define
)
2656 definedef
= ddefineseen
;
2660 definedef
= dignorerest
;
2665 * Make a tag for any macro, unless it is a constant
2666 * and constantypedefs is FALSE.
2668 definedef
= dignorerest
;
2669 *is_func_or_var
= (c
== '(');
2670 if (!*is_func_or_var
&& !constantypedefs
)
2677 error ("internal error: definedef value.", (char *)NULL
);
2686 if (toktype
== st_C_typedef
)
2708 if (structdef
== snone
&& fvdef
== fvnone
)
2727 * This structdef business is NOT invoked when we are ctags and the
2728 * file is plain C. This is because a struct tag may have the same
2729 * name as another tag, and this loses with ctags.
2733 case st_C_javastruct
:
2734 if (structdef
== stagseen
)
2735 structdef
= scolonseen
;
2740 && (*c_extp
& C_AUTO
) /* automatic detection of C++ language */
2741 && definedef
== dnone
&& structdef
== snone
2742 && typdef
== tnone
&& fvdef
== fvnone
)
2743 *c_extp
= (*c_extp
| C_PLPL
) & ~C_AUTO
;
2744 if (toktype
== st_C_template
)
2751 && (typdef
== tkeyseen
2752 || (typedefs_or_cplusplus
&& structdef
== snone
)))
2754 structdef
= skeyseen
;
2755 structtype
= toktype
;
2756 structcblev
= cblev
;
2761 if (structdef
== skeyseen
)
2763 structdef
= stagseen
;
2767 if (typdef
!= tnone
)
2770 /* Detect Objective C constructs. */
2780 objdef
= oimplementation
;
2784 case oimplementation
:
2785 /* Save the class tag for functions or variables defined inside. */
2786 objtag
= savenstr (str
, len
);
2790 /* Save the class tag for categories. */
2791 objtag
= savenstr (str
, len
);
2793 *is_func_or_var
= TRUE
;
2797 *is_func_or_var
= TRUE
;
2804 objdef
= omethodtag
;
2805 linebuffer_setlen (&token_name
, len
);
2806 strncpy (token_name
.buffer
, str
, len
);
2807 token_name
.buffer
[len
] = '\0';
2813 objdef
= omethodparm
;
2818 objdef
= omethodtag
;
2819 linebuffer_setlen (&token_name
, token_name
.len
+ len
);
2820 strncat (token_name
.buffer
, str
, len
);
2825 if (toktype
== st_C_objend
)
2827 /* Memory leakage here: the string pointed by objtag is
2828 never released, because many tests would be needed to
2829 avoid breaking on incorrect input code. The amount of
2830 memory leaked here is the sum of the lengths of the
2838 /* A function, variable or enum constant? */
2845 if (fvdef
!= finlist
&& fvdef
!= fignore
&& fvdef
!= vignore
)
2846 fvdef
= fvnone
; /* should be useless */
2854 *is_func_or_var
= TRUE
;
2858 && structdef
== snone
2859 && structtype
== st_C_enum
&& cblev
> structcblev
)
2860 return TRUE
; /* enum constant */
2866 fvdef
= fdefunname
; /* GNU macro */
2867 *is_func_or_var
= TRUE
;
2870 if ((strneq (str
, "asm", 3) && endtoken (str
[3]))
2871 || (strneq (str
, "__asm__", 7) && endtoken (str
[7])))
2876 if ((*c_extp
& C_PLPL
) && strneq (str
+len
-10, "::operator", 10))
2879 *is_func_or_var
= TRUE
;
2882 if (cblev
> 0 && !instruct
)
2884 fvdef
= fvnameseen
; /* function or variable */
2885 *is_func_or_var
= TRUE
;
2896 * C_entries often keeps pointers to tokens or lines which are older than
2897 * the line currently read. By keeping two line buffers, and switching
2898 * them at end of line, it is possible to use those pointers.
2906 #define current_lb_is_new (newndx == curndx)
2907 #define switch_line_buffers() (curndx = 1 - curndx)
2909 #define curlb (lbs[curndx].lb)
2910 #define newlb (lbs[newndx].lb)
2911 #define curlinepos (lbs[curndx].linepos)
2912 #define newlinepos (lbs[newndx].linepos)
2914 #define CNL_SAVE_DEFINEDEF() \
2916 curlinepos = charno; \
2918 linecharno = charno; \
2919 charno += readline (&curlb, inf); \
2920 lp = curlb.buffer; \
2927 CNL_SAVE_DEFINEDEF(); \
2928 if (savetoken.valid) \
2930 token = savetoken; \
2931 savetoken.valid = FALSE; \
2933 definedef = dnone; \
2941 /* This function should never be called when token.valid is FALSE, but
2942 we must protect against invalid input or internal errors. */
2943 if (DEBUG
|| token
.valid
)
2945 if (traditional_tag_style
)
2947 /* This was the original code. Now we call new_pfnote instead,
2948 which uses the new method for naming tags (see new_pfnote). */
2951 if (CTAGS
|| token
.named
)
2952 name
= savestr (token_name
.buffer
);
2953 if (DEBUG
&& !token
.valid
)
2956 name
= concat (name
, "##invalid##", "");
2958 name
= savestr ("##invalid##");
2960 pfnote (name
, isfun
, token
.line
,
2961 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
2964 new_pfnote (token_name
.buffer
, token_name
.len
, isfun
, token
.line
,
2965 token
.offset
+token
.length
+1, token
.lineno
, token
.linepos
);
2966 token
.valid
= FALSE
;
2973 * This routine finds functions, variables, typedefs,
2974 * #define's, enum constants and struct/union/enum definitions in
2975 * C syntax and adds them to the list.
2978 C_entries (c_ext
, inf
)
2979 int c_ext
; /* extension of C */
2980 FILE *inf
; /* input file */
2982 register char c
; /* latest char read; '\0' for end of line */
2983 register char *lp
; /* pointer one beyond the character `c' */
2984 int curndx
, newndx
; /* indices for current and new lb */
2985 register int tokoff
; /* offset in line of start of current token */
2986 register int toklen
; /* length of current token */
2987 char *qualifier
; /* string used to qualify names */
2988 int qlen
; /* length of qualifier */
2989 int cblev
; /* current curly brace level */
2990 int parlev
; /* current parenthesis level */
2991 int typdefcblev
; /* cblev where a typedef struct body begun */
2992 bool incomm
, inquote
, inchar
, quotednl
, midtoken
;
2994 bool yacc_rules
; /* in the rules part of a yacc file */
2995 struct tok savetoken
; /* token saved during preprocessor handling */
2998 initbuffer (&token_name
);
2999 initbuffer (&lbs
[0].lb
);
3000 initbuffer (&lbs
[1].lb
);
3001 if (cstack
.size
== 0)
3003 cstack
.size
= (DEBUG
) ? 1 : 4;
3005 cstack
.cname
= xnew (cstack
.size
, char *);
3006 cstack
.cblev
= xnew (cstack
.size
, int);
3009 tokoff
= toklen
= typdefcblev
= 0; /* keep compiler quiet */
3010 curndx
= newndx
= 0;
3016 fvdef
= fvnone
; fvextern
= FALSE
; typdef
= tnone
;
3017 structdef
= snone
; definedef
= dnone
; objdef
= onone
;
3019 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3020 token
.valid
= savetoken
.valid
= FALSE
;
3023 cplpl
= (c_ext
& C_PLPL
) == C_PLPL
;
3024 cjava
= (c_ext
& C_JAVA
) == C_JAVA
;
3026 { qualifier
= "."; qlen
= 1; }
3028 { qualifier
= "::"; qlen
= 2; }
3036 /* If we're at the end of the line, the next character is a
3037 '\0'; don't skip it, because it's the thing that tells us
3038 to read the next line. */
3059 /* Newlines inside comments do not end macro definitions in
3061 CNL_SAVE_DEFINEDEF ();
3074 /* Newlines inside strings do not end macro definitions
3075 in traditional cpp, even though compilers don't
3076 usually accept them. */
3077 CNL_SAVE_DEFINEDEF ();
3087 /* Hmmm, something went wrong. */
3116 if (fvdef
!= finlist
&& fvdef
!= fignore
&& fvdef
!=vignore
)
3129 else if (/* cplpl && */ *lp
== '/')
3137 if ((c_ext
& YACC
) && *lp
== '%')
3139 /* Entering or exiting rules section in yacc file. */
3141 definedef
= dnone
; fvdef
= fvnone
; fvextern
= FALSE
;
3142 typdef
= tnone
; structdef
= snone
;
3143 midtoken
= inquote
= inchar
= incomm
= quotednl
= FALSE
;
3145 yacc_rules
= !yacc_rules
;
3151 if (definedef
== dnone
)
3154 bool cpptoken
= TRUE
;
3156 /* Look back on this line. If all blanks, or nonblanks
3157 followed by an end of comment, this is a preprocessor
3159 for (cp
= newlb
.buffer
; cp
< lp
-1; cp
++)
3162 if (*cp
== '*' && *(cp
+1) == '/')
3171 definedef
= dsharpseen
;
3172 } /* if (definedef == dnone) */
3178 /* Consider token only if some involved conditions are satisfied. */
3179 if (typdef
!= tignore
3180 && definedef
!= dignorerest
3182 && structdef
!= sintemplate
3183 && (definedef
!= dnone
3184 || structdef
!= scolonseen
))
3190 if (c
== ':' && cplpl
&& *lp
== ':' && begtoken (lp
[1]))
3193 * This handles :: in the middle, but not at the
3194 * beginning of an identifier. Also, space-separated
3195 * :: is not recognised.
3200 goto still_in_token
;
3204 bool funorvar
= FALSE
;
3207 || consider_token (newlb
.buffer
+ tokoff
, toklen
, c
,
3208 &c_ext
, cblev
, parlev
, &funorvar
))
3210 if (fvdef
== foperator
)
3213 lp
= skip_spaces (lp
-1);
3217 && !iswhite (*lp
) && *lp
!= '(')
3220 toklen
+= lp
- oldlp
;
3222 token
.named
= FALSE
;
3223 if ((c_ext
& C_EXT
) /* not pure C */
3224 && nestlev
> 0 && definedef
== dnone
)
3225 /* in struct body */
3227 write_classname (&token_name
, qualifier
);
3228 linebuffer_setlen (&token_name
,
3229 token_name
.len
+qlen
+toklen
);
3230 strcat (token_name
.buffer
, qualifier
);
3231 strncat (token_name
.buffer
,
3232 newlb
.buffer
+ tokoff
, toklen
);
3235 else if (objdef
== ocatseen
)
3236 /* Objective C category */
3238 int len
= strlen (objtag
) + 2 + toklen
;
3239 linebuffer_setlen (&token_name
, len
);
3240 strcpy (token_name
.buffer
, objtag
);
3241 strcat (token_name
.buffer
, "(");
3242 strncat (token_name
.buffer
,
3243 newlb
.buffer
+ tokoff
, toklen
);
3244 strcat (token_name
.buffer
, ")");
3247 else if (objdef
== omethodtag
3248 || objdef
== omethodparm
)
3249 /* Objective C method */
3253 else if (fvdef
== fdefunname
)
3254 /* GNU DEFUN and similar macros */
3256 bool defun
= (newlb
.buffer
[tokoff
] == 'F');
3260 /* Rewrite the tag so that emacs lisp DEFUNs
3261 can be found by their elisp name */
3268 linebuffer_setlen (&token_name
, len
);
3269 strncpy (token_name
.buffer
,
3270 newlb
.buffer
+ off
, len
);
3271 token_name
.buffer
[len
] = '\0';
3274 if (token_name
.buffer
[len
] == '_')
3275 token_name
.buffer
[len
] = '-';
3276 token
.named
= defun
;
3280 linebuffer_setlen (&token_name
, toklen
);
3281 strncpy (token_name
.buffer
,
3282 newlb
.buffer
+ tokoff
, toklen
);
3283 token_name
.buffer
[toklen
] = '\0';
3284 /* Name macros and members. */
3285 token
.named
= (structdef
== stagseen
3286 || typdef
== ttypeseen
3289 && definedef
== dignorerest
)
3291 && definedef
== dnone
3292 && structdef
== snone
3295 token
.lineno
= lineno
;
3296 token
.offset
= tokoff
;
3297 token
.length
= toklen
;
3298 token
.line
= newlb
.buffer
;
3299 token
.linepos
= newlinepos
;
3302 if (definedef
== dnone
3303 && (fvdef
== fvnameseen
3304 || fvdef
== foperator
3305 || structdef
== stagseen
3307 || typdef
== ttypeseen
3308 || objdef
!= onone
))
3310 if (current_lb_is_new
)
3311 switch_line_buffers ();
3313 else if (definedef
!= dnone
3314 || fvdef
== fdefunname
3316 make_C_tag (funorvar
);
3320 } /* if (endtoken (c)) */
3321 else if (intoken (c
))
3327 } /* if (midtoken) */
3328 else if (begtoken (c
))
3339 make_C_tag (TRUE
); /* a function */
3346 if (structdef
== stagseen
&& !cjava
)
3348 popclass_above (cblev
);
3355 if (!yacc_rules
|| lp
== newlb
.buffer
+ 1)
3357 tokoff
= lp
- 1 - newlb
.buffer
;
3362 } /* if (begtoken) */
3363 } /* if must look at token */
3366 /* Detect end of line, colon, comma, semicolon and various braces
3367 after having handled a token.*/
3371 if (yacc_rules
&& token
.offset
== 0 && token
.valid
)
3373 make_C_tag (FALSE
); /* a yacc function */
3376 if (definedef
!= dnone
)
3382 make_C_tag (TRUE
); /* an Objective C class */
3386 objdef
= omethodcolon
;
3387 linebuffer_setlen (&token_name
, token_name
.len
+ 1);
3388 strcat (token_name
.buffer
, ":");
3391 if (structdef
== stagseen
)
3392 structdef
= scolonseen
;
3395 if (definedef
!= dnone
)
3401 make_C_tag (FALSE
); /* a typedef */
3411 if (typdef
== tignore
)
3415 if ((globals
&& cblev
== 0 && (!fvextern
|| declarations
))
3416 || (members
&& instruct
))
3417 make_C_tag (FALSE
); /* a variable */
3420 token
.valid
= FALSE
;
3423 if ((declarations
&& typdef
== tnone
&& !instruct
)
3424 || (members
&& typdef
!= tignore
&& instruct
))
3425 make_C_tag (TRUE
); /* a function declaration */
3431 && structdef
== stagseen
&& (c_ext
& C_PLPL
))
3432 make_C_tag (FALSE
); /* forward declaration */
3434 /* The following instruction invalidates the token.
3435 Probably the token should be invalidated in all other
3436 cases where some state machine is reset prematurely. */
3437 token
.valid
= FALSE
;
3438 } /* switch (fvdef) */
3444 if (structdef
== stagseen
)
3448 if (definedef
!= dnone
)
3454 make_C_tag (TRUE
); /* an Objective C method */
3470 case fvnameseen
: /* a variable */
3471 if ((globals
&& cblev
== 0 && (!fvextern
|| declarations
))
3472 || (members
&& instruct
))
3475 case flistseen
: /* a function */
3476 if ((declarations
&& typdef
== tnone
&& !instruct
)
3477 || (members
&& typdef
!= tignore
&& instruct
))
3479 make_C_tag (TRUE
); /* a function declaration */
3482 else if (!declarations
)
3484 token
.valid
= FALSE
;
3489 if (structdef
== stagseen
)
3493 if (definedef
!= dnone
)
3495 if (structdef
== stagseen
)
3502 make_C_tag (FALSE
); /* a typedef */
3514 if ((members
&& cblev
== 1)
3515 || (globals
&& cblev
== 0
3516 && (!fvextern
|| declarations
)))
3517 make_C_tag (FALSE
); /* a variable */
3526 if (definedef
!= dnone
)
3528 if (objdef
== otagseen
&& parlev
== 0)
3529 objdef
= oparenseen
;
3533 if (typdef
== ttypeseen
3537 /* This handles constructs like:
3538 typedef void OperatorFun (int fun); */
3555 if (definedef
!= dnone
)
3557 if (objdef
== ocatseen
&& parlev
== 1)
3559 make_C_tag (TRUE
); /* an Objective C category */
3573 || typdef
== ttypeseen
))
3576 make_C_tag (FALSE
); /* a typedef */
3579 else if (parlev
< 0) /* can happen due to ill-conceived #if's. */
3583 if (definedef
!= dnone
)
3585 if (typdef
== ttypeseen
)
3587 /* Whenever typdef is set to tinbody (currently only
3588 here), typdefcblev should be set to cblev. */
3590 typdefcblev
= cblev
;
3595 make_C_tag (TRUE
); /* a function */
3604 make_C_tag (TRUE
); /* an Objective C class */
3609 make_C_tag (TRUE
); /* an Objective C method */
3613 /* Neutralize `extern "C" {' grot. */
3614 if (cblev
== 0 && structdef
== snone
&& nestlev
== 0
3621 case skeyseen
: /* unnamed struct */
3622 pushclass_above (cblev
, NULL
, 0);
3625 case stagseen
: /* named struct or enum */
3626 case scolonseen
: /* a class */
3627 pushclass_above (cblev
, token
.line
+token
.offset
, token
.length
);
3629 make_C_tag (FALSE
); /* a struct or enum */
3635 if (definedef
!= dnone
)
3637 if (fvdef
== fstartlist
)
3638 fvdef
= fvnone
; /* avoid tagging `foo' in `foo (*bar()) ()' */
3641 if (definedef
!= dnone
)
3643 if (!noindentypedefs
&& lp
== newlb
.buffer
+ 1)
3645 cblev
= 0; /* reset curly brace level if first column */
3646 parlev
= 0; /* also reset paren level, just in case... */
3650 popclass_above (cblev
);
3652 /* Only if typdef == tinbody is typdefcblev significant. */
3653 if (typdef
== tinbody
&& cblev
<= typdefcblev
)
3655 assert (cblev
== typdefcblev
);
3660 if (definedef
!= dnone
)
3670 if ((members
&& cblev
== 1)
3671 || (globals
&& cblev
== 0 && (!fvextern
|| declarations
)))
3672 make_C_tag (FALSE
); /* a variable */
3679 if (cplpl
&& structdef
== stagseen
)
3681 structdef
= sintemplate
;
3686 if (structdef
== sintemplate
)
3688 structdef
= stagseen
;
3694 if (objdef
== oinbody
&& cblev
== 0)
3696 objdef
= omethodsign
;
3701 case '#': case '~': case '&': case '%': case '/': case '|':
3702 case '^': case '!': case '.': case '?': case ']':
3703 if (definedef
!= dnone
)
3705 /* These surely cannot follow a function tag in C. */
3718 if (objdef
== otagseen
)
3720 make_C_tag (TRUE
); /* an Objective C class */
3723 /* If a macro spans multiple lines don't reset its state. */
3725 CNL_SAVE_DEFINEDEF ();
3731 } /* while not eof */
3733 free (token_name
.buffer
);
3734 free (lbs
[0].lb
.buffer
);
3735 free (lbs
[1].lb
.buffer
);
3739 * Process either a C++ file or a C file depending on the setting
3743 default_C_entries (inf
)
3746 C_entries (cplusplus
? C_PLPL
: C_AUTO
, inf
);
3749 /* Always do plain C. */
3751 plain_C_entries (inf
)
3757 /* Always do C++. */
3759 Cplusplus_entries (inf
)
3762 C_entries (C_PLPL
, inf
);
3765 /* Always do Java. */
3770 C_entries (C_JAVA
, inf
);
3778 C_entries (C_STAR
, inf
);
3781 /* Always do Yacc. */
3786 C_entries (YACC
, inf
);
3790 /* Useful macros. */
3791 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3792 for (lineno = charno = 0; /* loop initialization */ \
3793 !feof (file_pointer) /* loop test */ \
3794 && (lineno++, /* instructions at start of loop */ \
3795 linecharno = charno, \
3796 charno += readline (&line_buffer, file_pointer), \
3797 char_pointer = lb.buffer, \
3800 #define LOOKING_AT(cp, keyword) /* keyword is a constant string */ \
3801 (strneq ((cp), keyword, sizeof(keyword)-1) /* cp points at keyword */ \
3802 && notinname ((cp)[sizeof(keyword)-1]) /* end of keyword */ \
3803 && ((cp) = skip_spaces((cp)+sizeof(keyword)-1))) /* skip spaces */
3806 * Read a file, but do no processing. This is used to do regexp
3807 * matching on files that have no language defined.
3810 just_read_file (inf
)
3813 register char *dummy
;
3815 LOOP_ON_INPUT_LINES (inf
, lb
, dummy
)
3820 /* Fortran parsing */
3822 static void F_takeprec
__P((void));
3823 static void F_getit
__P((FILE *));
3828 dbp
= skip_spaces (dbp
);
3832 dbp
= skip_spaces (dbp
);
3833 if (strneq (dbp
, "(*)", 3))
3838 if (!ISDIGIT (*dbp
))
3840 --dbp
; /* force failure */
3845 while (ISDIGIT (*dbp
));
3854 dbp
= skip_spaces (dbp
);
3858 linecharno
= charno
;
3859 charno
+= readline (&lb
, inf
);
3864 dbp
= skip_spaces (dbp
);
3866 if (!ISALPHA (*dbp
) && *dbp
!= '_' && *dbp
!= '$')
3868 for (cp
= dbp
+ 1; *cp
!= '\0' && intoken (*cp
); cp
++)
3870 pfnote (savenstr (dbp
, cp
-dbp
), TRUE
,
3871 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
3876 Fortran_functions (inf
)
3879 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
3882 dbp
++; /* Ratfor escape to fortran */
3883 dbp
= skip_spaces (dbp
);
3886 switch (lowcase (*dbp
))
3889 if (nocase_tail ("integer"))
3893 if (nocase_tail ("real"))
3897 if (nocase_tail ("logical"))
3901 if (nocase_tail ("complex") || nocase_tail ("character"))
3905 if (nocase_tail ("double"))
3907 dbp
= skip_spaces (dbp
);
3910 if (nocase_tail ("precision"))
3916 dbp
= skip_spaces (dbp
);
3919 switch (lowcase (*dbp
))
3922 if (nocase_tail ("function"))
3926 if (nocase_tail ("subroutine"))
3930 if (nocase_tail ("entry"))
3934 if (nocase_tail ("blockdata") || nocase_tail ("block data"))
3936 dbp
= skip_spaces (dbp
);
3937 if (*dbp
== '\0') /* assume un-named */
3938 pfnote (savestr ("blockdata"), TRUE
,
3939 lb
.buffer
, dbp
- lb
.buffer
, lineno
, linecharno
);
3941 F_getit (inf
); /* look for name */
3952 * Philippe Waroquiers <philippe.waroquiers@eurocontrol.be> (1998)
3955 static void Ada_getit
__P((FILE *, char *));
3957 /* Once we are positioned after an "interesting" keyword, let's get
3958 the real tag value necessary. */
3960 Ada_getit (inf
, name_qualifier
)
3962 char *name_qualifier
;
3970 dbp
= skip_spaces (dbp
);
3972 || (dbp
[0] == '-' && dbp
[1] == '-'))
3975 linecharno
= charno
;
3976 charno
+= readline (&lb
, inf
);
3979 switch (lowcase(*dbp
))
3982 if (nocase_tail ("body"))
3984 /* Skipping body of procedure body or package body or ....
3985 resetting qualifier to body instead of spec. */
3986 name_qualifier
= "/b";
3991 /* Skipping type of task type or protected type ... */
3992 if (nocase_tail ("type"))
3999 for (cp
= dbp
; *cp
!= '\0' && *cp
!= '"'; cp
++)
4004 dbp
= skip_spaces (dbp
);
4007 && (ISALPHA (*cp
) || ISDIGIT (*cp
) || *cp
== '_' || *cp
== '.'));
4015 name
= concat (dbp
, name_qualifier
, "");
4017 pfnote (name
, TRUE
, lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4028 bool inquote
= FALSE
;
4030 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4032 while (*dbp
!= '\0')
4034 /* Skip a string i.e. "abcd". */
4035 if (inquote
|| (*dbp
== '"'))
4037 dbp
= etags_strchr ((inquote
) ? dbp
: dbp
+1, '"');
4042 continue; /* advance char */
4047 break; /* advance line */
4051 /* Skip comments. */
4052 if (dbp
[0] == '-' && dbp
[1] == '-')
4053 break; /* advance line */
4055 /* Skip character enclosed in single quote i.e. 'a'
4056 and skip single quote starting an attribute i.e. 'Image. */
4065 /* Search for beginning of a token. */
4066 if (!begtoken (*dbp
))
4069 continue; /* advance char */
4072 /* We are at the beginning of a token. */
4073 switch (lowcase(*dbp
))
4076 if (!packages_only
&& nocase_tail ("function"))
4077 Ada_getit (inf
, "/f");
4079 break; /* from switch */
4080 continue; /* advance char */
4082 if (!packages_only
&& nocase_tail ("procedure"))
4083 Ada_getit (inf
, "/p");
4084 else if (nocase_tail ("package"))
4085 Ada_getit (inf
, "/s");
4086 else if (nocase_tail ("protected")) /* protected type */
4087 Ada_getit (inf
, "/t");
4089 break; /* from switch */
4090 continue; /* advance char */
4092 if (!packages_only
&& nocase_tail ("task"))
4093 Ada_getit (inf
, "/k");
4094 else if (typedefs
&& !packages_only
&& nocase_tail ("type"))
4096 Ada_getit (inf
, "/t");
4097 while (*dbp
!= '\0')
4101 break; /* from switch */
4102 continue; /* advance char */
4105 /* Look for the end of the token. */
4106 while (!endtoken (*dbp
))
4109 } /* advance char */
4110 } /* advance line */
4115 * Unix and microcontroller assembly tag handling
4116 * Labels: /^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]/
4117 * Idea by Bob Weiner, Motorola Inc. (1994)
4125 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4127 /* If first char is alphabetic or one of [_.$], test for colon
4128 following identifier. */
4129 if (ISALPHA (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4131 /* Read past label. */
4133 while (ISALNUM (*cp
) || *cp
== '_' || *cp
== '.' || *cp
== '$')
4135 if (*cp
== ':' || iswhite (*cp
))
4137 /* Found end of label, so copy it and add it to the table. */
4138 pfnote (savenstr(lb
.buffer
, cp
-lb
.buffer
), TRUE
,
4139 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4148 * Perl sub names: /^sub[ \t\n]+[^ \t\n{]+/
4149 * Perl variable names: /^(my|local).../
4150 * Original code by Bart Robinson <lomew@cs.utah.edu> (1995)
4151 * Additions by Michael Ernst <mernst@alum.mit.edu> (1997)
4152 * Ideas by Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE> (2001)
4155 Perl_functions (inf
)
4158 char *package
= savestr ("main"); /* current package name */
4161 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4165 if (LOOKING_AT (cp
, "package"))
4168 package
= get_tag (cp
);
4169 if (package
== NULL
) /* can't parse package name */
4170 package
= savestr ("");
4172 package
= savestr(package
); /* make a copy */
4174 else if (LOOKING_AT (cp
, "sub"))
4176 char *name
, *fullname
, *pos
;
4179 while (!notinname (*cp
))
4183 name
= savenstr (sp
, cp
-sp
);
4184 if ((pos
= etags_strchr (name
, ':')) != NULL
&& pos
[1] == ':')
4187 fullname
= concat (package
, "::", name
);
4188 pfnote (fullname
, TRUE
,
4189 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4190 if (name
!= fullname
)
4193 else if (globals
/* only if tagging global vars is enabled */
4194 && (LOOKING_AT (cp
, "my") || LOOKING_AT (cp
, "local")))
4196 /* After "my" or "local", but before any following paren or space. */
4197 char *varname
= NULL
;
4199 if (*cp
== '$' || *cp
== '@' || *cp
== '%')
4201 char* varstart
= ++cp
;
4202 while (ISALNUM (*cp
) || *cp
== '_')
4204 varname
= savenstr (varstart
, cp
-varstart
);
4208 /* Should be examining a variable list at this point;
4209 could insist on seeing an open parenthesis. */
4210 while (*cp
!= '\0' && *cp
!= ';' && *cp
!= '=' && *cp
!= ')')
4214 /* Perhaps I should back cp up one character, so the TAGS table
4215 doesn't mention (and so depend upon) the following char. */
4216 pfnote (varname
, FALSE
,
4217 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4225 * Look for /^[\t]*def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
4226 * Idea by Eric S. Raymond <esr@thyrsus.com> (1997)
4227 * More ideas by seb bacon <seb@jamkit.com> (2002)
4230 Python_functions (inf
)
4235 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4237 cp
= skip_spaces (cp
);
4238 if (LOOKING_AT (cp
, "def") || LOOKING_AT (cp
, "class"))
4241 while (!notinname (*cp
) && *cp
!= ':')
4243 pfnote (savenstr (name
, cp
-name
), TRUE
,
4244 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4253 * - /^[ \t]*function[ \t\n]+[^ \t\n(]+/
4254 * - /^[ \t]*class[ \t\n]+[^ \t\n]+/
4255 * - /^[ \t]*define\(\"[^\"]+/
4256 * Only with --members:
4257 * - /^[ \t]*var[ \t\n]+\$[^ \t\n=;]/
4258 * Idea by Diez B. Roggisch (2001)
4264 register char *cp
, *name
;
4265 bool search_identifier
= FALSE
;
4267 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4269 cp
= skip_spaces (cp
);
4271 if (search_identifier
4274 while (!notinname (*cp
))
4276 pfnote (savenstr (name
, cp
-name
), TRUE
,
4277 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4278 search_identifier
= FALSE
;
4280 else if (LOOKING_AT (cp
, "function"))
4283 cp
= skip_spaces (cp
+1);
4287 while (!notinname (*cp
))
4289 pfnote (savenstr (name
, cp
-name
), TRUE
,
4290 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4293 search_identifier
= TRUE
;
4295 else if (LOOKING_AT (cp
, "class"))
4300 while (*cp
!= '\0' && !iswhite (*cp
))
4302 pfnote (savenstr (name
, cp
-name
), FALSE
,
4303 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4306 search_identifier
= TRUE
;
4308 else if (strneq (cp
, "define", 6)
4309 && (cp
= skip_spaces (cp
+6))
4311 && (*cp
== '"' || *cp
== '\''))
4315 while (*cp
!= quote
&& *cp
!= '\0')
4317 pfnote (savenstr (name
, cp
-name
), FALSE
,
4318 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4321 && LOOKING_AT (cp
, "var")
4325 while (!notinname(*cp
))
4327 pfnote (savenstr (name
, cp
-name
), FALSE
,
4328 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4335 * Cobol tag functions
4336 * We could look for anything that could be a paragraph name.
4337 * i.e. anything that starts in column 8 is one word and ends in a full stop.
4338 * Idea by Corny de Souza (1993)
4341 Cobol_paragraphs (inf
)
4344 register char *bp
, *ep
;
4346 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4352 /* If eoln, compiler option or comment ignore whole line. */
4353 if (bp
[-1] != ' ' || !ISALNUM (bp
[0]))
4356 for (ep
= bp
; ISALNUM (*ep
) || *ep
== '-'; ep
++)
4359 pfnote (savenstr (bp
, ep
-bp
), TRUE
,
4360 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
4367 * Idea by Assar Westerlund <assar@sics.se> (2001)
4370 Makefile_targets (inf
)
4375 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4377 if (*bp
== '\t' || *bp
== '#')
4379 while (*bp
!= '\0' && *bp
!= '=' && *bp
!= ':')
4382 pfnote (savenstr (lb
.buffer
, bp
- lb
.buffer
), TRUE
,
4383 lb
.buffer
, bp
- lb
.buffer
+ 1, lineno
, linecharno
);
4390 * Original code by Mosur K. Mohan (1989)
4392 * Locates tags for procedures & functions. Doesn't do any type- or
4393 * var-definitions. It does look for the keyword "extern" or
4394 * "forward" immediately following the procedure statement; if found,
4395 * the tag is skipped.
4398 Pascal_functions (inf
)
4401 linebuffer tline
; /* mostly copied from C_entries */
4403 int save_lineno
, save_len
;
4404 char c
, *cp
, *namebuf
;
4406 bool /* each of these flags is TRUE iff: */
4407 incomment
, /* point is inside a comment */
4408 inquote
, /* point is inside '..' string */
4409 get_tagname
, /* point is after PROCEDURE/FUNCTION
4410 keyword, so next item = potential tag */
4411 found_tag
, /* point is after a potential tag */
4412 inparms
, /* point is within parameter-list */
4413 verify_tag
; /* point has passed the parm-list, so the
4414 next token will determine whether this
4415 is a FORWARD/EXTERN to be ignored, or
4416 whether it is a real tag */
4418 save_lcno
= save_lineno
= save_len
= 0; /* keep compiler quiet */
4419 namebuf
= NULL
; /* keep compiler quiet */
4424 initbuffer (&tline
);
4426 incomment
= inquote
= FALSE
;
4427 found_tag
= FALSE
; /* have a proc name; check if extern */
4428 get_tagname
= FALSE
; /* have found "procedure" keyword */
4429 inparms
= FALSE
; /* found '(' after "proc" */
4430 verify_tag
= FALSE
; /* check if "extern" is ahead */
4433 while (!feof (inf
)) /* long main loop to get next char */
4436 if (c
== '\0') /* if end of line */
4439 linecharno
= charno
;
4440 charno
+= readline (&lb
, inf
);
4444 if (!((found_tag
&& verify_tag
)
4446 c
= *dbp
++; /* only if don't need *dbp pointing
4447 to the beginning of the name of
4448 the procedure or function */
4452 if (c
== '}') /* within { } comments */
4454 else if (c
== '*' && *dbp
== ')') /* within (* *) comments */
4471 inquote
= TRUE
; /* found first quote */
4473 case '{': /* found open { comment */
4477 if (*dbp
== '*') /* found open (* comment */
4482 else if (found_tag
) /* found '(' after tag, i.e., parm-list */
4485 case ')': /* end of parms list */
4490 if (found_tag
&& !inparms
) /* end of proc or fn stmt */
4497 if (found_tag
&& verify_tag
&& (*dbp
!= ' '))
4499 /* check if this is an "extern" declaration */
4502 if (lowcase (*dbp
== 'e'))
4504 if (nocase_tail ("extern")) /* superfluous, really! */
4510 else if (lowcase (*dbp
) == 'f')
4512 if (nocase_tail ("forward")) /* check for forward reference */
4518 if (found_tag
&& verify_tag
) /* not external proc, so make tag */
4522 pfnote (namebuf
, TRUE
,
4523 tline
.buffer
, save_len
, save_lineno
, save_lcno
);
4527 if (get_tagname
) /* grab name of proc or fn */
4532 /* save all values for later tagging */
4533 linebuffer_setlen (&tline
, lb
.len
);
4534 strcpy (tline
.buffer
, lb
.buffer
);
4535 save_lineno
= lineno
;
4536 save_lcno
= linecharno
;
4538 /* grab block name */
4539 for (cp
= dbp
+ 1; *cp
!= '\0' && !endtoken (*cp
); cp
++)
4541 namebuf
= savenstr (dbp
, cp
-dbp
);
4542 dbp
= cp
; /* set dbp to e-o-token */
4543 save_len
= dbp
- lb
.buffer
+ 1;
4544 get_tagname
= FALSE
;
4548 /* and proceed to check for "extern" */
4550 else if (!incomment
&& !inquote
&& !found_tag
)
4552 /* check for proc/fn keywords */
4553 switch (lowcase (c
))
4556 if (nocase_tail ("rocedure")) /* c = 'p', dbp has advanced */
4560 if (nocase_tail ("unction"))
4565 } /* while not eof */
4567 free (tline
.buffer
);
4572 * Lisp tag functions
4573 * look for (def or (DEF, quote or QUOTE
4576 static void L_getit
__P((void));
4581 if (*dbp
== '\'') /* Skip prefix quote */
4583 else if (*dbp
== '(')
4586 /* Try to skip "(quote " */
4587 if (!LOOKING_AT (dbp
, "quote") && !LOOKING_AT (dbp
, "QUOTE"))
4588 /* Ok, then skip "(" before name in (defstruct (foo)) */
4589 dbp
= skip_spaces (dbp
);
4595 Lisp_functions (inf
)
4598 LOOP_ON_INPUT_LINES (inf
, lb
, dbp
)
4603 if (strneq (dbp
+1, "def", 3) || strneq (dbp
+1, "DEF", 3))
4605 dbp
= skip_non_spaces (dbp
);
4606 dbp
= skip_spaces (dbp
);
4611 /* Check for (foo::defmumble name-defined ... */
4614 while (!notinname (*dbp
) && *dbp
!= ':');
4619 while (*dbp
== ':');
4621 if (strneq (dbp
, "def", 3) || strneq (dbp
, "DEF", 3))
4623 dbp
= skip_non_spaces (dbp
);
4624 dbp
= skip_spaces (dbp
);
4634 * Postscript tag functions
4635 * Just look for lines where the first character is '/'
4636 * Also look at "defineps" for PSWrap
4638 * Richard Mlynarik <mly@adoc.xerox.com> (1997)
4639 * Masatake Yamato <masata-y@is.aist-nara.ac.jp> (1999)
4642 Postscript_functions (inf
)
4645 register char *bp
, *ep
;
4647 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4652 *ep
!= '\0' && *ep
!= ' ' && *ep
!= '{';
4655 pfnote (savenstr (bp
, ep
-bp
), TRUE
,
4656 lb
.buffer
, ep
- lb
.buffer
+ 1, lineno
, linecharno
);
4658 else if (LOOKING_AT (bp
, "defineps"))
4665 * Scheme tag functions
4666 * look for (def... xyzzy
4668 * (def ... ((...(xyzzy ....
4670 * Original code by Ken Haase (1985?)
4674 Scheme_functions (inf
)
4679 LOOP_ON_INPUT_LINES (inf
, lb
, bp
)
4681 if (strneq (bp
, "(def", 4) || strneq (bp
, "(DEF", 4))
4683 bp
= skip_non_spaces (bp
+4);
4684 /* Skip over open parens and white space */
4685 while (notinname (*bp
))
4689 if (LOOKING_AT (bp
, "(SET!") || LOOKING_AT (bp
, "(set!"))
4695 /* Find tags in TeX and LaTeX input files. */
4697 /* TEX_toktab is a table of TeX control sequences that define tags.
4698 Each TEX_tabent records one such control sequence.
4699 CONVERT THIS TO USE THE Stab TYPE!! */
4706 static struct TEX_tabent
*TEX_toktab
= NULL
; /* Table with tag tokens */
4708 /* Default set of control sequences to put into TEX_toktab.
4709 The value of environment var TEXTAGS is prepended to this. */
4711 static char *TEX_defenv
= "\
4712 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4713 :part:appendix:entry:index";
4715 static void TEX_mode
__P((FILE *));
4716 static struct TEX_tabent
*TEX_decode_env
__P((char *, char *));
4717 static int TEX_Token
__P((char *));
4719 static char TEX_esc
= '\\';
4720 static char TEX_opgrp
= '{';
4721 static char TEX_clgrp
= '}';
4724 * TeX/LaTeX scanning loop.
4733 /* Select either \ or ! as escape character. */
4736 /* Initialize token table once from environment. */
4738 TEX_toktab
= TEX_decode_env ("TEXTAGS", TEX_defenv
);
4740 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4743 /* Look at each esc in line. */
4744 while ((cp
= etags_strchr (cp
, TEX_esc
)) != NULL
)
4748 linecharno
+= cp
- lasthit
;
4750 i
= TEX_Token (lasthit
);
4754 for (lasthit
+= TEX_toktab
[i
].len
;
4755 *lasthit
== TEX_esc
|| *lasthit
== TEX_opgrp
;
4759 !iswhite (*p
) && *p
!= TEX_opgrp
&& *p
!= TEX_clgrp
;
4762 pfnote (savenstr (lasthit
, p
-lasthit
), TRUE
,
4763 lb
.buffer
, lb
.len
, lineno
, linecharno
);
4764 break; /* We only tag a line once */
4770 #define TEX_LESC '\\'
4771 #define TEX_SESC '!'
4774 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4775 chars accordingly. */
4782 while ((c
= getc (inf
)) != EOF
)
4784 /* Skip to next line if we hit the TeX comment char. */
4788 else if (c
== TEX_LESC
|| c
== TEX_SESC
)
4804 /* If the input file is compressed, inf is a pipe, and rewind may fail.
4805 No attempt is made to correct the situation. */
4809 /* Read environment and prepend it to the default string.
4810 Build token table. */
4811 static struct TEX_tabent
*
4812 TEX_decode_env (evarname
, defenv
)
4816 register char *env
, *p
;
4818 struct TEX_tabent
*tab
;
4821 /* Append default string to environment. */
4822 env
= getenv (evarname
);
4828 env
= concat (oldenv
, defenv
, "");
4831 /* Allocate a token table */
4832 for (size
= 1, p
= env
; p
;)
4833 if ((p
= etags_strchr (p
, ':')) && *++p
!= '\0')
4835 /* Add 1 to leave room for null terminator. */
4836 tab
= xnew (size
+ 1, struct TEX_tabent
);
4838 /* Unpack environment string into token table. Be careful about */
4839 /* zero-length strings (leading ':', "::" and trailing ':') */
4842 p
= etags_strchr (env
, ':');
4843 if (!p
) /* End of environment string. */
4844 p
= env
+ strlen (env
);
4846 { /* Only non-zero strings. */
4847 tab
[i
].name
= savenstr (env
, p
- env
);
4848 tab
[i
].len
= strlen (tab
[i
].name
);
4855 tab
[i
].name
= NULL
; /* Mark end of table. */
4863 /* If the text at CP matches one of the tag-defining TeX command names,
4864 return the pointer to the first occurrence of that command in TEX_toktab.
4865 Otherwise return -1.
4866 Keep the capital `T' in `token' for dumb truncating compilers
4867 (this distinguishes it from `TEX_toktab' */
4874 for (i
= 0; TEX_toktab
[i
].len
> 0; i
++)
4875 if (strneq (TEX_toktab
[i
].name
, cp
, TEX_toktab
[i
].len
))
4881 /* Texinfo support. Dave Love, Mar. 2000. */
4887 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4888 if (LOOKING_AT (cp
, "@node"))
4891 while (*cp
!= '\0' && *cp
!= ',')
4893 pfnote (savenstr (start
, cp
- start
), TRUE
,
4894 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
4902 * Assumes that the predicate or rule starts at column 0.
4903 * Only the first clause of a predicate or rule is added.
4904 * Original code by Sunichirou Sugou (1989)
4905 * Rewritten by Anders Lindgren (1996)
4907 static int prolog_pr
__P((char *, char *));
4908 static void prolog_skip_comment
__P((linebuffer
*, FILE *));
4909 static int prolog_atom
__P((char *, int));
4912 Prolog_functions (inf
)
4923 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
4925 if (cp
[0] == '\0') /* Empty line */
4927 else if (iswhite (cp
[0])) /* Not a predicate */
4929 else if (cp
[0] == '/' && cp
[1] == '*') /* comment. */
4930 prolog_skip_comment (&lb
, inf
);
4931 else if ((len
= prolog_pr (cp
, last
)) > 0)
4933 /* Predicate or rule. Store the function name so that we
4934 only generate a tag for the first clause. */
4936 last
= xnew(len
+ 1, char);
4937 else if (len
+ 1 > allocated
)
4938 xrnew (last
, len
+ 1, char);
4939 allocated
= len
+ 1;
4940 strncpy (last
, cp
, len
);
4948 prolog_skip_comment (plb
, inf
)
4956 for (cp
= plb
->buffer
; *cp
!= '\0'; cp
++)
4957 if (cp
[0] == '*' && cp
[1] == '/')
4960 linecharno
+= readline (plb
, inf
);
4966 * A predicate or rule definition is added if it matches:
4967 * <beginning of line><Prolog Atom><whitespace>(
4968 * or <beginning of line><Prolog Atom><whitespace>:-
4970 * It is added to the tags database if it doesn't match the
4971 * name of the previous clause header.
4973 * Return the size of the name of the predicate or rule, or 0 if no
4979 char *last
; /* Name of last clause. */
4984 pos
= prolog_atom (s
, 0);
4989 pos
= skip_spaces (s
+ pos
) - s
;
4992 || (s
[pos
] == '(' && (pos
+= 1))
4993 || (s
[pos
] == ':' && s
[pos
+ 1] == '-' && (pos
+= 2)))
4994 && (last
== NULL
/* save only the first clause */
4995 || len
!= strlen (last
)
4996 || !strneq (s
, last
, len
)))
4998 pfnote (savenstr (s
, len
), TRUE
, s
, pos
, lineno
, linecharno
);
5006 * Consume a Prolog atom.
5007 * Return the number of bytes consumed, or -1 if there was an error.
5009 * A prolog atom, in this context, could be one of:
5010 * - An alphanumeric sequence, starting with a lower case letter.
5011 * - A quoted arbitrary string. Single quotes can escape themselves.
5012 * Backslash quotes everything.
5015 prolog_atom (s
, pos
)
5023 if (ISLOWER(s
[pos
]) || (s
[pos
] == '_'))
5025 /* The atom is unquoted. */
5027 while (ISALNUM(s
[pos
]) || (s
[pos
] == '_'))
5031 return pos
- origpos
;
5033 else if (s
[pos
] == '\'')
5044 pos
++; /* A double quote */
5046 else if (s
[pos
] == '\0')
5047 /* Multiline quoted atoms are ignored. */
5049 else if (s
[pos
] == '\\')
5051 if (s
[pos
+1] == '\0')
5058 return pos
- origpos
;
5066 * Support for Erlang
5068 * Generates tags for functions, defines, and records.
5069 * Assumes that Erlang functions start at column 0.
5070 * Original code by Anders Lindgren (1996)
5072 static int erlang_func
__P((char *, char *));
5073 static void erlang_attribute
__P((char *));
5074 static int erlang_atom
__P((char *, int));
5077 Erlang_functions (inf
)
5088 LOOP_ON_INPUT_LINES (inf
, lb
, cp
)
5090 if (cp
[0] == '\0') /* Empty line */
5092 else if (iswhite (cp
[0])) /* Not function nor attribute */
5094 else if (cp
[0] == '%') /* comment */
5096 else if (cp
[0] == '"') /* Sometimes, strings start in column one */
5098 else if (cp
[0] == '-') /* attribute, e.g. "-define" */
5100 erlang_attribute (cp
);
5103 else if ((len
= erlang_func (cp
, last
)) > 0)
5106 * Function. Store the function name so that we only
5107 * generates a tag for the first clause.
5110 last
= xnew (len
+ 1, char);
5111 else if (len
+ 1 > allocated
)
5112 xrnew (last
, len
+ 1, char);
5113 allocated
= len
+ 1;
5114 strncpy (last
, cp
, len
);
5122 * A function definition is added if it matches:
5123 * <beginning of line><Erlang Atom><whitespace>(
5125 * It is added to the tags database if it doesn't match the
5126 * name of the previous clause header.
5128 * Return the size of the name of the function, or 0 if no function
5132 erlang_func (s
, last
)
5134 char *last
; /* Name of last clause. */
5139 pos
= erlang_atom (s
, 0);
5144 pos
= skip_spaces (s
+ pos
) - s
;
5146 /* Save only the first clause. */
5149 || len
!= (int)strlen (last
)
5150 || !strneq (s
, last
, len
)))
5152 pfnote (savenstr (s
, len
), TRUE
, s
, pos
, lineno
, linecharno
);
5161 * Handle attributes. Currently, tags are generated for defines
5164 * They are on the form:
5165 * -define(foo, bar).
5166 * -define(Foo(M, N), M+N).
5167 * -record(graph, {vtab = notable, cyclic = true}).
5170 erlang_attribute (s
)
5176 if (LOOKING_AT (s
, "-define") || LOOKING_AT (s
, "-record"))
5178 if (s
[pos
++] == '(')
5180 pos
= skip_spaces (s
+ pos
) - s
;
5181 len
= erlang_atom (s
, pos
);
5183 pfnote (savenstr (& s
[pos
], len
), TRUE
,
5184 s
, pos
+ len
, lineno
, linecharno
);
5192 * Consume an Erlang atom (or variable).
5193 * Return the number of bytes consumed, or -1 if there was an error.
5196 erlang_atom (s
, pos
)
5204 if (ISALPHA (s
[pos
]) || s
[pos
] == '_')
5206 /* The atom is unquoted. */
5208 while (ISALNUM (s
[pos
]) || s
[pos
] == '_')
5210 return pos
- origpos
;
5212 else if (s
[pos
] == '\'')
5223 else if (s
[pos
] == '\0')
5224 /* Multiline quoted atoms are ignored. */
5226 else if (s
[pos
] == '\\')
5228 if (s
[pos
+1] == '\0')
5235 return pos
- origpos
;
5242 #ifdef ETAGS_REGEXPS
5244 static char *scan_separators
__P((char *));
5245 static void analyse_regex
__P((char *, bool));
5246 static void add_regex
__P((char *, bool, language
*));
5247 static char *substitute
__P((char *, char *, struct re_registers
*));
5249 /* Take a string like "/blah/" and turn it into "blah", making sure
5250 that the first and last characters are the same, and handling
5251 quoted separator characters. Actually, stops on the occurrence of
5252 an unquoted separator. Also turns "\t" into a Tab character.
5253 Returns pointer to terminating separator. Works in place. Null
5254 terminates name string. */
5256 scan_separators (name
)
5260 char *copyto
= name
;
5261 bool quoted
= FALSE
;
5263 for (++name
; *name
!= '\0'; ++name
)
5269 else if (*name
== sep
)
5273 /* Something else is quoted, so preserve the quote. */
5279 else if (*name
== '\\')
5281 else if (*name
== sep
)
5287 /* Terminate copied string. */
5292 /* Look at the argument of --regex or --no-regex and do the right
5293 thing. Same for each line of a regexp file. */
5295 analyse_regex (regex_arg
, ignore_case
)
5299 if (regex_arg
== NULL
)
5301 free_patterns (); /* --no-regex: remove existing regexps */
5305 /* A real --regexp option or a line in a regexp file. */
5306 switch (regex_arg
[0])
5308 /* Comments in regexp file or null arg to --regex. */
5314 /* Read a regex file. This is recursive and may result in a
5315 loop, which will stop when the file descriptors are exhausted. */
5319 linebuffer regexbuf
;
5320 char *regexfile
= regex_arg
+ 1;
5322 /* regexfile is a file containing regexps, one per line. */
5323 regexfp
= fopen (regexfile
, "r");
5324 if (regexfp
== NULL
)
5329 initbuffer (®exbuf
);
5330 while (readline_internal (®exbuf
, regexfp
) > 0)
5331 analyse_regex (regexbuf
.buffer
, ignore_case
);
5332 free (regexbuf
.buffer
);
5337 /* Regexp to be used for a specific language only. */
5341 char *lang_name
= regex_arg
+ 1;
5344 for (cp
= lang_name
; *cp
!= '}'; cp
++)
5347 error ("unterminated language name in regex: %s", regex_arg
);
5351 lang
= get_language_from_langname (lang_name
);
5354 add_regex (cp
+ 1, ignore_case
, lang
);
5358 /* Regexp to be used for any language. */
5360 add_regex (regex_arg
, ignore_case
, NULL
);
5365 /* Turn a name, which is an ed-style (but Emacs syntax) regular
5366 expression, into a real regular expression by compiling it. */
5368 add_regex (regexp_pattern
, ignore_case
, lang
)
5369 char *regexp_pattern
;
5373 static struct re_pattern_buffer zeropattern
;
5376 struct re_pattern_buffer
*patbuf
;
5380 if (regexp_pattern
[strlen(regexp_pattern
)-1] != regexp_pattern
[0])
5382 error ("%s: unterminated regexp", regexp_pattern
);
5385 name
= scan_separators (regexp_pattern
);
5386 if (regexp_pattern
[0] == '\0')
5388 error ("null regexp", (char *)NULL
);
5391 (void) scan_separators (name
);
5393 patbuf
= xnew (1, struct re_pattern_buffer
);
5394 *patbuf
= zeropattern
;
5396 patbuf
->translate
= lc_trans
; /* translation table to fold case */
5398 err
= re_compile_pattern (regexp_pattern
, strlen (regexp_pattern
), patbuf
);
5401 error ("%s while compiling pattern", err
);
5406 p_head
= xnew (1, pattern
);
5407 p_head
->regex
= savestr (regexp_pattern
);
5408 p_head
->p_next
= pp
;
5409 p_head
->lang
= lang
;
5410 p_head
->pat
= patbuf
;
5411 p_head
->name_pattern
= savestr (name
);
5412 p_head
->error_signaled
= FALSE
;
5413 p_head
->ignore_case
= ignore_case
;
5417 * Do the substitutions indicated by the regular expression and
5421 substitute (in
, out
, regs
)
5423 struct re_registers
*regs
;
5426 int size
, dig
, diglen
;
5429 size
= strlen (out
);
5431 /* Pass 1: figure out how much to allocate by finding all \N strings. */
5432 if (out
[size
- 1] == '\\')
5433 fatal ("pattern error in \"%s\"", out
);
5434 for (t
= etags_strchr (out
, '\\');
5436 t
= etags_strchr (t
+ 2, '\\'))
5440 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
5446 /* Allocate space and do the substitutions. */
5447 result
= xnew (size
+ 1, char);
5449 for (t
= result
; *out
!= '\0'; out
++)
5450 if (*out
== '\\' && ISDIGIT (*++out
))
5453 diglen
= regs
->end
[dig
] - regs
->start
[dig
];
5454 strncpy (t
, in
+ regs
->start
[dig
], diglen
);
5461 assert (t
<= result
+ size
&& t
- result
== (int)strlen (result
));
5466 /* Deallocate all patterns. */
5471 while (p_head
!= NULL
)
5473 pp
= p_head
->p_next
;
5474 free (p_head
->regex
);
5475 free (p_head
->name_pattern
);
5481 #endif /* ETAGS_REGEXPS */
5488 register int len
= 0;
5490 while (*cp
!= '\0' && lowcase (*cp
) == lowcase (dbp
[len
]))
5492 if (*cp
== '\0' && !intoken (dbp
[len
]))
5504 register char *cp
, *name
;
5508 /* Go till you get to white space or a syntactic break */
5509 for (cp
= bp
+ 1; !notinname (*cp
); cp
++)
5511 name
= savenstr (bp
, cp
-bp
);
5513 lb
.buffer
, cp
- lb
.buffer
+ 1, lineno
, linecharno
);
5517 /* Initialize a linebuffer for use */
5522 lbp
->size
= (DEBUG
) ? 3 : 200;
5523 lbp
->buffer
= xnew (lbp
->size
, char);
5524 lbp
->buffer
[0] = '\0';
5529 * Read a line of text from `stream' into `lbp', excluding the
5530 * newline or CR-NL, if any. Return the number of characters read from
5531 * `stream', which is the length of the line including the newline.
5533 * On DOS or Windows we do not count the CR character, if any, before the
5534 * NL, in the returned length; this mirrors the behavior of emacs on those
5535 * platforms (for text files, it translates CR-NL to NL as it reads in the
5539 readline_internal (lbp
, stream
)
5541 register FILE *stream
;
5543 char *buffer
= lbp
->buffer
;
5544 register char *p
= lbp
->buffer
;
5545 register char *pend
;
5548 pend
= p
+ lbp
->size
; /* Separate to avoid 386/IX compiler bug. */
5552 register int c
= getc (stream
);
5555 /* We're at the end of linebuffer: expand it. */
5557 xrnew (buffer
, lbp
->size
, char);
5558 p
+= buffer
- lbp
->buffer
;
5559 pend
= buffer
+ lbp
->size
;
5560 lbp
->buffer
= buffer
;
5570 if (p
> buffer
&& p
[-1] == '\r')
5574 /* Assume CRLF->LF translation will be performed by Emacs
5575 when loading this file, so CRs won't appear in the buffer.
5576 It would be cleaner to compensate within Emacs;
5577 however, Emacs does not know how many CRs were deleted
5578 before any given point in the file. */
5593 lbp
->len
= p
- buffer
;
5595 return lbp
->len
+ chars_deleted
;
5599 * Like readline_internal, above, but in addition try to match the
5600 * input line against relevant regular expressions.
5603 readline (lbp
, stream
)
5607 /* Read new line. */
5608 long result
= readline_internal (lbp
, stream
);
5610 /* Honour #line directives. */
5611 if (!no_line_directive
)
5613 static bool discard_until_line_directive
;
5615 /* Check whether this is a #line directive. */
5616 if (result
> 12 && strneq (lbp
->buffer
, "#line ", 6))
5620 if (DEBUG
) start
= 0; /* shut up the compiler */
5621 if (sscanf (lbp
->buffer
, "#line %d \"%n", &lno
, &start
) == 1)
5623 char *endp
= lbp
->buffer
+ start
;
5626 while ((endp
= etags_strchr (endp
, '"')) != NULL
5627 && endp
[-1] == '\\')
5630 /* Ok, this is a real #line directive. Let's deal with it. */
5632 char *taggedabsname
; /* absolute name of original file */
5633 char *taggedfname
; /* name of original file as given */
5634 char *name
; /* temp var */
5636 discard_until_line_directive
= FALSE
; /* found it */
5637 name
= lbp
->buffer
+ start
;
5639 canonicalize_filename (name
); /* for DOS */
5640 taggedabsname
= absolute_filename (name
, curfdp
->infabsdir
);
5641 if (filename_is_absolute (name
)
5642 || filename_is_absolute (curfdp
->infname
))
5643 taggedfname
= savestr (taggedabsname
);
5645 taggedfname
= relative_filename (taggedabsname
,tagfiledir
);
5647 if (streq (curfdp
->taggedfname
, taggedfname
))
5648 /* The #line directive is only a line number change. We
5649 deal with this afterwards. */
5652 /* The tags following this #line directive should be
5653 attributed to taggedfname. In order to do this, set
5654 curfdp accordingly. */
5656 fdesc
*fdp
; /* file description pointer */
5658 /* Go look for a file description already set up for the
5659 file indicated in the #line directive. If there is
5660 one, use it from now until the next #line
5662 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
5663 if (streq (fdp
->infname
, curfdp
->infname
)
5664 && streq (fdp
->taggedfname
, taggedfname
))
5665 /* If we remove the second test above (after the &&)
5666 then all entries pertaining to the same file are
5667 coalesced in the tags file. If we use it, then
5668 entries pertaining to the same file but generated
5669 from different files (via #line directives) will
5670 go into separate sections in the tags file. These
5671 alternatives look equivalent. The first one
5672 destroys some apparently useless information. */
5678 /* Else, if we already tagged the real file, skip all
5679 input lines until the next #line directive. */
5680 if (fdp
== NULL
) /* not found */
5681 for (fdp
= fdhead
; fdp
!= NULL
; fdp
= fdp
->next
)
5682 if (streq (fdp
->infabsname
, taggedabsname
))
5684 discard_until_line_directive
= TRUE
;
5688 /* Else create a new file description and use that from
5689 now on, until the next #line directive. */
5690 if (fdp
== NULL
) /* not found */
5693 fdhead
= xnew (1, fdesc
);
5694 *fdhead
= *curfdp
; /* copy curr. file description */
5696 fdhead
->infname
= savestr (curfdp
->infname
);
5697 fdhead
->infabsname
= savestr (curfdp
->infabsname
);
5698 fdhead
->infabsdir
= savestr (curfdp
->infabsdir
);
5699 fdhead
->taggedfname
= taggedfname
;
5700 fdhead
->usecharno
= FALSE
;
5704 free (taggedabsname
);
5706 return readline (lbp
, stream
);
5707 } /* if a real #line directive */
5708 } /* if #line is followed by a a number */
5709 } /* if line begins with "#line " */
5711 /* If we are here, no #line directive was found. */
5712 if (discard_until_line_directive
)
5715 /* Do a tail recursion on ourselves, thus discarding the contents
5716 of the line buffer. */
5717 return readline (lbp
, stream
);
5719 discard_until_line_directive
= FALSE
;
5722 } /* if #line directives should be considered */
5724 #ifdef ETAGS_REGEXPS
5729 /* Match against relevant patterns. */
5731 for (pp
= p_head
; pp
!= NULL
; pp
= pp
->p_next
)
5733 /* Only use generic regexps or those for the current language. */
5734 if (pp
->lang
!= NULL
&& pp
->lang
!= fdhead
->lang
)
5737 match
= re_match (pp
->pat
, lbp
->buffer
, lbp
->len
, 0, &pp
->regs
);
5742 if (!pp
->error_signaled
)
5744 error ("error while matching \"%s\"", pp
->regex
);
5745 pp
->error_signaled
= TRUE
;
5752 /* Match occurred. Construct a tag. */
5753 if (pp
->name_pattern
[0] != '\0')
5755 /* Make a named tag. */
5756 char *name
= substitute (lbp
->buffer
,
5757 pp
->name_pattern
, &pp
->regs
);
5759 pfnote (name
, TRUE
, lbp
->buffer
, match
, lineno
, linecharno
);
5763 /* Make an unnamed tag. */
5764 pfnote ((char *)NULL
, TRUE
,
5765 lbp
->buffer
, match
, lineno
, linecharno
);
5771 #endif /* ETAGS_REGEXPS */
5778 * Return a pointer to a space of size strlen(cp)+1 allocated
5779 * with xnew where the string CP has been copied.
5785 return savenstr (cp
, strlen (cp
));
5789 * Return a pointer to a space of size LEN+1 allocated with xnew where
5790 * the string CP has been copied for at most the first LEN characters.
5799 dp
= xnew (len
+ 1, char);
5800 strncpy (dp
, cp
, len
);
5806 * Return the ptr in sp at which the character c last
5807 * appears; NULL if not found
5809 * Identical to POSIX strrchr, included for portability.
5812 etags_strrchr (sp
, c
)
5813 register const char *sp
;
5816 register const char *r
;
5828 * Return the ptr in sp at which the character c first
5829 * appears; NULL if not found
5831 * Identical to POSIX strchr, included for portability.
5834 etags_strchr (sp
, c
)
5835 register const char *sp
;
5847 * Return TRUE if the two strings are equal, ignoring case for alphabetic
5850 * Analogous to BSD's strcasecmp, included for portability.
5854 register const char *s1
;
5855 register const char *s2
;
5858 && (ISALPHA (*s1
) && ISALPHA (*s2
)
5859 ? lowcase (*s1
) == lowcase (*s2
)
5863 return (*s1
== *s2
);
5866 /* Skip spaces, return new pointer. */
5871 while (iswhite (*cp
))
5876 /* Skip non spaces, return new pointer. */
5878 skip_non_spaces (cp
)
5881 while (*cp
!= '\0' && !iswhite (*cp
))
5886 /* Print error message and exit. */
5904 suggest_asking_for_help ()
5906 fprintf (stderr
, "\tTry `%s %s' for a complete list of options.\n",
5917 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
5920 const char *s1
, *s2
;
5922 fprintf (stderr
, "%s: ", progname
);
5923 fprintf (stderr
, s1
, s2
);
5924 fprintf (stderr
, "\n");
5927 /* Return a newly-allocated string whose contents
5928 concatenate those of s1, s2, s3. */
5933 int len1
= strlen (s1
), len2
= strlen (s2
), len3
= strlen (s3
);
5934 char *result
= xnew (len1
+ len2
+ len3
+ 1, char);
5936 strcpy (result
, s1
);
5937 strcpy (result
+ len1
, s2
);
5938 strcpy (result
+ len1
+ len2
, s3
);
5939 result
[len1
+ len2
+ len3
] = '\0';
5945 /* Does the same work as the system V getcwd, but does not need to
5946 guess the buffer size in advance. */
5952 char *path
= xnew (bufsize
, char);
5954 while (getcwd (path
, bufsize
) == NULL
)
5956 if (errno
!= ERANGE
)
5960 path
= xnew (bufsize
, char);
5963 canonicalize_filename (path
);
5966 #else /* not HAVE_GETCWD */
5969 char *p
, path
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
5973 for (p
= path
; *p
!= '\0'; p
++)
5979 return strdup (path
);
5980 #else /* not MSDOS */
5985 pipe
= (FILE *) popen ("pwd 2>/dev/null", "r");
5986 if (pipe
== NULL
|| readline_internal (&path
, pipe
) == 0)
5991 #endif /* not MSDOS */
5992 #endif /* not HAVE_GETCWD */
5995 /* Return a newly allocated string containing the file name of FILE
5996 relative to the absolute directory DIR (which should end with a slash). */
5998 relative_filename (file
, dir
)
6001 char *fp
, *dp
, *afn
, *res
;
6004 /* Find the common root of file and dir (with a trailing slash). */
6005 afn
= absolute_filename (file
, cwd
);
6008 while (*fp
++ == *dp
++)
6010 fp
--, dp
--; /* back to the first differing char */
6012 if (fp
== afn
&& afn
[0] != '/') /* cannot build a relative name */
6015 do /* look at the equal chars until '/' */
6019 /* Build a sequence of "../" strings for the resulting relative file name. */
6021 while ((dp
= etags_strchr (dp
+ 1, '/')) != NULL
)
6023 res
= xnew (3*i
+ strlen (fp
+ 1) + 1, char);
6026 strcat (res
, "../");
6028 /* Add the file name relative to the common root of file and dir. */
6029 strcat (res
, fp
+ 1);
6035 /* Return a newly allocated string containing the absolute file name
6036 of FILE given DIR (which should end with a slash). */
6038 absolute_filename (file
, dir
)
6041 char *slashp
, *cp
, *res
;
6043 if (filename_is_absolute (file
))
6044 res
= savestr (file
);
6046 /* We don't support non-absolute file names with a drive
6047 letter, like `d:NAME' (it's too much hassle). */
6048 else if (file
[1] == ':')
6049 fatal ("%s: relative file names with drive letters not supported", file
);
6052 res
= concat (dir
, file
, "");
6054 /* Delete the "/dirname/.." and "/." substrings. */
6055 slashp
= etags_strchr (res
, '/');
6056 while (slashp
!= NULL
&& slashp
[0] != '\0')
6058 if (slashp
[1] == '.')
6060 if (slashp
[2] == '.'
6061 && (slashp
[3] == '/' || slashp
[3] == '\0'))
6066 while (cp
>= res
&& !filename_is_absolute (cp
));
6068 cp
= slashp
; /* the absolute name begins with "/.." */
6070 /* Under MSDOS and NT we get `d:/NAME' as absolute
6071 file name, so the luser could say `d:/../NAME'.
6072 We silently treat this as `d:/NAME'. */
6073 else if (cp
[0] != '/')
6076 strcpy (cp
, slashp
+ 3);
6080 else if (slashp
[2] == '/' || slashp
[2] == '\0')
6082 strcpy (slashp
, slashp
+ 2);
6087 slashp
= etags_strchr (slashp
+ 1, '/');
6091 return savestr ("/");
6096 /* Return a newly allocated string containing the absolute
6097 file name of dir where FILE resides given DIR (which should
6098 end with a slash). */
6100 absolute_dirname (file
, dir
)
6106 canonicalize_filename (file
);
6107 slashp
= etags_strrchr (file
, '/');
6109 return savestr (dir
);
6112 res
= absolute_filename (file
, dir
);
6118 /* Whether the argument string is an absolute file name. The argument
6119 string must have been canonicalized with canonicalize_filename. */
6121 filename_is_absolute (fn
)
6124 return (fn
[0] == '/'
6126 || (ISALPHA(fn
[0]) && fn
[1] == ':' && fn
[2] == '/')
6131 /* Translate backslashes into slashes. Works in place. */
6133 canonicalize_filename (fn
)
6137 /* Canonicalize drive letter case. */
6138 if (fn
[0] != '\0' && fn
[1] == ':' && ISLOWER (fn
[0]))
6139 fn
[0] = upcase (fn
[0]);
6140 /* Convert backslashes to slashes. */
6141 for (; *fn
!= '\0'; fn
++)
6146 fn
= NULL
; /* shut up the compiler */
6150 /* Set the minimum size of a string contained in a linebuffer. */
6152 linebuffer_setlen (lbp
, toksize
)
6156 while (lbp
->size
<= toksize
)
6159 xrnew (lbp
->buffer
, lbp
->size
, char);
6164 /* Like malloc but get fatal error if memory is exhausted. */
6169 PTR result
= (PTR
) malloc (size
);
6171 fatal ("virtual memory exhausted", (char *)NULL
);
6176 xrealloc (ptr
, size
)
6180 PTR result
= (PTR
) realloc (ptr
, size
);
6182 fatal ("virtual memory exhausted", (char *)NULL
);
6188 * c-indentation-style: gnu
6189 * indent-tabs-mode: t
6192 * c-font-lock-extra-types: ("FILE" "bool" "language" "linebuffer" "fdesc" "node")