1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 87, 88, 89, 93, 94, 95
3 Free Software Foundation, Inc. and Ken Arnold
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 * Sam Kendall added C++.
28 * Francesco Potorti` reorganised C and C++ based on work by Joe Wells.
29 * Regexp tags by Tom Tromey.
31 * Francesco Potorti` (F.Potorti@cnuce.cnr.it) is the current maintainer.
34 char pot_etags_version[] = "@(#) pot revision number is 12.28";
36 /* Prototyping magic snarfed from gmalloc.c */
37 #if defined (__cplusplus) || defined (__STDC__)
41 #define __ptr_t void *
42 #else /* Not C++ or ANSI C. */
48 #define __ptr_t char *
49 #endif /* C++ or ANSI C. */
53 /* On some systems, Emacs defines static as nothing for the sake
54 of unexec. We don't want that here since we don't use unexec. */
56 # define ETAGS_REGEXPS /* use the regexp features */
57 # define LONG_OPTIONS /* accept long options */
58 #endif /* HAVE_CONFIG_H */
72 # define MAXPATHLEN _MAX_PATH
73 # ifndef HAVE_CONFIG_H
75 # endif /* not HAVE_CONFIG_H */
76 #endif /* WIN32_NATIVE */
78 #if !defined (WIN32_NATIVE) && defined (STDC_HEADERS)
87 extern char *getcwd ();
89 #endif /* HAVE_UNISTD_H */
94 #include <sys/types.h>
97 #if !defined (S_ISREG) && defined (S_IFREG)
98 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
104 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
106 extern int optind, opterr;
107 #endif /* LONG_OPTIONS */
111 #endif /* ETAGS_REGEXPS */
113 /* Define CTAGS to make the program "ctags" compatible with the usual one.
114 Leave it undefined to make the program "etags", which makes emacs-style
115 tag tables and tags typedefs, #defines and struct/union/enum by default. */
123 /* Exit codes for success and failure. */
133 #define C_PLPL 0x00001 /* C++ */
134 #define C_STAR 0x00003 /* C* */
135 #define C_JAVA 0x00005 /* JAVA */
136 #define YACC 0x10000 /* yacc file */
138 #define streq(s,t) ((DEBUG && (s) == NULL && (t) == NULL \
139 && (abort (), 1)) || !strcmp (s, t))
140 #define strneq(s,t,n) ((DEBUG && (s) == NULL && (t) == NULL \
141 && (abort (), 1)) || !strncmp (s, t, n))
143 #define lowcase(c) tolower ((char)c)
145 #define CHARS 256 /* 2^sizeof(char) */
146 #define CHAR(x) ((unsigned int)x & (CHARS - 1))
147 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */
148 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
149 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
150 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
151 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
154 /*#undef OO_BROWSER*/
155 /* Due to the way this file is constructed, this unfortunately doesn't */
156 /* work except for documentation purposes. -slb */
161 #define set_construct(construct) \
162 if (!oo_browser_construct) oo_browser_construct = construct
163 void oo_browser_clear_all_globals(void);
164 void oo_browser_clear_some_globals(void);
165 void oo_browser_check_and_clear_structtype(void);
169 * xnew, xrnew -- allocate, reallocate storage
171 * SYNOPSIS: Type *xnew (int n, Type);
172 * Type *xrnew (OldPointer, int n, Type);
175 # include "chkmalloc.h"
176 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
177 (n) * sizeof (Type)))
178 # define xrnew(op,n,Type) ((Type *) trace_realloc (__FILE__, __LINE__, \
179 (op), (n) * sizeof (Type)))
181 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
182 # define xrnew(op,n,Type) ((Type *) xrealloc ((op), (n) * sizeof (Type)))
187 typedef void Lang_function (FILE *);
192 Lang_function *function;
197 typedef struct node_st
198 { /* sorting structure */
199 char *name; /* function or type name */
201 short int construct; /* Construct type for the OO-Browser */
203 char *file; /* file name */
204 bool is_func; /* use pattern or line no */
205 bool been_warned; /* set if noticed dup */
206 int lno; /* line number tag is on */
207 long cno; /* character number line starts on */
208 char *pat; /* search pattern */
209 struct node_st *left, *right; /* left and right sons */
213 /* If you add to this array, you must add a corresponding entry to the
215 static char *oo_browser_default_classes[] =
216 /* Lack of square brackets around some of these entries are intentional. */
217 {"null", "class", "method", "[constant]", "[enumeration]", "[enum_label]",
218 "extern", "[function]", "[macro]", "objc", "[structure]", "[type]",
219 "[union]", "[variable]"};
221 /* If you add to this enum, you must add a corresponding entry to the
223 enum oo_browser_constructs {C_NULL, C_CLASS, C_METHOD, C_CONSTANT, C_ENUMERATION,
224 C_ENUM_LABEL, C_EXTERN, C_FUNCTION, C_MACRO,
225 C_OBJC, C_STRUCTURE, C_TYPE, C_UNION, C_VARIABLE};
227 enum oo_browser_constructs oo_browser_construct = C_NULL;
231 * A `linebuffer' is a structure which holds a line of text.
232 * `readline_internal' reads a line from a stream into a linebuffer
233 * and works regardless of the length of the line.
234 * SIZE is the size of BUFFER, LEN is the length of the string in
235 * BUFFER after readline reads it.
244 extern char *getenv PP ((const char *envvar));
246 /* Many compilers barf on this:
247 Lang_function Asm_labels;
248 so let's write it this way */
249 void Asm_labels PP ((FILE *inf));
250 void C_entries PP ((int c_ext, FILE *inf));
251 void default_C_entries PP ((FILE *inf));
252 void plain_C_entries PP ((FILE *inf));
253 void Cjava_entries PP ((FILE *inf));
254 void Cplusplus_entries PP ((FILE *inf));
255 void Yacc_entries PP ((FILE *inf));
256 void Cobol_paragraphs PP ((FILE *inf));
257 void Cstar_entries PP ((FILE *inf));
258 void Erlang_functions PP ((FILE *inf));
259 void Fortran_functions PP ((FILE *inf));
260 void Lisp_functions PP ((FILE *inf));
261 void Pascal_functions PP ((FILE *inf));
262 void Perl_functions PP ((FILE *inf));
263 void Postscript_functions PP ((FILE *inf));
264 void Prolog_functions PP ((FILE *inf));
265 void Python_functions PP ((FILE *inf));
266 void Scheme_functions PP ((FILE *inf));
267 void TeX_functions PP ((FILE *inf));
268 void just_read_file PP ((FILE *inf));
270 void print_language_names PP ((void));
271 void print_version PP ((void));
272 void print_help PP ((void));
274 language *get_language_from_name PP ((char *name));
275 language *get_language_from_interpreter PP ((char *interpreter));
276 language *get_language_from_suffix PP ((char *suffix));
277 int total_size_of_entries PP ((node *np));
278 long readline PP ((linebuffer *lbp, FILE *stream));
279 long readline_internal PP ((linebuffer *lbp, FILE *stream));
281 void analyse_regex PP ((char *regex_arg));
282 void add_regex PP ((char *regexp_pattern, language *lang));
283 void free_patterns PP ((void));
284 #endif /* ETAGS_REGEXPS */
285 void error PP ((const char *s1, const char *s2));
286 void suggest_asking_for_help PP ((void));
287 void fatal PP ((char *s1, char *s2));
288 void pfatal PP ((char *s1));
289 void add_node PP ((node *np, node **cur_node_p));
291 void init PP ((void));
292 void initbuffer PP ((linebuffer *lbp));
293 void find_entries PP ((char *file, FILE *inf));
294 void free_tree PP ((node *np));
295 void pfnote PP ((char *name, bool is_func, char *linestart, int linelen, int lno, long cno));
296 void new_pfnote PP ((char *name, int namelen, bool is_func, char *linestart, int linelen, int lno, long cno));
297 void process_file PP ((char *file));
298 void put_entries PP ((node *np));
299 void takeprec PP ((void));
301 char *concat PP ((char *s1, char *s2, char *s3));
302 char *skip_spaces PP ((char *cp));
303 char *skip_non_spaces PP ((char *cp));
304 char *savenstr PP ((char *cp, int len));
305 char *savestr PP ((char *cp));
306 char *etags_strchr PP ((char *sp, int c));
307 char *etags_strrchr PP ((char *sp, int c));
308 char *etags_getcwd PP ((void));
309 char *relative_filename PP ((char *file, char *dir));
310 char *absolute_filename PP ((char *file, char *dir));
311 char *absolute_dirname PP ((char *file, char *dir));
312 bool filename_is_absolute PP ((char *fn));
313 void canonicalize_filename PP ((char *fn));
314 void grow_linebuffer PP ((linebuffer *lbp, int toksize));
315 long *xmalloc PP ((unsigned int size));
316 long *xrealloc PP ((char *ptr, unsigned int size));
319 char searchar = '/'; /* use /.../ searches */
321 char *tagfile; /* output file */
322 char *progname; /* name this program was invoked with */
323 char *cwd; /* current working directory */
324 char *tagfiledir; /* directory of tagfile */
325 FILE *tagf; /* ioptr for tags file */
327 char *curfile; /* current input file name */
328 language *curlang; /* current language */
330 int lineno; /* line number of current line */
331 long charno; /* current character number */
332 long linecharno; /* charno of start of current line */
333 char *dbp; /* pointer to start of current tag */
334 node *head; /* the head of the binary tree of tags */
336 linebuffer lb; /* the current line */
337 linebuffer token_name; /* used by C_entries as a temporary area */
341 linebuffer lb; /* used by C_entries instead of lb */
344 /* boolean "functions" (see init) */
345 bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
348 *white = " \f\t\n\r",
350 *nonam = " \f\t\n\r(=,[;",
351 /* token ending chars */
352 *endtk = " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
353 /* token starting chars */
354 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
355 /* valid in-token chars */
356 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
358 bool append_to_tagfile; /* -a: append to tags */
359 /* The following four default to TRUE for etags, but to FALSE for ctags. */
360 bool typedefs; /* -t: create tags for C typedefs */
361 bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */
362 /* 0 struct/enum/union decls, and C++ */
363 /* member functions. */
364 bool constantypedefs; /* -d: create tags for C #define, enum */
365 /* constants and variables. */
366 /* -D: opposite of -d. Default under ctags. */
367 bool globals; /* create tags for global variables */
368 bool members; /* create tags for C member variables */
369 bool update; /* -u: update tags */
370 bool vgrind_style; /* -v: create vgrind style index output */
371 bool no_warnings; /* -w: suppress warnings */
372 bool cxref_style; /* -x: create cxref style output */
373 bool cplusplus; /* .[hc] means C++, not C */
374 bool noindentypedefs; /* -I: ignore indentation in C */
376 bool oo_browser_format; /* -O: OO-Browser tags format */
380 struct option longopts[] =
382 { "append", no_argument, NULL, 'a' },
383 { "backward-search", no_argument, NULL, 'B' },
384 { "c++", no_argument, NULL, 'C' },
385 { "cxref", no_argument, NULL, 'x' },
386 { "defines", no_argument, NULL, 'd' },
387 { "no-defines", no_argument, NULL, 'D' },
388 { "globals", no_argument, &globals, TRUE },
389 { "no-globals", no_argument, &globals, FALSE },
390 { "help", no_argument, NULL, 'h' },
391 { "help", no_argument, NULL, 'H' },
392 { "ignore-indentation", no_argument, NULL, 'I' },
393 { "include", required_argument, NULL, 'i' },
394 { "language", required_argument, NULL, 'l' },
395 { "members", no_argument, &members, TRUE },
396 { "no-members", no_argument, &members, FALSE },
397 { "no-warn", no_argument, NULL, 'w' },
398 { "output", required_argument, NULL, 'o' },
400 { "oo-browser", no_argument, NULL, 'O' },
403 { "regex", required_argument, NULL, 'r' },
404 { "no-regex", no_argument, NULL, 'R' },
405 #endif /* ETAGS_REGEXPS */
406 { "typedefs", no_argument, NULL, 't' },
407 { "typedefs-and-c++", no_argument, NULL, 'T' },
408 { "update", no_argument, NULL, 'u' },
409 { "version", no_argument, NULL, 'V' },
410 { "vgrind", no_argument, NULL, 'v' },
413 #endif /* LONG_OPTIONS */
416 /* Structure defining a regular expression. Elements are
417 the compiled pattern, and the name string. */
418 typedef struct pattern
420 struct pattern *p_next;
423 struct re_pattern_buffer *pattern;
424 struct re_registers regs;
429 /* Array of all regexps. */
430 pattern *p_head = NULL;
431 #endif /* ETAGS_REGEXPS */
437 /* Non-NULL if language fixed. */
438 language *forced_lang = NULL;
441 char *Asm_suffixes [] = { "a", /* Unix assembler */
442 "asm", /* Microcontroller assembly */
443 "def", /* BSO/Tasking definition includes */
444 "inc", /* Microcontroller include files */
445 "ins", /* Microcontroller include files */
446 "s", "sa", /* Unix assembler */
447 "src", /* BSO/Tasking C compiler output */
451 /* Note that .c and .h can be considered C++, if the --c++ flag was
452 given. That is why default_C_entries is called here. */
453 char *default_C_suffixes [] =
456 char *Cplusplus_suffixes [] =
457 { "C", "H", "c++", "cc", "cpp", "cxx", "h++", "hh", "hpp", "hxx",
458 "M", /* Objective C++ */
459 "pdb", /* Postscript with C syntax */
462 char *Cjava_suffixes [] =
465 char *Cobol_suffixes [] =
466 { "COB", "cob", NULL };
468 char *Cstar_suffixes [] =
469 { "cs", "hs", NULL };
471 char *Erlang_suffixes [] =
472 { "erl", "hrl", NULL };
474 char *Fortran_suffixes [] =
475 { "F", "f", "f90", "for", NULL };
477 char *Lisp_suffixes [] =
478 { "cl", "clisp", "el", "l", "lisp", "lsp", "ml", NULL };
480 char *Pascal_suffixes [] =
481 { "p", "pas", NULL };
483 char *Perl_suffixes [] =
484 { "pl", "pm", NULL };
485 char *Perl_interpreters [] =
486 { "perl", "@PERL@", NULL };
488 char *plain_C_suffixes [] =
489 { "pc", /* Pro*C file */
490 "m", /* Objective C file */
491 "lm", /* Objective lex file */
494 char *Postscript_suffixes [] =
497 char *Prolog_suffixes [] =
500 char *Python_suffixes [] =
503 /* Can't do the `SCM' or `scm' prefix with a version number. */
504 char *Scheme_suffixes [] =
505 { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "ss", "t", NULL };
507 char *TeX_suffixes [] =
508 { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL };
510 char *Yacc_suffixes [] =
511 { "y", "ym", NULL }; /* .ym is Objective yacc file */
514 * Table of languages.
516 * It is ok for a given function to be listed under more than one
517 * name. I just didn't.
520 language lang_names [] =
522 { "asm", Asm_labels, Asm_suffixes, NULL },
523 { "c", default_C_entries, default_C_suffixes, NULL },
524 { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL },
525 { "c*", Cstar_entries, Cstar_suffixes, NULL },
526 { "cobol", Cobol_paragraphs, Cobol_suffixes, NULL },
527 { "erlang", Erlang_functions, Erlang_suffixes, NULL },
528 { "fortran", Fortran_functions, Fortran_suffixes, NULL },
529 { "java", Cjava_entries, Cjava_suffixes, NULL },
530 { "lisp", Lisp_functions, Lisp_suffixes, NULL },
531 { "pascal", Pascal_functions, Pascal_suffixes, NULL },
532 { "perl", Perl_functions, Perl_suffixes, Perl_interpreters },
533 { "postscript", Postscript_functions, Postscript_suffixes, NULL },
534 { "proc", plain_C_entries, plain_C_suffixes, NULL },
535 { "prolog", Prolog_functions, Prolog_suffixes, NULL },
536 { "python", Python_functions, Python_suffixes, NULL },
537 { "scheme", Scheme_functions, Scheme_suffixes, NULL },
538 { "tex", TeX_functions, TeX_suffixes, NULL },
539 { "yacc", Yacc_entries, Yacc_suffixes, NULL },
540 { "auto", NULL }, /* default guessing scheme */
541 { "none", just_read_file }, /* regexp matching only */
542 { NULL, NULL } /* end of list */
547 print_language_names ()
552 puts ("\nThese are the currently supported languages, along with the\n\
553 default file name suffixes:");
554 for (lang = lang_names; lang->name != NULL; lang++)
556 printf ("\t%s\t", lang->name);
557 if (lang->suffixes != NULL)
558 for (ext = lang->suffixes; *ext != NULL; ext++)
559 printf (" .%s", *ext);
562 puts ("Where `auto' means use default language for files based on file\n\
563 name suffix, and `none' means only do regexp processing on files.\n\
564 If no language is specified and no matching suffix is found,\n\
565 the first line of the file is read for a sharp-bang (#!) sequence\n\
566 followed by the name of an interpreter. If no such sequence is found,\n\
567 Fortran is tried first; if no tags are found, C is tried next.");
571 # define VERSION "20"
576 printf ("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION);
577 puts ("Copyright (C) 1996 Free Software Foundation, Inc. and Ken Arnold");
578 puts ("This program is distributed under the same terms as Emacs");
586 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
588 These are the options accepted by %s.\n", progname, progname);
590 puts ("You may use unambiguous abbreviations for the long option names.");
592 puts ("Long option names do not work with this executable, as it is not\n\
593 linked with GNU getopt.");
594 #endif /* LONG_OPTIONS */
595 puts ("A - as file name means read names from stdin (one per line).");
597 printf (" Absolute names are stored in the output file as they are.\n\
598 Relative ones are stored relative to the output file's directory.");
601 puts ("-a, --append\n\
602 Append tag entries to existing tags file.");
605 puts ("-B, --backward-search\n\
606 Write the search commands for the tag entries using '?', the\n\
607 backward-search command instead of '/', the forward-search command.");
610 Treat files whose name suffix defaults to C language as C++ files.");
613 puts ("-d, --defines\n\
614 Create tag entries for C #define constants and enum constants, too.");
616 puts ("-D, --no-defines\n\
617 Don't create tag entries for C #define constants and enum constants.\n\
618 This makes the tags file smaller.");
622 puts ("-i FILE, --include=FILE\n\
623 Include a note in tag file indicating that, when searching for\n\
624 a tag, one should also consult the tags file FILE after\n\
625 checking the current file.");
626 puts ("-l LANG, --language=LANG\n\
627 Force the following files to be considered as written in the\n\
628 named language up to the next --language=LANG option.");
633 Create tag entries for global variables in some languages.");
635 puts ("--no-globals\n\
636 Do not create tag entries for global variables in some\n\
637 languages. This makes the tags file smaller.");
639 Create tag entries for member variables in C and derived languages.");
642 puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
643 Make a tag for each line matching pattern REGEXP in the\n\
644 following files. regexfile is a file containing one REGEXP\n\
645 per line. REGEXP is anchored (as if preceded by ^).\n\
646 The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
647 named tags can be created with:\n\
648 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
649 puts ("-R, --no-regex\n\
650 Don't create tags from regexps for the following files.");
651 #endif /* ETAGS_REGEXPS */
652 puts ("-o FILE, --output=FILE\n\
653 Write the tags to FILE.");
655 puts ("-O, --oo-browser\n\
656 Generate a specialized tags format used only by the Altrasoft OO-Browser.");
658 puts ("-I, --ignore-indentation\n\
659 Don't rely on indentation quite as much as normal. Currently,\n\
660 this means not to assume that a closing brace in the first\n\
661 column is the final brace of a function or structure\n\
662 definition in C and C++.");
666 puts ("-t, --typedefs\n\
667 Generate tag entries for C typedefs.");
668 puts ("-T, --typedefs-and-c++\n\
669 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
670 and C++ member functions.");
671 puts ("-u, --update\n\
672 Update the tag entries for the given files, leaving tag\n\
673 entries for other files in place. Currently, this is\n\
674 implemented by deleting the existing entries for the given\n\
675 files and then rewriting the new entries at the end of the\n\
676 tags file. It is often faster to simply rebuild the entire\n\
677 tag file than to use this.");
678 puts ("-v, --vgrind\n\
679 Generates an index of items intended for human consumption,\n\
680 similar to the output of vgrind. The index is sorted, and\n\
681 gives the page number of each item.");
682 puts ("-w, --no-warn\n\
683 Suppress warning messages about entries defined in multiple\n\
685 puts ("-x, --cxref\n\
686 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
687 The output uses line numbers instead of page numbers, but\n\
688 beyond that the differences are cosmetic; try both to see\n\
692 puts ("-V, --version\n\
693 Print the version of the program.\n\
695 Print this help message.");
697 print_language_names ();
700 puts ("Report bugs to bug-gnu-emacs@prep.ai.mit.edu");
713 /* This structure helps us allow mixing of --lang and file names. */
716 enum argument_type arg_type;
721 #ifdef VMS /* VMS specific functions */
725 /* This is a BUG! ANY arbitrary limit is a BUG!
726 Won't someone please fix this? */
727 #define MAX_FILE_SPEC_LEN 255
730 char body[MAX_FILE_SPEC_LEN + 1];
734 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
735 returning in each successive call the next file name matching the input
736 spec. The function expects that each in_spec passed
737 to it will be processed to completion; in particular, up to and
738 including the call following that in which the last matching name
739 is returned, the function ignores the value of in_spec, and will
740 only start processing a new spec with the following call.
741 If an error occurs, on return out_spec contains the value
742 of in_spec when the error occurred.
744 With each successive file name returned in out_spec, the
745 function's return value is one. When there are no more matching
746 names the function returns zero. If on the first call no file
747 matches in_spec, or there is any other error, -1 is returned.
752 #define OUTSIZE MAX_FILE_SPEC_LEN
758 static long context = 0;
759 static struct dsc$descriptor_s o;
760 static struct dsc$descriptor_s i;
761 static bool pass1 = TRUE;
768 o.dsc$a_pointer = (char *) out;
769 o.dsc$w_length = (short)OUTSIZE;
770 i.dsc$a_pointer = in;
771 i.dsc$w_length = (short)strlen(in);
772 i.dsc$b_dtype = DSC$K_DTYPE_T;
773 i.dsc$b_class = DSC$K_CLASS_S;
774 o.dsc$b_dtype = DSC$K_DTYPE_VT;
775 o.dsc$b_class = DSC$K_CLASS_VS;
777 if ((status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL)
779 out->body[out->curlen] = EOS;
782 else if (status == RMS$_NMF)
786 strcpy(out->body, in);
789 lib$find_file_end(&context);
795 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
796 name of each file specified by the provided arg expanding wildcards.
799 gfnames (arg, p_error)
803 static vspec filename = {MAX_FILE_SPEC_LEN, "\0"};
805 switch (fn_exp (&filename, arg))
809 return filename.body;
815 return filename.body;
819 #ifndef OLD /* Newer versions of VMS do provide `system'. */
823 error ("%s", "system() function not implemented under VMS");
827 #define VERSION_DELIM ';'
828 char *massage_name (s)
834 if (*s == VERSION_DELIM)
847 main (int argc, char *argv[])
850 unsigned int nincluded_files;
851 char **included_files;
854 int current_arg, file_count;
855 linebuffer filename_lb;
861 _fmode = O_BINARY; /* all of files are treated as binary files */
862 #endif /* WIN32_NATIVE */
866 included_files = xnew (argc, char *);
870 /* Allocate enough no matter what happens. Overkill, but each one
872 argbuffer = xnew (argc, argument);
875 /* Set syntax for regular expression routines. */
876 re_set_syntax (RE_SYNTAX_EMACS | RE_INTERVALS);
877 #endif /* ETAGS_REGEXPS */
880 * If etags, always find typedefs and structure tags. Why not?
881 * Also default is to find macro constants, enum constants and
886 typedefs = typedefs_and_cplusplus = constantypedefs = TRUE;
898 optstring = "-aCdDf:Il:o:r:RStTi:BuvxwVhH";
900 optstring = "-aCdDf:Il:o:r:RStTi:BOuvxwVhH";
904 optstring = "-aCdDf:Il:o:StTi:BuvxwVhH";
906 optstring = "-aCdDf:Il:o:StTi:BOuvxwVhH";
908 #endif /* ETAGS_REGEXPS */
911 optstring = optstring + 1;
912 #endif /* LONG_OPTIONS */
914 opt = getopt_long (argc, argv, optstring, longopts, 0);
921 /* If getopt returns 0, then it has already processed a
922 long-named option. We should do nothing. */
926 /* This means that a file name has been seen. Record it. */
927 argbuffer[current_arg].arg_type = at_filename;
928 argbuffer[current_arg].what = optarg;
933 /* Common options. */
934 case 'a': append_to_tagfile = TRUE; break;
935 case 'C': cplusplus = TRUE; break;
936 case 'd': constantypedefs = TRUE; break;
937 case 'D': constantypedefs = FALSE; break;
938 case 'f': /* for compatibility with old makefiles */
942 /* convert char to string, to call error with */
944 sprintf (buf, "%c", opt);
945 error ("-%s option may only be given once.", buf);
946 suggest_asking_for_help ();
952 oo_browser_format = TRUE;
956 case 'S': /* for backward compatibility */
957 noindentypedefs = TRUE;
961 language *lang = get_language_from_name (optarg);
964 argbuffer[current_arg].lang = lang;
965 argbuffer[current_arg].arg_type = at_language;
972 argbuffer[current_arg].arg_type = at_regexp;
973 argbuffer[current_arg].what = optarg;
977 argbuffer[current_arg].arg_type = at_regexp;
978 argbuffer[current_arg].what = NULL;
981 #endif /* ETAGS_REGEXPS */
993 typedefs = typedefs_and_cplusplus = TRUE;
998 included_files[nincluded_files++] = optarg;
1001 /* Ctags options. */
1002 case 'B': searchar = '?'; break;
1003 case 'u': update = TRUE; break;
1004 case 'v': vgrind_style = TRUE; /*FALLTHRU*/
1005 case 'x': cxref_style = TRUE; break;
1006 case 'w': no_warnings = TRUE; break;
1009 suggest_asking_for_help ();
1013 for (; optind < argc; ++optind)
1015 argbuffer[current_arg].arg_type = at_filename;
1016 argbuffer[current_arg].what = argv[optind];
1021 if (nincluded_files == 0 && file_count == 0)
1023 error ("no input files specified.", 0);
1024 suggest_asking_for_help ();
1027 if (tagfile == NULL)
1028 tagfile = CTAGS ? "tags" : "TAGS";
1029 cwd = etags_getcwd (); /* the current working directory */
1030 if (cwd[strlen (cwd) - 1] != '/')
1033 cwd = concat (oldcwd, "/", "");
1036 if (streq (tagfile, "-"))
1039 tagfiledir = absolute_dirname (tagfile, cwd);
1041 init (); /* set up boolean "functions" */
1044 initbuffer (&token_name);
1045 initbuffer (&lbs[0].lb);
1046 initbuffer (&lbs[1].lb);
1047 initbuffer (&filename_lb);
1051 if (streq (tagfile, "-"))
1055 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1056 doesn't take effect until after `stdout' is already open). */
1057 if (!isatty (fileno (stdout)))
1058 setmode (fileno (stdout), O_BINARY);
1059 #endif /* WIN32_NATIVE */
1062 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1068 * Loop through files finding functions.
1070 for (i = 0; i < current_arg; ++i)
1072 switch (argbuffer[i].arg_type)
1075 forced_lang = argbuffer[i].lang;
1077 #ifdef ETAGS_REGEXPS
1079 analyse_regex (argbuffer[i].what);
1084 while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL)
1088 error ("can't find file %s\n", this_file);
1093 this_file = massage_name (this_file);
1096 this_file = argbuffer[i].what;
1099 oo_browser_clear_all_globals();
1101 /* Input file named "-" means read file names from stdin
1102 (one per line) and use them. */
1103 if (streq (this_file, "-"))
1104 while (readline_internal (&filename_lb, stdin) > 0)
1107 oo_browser_clear_some_globals();
1109 process_file (filename_lb.buffer);
1114 process_file (this_file);
1122 #ifdef ETAGS_REGEXPS
1124 #endif /* ETAGS_REGEXPS */
1128 while (nincluded_files-- > 0)
1129 fprintf (tagf, "\f\n%s,include\n", *included_files++);
1135 /* If CTAGS, we are here. process_file did not write the tags yet,
1136 because we want them ordered. Let's do it now. */
1146 for (i = 0; i < current_arg; ++i)
1148 if (argbuffer[i].arg_type != at_filename)
1151 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1152 tagfile, argbuffer[i].what, tagfile);
1153 if (system (cmd) != GOOD)
1154 fatal ("failed to execute shell command", (char *)NULL);
1156 append_to_tagfile = TRUE;
1159 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1168 sprintf (cmd, "sort %s -o %s", tagfile, tagfile);
1169 exit (system (cmd));
1176 * Return a language given the name.
1179 get_language_from_name (name)
1185 error ("empty language name", (char *)NULL);
1188 for (lang = lang_names; lang->name != NULL; lang++)
1189 if (streq (name, lang->name))
1191 error ("unknown language \"%s\"", name);
1199 * Return a language given the interpreter name.
1202 get_language_from_interpreter (interpreter)
1208 if (interpreter == NULL)
1210 for (lang = lang_names; lang->name != NULL; lang++)
1211 if (lang->interpreters != NULL)
1212 for (iname = lang->interpreters; *iname != NULL; iname++)
1213 if (streq (*iname, interpreter))
1222 * Return a language given the file suffix.
1225 get_language_from_suffix (suffix)
1233 for (lang = lang_names; lang->name != NULL; lang++)
1234 if (lang->suffixes != NULL)
1235 for (ext = lang->suffixes; *ext != NULL; ext++)
1236 if (streq (*ext, suffix))
1244 * This routine is called on each file argument.
1250 struct stat stat_buf;
1253 canonicalize_filename (file);
1254 if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode))
1256 error ("skipping %s: it is not a regular file.", file);
1259 if (streq (file, tagfile) && !streq (tagfile, "-"))
1261 error ("skipping inclusion of %s in self.", file);
1264 inf = fopen (file, "r");
1271 find_entries (file, inf);
1277 if (filename_is_absolute (file))
1279 /* file is an absolute file name. Canonicalise it. */
1280 filename = absolute_filename (file, cwd);
1284 /* file is a file name relative to cwd. Make it relative
1285 to the directory of the tags file. */
1286 filename = relative_filename (file, tagfiledir);
1289 if (oo_browser_format)
1290 fprintf (tagf, "\f\n%s\n", filename);
1293 fprintf (tagf, "\f\n%s,%d\n", filename, total_size_of_entries (head));
1302 * This routine sets up the boolean pseudo-functions which work
1303 * by setting boolean flags dependent upon the corresponding character.
1304 * Every char which is NOT in that string is not a white char. Therefore,
1305 * all of the array "_wht" is set to FALSE, and then the elements
1306 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1307 * of a char is TRUE if it is the string "white", else FALSE.
1315 for (i = 0; i < CHARS; i++)
1316 iswhite(i) = notinname(i) = begtoken(i) = intoken(i) = endtoken(i) = FALSE;
1317 for (sp = white; *sp != '\0'; sp++) iswhite (*sp) = TRUE;
1318 for (sp = nonam; *sp != '\0'; sp++) notinname (*sp) = TRUE;
1319 for (sp = begtk; *sp != '\0'; sp++) begtoken (*sp) = TRUE;
1320 for (sp = midtk; *sp != '\0'; sp++) intoken (*sp) = TRUE;
1321 for (sp = endtk; *sp != '\0'; sp++) endtoken (*sp) = TRUE;
1322 iswhite('\0') = iswhite('\n');
1323 notinname('\0') = notinname('\n');
1324 begtoken('\0') = begtoken('\n');
1325 intoken('\0') = intoken('\n');
1326 endtoken('\0') = endtoken('\n');
1330 * This routine opens the specified file and calls the function
1331 * which finds the function and type definitions.
1333 node *last_node = NULL;
1336 find_entries (file, inf)
1342 node *old_last_node;
1344 curfile = savestr (file);
1346 /* If user specified a language, use it. */
1348 if (lang != NULL && lang->function != NULL)
1351 lang->function (inf);
1357 cp = etags_strrchr (file, '.');
1361 lang = get_language_from_suffix (cp);
1362 if (lang != NULL && lang->function != NULL)
1365 lang->function (inf);
1372 /* Look for sharp-bang as the first two characters. */
1373 if (readline_internal (&lb, inf) > 0
1375 && lb.buffer[0] == '#'
1376 && lb.buffer[1] == '!')
1380 /* Set lp to point at the first char after the last slash in the
1381 line or, if no slashes, at the first nonblank. Then set cp to
1382 the first successive blank and terminate the string. */
1383 lp = etags_strrchr (lb.buffer+2, '/');
1387 lp = skip_spaces (lb.buffer + 2);
1388 cp = skip_non_spaces (lp);
1391 if (strlen (lp) > 0)
1393 lang = get_language_from_interpreter (lp);
1394 if (lang != NULL && lang->function != NULL)
1397 lang->function (inf);
1407 old_last_node = last_node;
1408 curlang = get_language_from_name ("fortran");
1409 Fortran_functions (inf);
1411 /* No Fortran entries found. Try C. */
1412 if (old_last_node == last_node)
1415 curlang = get_language_from_name (cplusplus ? "c++" : "c");
1416 default_C_entries (inf);
1425 pfnote (name, is_func, linestart, linelen, lno, cno)
1426 char *name; /* tag name, or NULL if unnamed */
1427 bool is_func; /* tag is a function */
1428 char *linestart; /* start of the line where tag is */
1429 int linelen; /* length of the line where tag is */
1430 int lno; /* line number */
1431 long cno; /* character number */
1435 if (CTAGS && name == NULL)
1438 np = xnew (1, node);
1440 /* If ctags mode, change name "main" to M<thisfilename>. */
1441 if (CTAGS && !cxref_style && streq (name, "main"))
1443 register char *fp = etags_strrchr (curfile, '/');
1444 np->name = concat ("M", fp == 0 ? curfile : fp + 1, "");
1445 fp = etags_strrchr (np->name, '.');
1446 if (fp && fp[1] != '\0' && fp[2] == '\0')
1451 np->been_warned = FALSE;
1453 np->is_func = is_func;
1455 /* Our char numbers are 0-base, because of C language tradition?
1456 ctags compatibility? old versions compatibility? I don't know.
1457 Anyway, since emacs's are 1-base we expect etags.el to take care
1458 of the difference. If we wanted to have 1-based numbers, we would
1459 uncomment the +1 below. */
1460 np->cno = cno /* + 1 */ ;
1461 np->left = np->right = NULL;
1462 if (CTAGS && !cxref_style)
1464 if (strlen (linestart) < 50)
1465 np->pat = concat (linestart, "$", "");
1467 np->pat = savenstr (linestart, 50);
1470 np->pat = savenstr (linestart, linelen);
1473 if (oo_browser_format)
1474 np->construct = oo_browser_construct;
1475 oo_browser_construct = C_NULL;
1476 oo_browser_check_and_clear_structtype();
1479 add_node (np, &head);
1482 /* Date: Wed, 22 Jan 1997 02:56:31 -0500 [last amended 18 Sep 1997]
1483 * From: Sam Kendall <kendall@mv.mv.com>
1484 * Subject: Proposal for firming up the TAGS format specification
1485 * To: F.Potorti@cnuce.cnr.it
1487 * pfnote should emit the optimized form [unnamed tag] only if:
1488 * 1. name does not contain any of the characters " \t\r\n(),;";
1489 * 2. linestart contains name as either a rightmost, or rightmost but
1490 * one character, substring;
1491 * 3. the character, if any, immediately before name in linestart must
1492 * be one of the characters " \t(),;";
1493 * 4. the character, if any, immediately after name in linestart must
1494 * also be one of the characters " \t(),;".
1496 * The real implementation uses the notinname() macro, which recognises
1497 * characters slightly different form " \t\r\n(),;". See the variable
1500 #define traditional_tag_style TRUE
1502 new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno)
1503 char *name; /* tag name, or NULL if unnamed */
1504 int namelen; /* tag length */
1505 bool is_func; /* tag is a function */
1506 char *linestart; /* start of the line where tag is */
1507 int linelen; /* length of the line where tag is */
1508 int lno; /* line number */
1509 long cno; /* character number */
1517 for (cp = name; !notinname (*cp); cp++)
1519 if (*cp == '\0') /* rule #1 */
1521 cp = linestart + linelen - namelen;
1522 if (notinname (linestart[linelen-1]))
1523 cp -= 1; /* rule #4 */
1525 if (!oo_browser_format
1526 && cp >= linestart /* rule #2 */
1528 if (cp >= linestart /* rule #2 */
1531 || notinname (cp[-1])) /* rule #3 */
1532 && strneq (name, cp, namelen)) /* rule #2 */
1533 named = FALSE; /* use unnamed tag */
1538 name = savenstr (name, namelen);
1541 pfnote (name, is_func, linestart, linelen, lno, cno);
1546 * recurse on left children, iterate on right children.
1554 register node *node_right = np->right;
1555 free_tree (np->left);
1556 if (np->name != NULL)
1566 * Adds a node to the tree of nodes. In etags mode, we don't keep
1567 * it sorted; we just keep a linear list. In ctags mode, maintain
1568 * an ordered tree, with no attempt at balancing.
1570 * add_node is the only function allowed to add nodes, so it can
1574 add_node (np, cur_node_p)
1575 node *np, **cur_node_p;
1578 register node *cur_node = *cur_node_p;
1580 if (cur_node == NULL)
1590 if (last_node == NULL)
1591 fatal ("internal error in add_node", (char *)NULL);
1592 last_node->right = np;
1598 dif = strcmp (np->name, cur_node->name);
1601 * If this tag name matches an existing one, then
1602 * do not add the node, but maybe print a warning.
1606 if (streq (np->file, cur_node->file))
1610 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1611 np->file, lineno, np->name);
1612 fprintf (stderr, "Second entry ignored\n");
1615 else if (!cur_node->been_warned && !no_warnings)
1619 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1620 np->file, cur_node->file, np->name);
1621 cur_node->been_warned = TRUE;
1626 /* Actually add the node */
1627 add_node (np, dif < 0 ? &cur_node->left : &cur_node->right);
1632 /* Default class name for the current OO-Browser tag. */
1633 static char *oo_browser_class;
1634 /* Prefix character to use in OO-Browser listings for the current tag. */
1635 static char oo_browser_prefix;
1639 put_entries (node *np)
1646 /* Output subentries that precede this one */
1647 put_entries (np->left);
1649 /* Output this entry */
1654 if (oo_browser_format)
1656 /* Omit C++ `class' and `method' entries as well as Objective-C
1657 entries from this OO-Browser tags file since the browser handles
1658 them independently of this file. Omit `extern' variable declarations
1659 as they are unused by the OO-Browser. */
1660 if (np->construct != C_CLASS
1661 && np->construct != C_METHOD
1662 && np->construct != C_EXTERN
1663 && np->construct != C_OBJC)
1665 oo_browser_class = oo_browser_default_classes[np->construct];
1666 switch (np->construct)
1675 oo_browser_prefix = '=';
1679 oo_browser_prefix = '-';
1682 if (np->name != NULL)
1683 fprintf (tagf, "%s@%c %s@%s\n",
1684 oo_browser_class, oo_browser_prefix,
1687 fprintf (tagf, "%s@%c ???@%s\n",
1688 oo_browser_class, oo_browser_prefix, np->pat);
1694 if (np->name != NULL)
1695 fprintf (tagf, "%s\177%s\001%d,%ld\n",
1696 np->pat, np->name, np->lno, np->cno);
1698 fprintf (tagf, "%s\177%d,%ld\n",
1699 np->pat, np->lno, np->cno);
1706 if (np->name == NULL)
1707 error ("internal error: NULL name in ctags mode.", (char *)NULL);
1712 fprintf (stdout, "%s %s %d\n",
1713 np->name, np->file, (np->lno + 63) / 64);
1715 fprintf (stdout, "%-16s %3d %-16s %s\n",
1716 np->name, np->lno, np->file, np->pat);
1720 fprintf (tagf, "%s\t%s\t", np->name, np->file);
1724 putc (searchar, tagf);
1727 for (sp = np->pat; *sp; sp++)
1729 if (*sp == '\\' || *sp == searchar)
1733 putc (searchar, tagf);
1736 { /* a typedef; text pattern inadequate */
1737 fprintf (tagf, "%d", np->lno);
1743 /* Output subentries that follow this one */
1744 put_entries (np->right);
1747 /* Length of a number's decimal representation. */
1748 int number_len PP ((long num));
1754 while ((num /= 10) > 0)
1760 * Return total number of characters that put_entries will output for
1761 * the nodes in the subtree of the specified node. Works only if
1762 * we are not ctags, but called only in that case. This count
1763 * is irrelevant with the new tags.el, but is still supplied for
1764 * backward compatibility.
1767 total_size_of_entries (np)
1775 for (total = 0; np != NULL; np = np->right)
1777 /* Count left subentries. */
1778 total += total_size_of_entries (np->left);
1780 /* Count this entry */
1781 total += strlen (np->pat) + 1;
1782 total += number_len ((long) np->lno) + 1 + number_len (np->cno) + 1;
1783 if (np->name != NULL)
1784 total += 1 + strlen (np->name); /* \001name */
1791 * The C symbol tables.
1796 st_C_objprot, st_C_objimpl, st_C_objend,
1800 st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec,
1803 , st_C_union, st_C_class, st_C_extern, st_C_inline
1807 /* Feed stuff between (but not including) %[ and %] lines to:
1808 gperf -c -k 1,3 -o -p -r -t
1810 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1812 @interface, 0, st_C_objprot
1813 @protocol, 0, st_C_objprot
1814 @implementation,0, st_C_objimpl
1815 @end, 0, st_C_objend
1816 import, C_JAVA, st_C_ignore
1817 package, C_JAVA, st_C_ignore
1818 friend, C_PLPL, st_C_ignore
1819 extends, C_JAVA, st_C_javastruct
1820 implements, C_JAVA, st_C_javastruct
1821 interface, C_JAVA, st_C_struct
1822 class, C_PLPL, st_C_class
1823 namespace, C_PLPL, st_C_struct
1824 domain, C_STAR, st_C_struct
1825 union, 0, st_C_union
1826 struct, 0, st_C_struct
1828 typedef, 0, st_C_typedef
1829 define, 0, st_C_define
1830 inline, 0, st_C_inline
1831 bool, C_PLPL, st_C_typespec
1832 long, 0, st_C_typespec
1833 short, 0, st_C_typespec
1834 int, 0, st_C_typespec
1835 char, 0, st_C_typespec
1836 float, 0, st_C_typespec
1837 double, 0, st_C_typespec
1838 signed, 0, st_C_typespec
1839 unsigned, 0, st_C_typespec
1840 auto, 0, st_C_typespec
1841 void, 0, st_C_typespec
1842 extern, 0, st_C_extern
1843 static, 0, st_C_typespec
1844 const, 0, st_C_const
1845 volatile, 0, st_C_typespec
1846 explicit, C_PLPL, st_C_typespec
1847 mutable, C_PLPL, st_C_typespec
1848 typename, C_PLPL, st_C_typespec
1849 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
1850 DEFUN, 0, st_C_gnumacro
1851 SYSCALL, 0, st_C_gnumacro
1852 ENTRY, 0, st_C_gnumacro
1853 PSEUDO, 0, st_C_gnumacro
1854 # These are defined inside C functions, so currently they are not met.
1855 # EXFUN used in glibc, DEFVAR_* in emacs.
1856 #EXFUN, 0, st_C_gnumacro
1857 #DEFVAR_, 0, st_C_gnumacro
1859 and replace lines between %< and %> with its output. */
1861 /* C code produced by gperf version 2.5 (GNU C++ version) */
1862 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
1863 struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
1865 #define TOTAL_KEYWORDS 41
1866 #define MIN_WORD_LENGTH 3
1867 #define MAX_WORD_LENGTH 15
1868 #define MIN_HASH_VALUE 13
1869 #define MAX_HASH_VALUE 129
1870 /* maximum key range = 117, duplicates = 0 */
1873 hash (char *str, unsigned int len)
1875 static unsigned char asso_values[] =
1877 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1878 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1879 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1880 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1881 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1882 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1883 130, 130, 130, 130, 13, 130, 130, 130, 33, 32,
1884 47, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1885 5, 130, 130, 20, 32, 130, 130, 130, 130, 130,
1886 130, 130, 130, 130, 130, 130, 130, 47, 55, 8,
1887 15, 33, 61, 38, 130, 60, 130, 130, 2, 9,
1888 10, 62, 59, 130, 28, 27, 50, 19, 3, 130,
1889 130, 130, 130, 130, 130, 130, 130, 130,
1892 asso_values[(unsigned char) str[2]] +
1893 asso_values[(unsigned char) str[0]];
1896 static struct C_stab_entry *
1897 in_word_set (char *str, unsigned int len)
1899 static struct C_stab_entry wordlist[] =
1901 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1902 {"",}, {"",}, {"",}, {"",},
1903 {"volatile", 0, st_C_typespec},
1905 {"long", 0, st_C_typespec},
1906 {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1907 {"const", 0, st_C_const},
1908 {"",}, {"",}, {"",},
1909 {"@end", 0, st_C_objend},
1910 {"namespace", C_PLPL, st_C_struct},
1912 {"domain", C_STAR, st_C_struct},
1914 {"@interface", 0, st_C_objprot},
1915 {"",}, {"",}, {"",},
1916 {"@implementation", 0, st_C_objimpl},
1918 {"double", 0, st_C_typespec},
1920 {"PSEUDO", 0, st_C_gnumacro},
1921 {"",}, {"",}, {"",},
1922 {"SYSCALL", 0, st_C_gnumacro},
1924 {"@protocol", 0, st_C_objprot},
1925 {"",}, {"",}, {"",},
1926 {"unsigned", 0, st_C_typespec},
1928 {"enum", 0, st_C_enum},
1930 {"char", 0, st_C_typespec},
1931 {"class", C_PLPL, st_C_class},
1932 {"struct", 0, st_C_struct},
1933 {"",}, {"",}, {"",}, {"",},
1934 {"mutable", C_PLPL, st_C_typespec},
1935 {"void", 0, st_C_typespec},
1936 {"inline", 0, st_C_inline},
1937 {"ENTRY", 0, st_C_gnumacro},
1939 {"signed", 0, st_C_typespec},
1941 {"package", C_JAVA, st_C_ignore},
1942 {"",}, {"",}, {"",}, {"",}, {"",},
1943 {"static", 0, st_C_typespec},
1945 {"define", 0, st_C_define},
1947 {"union", 0, st_C_union},
1948 {"DEFUN", 0, st_C_gnumacro},
1949 {"",}, {"",}, {"",},
1950 {"extern", 0, st_C_extern},
1951 {"extends", C_JAVA, st_C_javastruct},
1952 {"",}, {"",}, {"",},
1953 {"short", 0, st_C_typespec},
1954 {"",}, {"",}, {"",}, {"",}, {"",},
1955 {"explicit", C_PLPL, st_C_typespec},
1956 {"auto", 0, st_C_typespec},
1957 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1959 {"int", 0, st_C_typespec},
1961 {"typedef", 0, st_C_typedef},
1962 {"typename", C_PLPL, st_C_typespec},
1964 {"interface", C_JAVA, st_C_struct},
1966 {"bool", C_PLPL, st_C_typespec},
1967 {"",}, {"",}, {"",},
1968 {"import", C_JAVA, st_C_ignore},
1970 {"friend", C_PLPL, st_C_ignore},
1971 {"float", 0, st_C_typespec},
1972 {"implements", C_JAVA, st_C_javastruct},
1975 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
1977 register int key = hash (str, len);
1979 if (key <= MAX_HASH_VALUE && key >= 0)
1981 register char *s = wordlist[key].name;
1983 if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
1984 return &wordlist[key];
1991 enum sym_type C_symtype PP ((char *str, int len, int c_ext));
1993 C_symtype (str, len, c_ext)
1998 register struct C_stab_entry *se = in_word_set (str, len);
2000 if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
2006 * C functions and variables are recognized using a simple
2007 * finite automaton. fvdef is its state variable.
2011 fvnone, /* nothing seen */
2012 fvnameseen, /* function or variable name seen */
2013 fstartlist, /* func: just after open parenthesis */
2014 finlist, /* func: in parameter list */
2015 flistseen, /* func: after parameter list */
2016 fignore, /* func: before open brace */
2017 vignore /* var-like: ignore until ';' */
2022 * typedefs are recognized using a simple finite automaton.
2023 * typdef is its state variable.
2027 tnone, /* nothing seen */
2028 ttypedseen, /* typedef keyword seen */
2029 tinbody, /* inside typedef body */
2030 tend, /* just before typedef tag */
2031 tignore /* junk after typedef tag */
2036 * struct-like structures (enum, struct and union) are recognized
2037 * using another simple finite automaton. `structdef' is its state
2042 snone, /* nothing seen yet */
2043 skeyseen, /* struct-like keyword seen */
2044 stagseen, /* struct-like tag seen */
2045 scolonseen, /* colon seen after struct-like tag */
2046 sinbody /* in struct body: recognize member func defs*/
2050 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
2051 * struct tag, and structtype is the type of the preceding struct-like
2054 char *structtag = "<uninited>";
2055 enum sym_type structtype;
2059 oo_browser_check_and_clear_structtype(void)
2061 /* Allow for multiple enum_label tags. */
2062 if (structtype != st_C_enum)
2063 structtype = st_none;
2068 * When objdef is different from onone, objtag is the name of the class.
2070 char *objtag = "<uninited>";
2073 * Yet another little state machine to deal with preprocessor lines.
2077 dnone, /* nothing seen */
2078 dsharpseen, /* '#' seen as first char on line */
2079 ddefineseen, /* '#' and 'define' seen */
2080 dignorerest /* ignore rest of line */
2084 * State machine for Objective C protocols and implementations.
2085 * Tom R.Hageman <tom@basil.icce.rug.nl>
2089 onone, /* nothing seen */
2090 oprotocol, /* @interface or @protocol seen */
2091 oimplementation, /* @implementations seen */
2092 otagseen, /* class name seen */
2093 oparenseen, /* parenthesis before category seen */
2094 ocatseen, /* category name seen */
2095 oinbody, /* in @implementation body */
2096 omethodsign, /* in @implementation body, after +/- */
2097 omethodtag, /* after method name */
2098 omethodcolon, /* after method colon */
2099 omethodparm, /* after method parameter */
2100 oignore /* wait for @end */
2104 * Use this structure to keep info about the token read, and how it
2105 * should be tagged. Used by the make_C_tag function to build a tag.
2118 token tok; /* latest token read */
2121 * Set this to TRUE, and the next token considered is called a function.
2122 * Used only for GNU emacs's function-defining macros.
2124 bool next_token_is_func;
2127 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
2132 * methodlen is the length of the method name stored in token_name.
2138 oo_browser_clear_all_globals(void)
2140 /* Initialize globals so there is no carry over between files. */
2141 oo_browser_construct = C_NULL;
2142 fvdef = fvnone; typdef = tnone; structdef = snone;
2143 definedef = dnone; objdef = onone;
2144 structtype = st_none;
2145 next_token_is_func = yacc_rules = FALSE;
2149 oo_browser_clear_some_globals(void)
2151 oo_browser_construct = C_NULL;
2152 structtype = st_none;
2158 * checks to see if the current token is at the start of a
2159 * function or variable, or corresponds to a typedef, or
2160 * is a struct/union/enum tag, or #define, or an enum constant.
2162 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2163 * with args. C_EXT is which language we are looking at.
2165 * In the future we will need some way to adjust where the end of
2166 * the token is; for instance, implementing the C++ keyword
2167 * `operator' properly will adjust the end of the token to be after
2168 * whatever follows `operator'.
2176 * next_token_is_func IN OUT
2178 bool consider_token PP ((char *str, int len, int c, int c_ext,
2179 int cblev, int parlev, bool *is_func_or_var));
2181 consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var)
2182 register char *str; /* IN: token pointer */
2183 register int len; /* IN: token length */
2184 register int c; /* IN: first char after the token */
2185 int c_ext; /* IN: C extensions mask */
2186 int cblev; /* IN: curly brace level */
2187 int parlev; /* IN: parenthesis level */
2188 bool *is_func_or_var; /* OUT: function or variable found */
2190 enum sym_type toktype = C_symtype (str, len, c_ext);
2196 set_construct(C_STRUCTURE);
2199 set_construct(C_UNION);
2202 set_construct(C_CLASS);
2205 set_construct(C_ENUMERATION);
2208 set_construct(C_TYPE);
2211 set_construct(C_EXTERN);
2214 set_construct(C_FUNCTION);
2220 * Advance the definedef state machine.
2225 /* We're not on a preprocessor line. */
2228 if (toktype == st_C_define)
2230 definedef = ddefineseen;
2234 definedef = dignorerest;
2239 * Make a tag for any macro, unless it is a constant
2240 * and constantypedefs is FALSE.
2242 definedef = dignorerest;
2244 *is_func_or_var = (c == '(');
2247 char *p = str + len * sizeof(char);
2250 /* This must be a macro since there is no
2251 whitespace between the opening parenthesis
2252 and the definition name. */
2253 *is_func_or_var = TRUE;
2256 *is_func_or_var = FALSE;
2258 /* Handle possible whitespace between macro tag and opening
2259 parenthesis and ensure this is an actual macro.
2260 -- Bob Weiner, Altrasoft, 11/19/1997 */
2261 while (*p && isspace(*p)) p++;
2264 /* Skip over nested parentheses. */
2269 while (*++p && depth > 0 && *p != '\n')
2280 /* If this is a macro, we have just passed
2281 the arguments and there will be more on
2282 the line before the NULL character that marks
2283 the end of the line token. */
2284 while (*p == ' ' || *p == '\t') p++;
2285 if (*p) *is_func_or_var = TRUE;
2290 set_construct((*is_func_or_var) ? C_MACRO : C_CONSTANT);
2292 if (!*is_func_or_var && !constantypedefs)
2299 error ("internal error: definedef value.", (char *)NULL);
2308 if (toktype == st_C_typedef)
2311 typdef = ttypedseen;
2320 set_construct(C_CONSTANT);
2337 /* Do not return here, so the structdef stuff has a chance. */
2343 set_construct(C_CONSTANT);
2359 * This structdef business is currently only invoked when cblev==0.
2360 * It should be recursively invoked whatever the curly brace level,
2361 * and a stack of states kept, to allow for definitions of structs
2364 * This structdef business is NOT invoked when we are ctags and the
2365 * file is plain C. This is because a struct tag may have the same
2366 * name as another tag, and this loses with ctags.
2370 case st_C_javastruct:
2371 if (structdef == stagseen)
2372 structdef = scolonseen;
2381 if (typdef == ttypedseen
2382 || (typedefs_and_cplusplus && cblev == 0 && structdef == snone))
2384 structdef = skeyseen;
2385 structtype = toktype;
2390 if (structdef == skeyseen)
2392 /* Save the tag for struct/union/class, for functions and variables
2393 that may be defined inside. */
2395 if (structtype == st_C_struct)
2397 if (structtype == st_C_struct
2398 || structtype == st_C_union
2399 || structtype == st_C_class)
2401 structtag = savenstr (str, len);
2403 structtag = "<enum>";
2404 structdef = stagseen;
2408 /* Avoid entering fvdef stuff if typdef is going on. */
2409 if (typdef != tnone)
2415 /* Detect GNU macros.
2417 DEFUN note for writers of emacs C code:
2418 The DEFUN macro, used in emacs C source code, has a first arg
2419 that is a string (the lisp function name), and a second arg that
2420 is a C function name. Since etags skips strings, the second arg
2421 is tagged. This is unfortunate, as it would be better to tag the
2422 first arg. The simplest way to deal with this problem would be
2423 to name the tag with a name built from the function name, by
2424 removing the initial 'F' character and substituting '-' for '_'.
2425 Anyway, this assumes that the conventions of naming lisp
2426 functions will never change. Currently, this method is not
2427 implemented, so writers of emacs code are recommended to put the
2428 first two args of a DEFUN on the same line. */
2429 if (definedef == dnone && toktype == st_C_gnumacro)
2431 next_token_is_func = TRUE;
2434 if (next_token_is_func)
2436 next_token_is_func = FALSE;
2438 *is_func_or_var = TRUE;
2442 /* Detect Objective C constructs. */
2450 set_construct(C_OBJC);
2456 set_construct(C_OBJC);
2458 objdef = oimplementation;
2462 case oimplementation:
2463 /* Save the class tag for functions or variables defined inside. */
2464 objtag = savenstr (str, len);
2468 /* Save the class tag for categories. */
2469 objtag = savenstr (str, len);
2471 *is_func_or_var = TRUE;
2475 *is_func_or_var = TRUE;
2482 objdef = omethodtag;
2484 grow_linebuffer (&token_name, methodlen + 1);
2485 strncpy (token_name.buffer, str, len);
2486 token_name.buffer[methodlen] = '\0';
2487 token_name.len = methodlen;
2493 objdef = omethodparm;
2498 objdef = omethodtag;
2500 grow_linebuffer (&token_name, methodlen + 1);
2501 strncat (token_name.buffer, str, len);
2502 token_name.len = methodlen;
2507 if (toktype == st_C_objend)
2509 /* Memory leakage here: the string pointed by objtag is
2510 never released, because many tests would be needed to
2511 avoid breaking on incorrect input code. The amount of
2512 memory leaked here is the sum of the lengths of the
2520 /* A function, variable or enum constant? */
2524 set_construct(C_CONSTANT);
2530 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2531 fvdef = fvnone; /* should be useless */
2537 if (constantypedefs && structdef == sinbody && structtype == st_C_enum)
2540 oo_browser_construct = C_ENUM_LABEL;
2546 if (fvdef == fvnone)
2548 fvdef = fvnameseen; /* function or variable */
2549 *is_func_or_var = TRUE;
2559 * This routine finds functions, variables, typedefs,
2560 * #define's, enum constants and struct/union/enum definitions in
2561 * #C syntax and adds them to the list.
2563 #define current_lb_is_new (newndx == curndx)
2564 #define switch_line_buffers() (curndx = 1 - curndx)
2566 #define curlb (lbs[curndx].lb)
2567 #define othlb (lbs[1-curndx].lb)
2568 #define newlb (lbs[newndx].lb)
2569 #define curlinepos (lbs[curndx].linepos)
2570 #define othlinepos (lbs[1-curndx].linepos)
2571 #define newlinepos (lbs[newndx].linepos)
2573 #define CNL_SAVE_DEFINEDEF() \
2575 curlinepos = charno; \
2577 linecharno = charno; \
2578 charno += readline (&curlb, inf); \
2579 lp = curlb.buffer; \
2586 CNL_SAVE_DEFINEDEF(); \
2587 if (savetok.valid) \
2590 savetok.valid = FALSE; \
2592 definedef = dnone; \
2596 void make_C_tag PP ((bool isfun));
2601 /* This function should never be called when tok.valid is FALSE, but
2602 we must protect against invalid input or internal errors. */
2605 if (traditional_tag_style)
2607 /* This was the original code. Now we call new_pfnote instead,
2608 which uses the new method for naming tags (see new_pfnote). */
2611 if (CTAGS || tok.named)
2612 name = savestr (token_name.buffer);
2613 pfnote (name, isfun,
2614 tok.buffer, tok.linelen, tok.lineno, tok.linepos);
2617 new_pfnote (token_name.buffer, token_name.len, isfun,
2618 tok.buffer, tok.linelen, tok.lineno, tok.linepos);
2627 C_entries (c_ext, inf)
2628 int c_ext; /* extension of C */
2629 FILE *inf; /* input file */
2631 register char c; /* latest char read; '\0' for end of line */
2632 register char *lp; /* pointer one beyond the character `c' */
2633 int curndx, newndx; /* indices for current and new lb */
2634 register int tokoff; /* offset in line of start of current token */
2635 register int toklen; /* length of current token */
2636 char *qualifier; /* string used to qualify names */
2637 int qlen; /* length of qualifier */
2638 int cblev; /* current curly brace level */
2639 int parlev; /* current parenthesis level */
2640 bool incomm, inquote, inchar, quotednl, midtoken;
2642 token savetok; /* token saved during preprocessor handling */
2645 tokoff = toklen = 0; /* keep compiler quiet */
2646 curndx = newndx = 0;
2652 fvdef = fvnone; typdef = tnone; structdef = snone;
2653 definedef = dnone; objdef = onone;
2654 next_token_is_func = yacc_rules = FALSE;
2655 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2656 tok.valid = savetok.valid = FALSE;
2659 cplpl = (c_ext & C_PLPL) == C_PLPL;
2660 cjava = (c_ext & C_JAVA) == C_JAVA;
2662 { qualifier = "."; qlen = 1; }
2664 { qualifier = "::"; qlen = 2; }
2671 /* If we're at the end of the line, the next character is a
2672 '\0'; don't skip it, because it's the thing that tells us
2673 to read the next line. */
2694 /* Newlines inside comments do not end macro definitions in
2696 CNL_SAVE_DEFINEDEF ();
2709 /* Newlines inside strings do not end macro definitions
2710 in traditional cpp, even though compilers don't
2711 usually accept them. */
2712 CNL_SAVE_DEFINEDEF ();
2722 /* Hmmm, something went wrong. */
2736 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2741 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2751 else if (/* cplpl && */ *lp == '/')
2759 if ((c_ext & YACC) && *lp == '%')
2761 /* entering or exiting rules section in yacc file */
2763 definedef = dnone; fvdef = fvnone;
2764 typdef = tnone; structdef = snone;
2765 next_token_is_func = FALSE;
2766 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2768 yacc_rules = !yacc_rules;
2774 if (definedef == dnone)
2777 bool cpptoken = TRUE;
2779 /* Look back on this line. If all blanks, or nonblanks
2780 followed by an end of comment, this is a preprocessor
2782 for (cp = newlb.buffer; cp < lp-1; cp++)
2785 if (*cp == '*' && *(cp+1) == '/')
2794 definedef = dsharpseen;
2795 } /* if (definedef == dnone) */
2801 /* Consider token only if some complicated conditions are satisfied. */
2802 if ((definedef != dnone
2803 || (cblev == 0 && structdef != scolonseen)
2804 || (cblev == 1 && cplpl && structdef == sinbody)
2805 || (structdef == sinbody && structtype == st_C_enum))
2806 && typdef != tignore
2807 && definedef != dignorerest
2808 && fvdef != finlist)
2814 if (c == ':' && cplpl && *lp == ':' && begtoken(*(lp + 1)))
2817 * This handles :: in the middle, but not at the
2818 * beginning of an identifier.
2823 set_construct(C_METHOD);
2828 bool funorvar = FALSE;
2831 || consider_token (newlb.buffer + tokoff, toklen, c,
2832 c_ext, cblev, parlev, &funorvar))
2835 if (structdef == sinbody
2836 && definedef == dnone
2838 /* function or var defined in C++ class body */
2840 int len = strlen (structtag) + qlen + toklen;
2841 grow_linebuffer (&token_name, len + 1);
2842 strcpy (token_name.buffer, structtag);
2843 strcat (token_name.buffer, qualifier);
2844 strncat (token_name.buffer,
2845 newlb.buffer + tokoff, toklen);
2846 token_name.len = len;
2849 oo_browser_construct = C_METHOD;
2852 else if (objdef == ocatseen)
2853 /* Objective C category */
2855 int len = strlen (objtag) + 2 + toklen;
2856 grow_linebuffer (&token_name, len + 1);
2857 strcpy (token_name.buffer, objtag);
2858 strcat (token_name.buffer, "(");
2859 strncat (token_name.buffer,
2860 newlb.buffer + tokoff, toklen);
2861 strcat (token_name.buffer, ")");
2862 token_name.len = len;
2865 oo_browser_construct = C_OBJC;
2868 else if (objdef == omethodtag
2869 || objdef == omethodparm)
2870 /* Objective C method */
2874 oo_browser_construct = C_OBJC;
2879 grow_linebuffer (&token_name, toklen + 1);
2880 strncpy (token_name.buffer,
2881 newlb.buffer + tokoff, toklen);
2882 token_name.buffer[toklen] = '\0';
2883 token_name.len = toklen;
2886 = (structdef == stagseen
2889 /* Also name #define constants,
2890 enumerations and enum_labels.
2891 Conditionalize `funorvar' reference
2892 here or #defines will appear without
2894 -- Bob Weiner, Altrasoft, 4/25/1998 */
2895 || ((oo_browser_format || funorvar)
2896 && definedef == dignorerest)
2897 || (oo_browser_format
2898 && (oo_browser_construct == C_ENUMERATION
2899 || oo_browser_construct == C_ENUM_LABEL))
2902 && definedef == dignorerest)
2906 tok.lineno = lineno;
2907 tok.linelen = tokoff + toklen + 1;
2908 tok.buffer = newlb.buffer;
2909 tok.linepos = newlinepos;
2912 if (definedef == dnone
2913 && (fvdef == fvnameseen
2914 || structdef == stagseen
2916 || objdef != onone))
2918 if (current_lb_is_new)
2919 switch_line_buffers ();
2922 make_C_tag (funorvar);
2926 } /* if (endtoken (c)) */
2927 else if (intoken (c))
2932 } /* if (midtoken) */
2933 else if (begtoken (c))
2945 set_construct(C_MACRO);
2947 make_C_tag (TRUE); /* a function */
2954 if (structdef == stagseen && !cjava)
2960 if (!yacc_rules || lp == newlb.buffer + 1)
2962 tokoff = lp - 1 - newlb.buffer;
2967 } /* if (begtoken) */
2968 } /* if must look at token */
2971 /* Detect end of line, colon, comma, semicolon and various braces
2972 after having handled a token.*/
2976 if (definedef != dnone)
2982 make_C_tag (TRUE); /* an Objective C class */
2986 objdef = omethodcolon;
2988 grow_linebuffer (&token_name, methodlen + 1);
2989 strcat (token_name.buffer, ":");
2990 token_name.len = methodlen;
2993 if (structdef == stagseen)
2994 structdef = scolonseen;
3001 make_C_tag (FALSE); /* a yacc function */
3011 if (definedef != dnone)
3018 set_construct(C_TYPE);
3020 make_C_tag (FALSE); /* a typedef */
3030 if ((globals && cblev == 0) || (members && cblev == 1))
3032 make_C_tag (FALSE); /* a variable */
3034 /* if (constantypedefs && structdef == snone)*/
3040 set_construct(C_ENUMERATION);
3043 set_construct(C_CLASS);
3046 set_construct(C_VARIABLE);
3050 /* Force reset of st_C_enum structtype value. */
3051 structtype = st_none;
3057 /* The following instruction invalidates the token.
3058 Probably the token should be invalidated in all
3059 other cases where some state machine is reset. */
3062 if (structdef == stagseen)
3066 if (definedef != dnone)
3072 make_C_tag (TRUE); /* an Objective C method */
3083 if ((globals && cblev == 0) || (members && cblev == 1))
3084 make_C_tag (FALSE); /* a variable */
3089 if (structdef == stagseen)
3093 if (definedef != dnone)
3095 if (cblev == 0 && typdef == tend)
3098 set_construct(C_TYPE);
3101 make_C_tag (FALSE); /* a typedef */
3112 if ((globals && cblev == 0) || (members && cblev == 1))
3113 make_C_tag (FALSE); /* a variable */
3115 if (constantypedefs && structdef == snone)
3121 set_construct(C_ENUMERATION);
3124 set_construct(C_CLASS);
3127 set_construct(C_VARIABLE);
3131 /* Force reset of st_C_enum structtype value. */
3132 structtype = st_none;
3139 if (structdef == stagseen)
3143 if (definedef != dnone)
3145 if (objdef == otagseen && parlev == 0)
3146 objdef = oparenseen;
3154 if (tok.valid && *lp != '*')
3156 /* This handles constructs like:
3157 typedef void OperatorFun (int fun); */
3160 set_construct(C_TYPE);
3165 } /* switch (typdef) */
3177 if (definedef != dnone)
3179 if (objdef == ocatseen && parlev == 1)
3181 make_C_tag (TRUE); /* an Objective C category */
3193 if (cblev == 0 && typdef == tend)
3196 set_construct(C_TYPE);
3199 make_C_tag (FALSE); /* a typedef */
3202 else if (parlev < 0) /* can happen due to ill-conceived #if's. */
3206 if (definedef != dnone)
3208 if (typdef == ttypedseen)
3212 case skeyseen: /* unnamed struct */
3213 structdef = sinbody;
3214 structtag = "_anonymous_";
3217 case scolonseen: /* named struct */
3218 structdef = sinbody;
3219 make_C_tag (FALSE); /* a struct */
3226 set_construct(C_FUNCTION);
3227 /* Ensure function name is recorded.
3228 -- Bob Weiner, Altrasoft */
3231 make_C_tag (TRUE); /* a function */
3240 make_C_tag (TRUE); /* an Objective C class */
3245 make_C_tag (TRUE); /* an Objective C method */
3249 /* Neutralize `extern "C" {' grot. */
3250 if (cblev == 0 && structdef == snone && typdef == tnone)
3257 if (definedef != dnone)
3259 if (fvdef == fstartlist)
3260 fvdef = fvnone; /* avoid tagging `foo' in `foo (*bar()) ()' */
3263 if (definedef != dnone)
3265 if (!noindentypedefs && lp == newlb.buffer + 1)
3267 cblev = 0; /* reset curly brace level if first column */
3268 parlev = 0; /* also reset paren level, just in case... */
3274 if (typdef == tinbody)
3276 /* Memory leakage here: the string pointed by structtag is
3277 never released, because I fear to miss something and
3278 break things while freeing the area. The amount of
3279 memory leaked here is the sum of the lengths of the
3281 if (structdef == sinbody)
3282 free (structtag); */
3285 structtag = "<error>";
3287 /* Next line added to avoid any state carryover between
3288 functions. -- Bob Weiner, Altrasoft, 11/19/1997 */
3289 fvdef = fvnone; oo_browser_construct = C_NULL;
3294 if (definedef != dnone)
3307 if ((globals && cblev == 0) || (members && cblev == 1))
3309 make_C_tag (FALSE); /* a variable */
3316 set_construct(C_ENUMERATION);
3319 set_construct(C_CLASS);
3322 /* a global variable */
3323 set_construct(C_VARIABLE);
3327 /* ootags categorizes each tag found whereas etags doesn't.
3328 Set the is_method flag if this tag has been marked as
3329 such by an earlier section of code.
3330 -- Steve Baur, Altrasoft, 5/7/1998 */
3331 is_method = (oo_browser_construct == C_METHOD);
3334 /* Force reset of st_C_enum structtype value. */
3335 structtype = st_none;
3341 fvdef = is_method ? fignore : vignore;
3352 if (objdef == oinbody && cblev == 0)
3354 objdef = omethodsign;
3358 case '#': case '~': case '&': case '%': case '/': case '|':
3359 case '^': case '!': case '<': case '>': case '.': case '?': case ']':
3360 if (definedef != dnone)
3366 /* The above characters cannot follow a function tag in C, so
3367 unmark this as a function entry. For C++, these characters
3368 may follow an `operator' function construct, so skip the
3369 unmarking conditional below.
3370 -- Steve Baur, Altrasoft, 5/7/1998 */
3371 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
3378 if (objdef == otagseen)
3380 make_C_tag (TRUE); /* an Objective C class */
3383 /* If a macro spans multiple lines don't reset its state. */
3385 CNL_SAVE_DEFINEDEF ();
3391 } /* while not eof */
3395 * Process either a C++ file or a C file depending on the setting
3399 default_C_entries (inf)
3402 C_entries (cplusplus ? C_PLPL : 0, inf);
3405 /* Always do plain ANSI C. */
3407 plain_C_entries (inf)
3413 /* Always do C++. */
3415 Cplusplus_entries (inf)
3418 C_entries (C_PLPL, inf);
3421 /* Always do Java. */
3426 C_entries (C_JAVA, inf);
3434 C_entries (C_STAR, inf);
3437 /* Always do Yacc. */
3442 C_entries (YACC, inf);
3445 /* A useful macro. */
3446 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3447 for (lineno = charno = 0; /* loop initialization */ \
3448 !feof (file_pointer) /* loop test */ \
3449 && (lineno++, /* instructions at start of loop */ \
3450 linecharno = charno, \
3451 charno += readline (&line_buffer, file_pointer), \
3452 char_pointer = lb.buffer, \
3458 * Read a file, but do no processing. This is used to do regexp
3459 * matching on files that have no language defined.
3462 just_read_file (inf)
3465 register char *dummy;
3467 LOOP_ON_INPUT_LINES (inf, lb, dummy)
3471 /* Fortran parsing */
3473 bool tail PP ((char *cp));
3478 register int len = 0;
3480 while (*cp && lowcase(*cp) == lowcase(dbp[len]))
3482 if (*cp == '\0' && !intoken(dbp[len]))
3493 dbp = skip_spaces (dbp);
3497 dbp = skip_spaces (dbp);
3498 if (strneq (dbp, "(*)", 3))
3503 if (!isdigit (*dbp))
3505 --dbp; /* force failure */
3510 while (isdigit (*dbp));
3513 void getit PP ((FILE *inf));
3520 dbp = skip_spaces (dbp);
3524 linecharno = charno;
3525 charno += readline (&lb, inf);
3530 dbp = skip_spaces (dbp);
3536 for (cp = dbp + 1; *cp && intoken (*cp); cp++)
3538 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
3539 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3544 Fortran_functions (inf)
3547 LOOP_ON_INPUT_LINES (inf, lb, dbp)
3550 dbp++; /* Ratfor escape to fortran */
3551 dbp = skip_spaces (dbp);
3554 switch (lowcase (*dbp))
3557 if (tail ("integer"))
3565 if (tail ("logical"))
3569 if (tail ("complex") || tail ("character"))
3573 if (tail ("double"))
3575 dbp = skip_spaces (dbp);
3578 if (tail ("precision"))
3584 dbp = skip_spaces (dbp);
3587 switch (lowcase (*dbp))
3590 if (tail ("function"))
3594 if (tail ("subroutine"))
3602 if (tail ("program"))
3607 if (tail ("procedure"))
3615 * Bob Weiner, Motorola Inc., 4/3/94
3616 * Unix and microcontroller assembly tag handling
3617 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
3620 Asm_labels (FILE *inf)
3624 LOOP_ON_INPUT_LINES (inf, lb, cp)
3626 /* If first char is alphabetic or one of [_.$], test for colon
3627 following identifier. */
3628 if (isalpha (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3630 /* Read past label. */
3632 while (isalnum (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3634 if (*cp == ':' || isspace (*cp))
3636 /* Found end of label, so copy it and add it to the table. */
3637 pfnote ((CTAGS) ? savenstr(lb.buffer, cp-lb.buffer) : NULL, TRUE,
3638 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3645 * Perl support by Bart Robinson <lomew@cs.utah.edu>
3646 * enhanced by Michael Ernst <mernst@alum.mit.edu>
3647 * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/
3648 * Perl variable names: /^(my|local).../
3651 Perl_functions (inf)
3656 LOOP_ON_INPUT_LINES (inf, lb, cp)
3660 && *cp++ == 'b' && isspace (*cp++))
3662 cp = skip_spaces (cp);
3666 && !isspace (*cp) && *cp != '{' && *cp != '(')
3668 pfnote ((CTAGS) ? savenstr(lb.buffer, cp-lb.buffer) : NULL, TRUE,
3669 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3672 else if (globals /* only if tagging global vars is enabled */
3673 && ((cp = lb.buffer,
3682 && (*cp == '(' || isspace (*cp)))
3684 /* After "my" or "local", but before any following paren or space. */
3685 char *varname = NULL;
3687 cp = skip_spaces (cp);
3688 if (*cp == '$' || *cp == '@' || *cp == '%')
3690 char* varstart = ++cp;
3691 while (isalnum (*cp) || *cp == '_')
3693 varname = savenstr (varstart, cp-varstart);
3697 /* Should be examining a variable list at this point;
3698 could insist on seeing an open parenthesis. */
3699 while (*cp != '\0' && *cp != ';' && *cp != '=' && *cp != ')')
3703 /* Perhaps I should back cp up one character, so the TAGS table
3704 doesn't mention (and so depend upon) the following char. */
3705 pfnote ((CTAGS) ? savenstr (lb.buffer, cp-lb.buffer) : varname,
3706 FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3712 * Python support by Eric S. Raymond <esr@thyrsus.com>
3713 * Look for /^def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
3716 Python_functions (inf)
3721 LOOP_ON_INPUT_LINES (inf, lb, cp)
3725 && *cp++ == 'f' && isspace (*cp++))
3727 cp = skip_spaces (cp);
3728 while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':')
3730 pfnote ((char *) NULL, TRUE,
3731 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3739 && *cp++ == 's' && isspace (*cp++))
3741 cp = skip_spaces (cp);
3742 while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':')
3744 pfnote ((char *) NULL, TRUE,
3745 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3750 /* Idea by Corny de Souza
3751 * Cobol tag functions
3752 * We could look for anything that could be a paragraph name.
3753 * i.e. anything that starts in column 8 is one word and ends in a full stop.
3756 Cobol_paragraphs (inf)
3759 register char *bp, *ep;
3761 LOOP_ON_INPUT_LINES (inf, lb, bp)
3767 /* If eoln, compiler option or comment ignore whole line. */
3768 if (bp[-1] != ' ' || !isalnum (bp[0]))
3771 for (ep = bp; isalnum (*ep) || *ep == '-'; ep++)
3774 pfnote ((CTAGS) ? savenstr (bp, ep-bp) : NULL, TRUE,
3775 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
3779 /* Added by Mosur Mohan, 4/22/88 */
3780 /* Pascal parsing */
3783 * Locates tags for procedures & functions. Doesn't do any type- or
3784 * var-definitions. It does look for the keyword "extern" or
3785 * "forward" immediately following the procedure statement; if found,
3786 * the tag is skipped.
3789 Pascal_functions (inf)
3792 linebuffer tline; /* mostly copied from C_entries */
3794 int save_lineno, save_len;
3795 char c, *cp, *namebuf;
3797 bool /* each of these flags is TRUE iff: */
3798 incomment, /* point is inside a comment */
3799 inquote, /* point is inside '..' string */
3800 get_tagname, /* point is after PROCEDURE/FUNCTION
3801 keyword, so next item = potential tag */
3802 found_tag, /* point is after a potential tag */
3803 inparms, /* point is within parameter-list */
3804 verify_tag; /* point has passed the parm-list, so the
3805 next token will determine whether this
3806 is a FORWARD/EXTERN to be ignored, or
3807 whether it is a real tag */
3809 save_lcno = save_lineno = save_len = 0; /* keep compiler quiet */
3810 namebuf = NULL; /* keep compiler quiet */
3815 initbuffer (&tline);
3817 incomment = inquote = FALSE;
3818 found_tag = FALSE; /* have a proc name; check if extern */
3819 get_tagname = FALSE; /* have found "procedure" keyword */
3820 inparms = FALSE; /* found '(' after "proc" */
3821 verify_tag = FALSE; /* check if "extern" is ahead */
3824 while (!feof (inf)) /* long main loop to get next char */
3827 if (c == '\0') /* if end of line */
3830 linecharno = charno;
3831 charno += readline (&lb, inf);
3835 if (!((found_tag && verify_tag)
3837 c = *dbp++; /* only if don't need *dbp pointing
3838 to the beginning of the name of
3839 the procedure or function */
3843 if (c == '}') /* within { } comments */
3845 else if (c == '*' && *dbp == ')') /* within (* *) comments */
3862 inquote = TRUE; /* found first quote */
3864 case '{': /* found open { comment */
3868 if (*dbp == '*') /* found open (* comment */
3873 else if (found_tag) /* found '(' after tag, i.e., parm-list */
3876 case ')': /* end of parms list */
3881 if (found_tag && !inparms) /* end of proc or fn stmt */
3888 if (found_tag && verify_tag && (*dbp != ' '))
3890 /* check if this is an "extern" declaration */
3893 if (lowcase (*dbp == 'e'))
3895 if (tail ("extern")) /* superfluous, really! */
3901 else if (lowcase (*dbp) == 'f')
3903 if (tail ("forward")) /* check for forward reference */
3909 if (found_tag && verify_tag) /* not external proc, so make tag */
3913 pfnote (namebuf, TRUE,
3914 tline.buffer, save_len, save_lineno, save_lcno);
3918 if (get_tagname) /* grab name of proc or fn */
3923 /* save all values for later tagging */
3924 grow_linebuffer (&tline, lb.len + 1);
3925 strcpy (tline.buffer, lb.buffer);
3926 save_lineno = lineno;
3927 save_lcno = linecharno;
3929 /* grab block name */
3930 for (cp = dbp + 1; *cp != '\0' && !endtoken (*cp); cp++)
3932 namebuf = (CTAGS) ? savenstr (dbp, cp-dbp) : NULL;
3933 dbp = cp; /* set dbp to e-o-token */
3934 save_len = dbp - lb.buffer + 1;
3935 get_tagname = FALSE;
3939 /* and proceed to check for "extern" */
3941 else if (!incomment && !inquote && !found_tag)
3943 /* check for proc/fn keywords */
3944 switch (lowcase (c))
3947 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
3951 if (tail ("unction"))
3956 } /* while not eof */
3958 free (tline.buffer);
3962 * lisp tag functions
3963 * look for (def or (DEF, quote or QUOTE
3965 int L_isdef PP ((char *strp));
3968 register char *strp;
3970 return ((strp[1] == 'd' || strp[1] == 'D')
3971 && (strp[2] == 'e' || strp[2] == 'E')
3972 && (strp[3] == 'f' || strp[3] == 'F'));
3974 int L_isquote PP ((char *strp));
3977 register char *strp;
3979 return ((*++strp == 'q' || *strp == 'Q')
3980 && (*++strp == 'u' || *strp == 'U')
3981 && (*++strp == 'o' || *strp == 'O')
3982 && (*++strp == 't' || *strp == 'T')
3983 && (*++strp == 'e' || *strp == 'E')
3984 && isspace (*++strp));
3987 void L_getit PP ((void));
3993 if (*dbp == '\'') /* Skip prefix quote */
3995 else if (*dbp == '(')
3997 if (L_isquote (dbp))
3998 dbp += 7; /* Skip "(quote " */
4000 dbp += 1; /* Skip "(" before name in (defstruct (foo)) */
4001 dbp = skip_spaces (dbp);
4004 for (cp = dbp /*+1*/;
4005 *cp != '\0' && *cp != '(' && *cp != ' ' && *cp != ')';
4011 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
4012 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4016 Lisp_functions (inf)
4019 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4025 dbp = skip_non_spaces (dbp);
4026 dbp = skip_spaces (dbp);
4031 /* Check for (foo::defmumble name-defined ... */
4034 while (*dbp != '\0' && !isspace (*dbp)
4035 && *dbp != ':' && *dbp != '(' && *dbp != ')');
4040 while (*dbp == ':');
4042 if (L_isdef (dbp - 1))
4044 dbp = skip_non_spaces (dbp);
4045 dbp = skip_spaces (dbp);
4055 * Postscript tag functions
4056 * Just look for lines where the first character is '/'
4057 * Richard Mlynarik <mly@adoc.xerox.com>
4060 Postscript_functions (inf)
4063 register char *bp, *ep;
4065 LOOP_ON_INPUT_LINES (inf, lb, bp)
4070 *ep != '\0' && *ep != ' ' && *ep != '{';
4073 pfnote ((CTAGS) ? savenstr (bp, ep-bp) : NULL, TRUE,
4074 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
4081 * Scheme tag functions
4082 * look for (def... xyzzy
4083 * look for (def... (xyzzy
4084 * look for (def ... ((...(xyzzy ....
4085 * look for (set! xyzzy
4088 void get_scheme PP ((void));
4091 Scheme_functions (inf)
4094 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4097 && (dbp[1] == 'D' || dbp[1] == 'd')
4098 && (dbp[2] == 'E' || dbp[2] == 'e')
4099 && (dbp[3] == 'F' || dbp[3] == 'f'))
4101 dbp = skip_non_spaces (dbp);
4102 /* Skip over open parens and white space */
4103 while (isspace (*dbp) || *dbp == '(')
4108 && (dbp[1] == 'S' || dbp[1] == 's')
4109 && (dbp[2] == 'E' || dbp[2] == 'e')
4110 && (dbp[3] == 'T' || dbp[3] == 't')
4111 && (dbp[4] == '!' || dbp[4] == '!')
4112 && (isspace (dbp[5])))
4114 dbp = skip_non_spaces (dbp);
4115 dbp = skip_spaces (dbp);
4128 /* Go till you get to white space or a syntactic break */
4130 *cp != '\0' && *cp != '(' && *cp != ')' && !isspace (*cp);
4133 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
4134 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4137 /* Find tags in TeX and LaTeX input files. */
4139 /* TEX_toktab is a table of TeX control sequences that define tags.
4140 Each TEX_tabent records one such control sequence.
4141 CONVERT THIS TO USE THE Stab TYPE!! */
4148 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
4150 /* Default set of control sequences to put into TEX_toktab.
4151 The value of environment var TEXTAGS is prepended to this. */
4153 char *TEX_defenv = "\
4154 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4155 :part:appendix:entry:index";
4157 void TEX_mode PP ((FILE *inf));
4158 struct TEX_tabent *TEX_decode_env PP ((char *evarname, char *defenv));
4159 int TEX_Token PP ((char *cp));
4161 char TEX_esc = '\\';
4162 char TEX_opgrp = '{';
4163 char TEX_clgrp = '}';
4166 * TeX/LaTeX scanning loop.
4175 /* Select either \ or ! as escape character. */
4178 /* Initialize token table once from environment. */
4180 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
4182 LOOP_ON_INPUT_LINES (inf, lb, cp)
4185 /* Look at each esc in line. */
4186 while ((cp = etags_strchr (cp, TEX_esc)) != NULL)
4190 linecharno += cp - lasthit;
4192 i = TEX_Token (lasthit);
4195 /* We seem to include the TeX command in the tag name.
4197 for (p = lasthit + TEX_toktab[i].len;
4198 *p != '\0' && *p != TEX_clgrp;
4201 pfnote (/*savenstr (lasthit, p-lasthit)*/ (char *)NULL, TRUE,
4202 lb.buffer, lb.len, lineno, linecharno);
4203 break; /* We only tag a line once */
4209 #define TEX_LESC '\\'
4210 #define TEX_SESC '!'
4213 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4214 chars accordingly. */
4221 while ((c = getc (inf)) != EOF)
4223 /* Skip to next line if we hit the TeX comment char. */
4227 else if (c == TEX_LESC || c == TEX_SESC )
4246 /* Read environment and prepend it to the default string.
4247 Build token table. */
4249 TEX_decode_env (evarname, defenv)
4253 register char *env, *p;
4255 struct TEX_tabent *tab;
4258 /* Append default string to environment. */
4259 env = getenv (evarname);
4265 env = concat (oldenv, defenv, "");
4269 /* Allocate a token table */
4270 for (size = 1, p = env; p;)
4271 if ((p = etags_strchr (p, ':')) && *++p != '\0')
4273 /* Add 1 to leave room for null terminator. */
4274 tab = xnew (size + 1, struct TEX_tabent);
4276 /* Unpack environment string into token table. Be careful about */
4277 /* zero-length strings (leading ':', "::" and trailing ':') */
4280 p = etags_strchr (env, ':');
4281 if (!p) /* End of environment string. */
4282 p = env + strlen (env);
4284 { /* Only non-zero strings. */
4285 tab[i].name = savenstr (env, p - env);
4286 tab[i].len = strlen (tab[i].name);
4293 tab[i].name = NULL; /* Mark end of table. */
4301 /* If the text at CP matches one of the tag-defining TeX command names,
4302 return the pointer to the first occurrence of that command in TEX_toktab.
4303 Otherwise return -1.
4304 Keep the capital `T' in `token' for dumb truncating compilers
4305 (this distinguishes it from `TEX_toktab' */
4312 for (i = 0; TEX_toktab[i].len > 0; i++)
4313 if (strneq (TEX_toktab[i].name, cp, TEX_toktab[i].len))
4319 * Prolog support (rewritten) by Anders Lindgren, Mar. 96
4321 * Assumes that the predicate starts at column 0.
4322 * Only the first clause of a predicate is added.
4324 int prolog_pred PP ((char *s, char *last));
4325 void prolog_skip_comment PP ((linebuffer *plb, FILE *inf));
4326 int prolog_atom PP ((char *s, int pos));
4329 Prolog_functions (inf)
4340 LOOP_ON_INPUT_LINES (inf, lb, cp)
4342 if (cp[0] == '\0') /* Empty line */
4344 else if (isspace (cp[0])) /* Not a predicate */
4346 else if (cp[0] == '/' && cp[1] == '*') /* comment. */
4347 prolog_skip_comment (&lb, inf);
4348 else if ((len = prolog_pred (cp, last)) > 0)
4350 /* Predicate. Store the function name so that we only
4351 generate a tag for the first clause. */
4353 last = xnew(len + 1, char);
4354 else if (len + 1 > allocated)
4355 last = xrnew (last, len + 1, char);
4356 allocated = len + 1;
4357 strncpy (last, cp, len);
4365 prolog_skip_comment (plb, inf)
4373 for (cp = plb->buffer; *cp != '\0'; cp++)
4374 if (cp[0] == '*' && cp[1] == '/')
4377 linecharno += readline (plb, inf);
4383 * A predicate definition is added if it matches:
4384 * <beginning of line><Prolog Atom><whitespace>(
4386 * It is added to the tags database if it doesn't match the
4387 * name of the previous clause header.
4389 * Return the size of the name of the predicate, or 0 if no header
4393 prolog_pred (s, last)
4395 char *last; /* Name of last clause. */
4400 pos = prolog_atom (s, 0);
4405 pos = skip_spaces (s + pos) - s;
4407 if ((s[pos] == '(') || (s[pos] == '.'))
4412 /* Save only the first clause. */
4414 || len != strlen (last)
4415 || !strneq (s, last, len))
4417 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
4418 s, pos, lineno, linecharno);
4426 * Consume a Prolog atom.
4427 * Return the number of bytes consumed, or -1 if there was an error.
4429 * A prolog atom, in this context, could be one of:
4430 * - An alphanumeric sequence, starting with a lower case letter.
4431 * - A quoted arbitrary string. Single quotes can escape themselves.
4432 * Backslash quotes everything.
4435 prolog_atom (s, pos)
4443 if (islower(s[pos]) || (s[pos] == '_'))
4445 /* The atom is unquoted. */
4447 while (isalnum(s[pos]) || (s[pos] == '_'))
4451 return pos - origpos;
4453 else if (s[pos] == '\'')
4464 pos++; /* A double quote */
4466 else if (s[pos] == '\0')
4467 /* Multiline quoted atoms are ignored. */
4469 else if (s[pos] == '\\')
4471 if (s[pos+1] == '\0')
4478 return pos - origpos;
4485 * Support for Erlang -- Anders Lindgren, Feb 1996.
4487 * Generates tags for functions, defines, and records.
4489 * Assumes that Erlang functions start at column 0.
4491 int erlang_func PP ((char *s, char *last));
4492 void erlang_attribute PP ((char *s));
4493 int erlang_atom PP ((char *s, int pos));
4496 Erlang_functions (inf)
4507 LOOP_ON_INPUT_LINES (inf, lb, cp)
4509 if (cp[0] == '\0') /* Empty line */
4511 else if (isspace (cp[0])) /* Not function nor attribute */
4513 else if (cp[0] == '%') /* comment */
4515 else if (cp[0] == '"') /* Sometimes, strings start in column one */
4517 else if (cp[0] == '-') /* attribute, e.g. "-define" */
4519 erlang_attribute (cp);
4522 else if ((len = erlang_func (cp, last)) > 0)
4525 * Function. Store the function name so that we only
4526 * generates a tag for the first clause.
4529 last = xnew (len + 1, char);
4530 else if (len + 1 > allocated)
4531 last = xrnew (last, len + 1, char);
4532 allocated = len + 1;
4533 strncpy (last, cp, len);
4541 * A function definition is added if it matches:
4542 * <beginning of line><Erlang Atom><whitespace>(
4544 * It is added to the tags database if it doesn't match the
4545 * name of the previous clause header.
4547 * Return the size of the name of the function, or 0 if no function
4551 erlang_func (s, last)
4553 char *last; /* Name of last clause. */
4558 pos = erlang_atom (s, 0);
4563 pos = skip_spaces (s + pos) - s;
4565 /* Save only the first clause. */
4568 || len != strlen (last)
4569 || !strneq (s, last, len)))
4571 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
4572 s, pos, lineno, linecharno);
4581 * Handle attributes. Currently, tags are generated for defines
4584 * They are on the form:
4585 * -define(foo, bar).
4586 * -define(Foo(M, N), M+N).
4587 * -record(graph, {vtab = notable, cyclic = true}).
4590 erlang_attribute (s)
4596 if (strneq (s, "-define", 7) || strneq (s, "-record", 7))
4598 pos = skip_spaces (s + 7) - s;
4599 if (s[pos++] == '(')
4601 pos = skip_spaces (s + pos) - s;
4602 len = erlang_atom (s, pos);
4604 pfnote ((CTAGS) ? savenstr (& s[pos], len) : NULL, TRUE,
4605 s, pos + len, lineno, linecharno);
4613 * Consume an Erlang atom (or variable).
4614 * Return the number of bytes consumed, or -1 if there was an error.
4617 erlang_atom (s, pos)
4625 if (isalpha (s[pos]) || s[pos] == '_')
4627 /* The atom is unquoted. */
4629 while (isalnum (s[pos]) || s[pos] == '_')
4631 return pos - origpos;
4633 else if (s[pos] == '\'')
4644 else if (s[pos] == '\0')
4645 /* Multiline quoted atoms are ignored. */
4647 else if (s[pos] == '\\')
4649 if (s[pos+1] == '\0')
4656 return pos - origpos;
4662 #ifdef ETAGS_REGEXPS
4664 /* Take a string like "/blah/" and turn it into "blah", making sure
4665 that the first and last characters are the same, and handling
4666 quoted separator characters. Actually, stops on the occurrence of
4667 an unquoted separator. Also turns "\t" into a Tab character.
4668 Returns pointer to terminating separator. Works in place. Null
4669 terminates name string. */
4670 char * scan_separators PP ((char *name));
4672 scan_separators (name)
4676 char *copyto = name;
4677 bool quoted = FALSE;
4679 for (++name; *name != '\0'; ++name)
4685 else if (*name == sep)
4689 /* Something else is quoted, so preserve the quote. */
4695 else if (*name == '\\')
4697 else if (*name == sep)
4703 /* Terminate copied string. */
4708 /* Look at the argument of --regex or --no-regex and do the right
4709 thing. Same for each line of a regexp file. */
4711 analyse_regex (regex_arg)
4714 if (regex_arg == NULL)
4715 free_patterns (); /* --no-regex: remove existing regexps */
4717 /* A real --regexp option or a line in a regexp file. */
4718 switch (regex_arg[0])
4720 /* Comments in regexp file or null arg to --regex. */
4726 /* Read a regex file. This is recursive and may result in a
4727 loop, which will stop when the file descriptors are exhausted. */
4731 linebuffer regexbuf;
4732 char *regexfile = regex_arg + 1;
4734 /* regexfile is a file containing regexps, one per line. */
4735 regexfp = fopen (regexfile, "r");
4736 if (regexfp == NULL)
4741 initbuffer (®exbuf);
4742 while (readline_internal (®exbuf, regexfp) > 0)
4743 analyse_regex (regexbuf.buffer);
4744 free (regexbuf.buffer);
4749 /* Regexp to be used for a specific language only. */
4753 char *lang_name = regex_arg + 1;
4756 for (cp = lang_name; *cp != '}'; cp++)
4759 error ("unterminated language name in regex: %s", regex_arg);
4763 lang = get_language_from_name (lang_name);
4766 add_regex (cp + 1, lang);
4770 /* Regexp to be used for any language. */
4772 add_regex (regex_arg, NULL);
4777 /* Turn a name, which is an ed-style (but Emacs syntax) regular
4778 expression, into a real regular expression by compiling it. */
4780 add_regex (regexp_pattern, lang)
4781 char *regexp_pattern;
4786 struct re_pattern_buffer *patbuf;
4790 if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0])
4792 error ("%s: unterminated regexp", regexp_pattern);
4795 name = scan_separators (regexp_pattern);
4796 if (regexp_pattern[0] == '\0')
4798 error ("null regexp", (char *)NULL);
4801 (void) scan_separators (name);
4803 patbuf = xnew (1, struct re_pattern_buffer);
4804 patbuf->translate = NULL;
4805 patbuf->fastmap = NULL;
4806 patbuf->buffer = NULL;
4807 patbuf->allocated = 0;
4809 err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf);
4812 error ("%s while compiling pattern", err);
4817 p_head = xnew (1, pattern);
4818 p_head->regex = savestr (regexp_pattern);
4819 p_head->p_next = pp;
4820 p_head->language = lang;
4821 p_head->pattern = patbuf;
4822 p_head->name_pattern = savestr (name);
4823 p_head->error_signaled = FALSE;
4827 * Do the substitutions indicated by the regular expression and
4830 char * substitute PP ((char *in, char *out, struct re_registers *regs));
4832 substitute (in, out, regs)
4834 struct re_registers *regs;
4837 int size, dig, diglen;
4840 size = strlen (out);
4842 /* Pass 1: figure out how much to allocate by finding all \N strings. */
4843 if (out[size - 1] == '\\')
4844 fatal ("pattern error in \"%s\"", out);
4845 for (t = etags_strchr (out, '\\');
4847 t = etags_strchr (t + 2, '\\'))
4851 diglen = regs->end[dig] - regs->start[dig];
4857 /* Allocate space and do the substitutions. */
4858 result = xnew (size + 1, char);
4860 for (t = result; *out != '\0'; out++)
4861 if (*out == '\\' && isdigit (*++out))
4863 /* Using "dig2" satisfies my debugger. Bleah. */
4865 diglen = regs->end[dig] - regs->start[dig];
4866 strncpy (t, in + regs->start[dig], diglen);
4873 if (DEBUG && (t > result + size || t - result != strlen (result)))
4879 /* Deallocate all patterns. */
4884 while (p_head != NULL)
4886 pp = p_head->p_next;
4887 free (p_head->regex);
4888 free (p_head->name_pattern);
4895 #endif /* ETAGS_REGEXPS */
4896 /* Initialize a linebuffer for use */
4902 lbp->buffer = xnew (200, char);
4906 * Read a line of text from `stream' into `lbp', excluding the
4907 * newline or CR-NL, if any. Return the number of characters read from
4908 * `stream', which is the length of the line including the newline.
4910 * On DOS or Windows we do not count the CR character, if any, before the
4911 * NL, in the returned length; this mirrors the behavior of emacs on those
4912 * platforms (for text files, it translates CR-NL to NL as it reads in the
4916 readline_internal (lbp, stream)
4918 register FILE *stream;
4920 char *buffer = lbp->buffer;
4921 register char *p = lbp->buffer;
4922 register char *pend;
4925 pend = p + lbp->size; /* Separate to avoid 386/IX compiler bug. */
4929 register int c = getc (stream);
4932 /* We're at the end of linebuffer: expand it. */
4934 buffer = xrnew (buffer, lbp->size, char);
4935 p += buffer - lbp->buffer;
4936 pend = buffer + lbp->size;
4937 lbp->buffer = buffer;
4947 if (p > buffer && p[-1] == '\r')
4951 /* Assume CRLF->LF translation will be performed by Emacs
4952 when loading this file, so CRs won't appear in the buffer.
4953 It would be cleaner to compensate within Emacs;
4954 however, Emacs does not know how many CRs were deleted
4955 before any given point in the file. */
4970 lbp->len = p - buffer;
4972 return lbp->len + chars_deleted;
4976 * Like readline_internal, above, but in addition try to match the
4977 * input line against relevant regular expressions.
4980 readline (lbp, stream)
4984 /* Read new line. */
4985 long result = readline_internal (lbp, stream);
4986 #ifdef ETAGS_REGEXPS
4990 /* Match against relevant patterns. */
4992 for (pp = p_head; pp != NULL; pp = pp->p_next)
4994 /* Only use generic regexps or those for the current language. */
4995 if (pp->language != NULL && pp->language != curlang)
4998 match = re_match (pp->pattern, lbp->buffer, lbp->len, 0, &pp->regs);
5003 if (!pp->error_signaled)
5005 error ("error while matching \"%s\"", pp->regex);
5006 pp->error_signaled = TRUE;
5013 /* Match occurred. Construct a tag. */
5014 if (pp->name_pattern[0] != '\0')
5016 /* Make a named tag. */
5017 char *name = substitute (lbp->buffer,
5018 pp->name_pattern, &pp->regs);
5020 pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);
5024 /* Make an unnamed tag. */
5025 pfnote ((char *)NULL, TRUE,
5026 lbp->buffer, match, lineno, linecharno);
5031 #endif /* ETAGS_REGEXPS */
5037 * Return a pointer to a space of size strlen(cp)+1 allocated
5038 * with xnew where the string CP has been copied.
5044 return savenstr (cp, strlen (cp));
5048 * Return a pointer to a space of size LEN+1 allocated with xnew where
5049 * the string CP has been copied for at most the first LEN characters.
5058 dp = xnew (len + 1, char);
5059 strncpy (dp, cp, len);
5065 * Return the ptr in sp at which the character c last
5066 * appears; NULL if not found
5068 * Identical to System V strrchr, included for portability.
5071 etags_strrchr (sp, c)
5088 * Return the ptr in sp at which the character c first
5089 * appears; NULL if not found
5091 * Identical to System V strchr, included for portability.
5094 etags_strchr (sp, c)
5106 /* Skip spaces, return new pointer. */
5111 while (isspace (*cp)) /* isspace('\0')==FALSE */
5116 /* Skip non spaces, return new pointer. */
5118 skip_non_spaces (cp)
5121 while (!iswhite (*cp)) /* iswhite('\0')==TRUE */
5126 /* Print error message and exit. */
5144 suggest_asking_for_help ()
5146 fprintf (stderr, "\tTry `%s %s' for a complete list of options.\n",
5157 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
5160 const char *s1, *s2;
5162 fprintf (stderr, "%s: ", progname);
5163 fprintf (stderr, s1, s2);
5164 fprintf (stderr, "\n");
5167 /* Return a newly-allocated string whose contents
5168 concatenate those of s1, s2, s3. */
5173 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
5174 char *result = xnew (len1 + len2 + len3 + 1, char);
5176 strcpy (result, s1);
5177 strcpy (result + len1, s2);
5178 strcpy (result + len1 + len2, s3);
5179 result[len1 + len2 + len3] = '\0';
5184 /* Does the same work as the system V getcwd, but does not need to
5185 guess the buffer size in advance. */
5191 char *path = xnew (bufsize, char);
5193 while (getcwd (path, bufsize) == NULL)
5195 if (errno != ERANGE)
5199 path = xnew (bufsize, char);
5202 canonicalize_filename (path);
5205 #else /* not HAVE_GETCWD */
5210 pipe = (FILE *) popen ("pwd 2>/dev/null", "r");
5211 if (pipe == NULL || readline_internal (&path, pipe) == 0)
5216 #endif /* not HAVE_GETCWD */
5219 /* Return a newly allocated string containing the file name of FILE
5220 relative to the absolute directory DIR (which should end with a slash). */
5222 relative_filename (file, dir)
5225 char *fp, *dp, *afn, *res;
5228 /* Find the common root of file and dir (with a trailing slash). */
5229 afn = absolute_filename (file, cwd);
5232 while (*fp++ == *dp++)
5234 fp--, dp--; /* back to the first differing char */
5235 do /* look at the equal chars until '/' */
5239 /* Build a sequence of "../" strings for the resulting relative file name. */
5241 while ((dp = etags_strchr (dp + 1, '/')) != NULL)
5243 res = xnew (3*i + strlen (fp + 1) + 1, char);
5246 strcat (res, "../");
5248 /* Add the file name relative to the common root of file and dir. */
5249 strcat (res, fp + 1);
5255 /* Return a newly allocated string containing the absolute file name
5256 of FILE given DIR (which should end with a slash). */
5258 absolute_filename (file, dir)
5261 char *slashp, *cp, *res;
5263 if (filename_is_absolute (file))
5264 res = savestr (file);
5266 /* We don't support non-absolute file names with a drive
5267 letter, like `d:NAME' (it's too much hassle). */
5268 else if (file[1] == ':')
5269 fatal ("%s: relative file names with drive letters not supported", file);
5272 res = concat (dir, file, "");
5274 /* Delete the "/dirname/.." and "/." substrings. */
5275 slashp = etags_strchr (res, '/');
5276 while (slashp != NULL && slashp[0] != '\0')
5278 if (slashp[1] == '.')
5280 if (slashp[2] == '.'
5281 && (slashp[3] == '/' || slashp[3] == '\0'))
5286 while (cp >= res && !filename_is_absolute (cp));
5288 cp = slashp; /* the absolute name begins with "/.." */
5290 /* Under Windows we get `d:/NAME' as absolute
5291 file name, so the luser could say `d:/../NAME'.
5292 We silently treat this as `d:/NAME'. */
5293 else if (cp[0] != '/')
5296 strcpy (cp, slashp + 3);
5300 else if (slashp[2] == '/' || slashp[2] == '\0')
5302 strcpy (slashp, slashp + 2);
5307 slashp = etags_strchr (slashp + 1, '/');
5311 return savestr ("/");
5316 /* Return a newly allocated string containing the absolute
5317 file name of dir where FILE resides given DIR (which should
5318 end with a slash). */
5320 absolute_dirname (file, dir)
5326 canonicalize_filename (file);
5327 slashp = etags_strrchr (file, '/');
5329 return savestr (dir);
5332 res = absolute_filename (file, dir);
5338 /* Whether the argument string is an absolute file name. The argument
5339 string must have been canonicalized with canonicalize_filename. */
5341 filename_is_absolute (fn)
5344 return (fn[0] == '/'
5346 || (isalpha(fn[0]) && fn[1] == ':' && fn[2] == '/')
5351 /* Translate backslashes into slashes. Works in place. */
5353 canonicalize_filename (fn)
5357 for (; *fn != '\0'; fn++)
5365 /* Increase the size of a linebuffer. */
5367 grow_linebuffer (lbp, toksize)
5371 while (lbp->size < toksize)
5373 lbp->buffer = xrnew (lbp->buffer, lbp->size, char);
5376 /* Like malloc but get fatal error if memory is exhausted. */
5381 long *result = (long *) malloc (size);
5383 fatal ("virtual memory exhausted", (char *)NULL);
5388 xrealloc (ptr, size)
5392 long *result = (long *) realloc (ptr, size);
5394 fatal ("virtual memory exhausted", (char *)NULL);