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 */
69 # include <sys/param.h>
71 # ifndef HAVE_CONFIG_H
73 # include <sys/config.h>
82 # define MAXPATHLEN _MAX_PATH
88 # endif /* not HAVE_CONFIG_H */
89 #endif /* WINDOWSNT */
91 #if !defined (WINDOWSNT) && defined (STDC_HEADERS)
100 extern char *getcwd ();
102 #endif /* HAVE_UNISTD_H */
107 #include <sys/types.h>
108 #include <sys/stat.h>
110 #if !defined (S_ISREG) && defined (S_IFREG)
111 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
117 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
119 extern int optind, opterr;
120 #endif /* LONG_OPTIONS */
124 #endif /* ETAGS_REGEXPS */
126 /* Define CTAGS to make the program "ctags" compatible with the usual one.
127 Leave it undefined to make the program "etags", which makes emacs-style
128 tag tables and tags typedefs, #defines and struct/union/enum by default. */
136 /* Exit codes for success and failure. */
146 #define C_PLPL 0x00001 /* C++ */
147 #define C_STAR 0x00003 /* C* */
148 #define C_JAVA 0x00005 /* JAVA */
149 #define YACC 0x10000 /* yacc file */
151 #define streq(s,t) ((DEBUG && (s) == NULL && (t) == NULL \
152 && (abort (), 1)) || !strcmp (s, t))
153 #define strneq(s,t,n) ((DEBUG && (s) == NULL && (t) == NULL \
154 && (abort (), 1)) || !strncmp (s, t, n))
156 #define lowcase(c) tolower ((char)c)
158 #define CHARS 256 /* 2^sizeof(char) */
159 #define CHAR(x) ((unsigned int)x & (CHARS - 1))
160 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */
161 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
162 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
163 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
164 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
167 /*#undef OO_BROWSER*/
168 /* Due to the way this file is constructed, this unfortunately doesn't */
169 /* work except for documentation purposes. -slb */
174 #define set_construct(construct) \
175 if (!oo_browser_construct) oo_browser_construct = construct
176 void oo_browser_clear_all_globals(void);
177 void oo_browser_clear_some_globals(void);
178 void oo_browser_check_and_clear_structtype(void);
182 * xnew, xrnew -- allocate, reallocate storage
184 * SYNOPSIS: Type *xnew (int n, Type);
185 * Type *xrnew (OldPointer, int n, Type);
188 # include "chkmalloc.h"
189 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
190 (n) * sizeof (Type)))
191 # define xrnew(op,n,Type) ((Type *) trace_realloc (__FILE__, __LINE__, \
192 (op), (n) * sizeof (Type)))
194 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
195 # define xrnew(op,n,Type) ((Type *) xrealloc ((op), (n) * sizeof (Type)))
200 typedef void Lang_function (FILE *);
205 Lang_function *function;
210 typedef struct node_st
211 { /* sorting structure */
212 char *name; /* function or type name */
214 short int construct; /* Construct type for the OO-Browser */
216 char *file; /* file name */
217 bool is_func; /* use pattern or line no */
218 bool been_warned; /* set if noticed dup */
219 int lno; /* line number tag is on */
220 long cno; /* character number line starts on */
221 char *pat; /* search pattern */
222 struct node_st *left, *right; /* left and right sons */
226 /* If you add to this array, you must add a corresponding entry to the
228 static char *oo_browser_default_classes[] =
229 /* Lack of square brackets around some of these entries are intentional. */
230 {"null", "class", "method", "[constant]", "[enumeration]", "[enum_label]",
231 "extern", "[function]", "[macro]", "objc", "[structure]", "[type]",
232 "[union]", "[variable]"};
234 /* If you add to this enum, you must add a corresponding entry to the
236 enum oo_browser_constructs {C_NULL, C_CLASS, C_METHOD, C_CONSTANT, C_ENUMERATION,
237 C_ENUM_LABEL, C_EXTERN, C_FUNCTION, C_MACRO,
238 C_OBJC, C_STRUCTURE, C_TYPE, C_UNION, C_VARIABLE};
240 enum oo_browser_constructs oo_browser_construct = C_NULL;
244 * A `linebuffer' is a structure which holds a line of text.
245 * `readline_internal' reads a line from a stream into a linebuffer
246 * and works regardless of the length of the line.
247 * SIZE is the size of BUFFER, LEN is the length of the string in
248 * BUFFER after readline reads it.
257 extern char *getenv PP ((const char *envvar));
259 /* Many compilers barf on this:
260 Lang_function Asm_labels;
261 so let's write it this way */
262 void Asm_labels PP ((FILE *inf));
263 void C_entries PP ((int c_ext, FILE *inf));
264 void default_C_entries PP ((FILE *inf));
265 void plain_C_entries PP ((FILE *inf));
266 void Cjava_entries PP ((FILE *inf));
267 void Cplusplus_entries PP ((FILE *inf));
268 void Yacc_entries PP ((FILE *inf));
269 void Cobol_paragraphs PP ((FILE *inf));
270 void Cstar_entries PP ((FILE *inf));
271 void Erlang_functions PP ((FILE *inf));
272 void Fortran_functions PP ((FILE *inf));
273 void Lisp_functions PP ((FILE *inf));
274 void Pascal_functions PP ((FILE *inf));
275 void Perl_functions PP ((FILE *inf));
276 void Postscript_functions PP ((FILE *inf));
277 void Prolog_functions PP ((FILE *inf));
278 void Python_functions PP ((FILE *inf));
279 void Scheme_functions PP ((FILE *inf));
280 void TeX_functions PP ((FILE *inf));
281 void just_read_file PP ((FILE *inf));
283 void print_language_names PP ((void));
284 void print_version PP ((void));
285 void print_help PP ((void));
287 language *get_language_from_name PP ((char *name));
288 language *get_language_from_interpreter PP ((char *interpreter));
289 language *get_language_from_suffix PP ((char *suffix));
290 int total_size_of_entries PP ((node *np));
291 long readline PP ((linebuffer *lbp, FILE *stream));
292 long readline_internal PP ((linebuffer *lbp, FILE *stream));
294 void analyse_regex PP ((char *regex_arg));
295 void add_regex PP ((char *regexp_pattern, language *lang));
296 void free_patterns PP ((void));
297 #endif /* ETAGS_REGEXPS */
298 void error PP ((const char *s1, const char *s2));
299 void suggest_asking_for_help PP ((void));
300 void fatal PP ((char *s1, char *s2));
301 void pfatal PP ((char *s1));
302 void add_node PP ((node *np, node **cur_node_p));
304 void init PP ((void));
305 void initbuffer PP ((linebuffer *lbp));
306 void find_entries PP ((char *file, FILE *inf));
307 void free_tree PP ((node *np));
308 void pfnote PP ((char *name, bool is_func, char *linestart, int linelen, int lno, long cno));
309 void new_pfnote PP ((char *name, int namelen, bool is_func, char *linestart, int linelen, int lno, long cno));
310 void process_file PP ((char *file));
311 void put_entries PP ((node *np));
312 void takeprec PP ((void));
314 char *concat PP ((char *s1, char *s2, char *s3));
315 char *skip_spaces PP ((char *cp));
316 char *skip_non_spaces PP ((char *cp));
317 char *savenstr PP ((char *cp, int len));
318 char *savestr PP ((char *cp));
319 char *etags_strchr PP ((char *sp, int c));
320 char *etags_strrchr PP ((char *sp, int c));
321 char *etags_getcwd PP ((void));
322 char *relative_filename PP ((char *file, char *dir));
323 char *absolute_filename PP ((char *file, char *dir));
324 char *absolute_dirname PP ((char *file, char *dir));
325 bool filename_is_absolute PP ((char *fn));
326 void canonicalize_filename PP ((char *fn));
327 void grow_linebuffer PP ((linebuffer *lbp, int toksize));
328 long *xmalloc PP ((unsigned int size));
329 long *xrealloc PP ((char *ptr, unsigned int size));
332 char searchar = '/'; /* use /.../ searches */
334 char *tagfile; /* output file */
335 char *progname; /* name this program was invoked with */
336 char *cwd; /* current working directory */
337 char *tagfiledir; /* directory of tagfile */
338 FILE *tagf; /* ioptr for tags file */
340 char *curfile; /* current input file name */
341 language *curlang; /* current language */
343 int lineno; /* line number of current line */
344 long charno; /* current character number */
345 long linecharno; /* charno of start of current line */
346 char *dbp; /* pointer to start of current tag */
347 node *head; /* the head of the binary tree of tags */
349 linebuffer lb; /* the current line */
350 linebuffer token_name; /* used by C_entries as a temporary area */
354 linebuffer lb; /* used by C_entries instead of lb */
357 /* boolean "functions" (see init) */
358 bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
361 *white = " \f\t\n\r",
363 *nonam = " \f\t\n\r(=,[;",
364 /* token ending chars */
365 *endtk = " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
366 /* token starting chars */
367 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
368 /* valid in-token chars */
369 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
371 bool append_to_tagfile; /* -a: append to tags */
372 /* The following four default to TRUE for etags, but to FALSE for ctags. */
373 bool typedefs; /* -t: create tags for C typedefs */
374 bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */
375 /* 0 struct/enum/union decls, and C++ */
376 /* member functions. */
377 bool constantypedefs; /* -d: create tags for C #define, enum */
378 /* constants and variables. */
379 /* -D: opposite of -d. Default under ctags. */
380 bool globals; /* create tags for global variables */
381 bool members; /* create tags for C member variables */
382 bool update; /* -u: update tags */
383 bool vgrind_style; /* -v: create vgrind style index output */
384 bool no_warnings; /* -w: suppress warnings */
385 bool cxref_style; /* -x: create cxref style output */
386 bool cplusplus; /* .[hc] means C++, not C */
387 bool noindentypedefs; /* -I: ignore indentation in C */
389 bool oo_browser_format; /* -O: OO-Browser tags format */
393 struct option longopts[] =
395 { "append", no_argument, NULL, 'a' },
396 { "backward-search", no_argument, NULL, 'B' },
397 { "c++", no_argument, NULL, 'C' },
398 { "cxref", no_argument, NULL, 'x' },
399 { "defines", no_argument, NULL, 'd' },
400 { "no-defines", no_argument, NULL, 'D' },
401 { "globals", no_argument, &globals, TRUE },
402 { "no-globals", no_argument, &globals, FALSE },
403 { "help", no_argument, NULL, 'h' },
404 { "help", no_argument, NULL, 'H' },
405 { "ignore-indentation", no_argument, NULL, 'I' },
406 { "include", required_argument, NULL, 'i' },
407 { "language", required_argument, NULL, 'l' },
408 { "members", no_argument, &members, TRUE },
409 { "no-members", no_argument, &members, FALSE },
410 { "no-warn", no_argument, NULL, 'w' },
411 { "output", required_argument, NULL, 'o' },
413 { "oo-browser", no_argument, NULL, 'O' },
416 { "regex", required_argument, NULL, 'r' },
417 { "no-regex", no_argument, NULL, 'R' },
418 #endif /* ETAGS_REGEXPS */
419 { "typedefs", no_argument, NULL, 't' },
420 { "typedefs-and-c++", no_argument, NULL, 'T' },
421 { "update", no_argument, NULL, 'u' },
422 { "version", no_argument, NULL, 'V' },
423 { "vgrind", no_argument, NULL, 'v' },
426 #endif /* LONG_OPTIONS */
429 /* Structure defining a regular expression. Elements are
430 the compiled pattern, and the name string. */
431 typedef struct pattern
433 struct pattern *p_next;
436 struct re_pattern_buffer *pattern;
437 struct re_registers regs;
442 /* Array of all regexps. */
443 pattern *p_head = NULL;
444 #endif /* ETAGS_REGEXPS */
450 /* Non-NULL if language fixed. */
451 language *forced_lang = NULL;
454 char *Asm_suffixes [] = { "a", /* Unix assembler */
455 "asm", /* Microcontroller assembly */
456 "def", /* BSO/Tasking definition includes */
457 "inc", /* Microcontroller include files */
458 "ins", /* Microcontroller include files */
459 "s", "sa", /* Unix assembler */
460 "src", /* BSO/Tasking C compiler output */
464 /* Note that .c and .h can be considered C++, if the --c++ flag was
465 given. That is why default_C_entries is called here. */
466 char *default_C_suffixes [] =
469 char *Cplusplus_suffixes [] =
470 { "C", "H", "c++", "cc", "cpp", "cxx", "h++", "hh", "hpp", "hxx",
471 "M", /* Objective C++ */
472 "pdb", /* Postscript with C syntax */
475 char *Cjava_suffixes [] =
478 char *Cobol_suffixes [] =
479 { "COB", "cob", NULL };
481 char *Cstar_suffixes [] =
482 { "cs", "hs", NULL };
484 char *Erlang_suffixes [] =
485 { "erl", "hrl", NULL };
487 char *Fortran_suffixes [] =
488 { "F", "f", "f90", "for", NULL };
490 char *Lisp_suffixes [] =
491 { "cl", "clisp", "el", "l", "lisp", "lsp", "ml", NULL };
493 char *Pascal_suffixes [] =
494 { "p", "pas", NULL };
496 char *Perl_suffixes [] =
497 { "pl", "pm", NULL };
498 char *Perl_interpreters [] =
499 { "perl", "@PERL@", NULL };
501 char *plain_C_suffixes [] =
502 { "pc", /* Pro*C file */
503 "m", /* Objective C file */
504 "lm", /* Objective lex file */
507 char *Postscript_suffixes [] =
510 char *Prolog_suffixes [] =
513 char *Python_suffixes [] =
516 /* Can't do the `SCM' or `scm' prefix with a version number. */
517 char *Scheme_suffixes [] =
518 { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "ss", "t", NULL };
520 char *TeX_suffixes [] =
521 { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL };
523 char *Yacc_suffixes [] =
524 { "y", "ym", NULL }; /* .ym is Objective yacc file */
527 * Table of languages.
529 * It is ok for a given function to be listed under more than one
530 * name. I just didn't.
533 language lang_names [] =
535 { "asm", Asm_labels, Asm_suffixes, NULL },
536 { "c", default_C_entries, default_C_suffixes, NULL },
537 { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL },
538 { "c*", Cstar_entries, Cstar_suffixes, NULL },
539 { "cobol", Cobol_paragraphs, Cobol_suffixes, NULL },
540 { "erlang", Erlang_functions, Erlang_suffixes, NULL },
541 { "fortran", Fortran_functions, Fortran_suffixes, NULL },
542 { "java", Cjava_entries, Cjava_suffixes, NULL },
543 { "lisp", Lisp_functions, Lisp_suffixes, NULL },
544 { "pascal", Pascal_functions, Pascal_suffixes, NULL },
545 { "perl", Perl_functions, Perl_suffixes, Perl_interpreters },
546 { "postscript", Postscript_functions, Postscript_suffixes, NULL },
547 { "proc", plain_C_entries, plain_C_suffixes, NULL },
548 { "prolog", Prolog_functions, Prolog_suffixes, NULL },
549 { "python", Python_functions, Python_suffixes, NULL },
550 { "scheme", Scheme_functions, Scheme_suffixes, NULL },
551 { "tex", TeX_functions, TeX_suffixes, NULL },
552 { "yacc", Yacc_entries, Yacc_suffixes, NULL },
553 { "auto", NULL }, /* default guessing scheme */
554 { "none", just_read_file }, /* regexp matching only */
555 { NULL, NULL } /* end of list */
560 print_language_names ()
565 puts ("\nThese are the currently supported languages, along with the\n\
566 default file name suffixes:");
567 for (lang = lang_names; lang->name != NULL; lang++)
569 printf ("\t%s\t", lang->name);
570 if (lang->suffixes != NULL)
571 for (ext = lang->suffixes; *ext != NULL; ext++)
572 printf (" .%s", *ext);
575 puts ("Where `auto' means use default language for files based on file\n\
576 name suffix, and `none' means only do regexp processing on files.\n\
577 If no language is specified and no matching suffix is found,\n\
578 the first line of the file is read for a sharp-bang (#!) sequence\n\
579 followed by the name of an interpreter. If no such sequence is found,\n\
580 Fortran is tried first; if no tags are found, C is tried next.");
584 # define VERSION "20"
589 printf ("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION);
590 puts ("Copyright (C) 1996 Free Software Foundation, Inc. and Ken Arnold");
591 puts ("This program is distributed under the same terms as Emacs");
599 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
601 These are the options accepted by %s.\n", progname, progname);
603 puts ("You may use unambiguous abbreviations for the long option names.");
605 puts ("Long option names do not work with this executable, as it is not\n\
606 linked with GNU getopt.");
607 #endif /* LONG_OPTIONS */
608 puts ("A - as file name means read names from stdin (one per line).");
610 printf (" Absolute names are stored in the output file as they are.\n\
611 Relative ones are stored relative to the output file's directory.");
614 puts ("-a, --append\n\
615 Append tag entries to existing tags file.");
618 puts ("-B, --backward-search\n\
619 Write the search commands for the tag entries using '?', the\n\
620 backward-search command instead of '/', the forward-search command.");
623 Treat files whose name suffix defaults to C language as C++ files.");
626 puts ("-d, --defines\n\
627 Create tag entries for C #define constants and enum constants, too.");
629 puts ("-D, --no-defines\n\
630 Don't create tag entries for C #define constants and enum constants.\n\
631 This makes the tags file smaller.");
635 puts ("-i FILE, --include=FILE\n\
636 Include a note in tag file indicating that, when searching for\n\
637 a tag, one should also consult the tags file FILE after\n\
638 checking the current file.");
639 puts ("-l LANG, --language=LANG\n\
640 Force the following files to be considered as written in the\n\
641 named language up to the next --language=LANG option.");
646 Create tag entries for global variables in some languages.");
648 puts ("--no-globals\n\
649 Do not create tag entries for global variables in some\n\
650 languages. This makes the tags file smaller.");
652 Create tag entries for member variables in C and derived languages.");
655 puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
656 Make a tag for each line matching pattern REGEXP in the\n\
657 following files. regexfile is a file containing one REGEXP\n\
658 per line. REGEXP is anchored (as if preceded by ^).\n\
659 The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
660 named tags can be created with:\n\
661 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
662 puts ("-R, --no-regex\n\
663 Don't create tags from regexps for the following files.");
664 #endif /* ETAGS_REGEXPS */
665 puts ("-o FILE, --output=FILE\n\
666 Write the tags to FILE.");
668 puts ("-O, --oo-browser\n\
669 Generate a specialized tags format used only by the Altrasoft OO-Browser.");
671 puts ("-I, --ignore-indentation\n\
672 Don't rely on indentation quite as much as normal. Currently,\n\
673 this means not to assume that a closing brace in the first\n\
674 column is the final brace of a function or structure\n\
675 definition in C and C++.");
679 puts ("-t, --typedefs\n\
680 Generate tag entries for C typedefs.");
681 puts ("-T, --typedefs-and-c++\n\
682 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
683 and C++ member functions.");
684 puts ("-u, --update\n\
685 Update the tag entries for the given files, leaving tag\n\
686 entries for other files in place. Currently, this is\n\
687 implemented by deleting the existing entries for the given\n\
688 files and then rewriting the new entries at the end of the\n\
689 tags file. It is often faster to simply rebuild the entire\n\
690 tag file than to use this.");
691 puts ("-v, --vgrind\n\
692 Generates an index of items intended for human consumption,\n\
693 similar to the output of vgrind. The index is sorted, and\n\
694 gives the page number of each item.");
695 puts ("-w, --no-warn\n\
696 Suppress warning messages about entries defined in multiple\n\
698 puts ("-x, --cxref\n\
699 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
700 The output uses line numbers instead of page numbers, but\n\
701 beyond that the differences are cosmetic; try both to see\n\
705 puts ("-V, --version\n\
706 Print the version of the program.\n\
708 Print this help message.");
710 print_language_names ();
713 puts ("Report bugs to bug-gnu-emacs@prep.ai.mit.edu");
726 /* This structure helps us allow mixing of --lang and file names. */
729 enum argument_type arg_type;
734 #ifdef VMS /* VMS specific functions */
738 /* This is a BUG! ANY arbitrary limit is a BUG!
739 Won't someone please fix this? */
740 #define MAX_FILE_SPEC_LEN 255
743 char body[MAX_FILE_SPEC_LEN + 1];
747 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
748 returning in each successive call the next file name matching the input
749 spec. The function expects that each in_spec passed
750 to it will be processed to completion; in particular, up to and
751 including the call following that in which the last matching name
752 is returned, the function ignores the value of in_spec, and will
753 only start processing a new spec with the following call.
754 If an error occurs, on return out_spec contains the value
755 of in_spec when the error occurred.
757 With each successive file name returned in out_spec, the
758 function's return value is one. When there are no more matching
759 names the function returns zero. If on the first call no file
760 matches in_spec, or there is any other error, -1 is returned.
765 #define OUTSIZE MAX_FILE_SPEC_LEN
771 static long context = 0;
772 static struct dsc$descriptor_s o;
773 static struct dsc$descriptor_s i;
774 static bool pass1 = TRUE;
781 o.dsc$a_pointer = (char *) out;
782 o.dsc$w_length = (short)OUTSIZE;
783 i.dsc$a_pointer = in;
784 i.dsc$w_length = (short)strlen(in);
785 i.dsc$b_dtype = DSC$K_DTYPE_T;
786 i.dsc$b_class = DSC$K_CLASS_S;
787 o.dsc$b_dtype = DSC$K_DTYPE_VT;
788 o.dsc$b_class = DSC$K_CLASS_VS;
790 if ((status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL)
792 out->body[out->curlen] = EOS;
795 else if (status == RMS$_NMF)
799 strcpy(out->body, in);
802 lib$find_file_end(&context);
808 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
809 name of each file specified by the provided arg expanding wildcards.
812 gfnames (arg, p_error)
816 static vspec filename = {MAX_FILE_SPEC_LEN, "\0"};
818 switch (fn_exp (&filename, arg))
822 return filename.body;
828 return filename.body;
832 #ifndef OLD /* Newer versions of VMS do provide `system'. */
836 error ("%s", "system() function not implemented under VMS");
840 #define VERSION_DELIM ';'
841 char *massage_name (s)
847 if (*s == VERSION_DELIM)
860 main (int argc, char *argv[])
863 unsigned int nincluded_files;
864 char **included_files;
867 int current_arg, file_count;
868 linebuffer filename_lb;
874 _fmode = O_BINARY; /* all of files are treated as binary files */
879 included_files = xnew (argc, char *);
883 /* Allocate enough no matter what happens. Overkill, but each one
885 argbuffer = xnew (argc, argument);
888 /* Set syntax for regular expression routines. */
889 re_set_syntax (RE_SYNTAX_EMACS | RE_INTERVALS);
890 #endif /* ETAGS_REGEXPS */
893 * If etags, always find typedefs and structure tags. Why not?
894 * Also default is to find macro constants, enum constants and
899 typedefs = typedefs_and_cplusplus = constantypedefs = TRUE;
911 optstring = "-aCdDf:Il:o:r:RStTi:BuvxwVhH";
913 optstring = "-aCdDf:Il:o:r:RStTi:BOuvxwVhH";
917 optstring = "-aCdDf:Il:o:StTi:BuvxwVhH";
919 optstring = "-aCdDf:Il:o:StTi:BOuvxwVhH";
921 #endif /* ETAGS_REGEXPS */
924 optstring = optstring + 1;
925 #endif /* LONG_OPTIONS */
927 opt = getopt_long (argc, argv, optstring, longopts, 0);
934 /* If getopt returns 0, then it has already processed a
935 long-named option. We should do nothing. */
939 /* This means that a file name has been seen. Record it. */
940 argbuffer[current_arg].arg_type = at_filename;
941 argbuffer[current_arg].what = optarg;
946 /* Common options. */
947 case 'a': append_to_tagfile = TRUE; break;
948 case 'C': cplusplus = TRUE; break;
949 case 'd': constantypedefs = TRUE; break;
950 case 'D': constantypedefs = FALSE; break;
951 case 'f': /* for compatibility with old makefiles */
955 /* convert char to string, to call error with */
957 sprintf (buf, "%c", opt);
958 error ("-%s option may only be given once.", buf);
959 suggest_asking_for_help ();
965 oo_browser_format = TRUE;
969 case 'S': /* for backward compatibility */
970 noindentypedefs = TRUE;
974 language *lang = get_language_from_name (optarg);
977 argbuffer[current_arg].lang = lang;
978 argbuffer[current_arg].arg_type = at_language;
985 argbuffer[current_arg].arg_type = at_regexp;
986 argbuffer[current_arg].what = optarg;
990 argbuffer[current_arg].arg_type = at_regexp;
991 argbuffer[current_arg].what = NULL;
994 #endif /* ETAGS_REGEXPS */
1006 typedefs = typedefs_and_cplusplus = TRUE;
1011 included_files[nincluded_files++] = optarg;
1014 /* Ctags options. */
1015 case 'B': searchar = '?'; break;
1016 case 'u': update = TRUE; break;
1017 case 'v': vgrind_style = TRUE; /*FALLTHRU*/
1018 case 'x': cxref_style = TRUE; break;
1019 case 'w': no_warnings = TRUE; break;
1022 suggest_asking_for_help ();
1026 for (; optind < argc; ++optind)
1028 argbuffer[current_arg].arg_type = at_filename;
1029 argbuffer[current_arg].what = argv[optind];
1034 if (nincluded_files == 0 && file_count == 0)
1036 error ("no input files specified.", 0);
1037 suggest_asking_for_help ();
1040 if (tagfile == NULL)
1041 tagfile = CTAGS ? "tags" : "TAGS";
1042 cwd = etags_getcwd (); /* the current working directory */
1043 if (cwd[strlen (cwd) - 1] != '/')
1046 cwd = concat (oldcwd, "/", "");
1049 if (streq (tagfile, "-"))
1052 tagfiledir = absolute_dirname (tagfile, cwd);
1054 init (); /* set up boolean "functions" */
1057 initbuffer (&token_name);
1058 initbuffer (&lbs[0].lb);
1059 initbuffer (&lbs[1].lb);
1060 initbuffer (&filename_lb);
1064 if (streq (tagfile, "-"))
1068 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1069 doesn't take effect until after `stdout' is already open). */
1070 if (!isatty (fileno (stdout)))
1071 setmode (fileno (stdout), O_BINARY);
1075 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1081 * Loop through files finding functions.
1083 for (i = 0; i < current_arg; ++i)
1085 switch (argbuffer[i].arg_type)
1088 forced_lang = argbuffer[i].lang;
1090 #ifdef ETAGS_REGEXPS
1092 analyse_regex (argbuffer[i].what);
1097 while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL)
1101 error ("can't find file %s\n", this_file);
1106 this_file = massage_name (this_file);
1109 this_file = argbuffer[i].what;
1112 oo_browser_clear_all_globals();
1114 /* Input file named "-" means read file names from stdin
1115 (one per line) and use them. */
1116 if (streq (this_file, "-"))
1117 while (readline_internal (&filename_lb, stdin) > 0)
1120 oo_browser_clear_some_globals();
1122 process_file (filename_lb.buffer);
1127 process_file (this_file);
1135 #ifdef ETAGS_REGEXPS
1137 #endif /* ETAGS_REGEXPS */
1141 while (nincluded_files-- > 0)
1142 fprintf (tagf, "\f\n%s,include\n", *included_files++);
1148 /* If CTAGS, we are here. process_file did not write the tags yet,
1149 because we want them ordered. Let's do it now. */
1159 for (i = 0; i < current_arg; ++i)
1161 if (argbuffer[i].arg_type != at_filename)
1164 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1165 tagfile, argbuffer[i].what, tagfile);
1166 if (system (cmd) != GOOD)
1167 fatal ("failed to execute shell command", (char *)NULL);
1169 append_to_tagfile = TRUE;
1172 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1181 sprintf (cmd, "sort %s -o %s", tagfile, tagfile);
1182 exit (system (cmd));
1189 * Return a language given the name.
1192 get_language_from_name (name)
1198 error ("empty language name", (char *)NULL);
1201 for (lang = lang_names; lang->name != NULL; lang++)
1202 if (streq (name, lang->name))
1204 error ("unknown language \"%s\"", name);
1212 * Return a language given the interpreter name.
1215 get_language_from_interpreter (interpreter)
1221 if (interpreter == NULL)
1223 for (lang = lang_names; lang->name != NULL; lang++)
1224 if (lang->interpreters != NULL)
1225 for (iname = lang->interpreters; *iname != NULL; iname++)
1226 if (streq (*iname, interpreter))
1235 * Return a language given the file suffix.
1238 get_language_from_suffix (suffix)
1246 for (lang = lang_names; lang->name != NULL; lang++)
1247 if (lang->suffixes != NULL)
1248 for (ext = lang->suffixes; *ext != NULL; ext++)
1249 if (streq (*ext, suffix))
1257 * This routine is called on each file argument.
1263 struct stat stat_buf;
1266 canonicalize_filename (file);
1267 if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode))
1269 error ("skipping %s: it is not a regular file.", file);
1272 if (streq (file, tagfile) && !streq (tagfile, "-"))
1274 error ("skipping inclusion of %s in self.", file);
1277 inf = fopen (file, "r");
1284 find_entries (file, inf);
1290 if (filename_is_absolute (file))
1292 /* file is an absolute file name. Canonicalise it. */
1293 filename = absolute_filename (file, cwd);
1297 /* file is a file name relative to cwd. Make it relative
1298 to the directory of the tags file. */
1299 filename = relative_filename (file, tagfiledir);
1302 if (oo_browser_format)
1303 fprintf (tagf, "\f\n%s\n", filename);
1306 fprintf (tagf, "\f\n%s,%d\n", filename, total_size_of_entries (head));
1315 * This routine sets up the boolean pseudo-functions which work
1316 * by setting boolean flags dependent upon the corresponding character.
1317 * Every char which is NOT in that string is not a white char. Therefore,
1318 * all of the array "_wht" is set to FALSE, and then the elements
1319 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1320 * of a char is TRUE if it is the string "white", else FALSE.
1328 for (i = 0; i < CHARS; i++)
1329 iswhite(i) = notinname(i) = begtoken(i) = intoken(i) = endtoken(i) = FALSE;
1330 for (sp = white; *sp != '\0'; sp++) iswhite (*sp) = TRUE;
1331 for (sp = nonam; *sp != '\0'; sp++) notinname (*sp) = TRUE;
1332 for (sp = begtk; *sp != '\0'; sp++) begtoken (*sp) = TRUE;
1333 for (sp = midtk; *sp != '\0'; sp++) intoken (*sp) = TRUE;
1334 for (sp = endtk; *sp != '\0'; sp++) endtoken (*sp) = TRUE;
1335 iswhite('\0') = iswhite('\n');
1336 notinname('\0') = notinname('\n');
1337 begtoken('\0') = begtoken('\n');
1338 intoken('\0') = intoken('\n');
1339 endtoken('\0') = endtoken('\n');
1343 * This routine opens the specified file and calls the function
1344 * which finds the function and type definitions.
1346 node *last_node = NULL;
1349 find_entries (file, inf)
1355 node *old_last_node;
1357 curfile = savestr (file);
1359 /* If user specified a language, use it. */
1361 if (lang != NULL && lang->function != NULL)
1364 lang->function (inf);
1370 cp = etags_strrchr (file, '.');
1374 lang = get_language_from_suffix (cp);
1375 if (lang != NULL && lang->function != NULL)
1378 lang->function (inf);
1385 /* Look for sharp-bang as the first two characters. */
1386 if (readline_internal (&lb, inf) > 0
1388 && lb.buffer[0] == '#'
1389 && lb.buffer[1] == '!')
1393 /* Set lp to point at the first char after the last slash in the
1394 line or, if no slashes, at the first nonblank. Then set cp to
1395 the first successive blank and terminate the string. */
1396 lp = etags_strrchr (lb.buffer+2, '/');
1400 lp = skip_spaces (lb.buffer + 2);
1401 cp = skip_non_spaces (lp);
1404 if (strlen (lp) > 0)
1406 lang = get_language_from_interpreter (lp);
1407 if (lang != NULL && lang->function != NULL)
1410 lang->function (inf);
1420 old_last_node = last_node;
1421 curlang = get_language_from_name ("fortran");
1422 Fortran_functions (inf);
1424 /* No Fortran entries found. Try C. */
1425 if (old_last_node == last_node)
1428 curlang = get_language_from_name (cplusplus ? "c++" : "c");
1429 default_C_entries (inf);
1438 pfnote (name, is_func, linestart, linelen, lno, cno)
1439 char *name; /* tag name, or NULL if unnamed */
1440 bool is_func; /* tag is a function */
1441 char *linestart; /* start of the line where tag is */
1442 int linelen; /* length of the line where tag is */
1443 int lno; /* line number */
1444 long cno; /* character number */
1448 if (CTAGS && name == NULL)
1451 np = xnew (1, node);
1453 /* If ctags mode, change name "main" to M<thisfilename>. */
1454 if (CTAGS && !cxref_style && streq (name, "main"))
1456 register char *fp = etags_strrchr (curfile, '/');
1457 np->name = concat ("M", fp == 0 ? curfile : fp + 1, "");
1458 fp = etags_strrchr (np->name, '.');
1459 if (fp && fp[1] != '\0' && fp[2] == '\0')
1464 np->been_warned = FALSE;
1466 np->is_func = is_func;
1468 /* Our char numbers are 0-base, because of C language tradition?
1469 ctags compatibility? old versions compatibility? I don't know.
1470 Anyway, since emacs's are 1-base we expect etags.el to take care
1471 of the difference. If we wanted to have 1-based numbers, we would
1472 uncomment the +1 below. */
1473 np->cno = cno /* + 1 */ ;
1474 np->left = np->right = NULL;
1475 if (CTAGS && !cxref_style)
1477 if (strlen (linestart) < 50)
1478 np->pat = concat (linestart, "$", "");
1480 np->pat = savenstr (linestart, 50);
1483 np->pat = savenstr (linestart, linelen);
1486 if (oo_browser_format)
1487 np->construct = oo_browser_construct;
1488 oo_browser_construct = C_NULL;
1489 oo_browser_check_and_clear_structtype();
1492 add_node (np, &head);
1495 /* Date: Wed, 22 Jan 1997 02:56:31 -0500 [last amended 18 Sep 1997]
1496 * From: Sam Kendall <kendall@mv.mv.com>
1497 * Subject: Proposal for firming up the TAGS format specification
1498 * To: F.Potorti@cnuce.cnr.it
1500 * pfnote should emit the optimized form [unnamed tag] only if:
1501 * 1. name does not contain any of the characters " \t\r\n(),;";
1502 * 2. linestart contains name as either a rightmost, or rightmost but
1503 * one character, substring;
1504 * 3. the character, if any, immediately before name in linestart must
1505 * be one of the characters " \t(),;";
1506 * 4. the character, if any, immediately after name in linestart must
1507 * also be one of the characters " \t(),;".
1509 * The real implementation uses the notinname() macro, which recognises
1510 * characters slightly different form " \t\r\n(),;". See the variable
1513 #define traditional_tag_style TRUE
1515 new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno)
1516 char *name; /* tag name, or NULL if unnamed */
1517 int namelen; /* tag length */
1518 bool is_func; /* tag is a function */
1519 char *linestart; /* start of the line where tag is */
1520 int linelen; /* length of the line where tag is */
1521 int lno; /* line number */
1522 long cno; /* character number */
1530 for (cp = name; !notinname (*cp); cp++)
1532 if (*cp == '\0') /* rule #1 */
1534 cp = linestart + linelen - namelen;
1535 if (notinname (linestart[linelen-1]))
1536 cp -= 1; /* rule #4 */
1538 if (!oo_browser_format
1539 && cp >= linestart /* rule #2 */
1541 if (cp >= linestart /* rule #2 */
1544 || notinname (cp[-1])) /* rule #3 */
1545 && strneq (name, cp, namelen)) /* rule #2 */
1546 named = FALSE; /* use unnamed tag */
1551 name = savenstr (name, namelen);
1554 pfnote (name, is_func, linestart, linelen, lno, cno);
1559 * recurse on left children, iterate on right children.
1567 register node *node_right = np->right;
1568 free_tree (np->left);
1569 if (np->name != NULL)
1579 * Adds a node to the tree of nodes. In etags mode, we don't keep
1580 * it sorted; we just keep a linear list. In ctags mode, maintain
1581 * an ordered tree, with no attempt at balancing.
1583 * add_node is the only function allowed to add nodes, so it can
1587 add_node (np, cur_node_p)
1588 node *np, **cur_node_p;
1591 register node *cur_node = *cur_node_p;
1593 if (cur_node == NULL)
1603 if (last_node == NULL)
1604 fatal ("internal error in add_node", (char *)NULL);
1605 last_node->right = np;
1611 dif = strcmp (np->name, cur_node->name);
1614 * If this tag name matches an existing one, then
1615 * do not add the node, but maybe print a warning.
1619 if (streq (np->file, cur_node->file))
1623 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1624 np->file, lineno, np->name);
1625 fprintf (stderr, "Second entry ignored\n");
1628 else if (!cur_node->been_warned && !no_warnings)
1632 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1633 np->file, cur_node->file, np->name);
1634 cur_node->been_warned = TRUE;
1639 /* Actually add the node */
1640 add_node (np, dif < 0 ? &cur_node->left : &cur_node->right);
1645 /* Default class name for the current OO-Browser tag. */
1646 static char *oo_browser_class;
1647 /* Prefix character to use in OO-Browser listings for the current tag. */
1648 static char oo_browser_prefix;
1652 put_entries (node *np)
1659 /* Output subentries that precede this one */
1660 put_entries (np->left);
1662 /* Output this entry */
1667 if (oo_browser_format)
1669 /* Omit C++ `class' and `method' entries as well as Objective-C
1670 entries from this OO-Browser tags file since the browser handles
1671 them independently of this file. Omit `extern' variable declarations
1672 as they are unused by the OO-Browser. */
1673 if (np->construct != C_CLASS
1674 && np->construct != C_METHOD
1675 && np->construct != C_EXTERN
1676 && np->construct != C_OBJC)
1678 oo_browser_class = oo_browser_default_classes[np->construct];
1679 switch (np->construct)
1688 oo_browser_prefix = '=';
1692 oo_browser_prefix = '-';
1695 if (np->name != NULL)
1696 fprintf (tagf, "%s@%c %s@%s\n",
1697 oo_browser_class, oo_browser_prefix,
1700 fprintf (tagf, "%s@%c ???@%s\n",
1701 oo_browser_class, oo_browser_prefix, np->pat);
1707 if (np->name != NULL)
1708 fprintf (tagf, "%s\177%s\001%d,%ld\n",
1709 np->pat, np->name, np->lno, np->cno);
1711 fprintf (tagf, "%s\177%d,%ld\n",
1712 np->pat, np->lno, np->cno);
1719 if (np->name == NULL)
1720 error ("internal error: NULL name in ctags mode.", (char *)NULL);
1725 fprintf (stdout, "%s %s %d\n",
1726 np->name, np->file, (np->lno + 63) / 64);
1728 fprintf (stdout, "%-16s %3d %-16s %s\n",
1729 np->name, np->lno, np->file, np->pat);
1733 fprintf (tagf, "%s\t%s\t", np->name, np->file);
1737 putc (searchar, tagf);
1740 for (sp = np->pat; *sp; sp++)
1742 if (*sp == '\\' || *sp == searchar)
1746 putc (searchar, tagf);
1749 { /* a typedef; text pattern inadequate */
1750 fprintf (tagf, "%d", np->lno);
1756 /* Output subentries that follow this one */
1757 put_entries (np->right);
1760 /* Length of a number's decimal representation. */
1761 int number_len PP ((long num));
1767 while ((num /= 10) > 0)
1773 * Return total number of characters that put_entries will output for
1774 * the nodes in the subtree of the specified node. Works only if
1775 * we are not ctags, but called only in that case. This count
1776 * is irrelevant with the new tags.el, but is still supplied for
1777 * backward compatibility.
1780 total_size_of_entries (np)
1788 for (total = 0; np != NULL; np = np->right)
1790 /* Count left subentries. */
1791 total += total_size_of_entries (np->left);
1793 /* Count this entry */
1794 total += strlen (np->pat) + 1;
1795 total += number_len ((long) np->lno) + 1 + number_len (np->cno) + 1;
1796 if (np->name != NULL)
1797 total += 1 + strlen (np->name); /* \001name */
1804 * The C symbol tables.
1809 st_C_objprot, st_C_objimpl, st_C_objend,
1813 st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec,
1816 , st_C_union, st_C_class, st_C_extern, st_C_inline
1820 /* Feed stuff between (but not including) %[ and %] lines to:
1821 gperf -c -k 1,3 -o -p -r -t
1823 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1825 @interface, 0, st_C_objprot
1826 @protocol, 0, st_C_objprot
1827 @implementation,0, st_C_objimpl
1828 @end, 0, st_C_objend
1829 import, C_JAVA, st_C_ignore
1830 package, C_JAVA, st_C_ignore
1831 friend, C_PLPL, st_C_ignore
1832 extends, C_JAVA, st_C_javastruct
1833 implements, C_JAVA, st_C_javastruct
1834 interface, C_JAVA, st_C_struct
1835 class, C_PLPL, st_C_class
1836 namespace, C_PLPL, st_C_struct
1837 domain, C_STAR, st_C_struct
1838 union, 0, st_C_union
1839 struct, 0, st_C_struct
1841 typedef, 0, st_C_typedef
1842 define, 0, st_C_define
1843 inline, 0, st_C_inline
1844 bool, C_PLPL, st_C_typespec
1845 long, 0, st_C_typespec
1846 short, 0, st_C_typespec
1847 int, 0, st_C_typespec
1848 char, 0, st_C_typespec
1849 float, 0, st_C_typespec
1850 double, 0, st_C_typespec
1851 signed, 0, st_C_typespec
1852 unsigned, 0, st_C_typespec
1853 auto, 0, st_C_typespec
1854 void, 0, st_C_typespec
1855 extern, 0, st_C_extern
1856 static, 0, st_C_typespec
1857 const, 0, st_C_const
1858 volatile, 0, st_C_typespec
1859 explicit, C_PLPL, st_C_typespec
1860 mutable, C_PLPL, st_C_typespec
1861 typename, C_PLPL, st_C_typespec
1862 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
1863 DEFUN, 0, st_C_gnumacro
1864 SYSCALL, 0, st_C_gnumacro
1865 ENTRY, 0, st_C_gnumacro
1866 PSEUDO, 0, st_C_gnumacro
1867 # These are defined inside C functions, so currently they are not met.
1868 # EXFUN used in glibc, DEFVAR_* in emacs.
1869 #EXFUN, 0, st_C_gnumacro
1870 #DEFVAR_, 0, st_C_gnumacro
1872 and replace lines between %< and %> with its output. */
1874 /* C code produced by gperf version 2.5 (GNU C++ version) */
1875 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
1876 struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
1878 #define TOTAL_KEYWORDS 41
1879 #define MIN_WORD_LENGTH 3
1880 #define MAX_WORD_LENGTH 15
1881 #define MIN_HASH_VALUE 13
1882 #define MAX_HASH_VALUE 129
1883 /* maximum key range = 117, duplicates = 0 */
1886 hash (char *str, unsigned int len)
1888 static unsigned char asso_values[] =
1890 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1891 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1892 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1893 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1894 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1895 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1896 130, 130, 130, 130, 13, 130, 130, 130, 33, 32,
1897 47, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1898 5, 130, 130, 20, 32, 130, 130, 130, 130, 130,
1899 130, 130, 130, 130, 130, 130, 130, 47, 55, 8,
1900 15, 33, 61, 38, 130, 60, 130, 130, 2, 9,
1901 10, 62, 59, 130, 28, 27, 50, 19, 3, 130,
1902 130, 130, 130, 130, 130, 130, 130, 130,
1905 asso_values[(unsigned char) str[2]] +
1906 asso_values[(unsigned char) str[0]];
1909 static struct C_stab_entry *
1910 in_word_set (char *str, unsigned int len)
1912 static struct C_stab_entry wordlist[] =
1914 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1915 {"",}, {"",}, {"",}, {"",},
1916 {"volatile", 0, st_C_typespec},
1918 {"long", 0, st_C_typespec},
1919 {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1920 {"const", 0, st_C_const},
1921 {"",}, {"",}, {"",},
1922 {"@end", 0, st_C_objend},
1923 {"namespace", C_PLPL, st_C_struct},
1925 {"domain", C_STAR, st_C_struct},
1927 {"@interface", 0, st_C_objprot},
1928 {"",}, {"",}, {"",},
1929 {"@implementation", 0, st_C_objimpl},
1931 {"double", 0, st_C_typespec},
1933 {"PSEUDO", 0, st_C_gnumacro},
1934 {"",}, {"",}, {"",},
1935 {"SYSCALL", 0, st_C_gnumacro},
1937 {"@protocol", 0, st_C_objprot},
1938 {"",}, {"",}, {"",},
1939 {"unsigned", 0, st_C_typespec},
1941 {"enum", 0, st_C_enum},
1943 {"char", 0, st_C_typespec},
1944 {"class", C_PLPL, st_C_class},
1945 {"struct", 0, st_C_struct},
1946 {"",}, {"",}, {"",}, {"",},
1947 {"mutable", C_PLPL, st_C_typespec},
1948 {"void", 0, st_C_typespec},
1949 {"inline", 0, st_C_inline},
1950 {"ENTRY", 0, st_C_gnumacro},
1952 {"signed", 0, st_C_typespec},
1954 {"package", C_JAVA, st_C_ignore},
1955 {"",}, {"",}, {"",}, {"",}, {"",},
1956 {"static", 0, st_C_typespec},
1958 {"define", 0, st_C_define},
1960 {"union", 0, st_C_union},
1961 {"DEFUN", 0, st_C_gnumacro},
1962 {"",}, {"",}, {"",},
1963 {"extern", 0, st_C_extern},
1964 {"extends", C_JAVA, st_C_javastruct},
1965 {"",}, {"",}, {"",},
1966 {"short", 0, st_C_typespec},
1967 {"",}, {"",}, {"",}, {"",}, {"",},
1968 {"explicit", C_PLPL, st_C_typespec},
1969 {"auto", 0, st_C_typespec},
1970 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1972 {"int", 0, st_C_typespec},
1974 {"typedef", 0, st_C_typedef},
1975 {"typename", C_PLPL, st_C_typespec},
1977 {"interface", C_JAVA, st_C_struct},
1979 {"bool", C_PLPL, st_C_typespec},
1980 {"",}, {"",}, {"",},
1981 {"import", C_JAVA, st_C_ignore},
1983 {"friend", C_PLPL, st_C_ignore},
1984 {"float", 0, st_C_typespec},
1985 {"implements", C_JAVA, st_C_javastruct},
1988 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
1990 register int key = hash (str, len);
1992 if (key <= MAX_HASH_VALUE && key >= 0)
1994 register char *s = wordlist[key].name;
1996 if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
1997 return &wordlist[key];
2004 enum sym_type C_symtype PP ((char *str, int len, int c_ext));
2006 C_symtype (str, len, c_ext)
2011 register struct C_stab_entry *se = in_word_set (str, len);
2013 if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
2019 * C functions and variables are recognized using a simple
2020 * finite automaton. fvdef is its state variable.
2024 fvnone, /* nothing seen */
2025 fvnameseen, /* function or variable name seen */
2026 fstartlist, /* func: just after open parenthesis */
2027 finlist, /* func: in parameter list */
2028 flistseen, /* func: after parameter list */
2029 fignore, /* func: before open brace */
2030 vignore /* var-like: ignore until ';' */
2035 * typedefs are recognized using a simple finite automaton.
2036 * typdef is its state variable.
2040 tnone, /* nothing seen */
2041 ttypedseen, /* typedef keyword seen */
2042 tinbody, /* inside typedef body */
2043 tend, /* just before typedef tag */
2044 tignore /* junk after typedef tag */
2049 * struct-like structures (enum, struct and union) are recognized
2050 * using another simple finite automaton. `structdef' is its state
2055 snone, /* nothing seen yet */
2056 skeyseen, /* struct-like keyword seen */
2057 stagseen, /* struct-like tag seen */
2058 scolonseen, /* colon seen after struct-like tag */
2059 sinbody /* in struct body: recognize member func defs*/
2063 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
2064 * struct tag, and structtype is the type of the preceding struct-like
2067 char *structtag = "<uninited>";
2068 enum sym_type structtype;
2072 oo_browser_check_and_clear_structtype(void)
2074 /* Allow for multiple enum_label tags. */
2075 if (structtype != st_C_enum)
2076 structtype = st_none;
2081 * When objdef is different from onone, objtag is the name of the class.
2083 char *objtag = "<uninited>";
2086 * Yet another little state machine to deal with preprocessor lines.
2090 dnone, /* nothing seen */
2091 dsharpseen, /* '#' seen as first char on line */
2092 ddefineseen, /* '#' and 'define' seen */
2093 dignorerest /* ignore rest of line */
2097 * State machine for Objective C protocols and implementations.
2098 * Tom R.Hageman <tom@basil.icce.rug.nl>
2102 onone, /* nothing seen */
2103 oprotocol, /* @interface or @protocol seen */
2104 oimplementation, /* @implementations seen */
2105 otagseen, /* class name seen */
2106 oparenseen, /* parenthesis before category seen */
2107 ocatseen, /* category name seen */
2108 oinbody, /* in @implementation body */
2109 omethodsign, /* in @implementation body, after +/- */
2110 omethodtag, /* after method name */
2111 omethodcolon, /* after method colon */
2112 omethodparm, /* after method parameter */
2113 oignore /* wait for @end */
2117 * Use this structure to keep info about the token read, and how it
2118 * should be tagged. Used by the make_C_tag function to build a tag.
2131 token tok; /* latest token read */
2134 * Set this to TRUE, and the next token considered is called a function.
2135 * Used only for GNU emacs's function-defining macros.
2137 bool next_token_is_func;
2140 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
2145 * methodlen is the length of the method name stored in token_name.
2151 oo_browser_clear_all_globals(void)
2153 /* Initialize globals so there is no carry over between files. */
2154 oo_browser_construct = C_NULL;
2155 fvdef = fvnone; typdef = tnone; structdef = snone;
2156 definedef = dnone; objdef = onone;
2157 structtype = st_none;
2158 next_token_is_func = yacc_rules = FALSE;
2162 oo_browser_clear_some_globals(void)
2164 oo_browser_construct = C_NULL;
2165 structtype = st_none;
2171 * checks to see if the current token is at the start of a
2172 * function or variable, or corresponds to a typedef, or
2173 * is a struct/union/enum tag, or #define, or an enum constant.
2175 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2176 * with args. C_EXT is which language we are looking at.
2178 * In the future we will need some way to adjust where the end of
2179 * the token is; for instance, implementing the C++ keyword
2180 * `operator' properly will adjust the end of the token to be after
2181 * whatever follows `operator'.
2189 * next_token_is_func IN OUT
2191 bool consider_token PP ((char *str, int len, int c, int c_ext,
2192 int cblev, int parlev, bool *is_func_or_var));
2194 consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var)
2195 register char *str; /* IN: token pointer */
2196 register int len; /* IN: token length */
2197 register int c; /* IN: first char after the token */
2198 int c_ext; /* IN: C extensions mask */
2199 int cblev; /* IN: curly brace level */
2200 int parlev; /* IN: parenthesis level */
2201 bool *is_func_or_var; /* OUT: function or variable found */
2203 enum sym_type toktype = C_symtype (str, len, c_ext);
2209 set_construct(C_STRUCTURE);
2212 set_construct(C_UNION);
2215 set_construct(C_CLASS);
2218 set_construct(C_ENUMERATION);
2221 set_construct(C_TYPE);
2224 set_construct(C_EXTERN);
2227 set_construct(C_FUNCTION);
2233 * Advance the definedef state machine.
2238 /* We're not on a preprocessor line. */
2241 if (toktype == st_C_define)
2243 definedef = ddefineseen;
2247 definedef = dignorerest;
2252 * Make a tag for any macro, unless it is a constant
2253 * and constantypedefs is FALSE.
2255 definedef = dignorerest;
2257 *is_func_or_var = (c == '(');
2260 char *p = str + len * sizeof(char);
2263 /* This must be a macro since there is no
2264 whitespace between the opening parenthesis
2265 and the definition name. */
2266 *is_func_or_var = TRUE;
2269 *is_func_or_var = FALSE;
2271 /* Handle possible whitespace between macro tag and opening
2272 parenthesis and ensure this is an actual macro.
2273 -- Bob Weiner, Altrasoft, 11/19/1997 */
2274 while (*p && isspace(*p)) p++;
2277 /* Skip over nested parentheses. */
2282 while (*++p && depth > 0 && *p != '\n')
2293 /* If this is a macro, we have just passed
2294 the arguments and there will be more on
2295 the line before the NULL character that marks
2296 the end of the line token. */
2297 while (*p == ' ' || *p == '\t') p++;
2298 if (*p) *is_func_or_var = TRUE;
2303 set_construct((*is_func_or_var) ? C_MACRO : C_CONSTANT);
2305 if (!*is_func_or_var && !constantypedefs)
2312 error ("internal error: definedef value.", (char *)NULL);
2321 if (toktype == st_C_typedef)
2324 typdef = ttypedseen;
2333 set_construct(C_CONSTANT);
2350 /* Do not return here, so the structdef stuff has a chance. */
2356 set_construct(C_CONSTANT);
2372 * This structdef business is currently only invoked when cblev==0.
2373 * It should be recursively invoked whatever the curly brace level,
2374 * and a stack of states kept, to allow for definitions of structs
2377 * This structdef business is NOT invoked when we are ctags and the
2378 * file is plain C. This is because a struct tag may have the same
2379 * name as another tag, and this loses with ctags.
2383 case st_C_javastruct:
2384 if (structdef == stagseen)
2385 structdef = scolonseen;
2394 if (typdef == ttypedseen
2395 || (typedefs_and_cplusplus && cblev == 0 && structdef == snone))
2397 structdef = skeyseen;
2398 structtype = toktype;
2403 if (structdef == skeyseen)
2405 /* Save the tag for struct/union/class, for functions and variables
2406 that may be defined inside. */
2408 if (structtype == st_C_struct)
2410 if (structtype == st_C_struct
2411 || structtype == st_C_union
2412 || structtype == st_C_class)
2414 structtag = savenstr (str, len);
2416 structtag = "<enum>";
2417 structdef = stagseen;
2421 /* Avoid entering fvdef stuff if typdef is going on. */
2422 if (typdef != tnone)
2428 /* Detect GNU macros.
2430 DEFUN note for writers of emacs C code:
2431 The DEFUN macro, used in emacs C source code, has a first arg
2432 that is a string (the lisp function name), and a second arg that
2433 is a C function name. Since etags skips strings, the second arg
2434 is tagged. This is unfortunate, as it would be better to tag the
2435 first arg. The simplest way to deal with this problem would be
2436 to name the tag with a name built from the function name, by
2437 removing the initial 'F' character and substituting '-' for '_'.
2438 Anyway, this assumes that the conventions of naming lisp
2439 functions will never change. Currently, this method is not
2440 implemented, so writers of emacs code are recommended to put the
2441 first two args of a DEFUN on the same line. */
2442 if (definedef == dnone && toktype == st_C_gnumacro)
2444 next_token_is_func = TRUE;
2447 if (next_token_is_func)
2449 next_token_is_func = FALSE;
2451 *is_func_or_var = TRUE;
2455 /* Detect Objective C constructs. */
2463 set_construct(C_OBJC);
2469 set_construct(C_OBJC);
2471 objdef = oimplementation;
2475 case oimplementation:
2476 /* Save the class tag for functions or variables defined inside. */
2477 objtag = savenstr (str, len);
2481 /* Save the class tag for categories. */
2482 objtag = savenstr (str, len);
2484 *is_func_or_var = TRUE;
2488 *is_func_or_var = TRUE;
2495 objdef = omethodtag;
2497 grow_linebuffer (&token_name, methodlen + 1);
2498 strncpy (token_name.buffer, str, len);
2499 token_name.buffer[methodlen] = '\0';
2500 token_name.len = methodlen;
2506 objdef = omethodparm;
2511 objdef = omethodtag;
2513 grow_linebuffer (&token_name, methodlen + 1);
2514 strncat (token_name.buffer, str, len);
2515 token_name.len = methodlen;
2520 if (toktype == st_C_objend)
2522 /* Memory leakage here: the string pointed by objtag is
2523 never released, because many tests would be needed to
2524 avoid breaking on incorrect input code. The amount of
2525 memory leaked here is the sum of the lengths of the
2533 /* A function, variable or enum constant? */
2537 set_construct(C_CONSTANT);
2543 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2544 fvdef = fvnone; /* should be useless */
2550 if (constantypedefs && structdef == sinbody && structtype == st_C_enum)
2553 oo_browser_construct = C_ENUM_LABEL;
2559 if (fvdef == fvnone)
2561 fvdef = fvnameseen; /* function or variable */
2562 *is_func_or_var = TRUE;
2572 * This routine finds functions, variables, typedefs,
2573 * #define's, enum constants and struct/union/enum definitions in
2574 * #C syntax and adds them to the list.
2576 #define current_lb_is_new (newndx == curndx)
2577 #define switch_line_buffers() (curndx = 1 - curndx)
2579 #define curlb (lbs[curndx].lb)
2580 #define othlb (lbs[1-curndx].lb)
2581 #define newlb (lbs[newndx].lb)
2582 #define curlinepos (lbs[curndx].linepos)
2583 #define othlinepos (lbs[1-curndx].linepos)
2584 #define newlinepos (lbs[newndx].linepos)
2586 #define CNL_SAVE_DEFINEDEF() \
2588 curlinepos = charno; \
2590 linecharno = charno; \
2591 charno += readline (&curlb, inf); \
2592 lp = curlb.buffer; \
2599 CNL_SAVE_DEFINEDEF(); \
2600 if (savetok.valid) \
2603 savetok.valid = FALSE; \
2605 definedef = dnone; \
2609 void make_C_tag PP ((bool isfun));
2614 /* This function should never be called when tok.valid is FALSE, but
2615 we must protect against invalid input or internal errors. */
2618 if (traditional_tag_style)
2620 /* This was the original code. Now we call new_pfnote instead,
2621 which uses the new method for naming tags (see new_pfnote). */
2624 if (CTAGS || tok.named)
2625 name = savestr (token_name.buffer);
2626 pfnote (name, isfun,
2627 tok.buffer, tok.linelen, tok.lineno, tok.linepos);
2630 new_pfnote (token_name.buffer, token_name.len, isfun,
2631 tok.buffer, tok.linelen, tok.lineno, tok.linepos);
2640 C_entries (c_ext, inf)
2641 int c_ext; /* extension of C */
2642 FILE *inf; /* input file */
2644 register char c; /* latest char read; '\0' for end of line */
2645 register char *lp; /* pointer one beyond the character `c' */
2646 int curndx, newndx; /* indices for current and new lb */
2647 register int tokoff; /* offset in line of start of current token */
2648 register int toklen; /* length of current token */
2649 char *qualifier; /* string used to qualify names */
2650 int qlen; /* length of qualifier */
2651 int cblev; /* current curly brace level */
2652 int parlev; /* current parenthesis level */
2653 bool incomm, inquote, inchar, quotednl, midtoken;
2655 token savetok; /* token saved during preprocessor handling */
2658 tokoff = toklen = 0; /* keep compiler quiet */
2659 curndx = newndx = 0;
2665 fvdef = fvnone; typdef = tnone; structdef = snone;
2666 definedef = dnone; objdef = onone;
2667 next_token_is_func = yacc_rules = FALSE;
2668 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2669 tok.valid = savetok.valid = FALSE;
2672 cplpl = (c_ext & C_PLPL) == C_PLPL;
2673 cjava = (c_ext & C_JAVA) == C_JAVA;
2675 { qualifier = "."; qlen = 1; }
2677 { qualifier = "::"; qlen = 2; }
2684 /* If we're at the end of the line, the next character is a
2685 '\0'; don't skip it, because it's the thing that tells us
2686 to read the next line. */
2707 /* Newlines inside comments do not end macro definitions in
2709 CNL_SAVE_DEFINEDEF ();
2722 /* Newlines inside strings do not end macro definitions
2723 in traditional cpp, even though compilers don't
2724 usually accept them. */
2725 CNL_SAVE_DEFINEDEF ();
2735 /* Hmmm, something went wrong. */
2749 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2754 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2764 else if (/* cplpl && */ *lp == '/')
2772 if ((c_ext & YACC) && *lp == '%')
2774 /* entering or exiting rules section in yacc file */
2776 definedef = dnone; fvdef = fvnone;
2777 typdef = tnone; structdef = snone;
2778 next_token_is_func = FALSE;
2779 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2781 yacc_rules = !yacc_rules;
2787 if (definedef == dnone)
2790 bool cpptoken = TRUE;
2792 /* Look back on this line. If all blanks, or nonblanks
2793 followed by an end of comment, this is a preprocessor
2795 for (cp = newlb.buffer; cp < lp-1; cp++)
2798 if (*cp == '*' && *(cp+1) == '/')
2807 definedef = dsharpseen;
2808 } /* if (definedef == dnone) */
2814 /* Consider token only if some complicated conditions are satisfied. */
2815 if ((definedef != dnone
2816 || (cblev == 0 && structdef != scolonseen)
2817 || (cblev == 1 && cplpl && structdef == sinbody)
2818 || (structdef == sinbody && structtype == st_C_enum))
2819 && typdef != tignore
2820 && definedef != dignorerest
2821 && fvdef != finlist)
2827 if (c == ':' && cplpl && *lp == ':' && begtoken(*(lp + 1)))
2830 * This handles :: in the middle, but not at the
2831 * beginning of an identifier.
2836 set_construct(C_METHOD);
2841 bool funorvar = FALSE;
2844 || consider_token (newlb.buffer + tokoff, toklen, c,
2845 c_ext, cblev, parlev, &funorvar))
2848 if (structdef == sinbody
2849 && definedef == dnone
2851 /* function or var defined in C++ class body */
2853 int len = strlen (structtag) + qlen + toklen;
2854 grow_linebuffer (&token_name, len + 1);
2855 strcpy (token_name.buffer, structtag);
2856 strcat (token_name.buffer, qualifier);
2857 strncat (token_name.buffer,
2858 newlb.buffer + tokoff, toklen);
2859 token_name.len = len;
2862 oo_browser_construct = C_METHOD;
2865 else if (objdef == ocatseen)
2866 /* Objective C category */
2868 int len = strlen (objtag) + 2 + toklen;
2869 grow_linebuffer (&token_name, len + 1);
2870 strcpy (token_name.buffer, objtag);
2871 strcat (token_name.buffer, "(");
2872 strncat (token_name.buffer,
2873 newlb.buffer + tokoff, toklen);
2874 strcat (token_name.buffer, ")");
2875 token_name.len = len;
2878 oo_browser_construct = C_OBJC;
2881 else if (objdef == omethodtag
2882 || objdef == omethodparm)
2883 /* Objective C method */
2887 oo_browser_construct = C_OBJC;
2892 grow_linebuffer (&token_name, toklen + 1);
2893 strncpy (token_name.buffer,
2894 newlb.buffer + tokoff, toklen);
2895 token_name.buffer[toklen] = '\0';
2896 token_name.len = toklen;
2899 = (structdef == stagseen
2902 /* Also name #define constants,
2903 enumerations and enum_labels.
2904 Conditionalize `funorvar' reference
2905 here or #defines will appear without
2907 -- Bob Weiner, Altrasoft, 4/25/1998 */
2908 || ((oo_browser_format || funorvar)
2909 && definedef == dignorerest)
2910 || (oo_browser_format
2911 && (oo_browser_construct == C_ENUMERATION
2912 || oo_browser_construct == C_ENUM_LABEL))
2915 && definedef == dignorerest)
2919 tok.lineno = lineno;
2920 tok.linelen = tokoff + toklen + 1;
2921 tok.buffer = newlb.buffer;
2922 tok.linepos = newlinepos;
2925 if (definedef == dnone
2926 && (fvdef == fvnameseen
2927 || structdef == stagseen
2929 || objdef != onone))
2931 if (current_lb_is_new)
2932 switch_line_buffers ();
2935 make_C_tag (funorvar);
2939 } /* if (endtoken (c)) */
2940 else if (intoken (c))
2945 } /* if (midtoken) */
2946 else if (begtoken (c))
2958 set_construct(C_MACRO);
2960 make_C_tag (TRUE); /* a function */
2967 if (structdef == stagseen && !cjava)
2973 if (!yacc_rules || lp == newlb.buffer + 1)
2975 tokoff = lp - 1 - newlb.buffer;
2980 } /* if (begtoken) */
2981 } /* if must look at token */
2984 /* Detect end of line, colon, comma, semicolon and various braces
2985 after having handled a token.*/
2989 if (definedef != dnone)
2995 make_C_tag (TRUE); /* an Objective C class */
2999 objdef = omethodcolon;
3001 grow_linebuffer (&token_name, methodlen + 1);
3002 strcat (token_name.buffer, ":");
3003 token_name.len = methodlen;
3006 if (structdef == stagseen)
3007 structdef = scolonseen;
3014 make_C_tag (FALSE); /* a yacc function */
3024 if (definedef != dnone)
3031 set_construct(C_TYPE);
3033 make_C_tag (FALSE); /* a typedef */
3043 if ((globals && cblev == 0) || (members && cblev == 1))
3045 make_C_tag (FALSE); /* a variable */
3047 /* if (constantypedefs && structdef == snone)*/
3053 set_construct(C_ENUMERATION);
3056 set_construct(C_CLASS);
3059 set_construct(C_VARIABLE);
3063 /* Force reset of st_C_enum structtype value. */
3064 structtype = st_none;
3070 /* The following instruction invalidates the token.
3071 Probably the token should be invalidated in all
3072 other cases where some state machine is reset. */
3075 if (structdef == stagseen)
3079 if (definedef != dnone)
3085 make_C_tag (TRUE); /* an Objective C method */
3096 if ((globals && cblev == 0) || (members && cblev == 1))
3097 make_C_tag (FALSE); /* a variable */
3102 if (structdef == stagseen)
3106 if (definedef != dnone)
3108 if (cblev == 0 && typdef == tend)
3111 set_construct(C_TYPE);
3114 make_C_tag (FALSE); /* a typedef */
3125 if ((globals && cblev == 0) || (members && cblev == 1))
3126 make_C_tag (FALSE); /* a variable */
3128 if (constantypedefs && structdef == snone)
3134 set_construct(C_ENUMERATION);
3137 set_construct(C_CLASS);
3140 set_construct(C_VARIABLE);
3144 /* Force reset of st_C_enum structtype value. */
3145 structtype = st_none;
3152 if (structdef == stagseen)
3156 if (definedef != dnone)
3158 if (objdef == otagseen && parlev == 0)
3159 objdef = oparenseen;
3167 if (tok.valid && *lp != '*')
3169 /* This handles constructs like:
3170 typedef void OperatorFun (int fun); */
3173 set_construct(C_TYPE);
3178 } /* switch (typdef) */
3190 if (definedef != dnone)
3192 if (objdef == ocatseen && parlev == 1)
3194 make_C_tag (TRUE); /* an Objective C category */
3206 if (cblev == 0 && typdef == tend)
3209 set_construct(C_TYPE);
3212 make_C_tag (FALSE); /* a typedef */
3215 else if (parlev < 0) /* can happen due to ill-conceived #if's. */
3219 if (definedef != dnone)
3221 if (typdef == ttypedseen)
3225 case skeyseen: /* unnamed struct */
3226 structdef = sinbody;
3227 structtag = "_anonymous_";
3230 case scolonseen: /* named struct */
3231 structdef = sinbody;
3232 make_C_tag (FALSE); /* a struct */
3239 set_construct(C_FUNCTION);
3240 /* Ensure function name is recorded.
3241 -- Bob Weiner, Altrasoft */
3244 make_C_tag (TRUE); /* a function */
3253 make_C_tag (TRUE); /* an Objective C class */
3258 make_C_tag (TRUE); /* an Objective C method */
3262 /* Neutralize `extern "C" {' grot. */
3263 if (cblev == 0 && structdef == snone && typdef == tnone)
3270 if (definedef != dnone)
3272 if (fvdef == fstartlist)
3273 fvdef = fvnone; /* avoid tagging `foo' in `foo (*bar()) ()' */
3276 if (definedef != dnone)
3278 if (!noindentypedefs && lp == newlb.buffer + 1)
3280 cblev = 0; /* reset curly brace level if first column */
3281 parlev = 0; /* also reset paren level, just in case... */
3287 if (typdef == tinbody)
3289 /* Memory leakage here: the string pointed by structtag is
3290 never released, because I fear to miss something and
3291 break things while freeing the area. The amount of
3292 memory leaked here is the sum of the lengths of the
3294 if (structdef == sinbody)
3295 free (structtag); */
3298 structtag = "<error>";
3300 /* Next line added to avoid any state carryover between
3301 functions. -- Bob Weiner, Altrasoft, 11/19/1997 */
3302 fvdef = fvnone; oo_browser_construct = C_NULL;
3307 if (definedef != dnone)
3320 if ((globals && cblev == 0) || (members && cblev == 1))
3322 make_C_tag (FALSE); /* a variable */
3329 set_construct(C_ENUMERATION);
3332 set_construct(C_CLASS);
3335 /* a global variable */
3336 set_construct(C_VARIABLE);
3340 /* ootags categorizes each tag found whereas etags doesn't.
3341 Set the is_method flag if this tag has been marked as
3342 such by an earlier section of code.
3343 -- Steve Baur, Altrasoft, 5/7/1998 */
3344 is_method = (oo_browser_construct == C_METHOD);
3347 /* Force reset of st_C_enum structtype value. */
3348 structtype = st_none;
3354 fvdef = is_method ? fignore : vignore;
3365 if (objdef == oinbody && cblev == 0)
3367 objdef = omethodsign;
3371 case '#': case '~': case '&': case '%': case '/': case '|':
3372 case '^': case '!': case '<': case '>': case '.': case '?': case ']':
3373 if (definedef != dnone)
3379 /* The above characters cannot follow a function tag in C, so
3380 unmark this as a function entry. For C++, these characters
3381 may follow an `operator' function construct, so skip the
3382 unmarking conditional below.
3383 -- Steve Baur, Altrasoft, 5/7/1998 */
3384 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
3391 if (objdef == otagseen)
3393 make_C_tag (TRUE); /* an Objective C class */
3396 /* If a macro spans multiple lines don't reset its state. */
3398 CNL_SAVE_DEFINEDEF ();
3404 } /* while not eof */
3408 * Process either a C++ file or a C file depending on the setting
3412 default_C_entries (inf)
3415 C_entries (cplusplus ? C_PLPL : 0, inf);
3418 /* Always do plain ANSI C. */
3420 plain_C_entries (inf)
3426 /* Always do C++. */
3428 Cplusplus_entries (inf)
3431 C_entries (C_PLPL, inf);
3434 /* Always do Java. */
3439 C_entries (C_JAVA, inf);
3447 C_entries (C_STAR, inf);
3450 /* Always do Yacc. */
3455 C_entries (YACC, inf);
3458 /* A useful macro. */
3459 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3460 for (lineno = charno = 0; /* loop initialization */ \
3461 !feof (file_pointer) /* loop test */ \
3462 && (lineno++, /* instructions at start of loop */ \
3463 linecharno = charno, \
3464 charno += readline (&line_buffer, file_pointer), \
3465 char_pointer = lb.buffer, \
3471 * Read a file, but do no processing. This is used to do regexp
3472 * matching on files that have no language defined.
3475 just_read_file (inf)
3478 register char *dummy;
3480 LOOP_ON_INPUT_LINES (inf, lb, dummy)
3484 /* Fortran parsing */
3486 bool tail PP ((char *cp));
3491 register int len = 0;
3493 while (*cp && lowcase(*cp) == lowcase(dbp[len]))
3495 if (*cp == '\0' && !intoken(dbp[len]))
3506 dbp = skip_spaces (dbp);
3510 dbp = skip_spaces (dbp);
3511 if (strneq (dbp, "(*)", 3))
3516 if (!isdigit (*dbp))
3518 --dbp; /* force failure */
3523 while (isdigit (*dbp));
3526 void getit PP ((FILE *inf));
3533 dbp = skip_spaces (dbp);
3537 linecharno = charno;
3538 charno += readline (&lb, inf);
3543 dbp = skip_spaces (dbp);
3549 for (cp = dbp + 1; *cp && intoken (*cp); cp++)
3551 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
3552 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3557 Fortran_functions (inf)
3560 LOOP_ON_INPUT_LINES (inf, lb, dbp)
3563 dbp++; /* Ratfor escape to fortran */
3564 dbp = skip_spaces (dbp);
3567 switch (lowcase (*dbp))
3570 if (tail ("integer"))
3578 if (tail ("logical"))
3582 if (tail ("complex") || tail ("character"))
3586 if (tail ("double"))
3588 dbp = skip_spaces (dbp);
3591 if (tail ("precision"))
3597 dbp = skip_spaces (dbp);
3600 switch (lowcase (*dbp))
3603 if (tail ("function"))
3607 if (tail ("subroutine"))
3615 if (tail ("program"))
3620 if (tail ("procedure"))
3628 * Bob Weiner, Motorola Inc., 4/3/94
3629 * Unix and microcontroller assembly tag handling
3630 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
3633 Asm_labels (FILE *inf)
3637 LOOP_ON_INPUT_LINES (inf, lb, cp)
3639 /* If first char is alphabetic or one of [_.$], test for colon
3640 following identifier. */
3641 if (isalpha (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3643 /* Read past label. */
3645 while (isalnum (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3647 if (*cp == ':' || isspace (*cp))
3649 /* Found end of label, so copy it and add it to the table. */
3650 pfnote ((CTAGS) ? savenstr(lb.buffer, cp-lb.buffer) : NULL, TRUE,
3651 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3658 * Perl support by Bart Robinson <lomew@cs.utah.edu>
3659 * enhanced by Michael Ernst <mernst@alum.mit.edu>
3660 * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/
3661 * Perl variable names: /^(my|local).../
3664 Perl_functions (inf)
3669 LOOP_ON_INPUT_LINES (inf, lb, cp)
3673 && *cp++ == 'b' && isspace (*cp++))
3675 cp = skip_spaces (cp);
3679 && !isspace (*cp) && *cp != '{' && *cp != '(')
3681 pfnote ((CTAGS) ? savenstr(lb.buffer, cp-lb.buffer) : NULL, TRUE,
3682 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3685 else if (globals /* only if tagging global vars is enabled */
3686 && ((cp = lb.buffer,
3695 && (*cp == '(' || isspace (*cp)))
3697 /* After "my" or "local", but before any following paren or space. */
3698 char *varname = NULL;
3700 cp = skip_spaces (cp);
3701 if (*cp == '$' || *cp == '@' || *cp == '%')
3703 char* varstart = ++cp;
3704 while (isalnum (*cp) || *cp == '_')
3706 varname = savenstr (varstart, cp-varstart);
3710 /* Should be examining a variable list at this point;
3711 could insist on seeing an open parenthesis. */
3712 while (*cp != '\0' && *cp != ';' && *cp != '=' && *cp != ')')
3716 /* Perhaps I should back cp up one character, so the TAGS table
3717 doesn't mention (and so depend upon) the following char. */
3718 pfnote ((CTAGS) ? savenstr (lb.buffer, cp-lb.buffer) : varname,
3719 FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3725 * Python support by Eric S. Raymond <esr@thyrsus.com>
3726 * Look for /^def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
3729 Python_functions (inf)
3734 LOOP_ON_INPUT_LINES (inf, lb, cp)
3738 && *cp++ == 'f' && isspace (*cp++))
3740 cp = skip_spaces (cp);
3741 while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':')
3743 pfnote ((char *) NULL, TRUE,
3744 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3752 && *cp++ == 's' && isspace (*cp++))
3754 cp = skip_spaces (cp);
3755 while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':')
3757 pfnote ((char *) NULL, TRUE,
3758 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3763 /* Idea by Corny de Souza
3764 * Cobol tag functions
3765 * We could look for anything that could be a paragraph name.
3766 * i.e. anything that starts in column 8 is one word and ends in a full stop.
3769 Cobol_paragraphs (inf)
3772 register char *bp, *ep;
3774 LOOP_ON_INPUT_LINES (inf, lb, bp)
3780 /* If eoln, compiler option or comment ignore whole line. */
3781 if (bp[-1] != ' ' || !isalnum (bp[0]))
3784 for (ep = bp; isalnum (*ep) || *ep == '-'; ep++)
3787 pfnote ((CTAGS) ? savenstr (bp, ep-bp) : NULL, TRUE,
3788 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
3792 /* Added by Mosur Mohan, 4/22/88 */
3793 /* Pascal parsing */
3796 * Locates tags for procedures & functions. Doesn't do any type- or
3797 * var-definitions. It does look for the keyword "extern" or
3798 * "forward" immediately following the procedure statement; if found,
3799 * the tag is skipped.
3802 Pascal_functions (inf)
3805 linebuffer tline; /* mostly copied from C_entries */
3807 int save_lineno, save_len;
3808 char c, *cp, *namebuf;
3810 bool /* each of these flags is TRUE iff: */
3811 incomment, /* point is inside a comment */
3812 inquote, /* point is inside '..' string */
3813 get_tagname, /* point is after PROCEDURE/FUNCTION
3814 keyword, so next item = potential tag */
3815 found_tag, /* point is after a potential tag */
3816 inparms, /* point is within parameter-list */
3817 verify_tag; /* point has passed the parm-list, so the
3818 next token will determine whether this
3819 is a FORWARD/EXTERN to be ignored, or
3820 whether it is a real tag */
3822 save_lcno = save_lineno = save_len = 0; /* keep compiler quiet */
3823 namebuf = NULL; /* keep compiler quiet */
3828 initbuffer (&tline);
3830 incomment = inquote = FALSE;
3831 found_tag = FALSE; /* have a proc name; check if extern */
3832 get_tagname = FALSE; /* have found "procedure" keyword */
3833 inparms = FALSE; /* found '(' after "proc" */
3834 verify_tag = FALSE; /* check if "extern" is ahead */
3837 while (!feof (inf)) /* long main loop to get next char */
3840 if (c == '\0') /* if end of line */
3843 linecharno = charno;
3844 charno += readline (&lb, inf);
3848 if (!((found_tag && verify_tag)
3850 c = *dbp++; /* only if don't need *dbp pointing
3851 to the beginning of the name of
3852 the procedure or function */
3856 if (c == '}') /* within { } comments */
3858 else if (c == '*' && *dbp == ')') /* within (* *) comments */
3875 inquote = TRUE; /* found first quote */
3877 case '{': /* found open { comment */
3881 if (*dbp == '*') /* found open (* comment */
3886 else if (found_tag) /* found '(' after tag, i.e., parm-list */
3889 case ')': /* end of parms list */
3894 if (found_tag && !inparms) /* end of proc or fn stmt */
3901 if (found_tag && verify_tag && (*dbp != ' '))
3903 /* check if this is an "extern" declaration */
3906 if (lowcase (*dbp == 'e'))
3908 if (tail ("extern")) /* superfluous, really! */
3914 else if (lowcase (*dbp) == 'f')
3916 if (tail ("forward")) /* check for forward reference */
3922 if (found_tag && verify_tag) /* not external proc, so make tag */
3926 pfnote (namebuf, TRUE,
3927 tline.buffer, save_len, save_lineno, save_lcno);
3931 if (get_tagname) /* grab name of proc or fn */
3936 /* save all values for later tagging */
3937 grow_linebuffer (&tline, lb.len + 1);
3938 strcpy (tline.buffer, lb.buffer);
3939 save_lineno = lineno;
3940 save_lcno = linecharno;
3942 /* grab block name */
3943 for (cp = dbp + 1; *cp != '\0' && !endtoken (*cp); cp++)
3945 namebuf = (CTAGS) ? savenstr (dbp, cp-dbp) : NULL;
3946 dbp = cp; /* set dbp to e-o-token */
3947 save_len = dbp - lb.buffer + 1;
3948 get_tagname = FALSE;
3952 /* and proceed to check for "extern" */
3954 else if (!incomment && !inquote && !found_tag)
3956 /* check for proc/fn keywords */
3957 switch (lowcase (c))
3960 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
3964 if (tail ("unction"))
3969 } /* while not eof */
3971 free (tline.buffer);
3975 * lisp tag functions
3976 * look for (def or (DEF, quote or QUOTE
3978 int L_isdef PP ((char *strp));
3981 register char *strp;
3983 return ((strp[1] == 'd' || strp[1] == 'D')
3984 && (strp[2] == 'e' || strp[2] == 'E')
3985 && (strp[3] == 'f' || strp[3] == 'F'));
3987 int L_isquote PP ((char *strp));
3990 register char *strp;
3992 return ((*++strp == 'q' || *strp == 'Q')
3993 && (*++strp == 'u' || *strp == 'U')
3994 && (*++strp == 'o' || *strp == 'O')
3995 && (*++strp == 't' || *strp == 'T')
3996 && (*++strp == 'e' || *strp == 'E')
3997 && isspace (*++strp));
4000 void L_getit PP ((void));
4006 if (*dbp == '\'') /* Skip prefix quote */
4008 else if (*dbp == '(')
4010 if (L_isquote (dbp))
4011 dbp += 7; /* Skip "(quote " */
4013 dbp += 1; /* Skip "(" before name in (defstruct (foo)) */
4014 dbp = skip_spaces (dbp);
4017 for (cp = dbp /*+1*/;
4018 *cp != '\0' && *cp != '(' && *cp != ' ' && *cp != ')';
4024 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
4025 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4029 Lisp_functions (inf)
4032 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4038 dbp = skip_non_spaces (dbp);
4039 dbp = skip_spaces (dbp);
4044 /* Check for (foo::defmumble name-defined ... */
4047 while (*dbp != '\0' && !isspace (*dbp)
4048 && *dbp != ':' && *dbp != '(' && *dbp != ')');
4053 while (*dbp == ':');
4055 if (L_isdef (dbp - 1))
4057 dbp = skip_non_spaces (dbp);
4058 dbp = skip_spaces (dbp);
4068 * Postscript tag functions
4069 * Just look for lines where the first character is '/'
4070 * Richard Mlynarik <mly@adoc.xerox.com>
4073 Postscript_functions (inf)
4076 register char *bp, *ep;
4078 LOOP_ON_INPUT_LINES (inf, lb, bp)
4083 *ep != '\0' && *ep != ' ' && *ep != '{';
4086 pfnote ((CTAGS) ? savenstr (bp, ep-bp) : NULL, TRUE,
4087 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
4094 * Scheme tag functions
4095 * look for (def... xyzzy
4096 * look for (def... (xyzzy
4097 * look for (def ... ((...(xyzzy ....
4098 * look for (set! xyzzy
4101 void get_scheme PP ((void));
4104 Scheme_functions (inf)
4107 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4110 && (dbp[1] == 'D' || dbp[1] == 'd')
4111 && (dbp[2] == 'E' || dbp[2] == 'e')
4112 && (dbp[3] == 'F' || dbp[3] == 'f'))
4114 dbp = skip_non_spaces (dbp);
4115 /* Skip over open parens and white space */
4116 while (isspace (*dbp) || *dbp == '(')
4121 && (dbp[1] == 'S' || dbp[1] == 's')
4122 && (dbp[2] == 'E' || dbp[2] == 'e')
4123 && (dbp[3] == 'T' || dbp[3] == 't')
4124 && (dbp[4] == '!' || dbp[4] == '!')
4125 && (isspace (dbp[5])))
4127 dbp = skip_non_spaces (dbp);
4128 dbp = skip_spaces (dbp);
4141 /* Go till you get to white space or a syntactic break */
4143 *cp != '\0' && *cp != '(' && *cp != ')' && !isspace (*cp);
4146 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
4147 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4150 /* Find tags in TeX and LaTeX input files. */
4152 /* TEX_toktab is a table of TeX control sequences that define tags.
4153 Each TEX_tabent records one such control sequence.
4154 CONVERT THIS TO USE THE Stab TYPE!! */
4161 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
4163 /* Default set of control sequences to put into TEX_toktab.
4164 The value of environment var TEXTAGS is prepended to this. */
4166 char *TEX_defenv = "\
4167 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4168 :part:appendix:entry:index";
4170 void TEX_mode PP ((FILE *inf));
4171 struct TEX_tabent *TEX_decode_env PP ((char *evarname, char *defenv));
4172 int TEX_Token PP ((char *cp));
4174 char TEX_esc = '\\';
4175 char TEX_opgrp = '{';
4176 char TEX_clgrp = '}';
4179 * TeX/LaTeX scanning loop.
4188 /* Select either \ or ! as escape character. */
4191 /* Initialize token table once from environment. */
4193 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
4195 LOOP_ON_INPUT_LINES (inf, lb, cp)
4198 /* Look at each esc in line. */
4199 while ((cp = etags_strchr (cp, TEX_esc)) != NULL)
4203 linecharno += cp - lasthit;
4205 i = TEX_Token (lasthit);
4208 /* We seem to include the TeX command in the tag name.
4210 for (p = lasthit + TEX_toktab[i].len;
4211 *p != '\0' && *p != TEX_clgrp;
4214 pfnote (/*savenstr (lasthit, p-lasthit)*/ (char *)NULL, TRUE,
4215 lb.buffer, lb.len, lineno, linecharno);
4216 break; /* We only tag a line once */
4222 #define TEX_LESC '\\'
4223 #define TEX_SESC '!'
4226 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4227 chars accordingly. */
4234 while ((c = getc (inf)) != EOF)
4236 /* Skip to next line if we hit the TeX comment char. */
4240 else if (c == TEX_LESC || c == TEX_SESC )
4259 /* Read environment and prepend it to the default string.
4260 Build token table. */
4262 TEX_decode_env (evarname, defenv)
4266 register char *env, *p;
4268 struct TEX_tabent *tab;
4271 /* Append default string to environment. */
4272 env = getenv (evarname);
4278 env = concat (oldenv, defenv, "");
4282 /* Allocate a token table */
4283 for (size = 1, p = env; p;)
4284 if ((p = etags_strchr (p, ':')) && *++p != '\0')
4286 /* Add 1 to leave room for null terminator. */
4287 tab = xnew (size + 1, struct TEX_tabent);
4289 /* Unpack environment string into token table. Be careful about */
4290 /* zero-length strings (leading ':', "::" and trailing ':') */
4293 p = etags_strchr (env, ':');
4294 if (!p) /* End of environment string. */
4295 p = env + strlen (env);
4297 { /* Only non-zero strings. */
4298 tab[i].name = savenstr (env, p - env);
4299 tab[i].len = strlen (tab[i].name);
4306 tab[i].name = NULL; /* Mark end of table. */
4314 /* If the text at CP matches one of the tag-defining TeX command names,
4315 return the pointer to the first occurrence of that command in TEX_toktab.
4316 Otherwise return -1.
4317 Keep the capital `T' in `token' for dumb truncating compilers
4318 (this distinguishes it from `TEX_toktab' */
4325 for (i = 0; TEX_toktab[i].len > 0; i++)
4326 if (strneq (TEX_toktab[i].name, cp, TEX_toktab[i].len))
4332 * Prolog support (rewritten) by Anders Lindgren, Mar. 96
4334 * Assumes that the predicate starts at column 0.
4335 * Only the first clause of a predicate is added.
4337 int prolog_pred PP ((char *s, char *last));
4338 void prolog_skip_comment PP ((linebuffer *plb, FILE *inf));
4339 int prolog_atom PP ((char *s, int pos));
4342 Prolog_functions (inf)
4353 LOOP_ON_INPUT_LINES (inf, lb, cp)
4355 if (cp[0] == '\0') /* Empty line */
4357 else if (isspace (cp[0])) /* Not a predicate */
4359 else if (cp[0] == '/' && cp[1] == '*') /* comment. */
4360 prolog_skip_comment (&lb, inf);
4361 else if ((len = prolog_pred (cp, last)) > 0)
4363 /* Predicate. Store the function name so that we only
4364 generate a tag for the first clause. */
4366 last = xnew(len + 1, char);
4367 else if (len + 1 > allocated)
4368 last = xrnew (last, len + 1, char);
4369 allocated = len + 1;
4370 strncpy (last, cp, len);
4378 prolog_skip_comment (plb, inf)
4386 for (cp = plb->buffer; *cp != '\0'; cp++)
4387 if (cp[0] == '*' && cp[1] == '/')
4390 linecharno += readline (plb, inf);
4396 * A predicate definition is added if it matches:
4397 * <beginning of line><Prolog Atom><whitespace>(
4399 * It is added to the tags database if it doesn't match the
4400 * name of the previous clause header.
4402 * Return the size of the name of the predicate, or 0 if no header
4406 prolog_pred (s, last)
4408 char *last; /* Name of last clause. */
4413 pos = prolog_atom (s, 0);
4418 pos = skip_spaces (s + pos) - s;
4420 if ((s[pos] == '(') || (s[pos] == '.'))
4425 /* Save only the first clause. */
4427 || len != strlen (last)
4428 || !strneq (s, last, len))
4430 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
4431 s, pos, lineno, linecharno);
4439 * Consume a Prolog atom.
4440 * Return the number of bytes consumed, or -1 if there was an error.
4442 * A prolog atom, in this context, could be one of:
4443 * - An alphanumeric sequence, starting with a lower case letter.
4444 * - A quoted arbitrary string. Single quotes can escape themselves.
4445 * Backslash quotes everything.
4448 prolog_atom (s, pos)
4456 if (islower(s[pos]) || (s[pos] == '_'))
4458 /* The atom is unquoted. */
4460 while (isalnum(s[pos]) || (s[pos] == '_'))
4464 return pos - origpos;
4466 else if (s[pos] == '\'')
4477 pos++; /* A double quote */
4479 else if (s[pos] == '\0')
4480 /* Multiline quoted atoms are ignored. */
4482 else if (s[pos] == '\\')
4484 if (s[pos+1] == '\0')
4491 return pos - origpos;
4498 * Support for Erlang -- Anders Lindgren, Feb 1996.
4500 * Generates tags for functions, defines, and records.
4502 * Assumes that Erlang functions start at column 0.
4504 int erlang_func PP ((char *s, char *last));
4505 void erlang_attribute PP ((char *s));
4506 int erlang_atom PP ((char *s, int pos));
4509 Erlang_functions (inf)
4520 LOOP_ON_INPUT_LINES (inf, lb, cp)
4522 if (cp[0] == '\0') /* Empty line */
4524 else if (isspace (cp[0])) /* Not function nor attribute */
4526 else if (cp[0] == '%') /* comment */
4528 else if (cp[0] == '"') /* Sometimes, strings start in column one */
4530 else if (cp[0] == '-') /* attribute, e.g. "-define" */
4532 erlang_attribute (cp);
4535 else if ((len = erlang_func (cp, last)) > 0)
4538 * Function. Store the function name so that we only
4539 * generates a tag for the first clause.
4542 last = xnew (len + 1, char);
4543 else if (len + 1 > allocated)
4544 last = xrnew (last, len + 1, char);
4545 allocated = len + 1;
4546 strncpy (last, cp, len);
4554 * A function definition is added if it matches:
4555 * <beginning of line><Erlang Atom><whitespace>(
4557 * It is added to the tags database if it doesn't match the
4558 * name of the previous clause header.
4560 * Return the size of the name of the function, or 0 if no function
4564 erlang_func (s, last)
4566 char *last; /* Name of last clause. */
4571 pos = erlang_atom (s, 0);
4576 pos = skip_spaces (s + pos) - s;
4578 /* Save only the first clause. */
4581 || len != strlen (last)
4582 || !strneq (s, last, len)))
4584 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
4585 s, pos, lineno, linecharno);
4594 * Handle attributes. Currently, tags are generated for defines
4597 * They are on the form:
4598 * -define(foo, bar).
4599 * -define(Foo(M, N), M+N).
4600 * -record(graph, {vtab = notable, cyclic = true}).
4603 erlang_attribute (s)
4609 if (strneq (s, "-define", 7) || strneq (s, "-record", 7))
4611 pos = skip_spaces (s + 7) - s;
4612 if (s[pos++] == '(')
4614 pos = skip_spaces (s + pos) - s;
4615 len = erlang_atom (s, pos);
4617 pfnote ((CTAGS) ? savenstr (& s[pos], len) : NULL, TRUE,
4618 s, pos + len, lineno, linecharno);
4626 * Consume an Erlang atom (or variable).
4627 * Return the number of bytes consumed, or -1 if there was an error.
4630 erlang_atom (s, pos)
4638 if (isalpha (s[pos]) || s[pos] == '_')
4640 /* The atom is unquoted. */
4642 while (isalnum (s[pos]) || s[pos] == '_')
4644 return pos - origpos;
4646 else if (s[pos] == '\'')
4657 else if (s[pos] == '\0')
4658 /* Multiline quoted atoms are ignored. */
4660 else if (s[pos] == '\\')
4662 if (s[pos+1] == '\0')
4669 return pos - origpos;
4675 #ifdef ETAGS_REGEXPS
4677 /* Take a string like "/blah/" and turn it into "blah", making sure
4678 that the first and last characters are the same, and handling
4679 quoted separator characters. Actually, stops on the occurrence of
4680 an unquoted separator. Also turns "\t" into a Tab character.
4681 Returns pointer to terminating separator. Works in place. Null
4682 terminates name string. */
4683 char * scan_separators PP ((char *name));
4685 scan_separators (name)
4689 char *copyto = name;
4690 bool quoted = FALSE;
4692 for (++name; *name != '\0'; ++name)
4698 else if (*name == sep)
4702 /* Something else is quoted, so preserve the quote. */
4708 else if (*name == '\\')
4710 else if (*name == sep)
4716 /* Terminate copied string. */
4721 /* Look at the argument of --regex or --no-regex and do the right
4722 thing. Same for each line of a regexp file. */
4724 analyse_regex (regex_arg)
4727 if (regex_arg == NULL)
4728 free_patterns (); /* --no-regex: remove existing regexps */
4730 /* A real --regexp option or a line in a regexp file. */
4731 switch (regex_arg[0])
4733 /* Comments in regexp file or null arg to --regex. */
4739 /* Read a regex file. This is recursive and may result in a
4740 loop, which will stop when the file descriptors are exhausted. */
4744 linebuffer regexbuf;
4745 char *regexfile = regex_arg + 1;
4747 /* regexfile is a file containing regexps, one per line. */
4748 regexfp = fopen (regexfile, "r");
4749 if (regexfp == NULL)
4754 initbuffer (®exbuf);
4755 while (readline_internal (®exbuf, regexfp) > 0)
4756 analyse_regex (regexbuf.buffer);
4757 free (regexbuf.buffer);
4762 /* Regexp to be used for a specific language only. */
4766 char *lang_name = regex_arg + 1;
4769 for (cp = lang_name; *cp != '}'; cp++)
4772 error ("unterminated language name in regex: %s", regex_arg);
4776 lang = get_language_from_name (lang_name);
4779 add_regex (cp + 1, lang);
4783 /* Regexp to be used for any language. */
4785 add_regex (regex_arg, NULL);
4790 /* Turn a name, which is an ed-style (but Emacs syntax) regular
4791 expression, into a real regular expression by compiling it. */
4793 add_regex (regexp_pattern, lang)
4794 char *regexp_pattern;
4799 struct re_pattern_buffer *patbuf;
4803 if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0])
4805 error ("%s: unterminated regexp", regexp_pattern);
4808 name = scan_separators (regexp_pattern);
4809 if (regexp_pattern[0] == '\0')
4811 error ("null regexp", (char *)NULL);
4814 (void) scan_separators (name);
4816 patbuf = xnew (1, struct re_pattern_buffer);
4817 patbuf->translate = NULL;
4818 patbuf->fastmap = NULL;
4819 patbuf->buffer = NULL;
4820 patbuf->allocated = 0;
4822 err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf);
4825 error ("%s while compiling pattern", err);
4830 p_head = xnew (1, pattern);
4831 p_head->regex = savestr (regexp_pattern);
4832 p_head->p_next = pp;
4833 p_head->language = lang;
4834 p_head->pattern = patbuf;
4835 p_head->name_pattern = savestr (name);
4836 p_head->error_signaled = FALSE;
4840 * Do the substitutions indicated by the regular expression and
4843 char * substitute PP ((char *in, char *out, struct re_registers *regs));
4845 substitute (in, out, regs)
4847 struct re_registers *regs;
4850 int size, dig, diglen;
4853 size = strlen (out);
4855 /* Pass 1: figure out how much to allocate by finding all \N strings. */
4856 if (out[size - 1] == '\\')
4857 fatal ("pattern error in \"%s\"", out);
4858 for (t = etags_strchr (out, '\\');
4860 t = etags_strchr (t + 2, '\\'))
4864 diglen = regs->end[dig] - regs->start[dig];
4870 /* Allocate space and do the substitutions. */
4871 result = xnew (size + 1, char);
4873 for (t = result; *out != '\0'; out++)
4874 if (*out == '\\' && isdigit (*++out))
4876 /* Using "dig2" satisfies my debugger. Bleah. */
4878 diglen = regs->end[dig] - regs->start[dig];
4879 strncpy (t, in + regs->start[dig], diglen);
4886 if (DEBUG && (t > result + size || t - result != strlen (result)))
4892 /* Deallocate all patterns. */
4897 while (p_head != NULL)
4899 pp = p_head->p_next;
4900 free (p_head->regex);
4901 free (p_head->name_pattern);
4908 #endif /* ETAGS_REGEXPS */
4909 /* Initialize a linebuffer for use */
4915 lbp->buffer = xnew (200, char);
4919 * Read a line of text from `stream' into `lbp', excluding the
4920 * newline or CR-NL, if any. Return the number of characters read from
4921 * `stream', which is the length of the line including the newline.
4923 * On DOS or Windows we do not count the CR character, if any, before the
4924 * NL, in the returned length; this mirrors the behavior of emacs on those
4925 * platforms (for text files, it translates CR-NL to NL as it reads in the
4929 readline_internal (lbp, stream)
4931 register FILE *stream;
4933 char *buffer = lbp->buffer;
4934 register char *p = lbp->buffer;
4935 register char *pend;
4938 pend = p + lbp->size; /* Separate to avoid 386/IX compiler bug. */
4942 register int c = getc (stream);
4945 /* We're at the end of linebuffer: expand it. */
4947 buffer = xrnew (buffer, lbp->size, char);
4948 p += buffer - lbp->buffer;
4949 pend = buffer + lbp->size;
4950 lbp->buffer = buffer;
4960 if (p > buffer && p[-1] == '\r')
4964 /* Assume CRLF->LF translation will be performed by Emacs
4965 when loading this file, so CRs won't appear in the buffer.
4966 It would be cleaner to compensate within Emacs;
4967 however, Emacs does not know how many CRs were deleted
4968 before any given point in the file. */
4983 lbp->len = p - buffer;
4985 return lbp->len + chars_deleted;
4989 * Like readline_internal, above, but in addition try to match the
4990 * input line against relevant regular expressions.
4993 readline (lbp, stream)
4997 /* Read new line. */
4998 long result = readline_internal (lbp, stream);
4999 #ifdef ETAGS_REGEXPS
5003 /* Match against relevant patterns. */
5005 for (pp = p_head; pp != NULL; pp = pp->p_next)
5007 /* Only use generic regexps or those for the current language. */
5008 if (pp->language != NULL && pp->language != curlang)
5011 match = re_match (pp->pattern, lbp->buffer, lbp->len, 0, &pp->regs);
5016 if (!pp->error_signaled)
5018 error ("error while matching \"%s\"", pp->regex);
5019 pp->error_signaled = TRUE;
5026 /* Match occurred. Construct a tag. */
5027 if (pp->name_pattern[0] != '\0')
5029 /* Make a named tag. */
5030 char *name = substitute (lbp->buffer,
5031 pp->name_pattern, &pp->regs);
5033 pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);
5037 /* Make an unnamed tag. */
5038 pfnote ((char *)NULL, TRUE,
5039 lbp->buffer, match, lineno, linecharno);
5044 #endif /* ETAGS_REGEXPS */
5050 * Return a pointer to a space of size strlen(cp)+1 allocated
5051 * with xnew where the string CP has been copied.
5057 return savenstr (cp, strlen (cp));
5061 * Return a pointer to a space of size LEN+1 allocated with xnew where
5062 * the string CP has been copied for at most the first LEN characters.
5071 dp = xnew (len + 1, char);
5072 strncpy (dp, cp, len);
5078 * Return the ptr in sp at which the character c last
5079 * appears; NULL if not found
5081 * Identical to System V strrchr, included for portability.
5084 etags_strrchr (sp, c)
5101 * Return the ptr in sp at which the character c first
5102 * appears; NULL if not found
5104 * Identical to System V strchr, included for portability.
5107 etags_strchr (sp, c)
5119 /* Skip spaces, return new pointer. */
5124 while (isspace (*cp)) /* isspace('\0')==FALSE */
5129 /* Skip non spaces, return new pointer. */
5131 skip_non_spaces (cp)
5134 while (!iswhite (*cp)) /* iswhite('\0')==TRUE */
5139 /* Print error message and exit. */
5157 suggest_asking_for_help ()
5159 fprintf (stderr, "\tTry `%s %s' for a complete list of options.\n",
5170 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
5173 const char *s1, *s2;
5175 fprintf (stderr, "%s: ", progname);
5176 fprintf (stderr, s1, s2);
5177 fprintf (stderr, "\n");
5180 /* Return a newly-allocated string whose contents
5181 concatenate those of s1, s2, s3. */
5186 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
5187 char *result = xnew (len1 + len2 + len3 + 1, char);
5189 strcpy (result, s1);
5190 strcpy (result + len1, s2);
5191 strcpy (result + len1 + len2, s3);
5192 result[len1 + len2 + len3] = '\0';
5197 /* Does the same work as the system V getcwd, but does not need to
5198 guess the buffer size in advance. */
5204 char *path = xnew (bufsize, char);
5206 while (getcwd (path, bufsize) == NULL)
5208 if (errno != ERANGE)
5212 path = xnew (bufsize, char);
5215 canonicalize_filename (path);
5218 #else /* not HAVE_GETCWD */
5220 char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */
5224 for (p = path; *p != '\0'; p++)
5230 return strdup (path);
5231 #else /* not MSDOS */
5236 pipe = (FILE *) popen ("pwd 2>/dev/null", "r");
5237 if (pipe == NULL || readline_internal (&path, pipe) == 0)
5242 #endif /* not MSDOS */
5243 #endif /* not HAVE_GETCWD */
5246 /* Return a newly allocated string containing the file name of FILE
5247 relative to the absolute directory DIR (which should end with a slash). */
5249 relative_filename (file, dir)
5252 char *fp, *dp, *afn, *res;
5255 /* Find the common root of file and dir (with a trailing slash). */
5256 afn = absolute_filename (file, cwd);
5259 while (*fp++ == *dp++)
5261 fp--, dp--; /* back to the first differing char */
5262 do /* look at the equal chars until '/' */
5266 /* Build a sequence of "../" strings for the resulting relative file name. */
5268 while ((dp = etags_strchr (dp + 1, '/')) != NULL)
5270 res = xnew (3*i + strlen (fp + 1) + 1, char);
5273 strcat (res, "../");
5275 /* Add the file name relative to the common root of file and dir. */
5276 strcat (res, fp + 1);
5282 /* Return a newly allocated string containing the absolute file name
5283 of FILE given DIR (which should end with a slash). */
5285 absolute_filename (file, dir)
5288 char *slashp, *cp, *res;
5290 if (filename_is_absolute (file))
5291 res = savestr (file);
5293 /* We don't support non-absolute file names with a drive
5294 letter, like `d:NAME' (it's too much hassle). */
5295 else if (file[1] == ':')
5296 fatal ("%s: relative file names with drive letters not supported", file);
5299 res = concat (dir, file, "");
5301 /* Delete the "/dirname/.." and "/." substrings. */
5302 slashp = etags_strchr (res, '/');
5303 while (slashp != NULL && slashp[0] != '\0')
5305 if (slashp[1] == '.')
5307 if (slashp[2] == '.'
5308 && (slashp[3] == '/' || slashp[3] == '\0'))
5313 while (cp >= res && !filename_is_absolute (cp));
5315 cp = slashp; /* the absolute name begins with "/.." */
5317 /* Under MSDOS and NT we get `d:/NAME' as absolute
5318 file name, so the luser could say `d:/../NAME'.
5319 We silently treat this as `d:/NAME'. */
5320 else if (cp[0] != '/')
5323 strcpy (cp, slashp + 3);
5327 else if (slashp[2] == '/' || slashp[2] == '\0')
5329 strcpy (slashp, slashp + 2);
5334 slashp = etags_strchr (slashp + 1, '/');
5338 return savestr ("/");
5343 /* Return a newly allocated string containing the absolute
5344 file name of dir where FILE resides given DIR (which should
5345 end with a slash). */
5347 absolute_dirname (file, dir)
5353 canonicalize_filename (file);
5354 slashp = etags_strrchr (file, '/');
5356 return savestr (dir);
5359 res = absolute_filename (file, dir);
5365 /* Whether the argument string is an absolute file name. The argument
5366 string must have been canonicalized with canonicalize_filename. */
5368 filename_is_absolute (fn)
5371 return (fn[0] == '/'
5373 || (isalpha(fn[0]) && fn[1] == ':' && fn[2] == '/')
5378 /* Translate backslashes into slashes. Works in place. */
5380 canonicalize_filename (fn)
5384 for (; *fn != '\0'; fn++)
5392 /* Increase the size of a linebuffer. */
5394 grow_linebuffer (lbp, toksize)
5398 while (lbp->size < toksize)
5400 lbp->buffer = xrnew (lbp->buffer, lbp->size, char);
5403 /* Like malloc but get fatal error if memory is exhausted. */
5408 long *result = (long *) malloc (size);
5410 fatal ("virtual memory exhausted", (char *)NULL);
5415 xrealloc (ptr, size)
5419 long *result = (long *) realloc (ptr, size);
5421 fatal ("virtual memory exhausted", (char *)NULL);