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 */
110 #include <sys/types.h>
111 #include <sys/stat.h>
113 #if !defined (S_ISREG) && defined (S_IFREG)
114 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
120 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
122 extern int optind, opterr;
123 #endif /* LONG_OPTIONS */
127 #endif /* ETAGS_REGEXPS */
129 /* Define CTAGS to make the program "ctags" compatible with the usual one.
130 Leave it undefined to make the program "etags", which makes emacs-style
131 tag tables and tags typedefs, #defines and struct/union/enum by default. */
139 /* Exit codes for success and failure. */
149 #define C_PLPL 0x00001 /* C++ */
150 #define C_STAR 0x00003 /* C* */
151 #define C_JAVA 0x00005 /* JAVA */
152 #define YACC 0x10000 /* yacc file */
154 #define streq(s,t) ((DEBUG && (s) == NULL && (t) == NULL \
155 && (abort (), 1)) || !strcmp (s, t))
156 #define strneq(s,t,n) ((DEBUG && (s) == NULL && (t) == NULL \
157 && (abort (), 1)) || !strncmp (s, t, n))
159 #define lowcase(c) tolower ((char)c)
161 #define CHARS 256 /* 2^sizeof(char) */
162 #define CHAR(x) ((unsigned int)x & (CHARS - 1))
163 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */
164 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
165 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
166 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
167 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
170 /*#undef OO_BROWSER*/
171 /* Due to the way this file is constructed, this unfortunately doesn't */
172 /* work except for documentation purposes. -slb */
177 #define set_construct(construct) \
178 if (!oo_browser_construct) oo_browser_construct = construct
179 void oo_browser_clear_all_globals();
180 void oo_browser_clear_some_globals();
181 void oo_browser_check_and_clear_structtype();
185 * xnew, xrnew -- allocate, reallocate storage
187 * SYNOPSIS: Type *xnew (int n, Type);
188 * Type *xrnew (OldPointer, int n, Type);
191 # include "chkmalloc.h"
192 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
193 (n) * sizeof (Type)))
194 # define xrnew(op,n,Type) ((Type *) trace_realloc (__FILE__, __LINE__, \
195 (op), (n) * sizeof (Type)))
197 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
198 # define xrnew(op,n,Type) ((Type *) xrealloc ((op), (n) * sizeof (Type)))
203 typedef void Lang_function ();
208 Lang_function *function;
213 typedef struct node_st
214 { /* sorting structure */
215 char *name; /* function or type name */
217 short int construct; /* Construct type for the OO-Browser */
219 char *file; /* file name */
220 bool is_func; /* use pattern or line no */
221 bool been_warned; /* set if noticed dup */
222 int lno; /* line number tag is on */
223 long cno; /* character number line starts on */
224 char *pat; /* search pattern */
225 struct node_st *left, *right; /* left and right sons */
229 /* If you add to this array, you must add a corresponding entry to the
231 static char *oo_browser_default_classes[] =
232 /* Lack of square brackets around some of these entries are intentional. */
233 {"null", "class", "method", "[constant]", "[enumeration]", "[enum_label]",
234 "extern", "[function]", "[macro]", "objc", "[structure]", "[type]",
235 "[union]", "[variable]"};
237 /* If you add to this enum, you must add a corresponding entry to the
239 enum oo_browser_constructs {C_NULL, C_CLASS, C_METHOD, C_CONSTANT, C_ENUMERATION,
240 C_ENUM_LABEL, C_EXTERN, C_FUNCTION, C_MACRO,
241 C_OBJC, C_STRUCTURE, C_TYPE, C_UNION, C_VARIABLE};
243 enum oo_browser_constructs oo_browser_construct = C_NULL;
247 * A `linebuffer' is a structure which holds a line of text.
248 * `readline_internal' reads a line from a stream into a linebuffer
249 * and works regardless of the length of the line.
250 * SIZE is the size of BUFFER, LEN is the length of the string in
251 * BUFFER after readline reads it.
260 extern char *getenv PP ((const char *envvar));
262 /* Many compilers barf on this:
263 Lang_function Asm_labels;
264 so let's write it this way */
265 void Asm_labels PP ((FILE *inf));
266 void C_entries PP ((int c_ext, FILE *inf));
267 void default_C_entries PP ((FILE *inf));
268 void plain_C_entries PP ((FILE *inf));
269 void Cjava_entries PP ((FILE *inf));
270 void Cplusplus_entries PP ((FILE *inf));
271 void Yacc_entries PP ((FILE *inf));
272 void Cobol_paragraphs PP ((FILE *inf));
273 void Cstar_entries PP ((FILE *inf));
274 void Erlang_functions PP ((FILE *inf));
275 void Fortran_functions PP ((FILE *inf));
276 void Lisp_functions PP ((FILE *inf));
277 void Pascal_functions PP ((FILE *inf));
278 void Perl_functions PP ((FILE *inf));
279 void Postscript_functions PP ((FILE *inf));
280 void Prolog_functions PP ((FILE *inf));
281 void Python_functions PP ((FILE *inf));
282 void Scheme_functions PP ((FILE *inf));
283 void TeX_functions PP ((FILE *inf));
284 void just_read_file PP ((FILE *inf));
286 void print_language_names PP ((void));
287 void print_version PP ((void));
288 void print_help PP ((void));
290 language *get_language_from_name PP ((char *name));
291 language *get_language_from_interpreter PP ((char *interpreter));
292 language *get_language_from_suffix PP ((char *suffix));
293 int total_size_of_entries PP ((node *np));
294 long readline PP ((linebuffer *lbp, FILE *stream));
295 long readline_internal PP ((linebuffer *lbp, FILE *stream));
297 void analyse_regex PP ((char *regex_arg));
298 void add_regex PP ((char *regexp_pattern, language *lang));
299 void free_patterns PP ((void));
300 #endif /* ETAGS_REGEXPS */
301 void error PP ((const char *s1, const char *s2));
302 void suggest_asking_for_help PP ((void));
303 void fatal PP ((char *s1, char *s2));
304 void pfatal PP ((char *s1));
305 void add_node PP ((node *np, node **cur_node_p));
307 void init PP ((void));
308 void initbuffer PP ((linebuffer *lbp));
309 void find_entries PP ((char *file, FILE *inf));
310 void free_tree PP ((node *np));
311 void pfnote PP ((char *name, bool is_func, char *linestart, int linelen, int lno, long cno));
312 void new_pfnote PP ((char *name, int namelen, bool is_func, char *linestart, int linelen, int lno, long cno));
313 void process_file PP ((char *file));
314 void put_entries PP ((node *np));
315 void takeprec PP ((void));
317 char *concat PP ((char *s1, char *s2, char *s3));
318 char *skip_spaces PP ((char *cp));
319 char *skip_non_spaces PP ((char *cp));
320 char *savenstr PP ((char *cp, int len));
321 char *savestr PP ((char *cp));
322 char *etags_strchr PP ((char *sp, int c));
323 char *etags_strrchr PP ((char *sp, int c));
324 char *etags_getcwd PP ((void));
325 char *relative_filename PP ((char *file, char *dir));
326 char *absolute_filename PP ((char *file, char *dir));
327 char *absolute_dirname PP ((char *file, char *dir));
328 bool filename_is_absolute PP ((char *fn));
329 void canonicalize_filename PP ((char *fn));
330 void grow_linebuffer PP ((linebuffer *lbp, int toksize));
331 long *xmalloc PP ((unsigned int size));
332 long *xrealloc PP ((char *ptr, unsigned int size));
335 char searchar = '/'; /* use /.../ searches */
337 char *tagfile; /* output file */
338 char *progname; /* name this program was invoked with */
339 char *cwd; /* current working directory */
340 char *tagfiledir; /* directory of tagfile */
341 FILE *tagf; /* ioptr for tags file */
343 char *curfile; /* current input file name */
344 language *curlang; /* current language */
346 int lineno; /* line number of current line */
347 long charno; /* current character number */
348 long linecharno; /* charno of start of current line */
349 char *dbp; /* pointer to start of current tag */
350 node *head; /* the head of the binary tree of tags */
352 linebuffer lb; /* the current line */
353 linebuffer token_name; /* used by C_entries as a temporary area */
357 linebuffer lb; /* used by C_entries instead of lb */
360 /* boolean "functions" (see init) */
361 bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
364 *white = " \f\t\n\r",
366 *nonam = " \f\t\n\r(=,[;",
367 /* token ending chars */
368 *endtk = " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
369 /* token starting chars */
370 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
371 /* valid in-token chars */
372 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
374 bool append_to_tagfile; /* -a: append to tags */
375 /* The following four default to TRUE for etags, but to FALSE for ctags. */
376 bool typedefs; /* -t: create tags for C typedefs */
377 bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */
378 /* 0 struct/enum/union decls, and C++ */
379 /* member functions. */
380 bool constantypedefs; /* -d: create tags for C #define, enum */
381 /* constants and variables. */
382 /* -D: opposite of -d. Default under ctags. */
383 bool globals; /* create tags for global variables */
384 bool members; /* create tags for C member variables */
385 bool update; /* -u: update tags */
386 bool vgrind_style; /* -v: create vgrind style index output */
387 bool no_warnings; /* -w: suppress warnings */
388 bool cxref_style; /* -x: create cxref style output */
389 bool cplusplus; /* .[hc] means C++, not C */
390 bool noindentypedefs; /* -I: ignore indentation in C */
392 bool oo_browser_format; /* -O: OO-Browser tags format */
396 struct option longopts[] =
398 { "append", no_argument, NULL, 'a' },
399 { "backward-search", no_argument, NULL, 'B' },
400 { "c++", no_argument, NULL, 'C' },
401 { "cxref", no_argument, NULL, 'x' },
402 { "defines", no_argument, NULL, 'd' },
403 { "no-defines", no_argument, NULL, 'D' },
404 { "globals", no_argument, &globals, TRUE },
405 { "no-globals", no_argument, &globals, FALSE },
406 { "help", no_argument, NULL, 'h' },
407 { "help", no_argument, NULL, 'H' },
408 { "ignore-indentation", no_argument, NULL, 'I' },
409 { "include", required_argument, NULL, 'i' },
410 { "language", required_argument, NULL, 'l' },
411 { "members", no_argument, &members, TRUE },
412 { "no-members", no_argument, &members, FALSE },
413 { "no-warn", no_argument, NULL, 'w' },
414 { "output", required_argument, NULL, 'o' },
416 { "oo-browser", no_argument, NULL, 'O' },
419 { "regex", required_argument, NULL, 'r' },
420 { "no-regex", no_argument, NULL, 'R' },
421 #endif /* ETAGS_REGEXPS */
422 { "typedefs", no_argument, NULL, 't' },
423 { "typedefs-and-c++", no_argument, NULL, 'T' },
424 { "update", no_argument, NULL, 'u' },
425 { "version", no_argument, NULL, 'V' },
426 { "vgrind", no_argument, NULL, 'v' },
429 #endif /* LONG_OPTIONS */
432 /* Structure defining a regular expression. Elements are
433 the compiled pattern, and the name string. */
434 typedef struct pattern
436 struct pattern *p_next;
439 struct re_pattern_buffer *pattern;
440 struct re_registers regs;
445 /* Array of all regexps. */
446 pattern *p_head = NULL;
447 #endif /* ETAGS_REGEXPS */
453 /* Non-NULL if language fixed. */
454 language *forced_lang = NULL;
457 char *Asm_suffixes [] = { "a", /* Unix assembler */
458 "asm", /* Microcontroller assembly */
459 "def", /* BSO/Tasking definition includes */
460 "inc", /* Microcontroller include files */
461 "ins", /* Microcontroller include files */
462 "s", "sa", /* Unix assembler */
463 "src", /* BSO/Tasking C compiler output */
467 /* Note that .c and .h can be considered C++, if the --c++ flag was
468 given. That is why default_C_entries is called here. */
469 char *default_C_suffixes [] =
472 char *Cplusplus_suffixes [] =
473 { "C", "H", "c++", "cc", "cpp", "cxx", "h++", "hh", "hpp", "hxx",
474 "M", /* Objective C++ */
475 "pdb", /* Postscript with C syntax */
478 char *Cjava_suffixes [] =
481 char *Cobol_suffixes [] =
482 { "COB", "cob", NULL };
484 char *Cstar_suffixes [] =
485 { "cs", "hs", NULL };
487 char *Erlang_suffixes [] =
488 { "erl", "hrl", NULL };
490 char *Fortran_suffixes [] =
491 { "F", "f", "f90", "for", NULL };
493 char *Lisp_suffixes [] =
494 { "cl", "clisp", "el", "l", "lisp", "lsp", "ml", NULL };
496 char *Pascal_suffixes [] =
497 { "p", "pas", NULL };
499 char *Perl_suffixes [] =
500 { "pl", "pm", NULL };
501 char *Perl_interpreters [] =
502 { "perl", "@PERL@", NULL };
504 char *plain_C_suffixes [] =
505 { "pc", /* Pro*C file */
506 "m", /* Objective C file */
507 "lm", /* Objective lex file */
510 char *Postscript_suffixes [] =
513 char *Prolog_suffixes [] =
516 char *Python_suffixes [] =
519 /* Can't do the `SCM' or `scm' prefix with a version number. */
520 char *Scheme_suffixes [] =
521 { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "ss", "t", NULL };
523 char *TeX_suffixes [] =
524 { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL };
526 char *Yacc_suffixes [] =
527 { "y", "ym", NULL }; /* .ym is Objective yacc file */
530 * Table of languages.
532 * It is ok for a given function to be listed under more than one
533 * name. I just didn't.
536 language lang_names [] =
538 { "asm", Asm_labels, Asm_suffixes, NULL },
539 { "c", default_C_entries, default_C_suffixes, NULL },
540 { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL },
541 { "c*", Cstar_entries, Cstar_suffixes, NULL },
542 { "cobol", Cobol_paragraphs, Cobol_suffixes, NULL },
543 { "erlang", Erlang_functions, Erlang_suffixes, NULL },
544 { "fortran", Fortran_functions, Fortran_suffixes, NULL },
545 { "java", Cjava_entries, Cjava_suffixes, NULL },
546 { "lisp", Lisp_functions, Lisp_suffixes, NULL },
547 { "pascal", Pascal_functions, Pascal_suffixes, NULL },
548 { "perl", Perl_functions, Perl_suffixes, Perl_interpreters },
549 { "postscript", Postscript_functions, Postscript_suffixes, NULL },
550 { "proc", plain_C_entries, plain_C_suffixes, NULL },
551 { "prolog", Prolog_functions, Prolog_suffixes, NULL },
552 { "python", Python_functions, Python_suffixes, NULL },
553 { "scheme", Scheme_functions, Scheme_suffixes, NULL },
554 { "tex", TeX_functions, TeX_suffixes, NULL },
555 { "yacc", Yacc_entries, Yacc_suffixes, NULL },
556 { "auto", NULL }, /* default guessing scheme */
557 { "none", just_read_file }, /* regexp matching only */
558 { NULL, NULL } /* end of list */
563 print_language_names ()
568 puts ("\nThese are the currently supported languages, along with the\n\
569 default file name suffixes:");
570 for (lang = lang_names; lang->name != NULL; lang++)
572 printf ("\t%s\t", lang->name);
573 if (lang->suffixes != NULL)
574 for (ext = lang->suffixes; *ext != NULL; ext++)
575 printf (" .%s", *ext);
578 puts ("Where `auto' means use default language for files based on file\n\
579 name suffix, and `none' means only do regexp processing on files.\n\
580 If no language is specified and no matching suffix is found,\n\
581 the first line of the file is read for a sharp-bang (#!) sequence\n\
582 followed by the name of an interpreter. If no such sequence is found,\n\
583 Fortran is tried first; if no tags are found, C is tried next.");
587 # define VERSION "20"
592 printf ("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION);
593 puts ("Copyright (C) 1996 Free Software Foundation, Inc. and Ken Arnold");
594 puts ("This program is distributed under the same terms as Emacs");
602 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
604 These are the options accepted by %s.\n", progname, progname);
606 puts ("You may use unambiguous abbreviations for the long option names.");
608 puts ("Long option names do not work with this executable, as it is not\n\
609 linked with GNU getopt.");
610 #endif /* LONG_OPTIONS */
611 puts ("A - as file name means read names from stdin (one per line).");
613 printf (" Absolute names are stored in the output file as they are.\n\
614 Relative ones are stored relative to the output file's directory.");
617 puts ("-a, --append\n\
618 Append tag entries to existing tags file.");
621 puts ("-B, --backward-search\n\
622 Write the search commands for the tag entries using '?', the\n\
623 backward-search command instead of '/', the forward-search command.");
626 Treat files whose name suffix defaults to C language as C++ files.");
629 puts ("-d, --defines\n\
630 Create tag entries for C #define constants and enum constants, too.");
632 puts ("-D, --no-defines\n\
633 Don't create tag entries for C #define constants and enum constants.\n\
634 This makes the tags file smaller.");
638 puts ("-i FILE, --include=FILE\n\
639 Include a note in tag file indicating that, when searching for\n\
640 a tag, one should also consult the tags file FILE after\n\
641 checking the current file.");
642 puts ("-l LANG, --language=LANG\n\
643 Force the following files to be considered as written in the\n\
644 named language up to the next --language=LANG option.");
649 Create tag entries for global variables in some languages.");
651 puts ("--no-globals\n\
652 Do not create tag entries for global variables in some\n\
653 languages. This makes the tags file smaller.");
655 Create tag entries for member variables in C and derived languages.");
658 puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
659 Make a tag for each line matching pattern REGEXP in the\n\
660 following files. regexfile is a file containing one REGEXP\n\
661 per line. REGEXP is anchored (as if preceded by ^).\n\
662 The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
663 named tags can be created with:\n\
664 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
665 puts ("-R, --no-regex\n\
666 Don't create tags from regexps for the following files.");
667 #endif /* ETAGS_REGEXPS */
668 puts ("-o FILE, --output=FILE\n\
669 Write the tags to FILE.");
671 puts ("-O, --oo-browser\n\
672 Generate a specialized tags format used only by the Altrasoft OO-Browser.");
674 puts ("-I, --ignore-indentation\n\
675 Don't rely on indentation quite as much as normal. Currently,\n\
676 this means not to assume that a closing brace in the first\n\
677 column is the final brace of a function or structure\n\
678 definition in C and C++.");
682 puts ("-t, --typedefs\n\
683 Generate tag entries for C typedefs.");
684 puts ("-T, --typedefs-and-c++\n\
685 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
686 and C++ member functions.");
687 puts ("-u, --update\n\
688 Update the tag entries for the given files, leaving tag\n\
689 entries for other files in place. Currently, this is\n\
690 implemented by deleting the existing entries for the given\n\
691 files and then rewriting the new entries at the end of the\n\
692 tags file. It is often faster to simply rebuild the entire\n\
693 tag file than to use this.");
694 puts ("-v, --vgrind\n\
695 Generates an index of items intended for human consumption,\n\
696 similar to the output of vgrind. The index is sorted, and\n\
697 gives the page number of each item.");
698 puts ("-w, --no-warn\n\
699 Suppress warning messages about entries defined in multiple\n\
701 puts ("-x, --cxref\n\
702 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
703 The output uses line numbers instead of page numbers, but\n\
704 beyond that the differences are cosmetic; try both to see\n\
708 puts ("-V, --version\n\
709 Print the version of the program.\n\
711 Print this help message.");
713 print_language_names ();
716 puts ("Report bugs to bug-gnu-emacs@prep.ai.mit.edu");
729 /* This structure helps us allow mixing of --lang and file names. */
732 enum argument_type arg_type;
737 #ifdef VMS /* VMS specific functions */
741 /* This is a BUG! ANY arbitrary limit is a BUG!
742 Won't someone please fix this? */
743 #define MAX_FILE_SPEC_LEN 255
746 char body[MAX_FILE_SPEC_LEN + 1];
750 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
751 returning in each successive call the next file name matching the input
752 spec. The function expects that each in_spec passed
753 to it will be processed to completion; in particular, up to and
754 including the call following that in which the last matching name
755 is returned, the function ignores the value of in_spec, and will
756 only start processing a new spec with the following call.
757 If an error occurs, on return out_spec contains the value
758 of in_spec when the error occurred.
760 With each successive file name returned in out_spec, the
761 function's return value is one. When there are no more matching
762 names the function returns zero. If on the first call no file
763 matches in_spec, or there is any other error, -1 is returned.
768 #define OUTSIZE MAX_FILE_SPEC_LEN
774 static long context = 0;
775 static struct dsc$descriptor_s o;
776 static struct dsc$descriptor_s i;
777 static bool pass1 = TRUE;
784 o.dsc$a_pointer = (char *) out;
785 o.dsc$w_length = (short)OUTSIZE;
786 i.dsc$a_pointer = in;
787 i.dsc$w_length = (short)strlen(in);
788 i.dsc$b_dtype = DSC$K_DTYPE_T;
789 i.dsc$b_class = DSC$K_CLASS_S;
790 o.dsc$b_dtype = DSC$K_DTYPE_VT;
791 o.dsc$b_class = DSC$K_CLASS_VS;
793 if ((status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL)
795 out->body[out->curlen] = EOS;
798 else if (status == RMS$_NMF)
802 strcpy(out->body, in);
805 lib$find_file_end(&context);
811 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
812 name of each file specified by the provided arg expanding wildcards.
815 gfnames (arg, p_error)
819 static vspec filename = {MAX_FILE_SPEC_LEN, "\0"};
821 switch (fn_exp (&filename, arg))
825 return filename.body;
831 return filename.body;
835 #ifndef OLD /* Newer versions of VMS do provide `system'. */
839 error ("%s", "system() function not implemented under VMS");
843 #define VERSION_DELIM ';'
844 char *massage_name (s)
850 if (*s == VERSION_DELIM)
868 unsigned int nincluded_files;
869 char **included_files;
872 int current_arg, file_count;
873 linebuffer filename_lb;
879 _fmode = O_BINARY; /* all of files are treated as binary files */
884 included_files = xnew (argc, char *);
888 /* Allocate enough no matter what happens. Overkill, but each one
890 argbuffer = xnew (argc, argument);
893 /* Set syntax for regular expression routines. */
894 re_set_syntax (RE_SYNTAX_EMACS | RE_INTERVALS);
895 #endif /* ETAGS_REGEXPS */
898 * If etags, always find typedefs and structure tags. Why not?
899 * Also default is to find macro constants, enum constants and
904 typedefs = typedefs_and_cplusplus = constantypedefs = TRUE;
916 optstring = "-aCdDf:Il:o:r:RStTi:BuvxwVhH";
918 optstring = "-aCdDf:Il:o:r:RStTi:BOuvxwVhH";
922 optstring = "-aCdDf:Il:o:StTi:BuvxwVhH";
924 optstring = "-aCdDf:Il:o:StTi:BOuvxwVhH";
926 #endif /* ETAGS_REGEXPS */
929 optstring = optstring + 1;
930 #endif /* LONG_OPTIONS */
932 opt = getopt_long (argc, argv, optstring, longopts, 0);
939 /* If getopt returns 0, then it has already processed a
940 long-named option. We should do nothing. */
944 /* This means that a file name has been seen. Record it. */
945 argbuffer[current_arg].arg_type = at_filename;
946 argbuffer[current_arg].what = optarg;
951 /* Common options. */
952 case 'a': append_to_tagfile = TRUE; break;
953 case 'C': cplusplus = TRUE; break;
954 case 'd': constantypedefs = TRUE; break;
955 case 'D': constantypedefs = FALSE; break;
956 case 'f': /* for compatibility with old makefiles */
960 /* convert char to string, to call error with */
962 sprintf (buf, "%c", opt);
963 error ("-%s option may only be given once.", buf);
964 suggest_asking_for_help ();
970 oo_browser_format = TRUE;
974 case 'S': /* for backward compatibility */
975 noindentypedefs = TRUE;
979 language *lang = get_language_from_name (optarg);
982 argbuffer[current_arg].lang = lang;
983 argbuffer[current_arg].arg_type = at_language;
990 argbuffer[current_arg].arg_type = at_regexp;
991 argbuffer[current_arg].what = optarg;
995 argbuffer[current_arg].arg_type = at_regexp;
996 argbuffer[current_arg].what = NULL;
999 #endif /* ETAGS_REGEXPS */
1011 typedefs = typedefs_and_cplusplus = TRUE;
1016 included_files[nincluded_files++] = optarg;
1019 /* Ctags options. */
1020 case 'B': searchar = '?'; break;
1021 case 'u': update = TRUE; break;
1022 case 'v': vgrind_style = TRUE; /*FALLTHRU*/
1023 case 'x': cxref_style = TRUE; break;
1024 case 'w': no_warnings = TRUE; break;
1027 suggest_asking_for_help ();
1031 for (; optind < argc; ++optind)
1033 argbuffer[current_arg].arg_type = at_filename;
1034 argbuffer[current_arg].what = argv[optind];
1039 if (nincluded_files == 0 && file_count == 0)
1041 error ("no input files specified.", 0);
1042 suggest_asking_for_help ();
1045 if (tagfile == NULL)
1046 tagfile = CTAGS ? "tags" : "TAGS";
1047 cwd = etags_getcwd (); /* the current working directory */
1048 if (cwd[strlen (cwd) - 1] != '/')
1051 cwd = concat (oldcwd, "/", "");
1054 if (streq (tagfile, "-"))
1057 tagfiledir = absolute_dirname (tagfile, cwd);
1059 init (); /* set up boolean "functions" */
1062 initbuffer (&token_name);
1063 initbuffer (&lbs[0].lb);
1064 initbuffer (&lbs[1].lb);
1065 initbuffer (&filename_lb);
1069 if (streq (tagfile, "-"))
1073 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1074 doesn't take effect until after `stdout' is already open). */
1075 if (!isatty (fileno (stdout)))
1076 setmode (fileno (stdout), O_BINARY);
1080 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1086 * Loop through files finding functions.
1088 for (i = 0; i < current_arg; ++i)
1090 switch (argbuffer[i].arg_type)
1093 forced_lang = argbuffer[i].lang;
1095 #ifdef ETAGS_REGEXPS
1097 analyse_regex (argbuffer[i].what);
1102 while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL)
1106 error ("can't find file %s\n", this_file);
1111 this_file = massage_name (this_file);
1114 this_file = argbuffer[i].what;
1117 oo_browser_clear_all_globals();
1119 /* Input file named "-" means read file names from stdin
1120 (one per line) and use them. */
1121 if (streq (this_file, "-"))
1122 while (readline_internal (&filename_lb, stdin) > 0)
1125 oo_browser_clear_some_globals();
1127 process_file (filename_lb.buffer);
1132 process_file (this_file);
1140 #ifdef ETAGS_REGEXPS
1142 #endif /* ETAGS_REGEXPS */
1146 while (nincluded_files-- > 0)
1147 fprintf (tagf, "\f\n%s,include\n", *included_files++);
1153 /* If CTAGS, we are here. process_file did not write the tags yet,
1154 because we want them ordered. Let's do it now. */
1164 for (i = 0; i < current_arg; ++i)
1166 if (argbuffer[i].arg_type != at_filename)
1169 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1170 tagfile, argbuffer[i].what, tagfile);
1171 if (system (cmd) != GOOD)
1172 fatal ("failed to execute shell command", (char *)NULL);
1174 append_to_tagfile = TRUE;
1177 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1186 sprintf (cmd, "sort %s -o %s", tagfile, tagfile);
1187 exit (system (cmd));
1194 * Return a language given the name.
1197 get_language_from_name (name)
1203 error ("empty language name", (char *)NULL);
1206 for (lang = lang_names; lang->name != NULL; lang++)
1207 if (streq (name, lang->name))
1209 error ("unknown language \"%s\"", name);
1217 * Return a language given the interpreter name.
1220 get_language_from_interpreter (interpreter)
1226 if (interpreter == NULL)
1228 for (lang = lang_names; lang->name != NULL; lang++)
1229 if (lang->interpreters != NULL)
1230 for (iname = lang->interpreters; *iname != NULL; iname++)
1231 if (streq (*iname, interpreter))
1240 * Return a language given the file suffix.
1243 get_language_from_suffix (suffix)
1251 for (lang = lang_names; lang->name != NULL; lang++)
1252 if (lang->suffixes != NULL)
1253 for (ext = lang->suffixes; *ext != NULL; ext++)
1254 if (streq (*ext, suffix))
1262 * This routine is called on each file argument.
1268 struct stat stat_buf;
1271 canonicalize_filename (file);
1272 if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode))
1274 error ("skipping %s: it is not a regular file.", file);
1277 if (streq (file, tagfile) && !streq (tagfile, "-"))
1279 error ("skipping inclusion of %s in self.", file);
1282 inf = fopen (file, "r");
1289 find_entries (file, inf);
1295 if (filename_is_absolute (file))
1297 /* file is an absolute file name. Canonicalise it. */
1298 filename = absolute_filename (file, cwd);
1302 /* file is a file name relative to cwd. Make it relative
1303 to the directory of the tags file. */
1304 filename = relative_filename (file, tagfiledir);
1307 if (oo_browser_format)
1308 fprintf (tagf, "\f\n%s\n", filename);
1311 fprintf (tagf, "\f\n%s,%d\n", filename, total_size_of_entries (head));
1320 * This routine sets up the boolean pseudo-functions which work
1321 * by setting boolean flags dependent upon the corresponding character.
1322 * Every char which is NOT in that string is not a white char. Therefore,
1323 * all of the array "_wht" is set to FALSE, and then the elements
1324 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1325 * of a char is TRUE if it is the string "white", else FALSE.
1333 for (i = 0; i < CHARS; i++)
1334 iswhite(i) = notinname(i) = begtoken(i) = intoken(i) = endtoken(i) = FALSE;
1335 for (sp = white; *sp != '\0'; sp++) iswhite (*sp) = TRUE;
1336 for (sp = nonam; *sp != '\0'; sp++) notinname (*sp) = TRUE;
1337 for (sp = begtk; *sp != '\0'; sp++) begtoken (*sp) = TRUE;
1338 for (sp = midtk; *sp != '\0'; sp++) intoken (*sp) = TRUE;
1339 for (sp = endtk; *sp != '\0'; sp++) endtoken (*sp) = TRUE;
1340 iswhite('\0') = iswhite('\n');
1341 notinname('\0') = notinname('\n');
1342 begtoken('\0') = begtoken('\n');
1343 intoken('\0') = intoken('\n');
1344 endtoken('\0') = endtoken('\n');
1348 * This routine opens the specified file and calls the function
1349 * which finds the function and type definitions.
1351 node *last_node = NULL;
1354 find_entries (file, inf)
1360 node *old_last_node;
1362 curfile = savestr (file);
1364 /* If user specified a language, use it. */
1366 if (lang != NULL && lang->function != NULL)
1369 lang->function (inf);
1375 cp = etags_strrchr (file, '.');
1379 lang = get_language_from_suffix (cp);
1380 if (lang != NULL && lang->function != NULL)
1383 lang->function (inf);
1390 /* Look for sharp-bang as the first two characters. */
1391 if (readline_internal (&lb, inf) > 0
1393 && lb.buffer[0] == '#'
1394 && lb.buffer[1] == '!')
1398 /* Set lp to point at the first char after the last slash in the
1399 line or, if no slashes, at the first nonblank. Then set cp to
1400 the first successive blank and terminate the string. */
1401 lp = etags_strrchr (lb.buffer+2, '/');
1405 lp = skip_spaces (lb.buffer + 2);
1406 cp = skip_non_spaces (lp);
1409 if (strlen (lp) > 0)
1411 lang = get_language_from_interpreter (lp);
1412 if (lang != NULL && lang->function != NULL)
1415 lang->function (inf);
1425 old_last_node = last_node;
1426 curlang = get_language_from_name ("fortran");
1427 Fortran_functions (inf);
1429 /* No Fortran entries found. Try C. */
1430 if (old_last_node == last_node)
1433 curlang = get_language_from_name (cplusplus ? "c++" : "c");
1434 default_C_entries (inf);
1443 pfnote (name, is_func, linestart, linelen, lno, cno)
1444 char *name; /* tag name, or NULL if unnamed */
1445 bool is_func; /* tag is a function */
1446 char *linestart; /* start of the line where tag is */
1447 int linelen; /* length of the line where tag is */
1448 int lno; /* line number */
1449 long cno; /* character number */
1453 if (CTAGS && name == NULL)
1456 np = xnew (1, node);
1458 /* If ctags mode, change name "main" to M<thisfilename>. */
1459 if (CTAGS && !cxref_style && streq (name, "main"))
1461 register char *fp = etags_strrchr (curfile, '/');
1462 np->name = concat ("M", fp == 0 ? curfile : fp + 1, "");
1463 fp = etags_strrchr (np->name, '.');
1464 if (fp && fp[1] != '\0' && fp[2] == '\0')
1469 np->been_warned = FALSE;
1471 np->is_func = is_func;
1473 /* Our char numbers are 0-base, because of C language tradition?
1474 ctags compatibility? old versions compatibility? I don't know.
1475 Anyway, since emacs's are 1-base we expect etags.el to take care
1476 of the difference. If we wanted to have 1-based numbers, we would
1477 uncomment the +1 below. */
1478 np->cno = cno /* + 1 */ ;
1479 np->left = np->right = NULL;
1480 if (CTAGS && !cxref_style)
1482 if (strlen (linestart) < 50)
1483 np->pat = concat (linestart, "$", "");
1485 np->pat = savenstr (linestart, 50);
1488 np->pat = savenstr (linestart, linelen);
1491 if (oo_browser_format)
1492 np->construct = oo_browser_construct;
1493 oo_browser_construct = C_NULL;
1494 oo_browser_check_and_clear_structtype();
1497 add_node (np, &head);
1500 /* Date: Wed, 22 Jan 1997 02:56:31 -0500 [last amended 18 Sep 1997]
1501 * From: Sam Kendall <kendall@mv.mv.com>
1502 * Subject: Proposal for firming up the TAGS format specification
1503 * To: F.Potorti@cnuce.cnr.it
1505 * pfnote should emit the optimized form [unnamed tag] only if:
1506 * 1. name does not contain any of the characters " \t\r\n(),;";
1507 * 2. linestart contains name as either a rightmost, or rightmost but
1508 * one character, substring;
1509 * 3. the character, if any, immediately before name in linestart must
1510 * be one of the characters " \t(),;";
1511 * 4. the character, if any, immediately after name in linestart must
1512 * also be one of the characters " \t(),;".
1514 * The real implementation uses the notinname() macro, which recognises
1515 * characters slightly different form " \t\r\n(),;". See the variable
1518 #define traditional_tag_style TRUE
1520 new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno)
1521 char *name; /* tag name, or NULL if unnamed */
1522 int namelen; /* tag length */
1523 bool is_func; /* tag is a function */
1524 char *linestart; /* start of the line where tag is */
1525 int linelen; /* length of the line where tag is */
1526 int lno; /* line number */
1527 long cno; /* character number */
1535 for (cp = name; !notinname (*cp); cp++)
1537 if (*cp == '\0') /* rule #1 */
1539 cp = linestart + linelen - namelen;
1540 if (notinname (linestart[linelen-1]))
1541 cp -= 1; /* rule #4 */
1543 if (!oo_browser_format
1544 && cp >= linestart /* rule #2 */
1546 if (cp >= linestart /* rule #2 */
1549 || notinname (cp[-1])) /* rule #3 */
1550 && strneq (name, cp, namelen)) /* rule #2 */
1551 named = FALSE; /* use unnamed tag */
1556 name = savenstr (name, namelen);
1559 pfnote (name, is_func, linestart, linelen, lno, cno);
1564 * recurse on left children, iterate on right children.
1572 register node *node_right = np->right;
1573 free_tree (np->left);
1574 if (np->name != NULL)
1584 * Adds a node to the tree of nodes. In etags mode, we don't keep
1585 * it sorted; we just keep a linear list. In ctags mode, maintain
1586 * an ordered tree, with no attempt at balancing.
1588 * add_node is the only function allowed to add nodes, so it can
1592 add_node (np, cur_node_p)
1593 node *np, **cur_node_p;
1596 register node *cur_node = *cur_node_p;
1598 if (cur_node == NULL)
1608 if (last_node == NULL)
1609 fatal ("internal error in add_node", (char *)NULL);
1610 last_node->right = np;
1616 dif = strcmp (np->name, cur_node->name);
1619 * If this tag name matches an existing one, then
1620 * do not add the node, but maybe print a warning.
1624 if (streq (np->file, cur_node->file))
1628 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1629 np->file, lineno, np->name);
1630 fprintf (stderr, "Second entry ignored\n");
1633 else if (!cur_node->been_warned && !no_warnings)
1637 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1638 np->file, cur_node->file, np->name);
1639 cur_node->been_warned = TRUE;
1644 /* Actually add the node */
1645 add_node (np, dif < 0 ? &cur_node->left : &cur_node->right);
1650 /* Default class name for the current OO-Browser tag. */
1651 static char *oo_browser_class;
1652 /* Prefix character to use in OO-Browser listings for the current tag. */
1653 static char oo_browser_prefix;
1665 /* Output subentries that precede this one */
1666 put_entries (np->left);
1668 /* Output this entry */
1673 if (oo_browser_format)
1675 /* Omit C++ `class' and `method' entries as well as Objective-C
1676 entries from this OO-Browser tags file since the browser handles
1677 them independently of this file. Omit `extern' variable declarations
1678 as they are unused by the OO-Browser. */
1679 if (np->construct != C_CLASS
1680 && np->construct != C_METHOD
1681 && np->construct != C_EXTERN
1682 && np->construct != C_OBJC)
1684 oo_browser_class = oo_browser_default_classes[np->construct];
1685 switch (np->construct)
1694 oo_browser_prefix = '=';
1698 oo_browser_prefix = '-';
1701 if (np->name != NULL)
1702 fprintf (tagf, "%s@%c %s@%s\n",
1703 oo_browser_class, oo_browser_prefix,
1706 fprintf (tagf, "%s@%c ???@%s\n",
1707 oo_browser_class, oo_browser_prefix, np->pat);
1713 if (np->name != NULL)
1714 fprintf (tagf, "%s\177%s\001%d,%ld\n",
1715 np->pat, np->name, np->lno, np->cno);
1717 fprintf (tagf, "%s\177%d,%ld\n",
1718 np->pat, np->lno, np->cno);
1725 if (np->name == NULL)
1726 error ("internal error: NULL name in ctags mode.", (char *)NULL);
1731 fprintf (stdout, "%s %s %d\n",
1732 np->name, np->file, (np->lno + 63) / 64);
1734 fprintf (stdout, "%-16s %3d %-16s %s\n",
1735 np->name, np->lno, np->file, np->pat);
1739 fprintf (tagf, "%s\t%s\t", np->name, np->file);
1743 putc (searchar, tagf);
1746 for (sp = np->pat; *sp; sp++)
1748 if (*sp == '\\' || *sp == searchar)
1752 putc (searchar, tagf);
1755 { /* a typedef; text pattern inadequate */
1756 fprintf (tagf, "%d", np->lno);
1762 /* Output subentries that follow this one */
1763 put_entries (np->right);
1766 /* Length of a number's decimal representation. */
1767 int number_len PP ((long num));
1773 while ((num /= 10) > 0)
1779 * Return total number of characters that put_entries will output for
1780 * the nodes in the subtree of the specified node. Works only if
1781 * we are not ctags, but called only in that case. This count
1782 * is irrelevant with the new tags.el, but is still supplied for
1783 * backward compatibility.
1786 total_size_of_entries (np)
1794 for (total = 0; np != NULL; np = np->right)
1796 /* Count left subentries. */
1797 total += total_size_of_entries (np->left);
1799 /* Count this entry */
1800 total += strlen (np->pat) + 1;
1801 total += number_len ((long) np->lno) + 1 + number_len (np->cno) + 1;
1802 if (np->name != NULL)
1803 total += 1 + strlen (np->name); /* \001name */
1810 * The C symbol tables.
1815 st_C_objprot, st_C_objimpl, st_C_objend,
1819 st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec,
1822 , st_C_union, st_C_class, st_C_extern, st_C_inline
1826 /* Feed stuff between (but not including) %[ and %] lines to:
1827 gperf -c -k 1,3 -o -p -r -t
1829 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1831 @interface, 0, st_C_objprot
1832 @protocol, 0, st_C_objprot
1833 @implementation,0, st_C_objimpl
1834 @end, 0, st_C_objend
1835 import, C_JAVA, st_C_ignore
1836 package, C_JAVA, st_C_ignore
1837 friend, C_PLPL, st_C_ignore
1838 extends, C_JAVA, st_C_javastruct
1839 implements, C_JAVA, st_C_javastruct
1840 interface, C_JAVA, st_C_struct
1841 class, C_PLPL, st_C_class
1842 namespace, C_PLPL, st_C_struct
1843 domain, C_STAR, st_C_struct
1844 union, 0, st_C_union
1845 struct, 0, st_C_struct
1847 typedef, 0, st_C_typedef
1848 define, 0, st_C_define
1849 inline, 0, st_C_inline
1850 bool, C_PLPL, st_C_typespec
1851 long, 0, st_C_typespec
1852 short, 0, st_C_typespec
1853 int, 0, st_C_typespec
1854 char, 0, st_C_typespec
1855 float, 0, st_C_typespec
1856 double, 0, st_C_typespec
1857 signed, 0, st_C_typespec
1858 unsigned, 0, st_C_typespec
1859 auto, 0, st_C_typespec
1860 void, 0, st_C_typespec
1861 extern, 0, st_C_extern
1862 static, 0, st_C_typespec
1863 const, 0, st_C_const
1864 volatile, 0, st_C_typespec
1865 explicit, C_PLPL, st_C_typespec
1866 mutable, C_PLPL, st_C_typespec
1867 typename, C_PLPL, st_C_typespec
1868 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
1869 DEFUN, 0, st_C_gnumacro
1870 SYSCALL, 0, st_C_gnumacro
1871 ENTRY, 0, st_C_gnumacro
1872 PSEUDO, 0, st_C_gnumacro
1873 # These are defined inside C functions, so currently they are not met.
1874 # EXFUN used in glibc, DEFVAR_* in emacs.
1875 #EXFUN, 0, st_C_gnumacro
1876 #DEFVAR_, 0, st_C_gnumacro
1878 and replace lines between %< and %> with its output. */
1880 /* C code produced by gperf version 2.5 (GNU C++ version) */
1881 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
1882 struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
1884 #define TOTAL_KEYWORDS 41
1885 #define MIN_WORD_LENGTH 3
1886 #define MAX_WORD_LENGTH 15
1887 #define MIN_HASH_VALUE 13
1888 #define MAX_HASH_VALUE 129
1889 /* maximum key range = 117, duplicates = 0 */
1894 register int unsigned len;
1896 static unsigned char asso_values[] =
1898 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1899 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1900 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1901 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1902 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1903 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1904 130, 130, 130, 130, 13, 130, 130, 130, 33, 32,
1905 47, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1906 5, 130, 130, 20, 32, 130, 130, 130, 130, 130,
1907 130, 130, 130, 130, 130, 130, 130, 47, 55, 8,
1908 15, 33, 61, 38, 130, 60, 130, 130, 2, 9,
1909 10, 62, 59, 130, 28, 27, 50, 19, 3, 130,
1910 130, 130, 130, 130, 130, 130, 130, 130,
1912 return len + asso_values[str[2]] + asso_values[str[0]];
1915 struct C_stab_entry *
1916 in_word_set (str, len)
1918 register unsigned int len;
1920 static struct C_stab_entry wordlist[] =
1922 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1923 {"",}, {"",}, {"",}, {"",},
1924 {"volatile", 0, st_C_typespec},
1926 {"long", 0, st_C_typespec},
1927 {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1928 {"const", 0, st_C_const},
1929 {"",}, {"",}, {"",},
1930 {"@end", 0, st_C_objend},
1931 {"namespace", C_PLPL, st_C_struct},
1933 {"domain", C_STAR, st_C_struct},
1935 {"@interface", 0, st_C_objprot},
1936 {"",}, {"",}, {"",},
1937 {"@implementation", 0, st_C_objimpl},
1939 {"double", 0, st_C_typespec},
1941 {"PSEUDO", 0, st_C_gnumacro},
1942 {"",}, {"",}, {"",},
1943 {"SYSCALL", 0, st_C_gnumacro},
1945 {"@protocol", 0, st_C_objprot},
1946 {"",}, {"",}, {"",},
1947 {"unsigned", 0, st_C_typespec},
1949 {"enum", 0, st_C_enum},
1951 {"char", 0, st_C_typespec},
1952 {"class", C_PLPL, st_C_class},
1953 {"struct", 0, st_C_struct},
1954 {"",}, {"",}, {"",}, {"",},
1955 {"mutable", C_PLPL, st_C_typespec},
1956 {"void", 0, st_C_typespec},
1957 {"inline", 0, st_C_inline},
1958 {"ENTRY", 0, st_C_gnumacro},
1960 {"signed", 0, st_C_typespec},
1962 {"package", C_JAVA, st_C_ignore},
1963 {"",}, {"",}, {"",}, {"",}, {"",},
1964 {"static", 0, st_C_typespec},
1966 {"define", 0, st_C_define},
1968 {"union", 0, st_C_union},
1969 {"DEFUN", 0, st_C_gnumacro},
1970 {"",}, {"",}, {"",},
1971 {"extern", 0, st_C_extern},
1972 {"extends", C_JAVA, st_C_javastruct},
1973 {"",}, {"",}, {"",},
1974 {"short", 0, st_C_typespec},
1975 {"",}, {"",}, {"",}, {"",}, {"",},
1976 {"explicit", C_PLPL, st_C_typespec},
1977 {"auto", 0, st_C_typespec},
1978 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1980 {"int", 0, st_C_typespec},
1982 {"typedef", 0, st_C_typedef},
1983 {"typename", C_PLPL, st_C_typespec},
1985 {"interface", C_JAVA, st_C_struct},
1987 {"bool", C_PLPL, st_C_typespec},
1988 {"",}, {"",}, {"",},
1989 {"import", C_JAVA, st_C_ignore},
1991 {"friend", C_PLPL, st_C_ignore},
1992 {"float", 0, st_C_typespec},
1993 {"implements", C_JAVA, st_C_javastruct},
1996 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
1998 register int key = hash (str, len);
2000 if (key <= MAX_HASH_VALUE && key >= 0)
2002 register char *s = wordlist[key].name;
2004 if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
2005 return &wordlist[key];
2012 enum sym_type C_symtype PP ((char *str, int len, int c_ext));
2014 C_symtype (str, len, c_ext)
2019 register struct C_stab_entry *se = in_word_set (str, len);
2021 if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
2027 * C functions and variables are recognized using a simple
2028 * finite automaton. fvdef is its state variable.
2032 fvnone, /* nothing seen */
2033 fvnameseen, /* function or variable name seen */
2034 fstartlist, /* func: just after open parenthesis */
2035 finlist, /* func: in parameter list */
2036 flistseen, /* func: after parameter list */
2037 fignore, /* func: before open brace */
2038 vignore /* var-like: ignore until ';' */
2043 * typedefs are recognized using a simple finite automaton.
2044 * typdef is its state variable.
2048 tnone, /* nothing seen */
2049 ttypedseen, /* typedef keyword seen */
2050 tinbody, /* inside typedef body */
2051 tend, /* just before typedef tag */
2052 tignore /* junk after typedef tag */
2057 * struct-like structures (enum, struct and union) are recognized
2058 * using another simple finite automaton. `structdef' is its state
2063 snone, /* nothing seen yet */
2064 skeyseen, /* struct-like keyword seen */
2065 stagseen, /* struct-like tag seen */
2066 scolonseen, /* colon seen after struct-like tag */
2067 sinbody /* in struct body: recognize member func defs*/
2071 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
2072 * struct tag, and structtype is the type of the preceding struct-like
2075 char *structtag = "<uninited>";
2076 enum sym_type structtype;
2080 oo_browser_check_and_clear_structtype()
2082 /* Allow for multiple enum_label tags. */
2083 if (structtype != st_C_enum)
2084 structtype = st_none;
2089 * When objdef is different from onone, objtag is the name of the class.
2091 char *objtag = "<uninited>";
2094 * Yet another little state machine to deal with preprocessor lines.
2098 dnone, /* nothing seen */
2099 dsharpseen, /* '#' seen as first char on line */
2100 ddefineseen, /* '#' and 'define' seen */
2101 dignorerest /* ignore rest of line */
2105 * State machine for Objective C protocols and implementations.
2106 * Tom R.Hageman <tom@basil.icce.rug.nl>
2110 onone, /* nothing seen */
2111 oprotocol, /* @interface or @protocol seen */
2112 oimplementation, /* @implementations seen */
2113 otagseen, /* class name seen */
2114 oparenseen, /* parenthesis before category seen */
2115 ocatseen, /* category name seen */
2116 oinbody, /* in @implementation body */
2117 omethodsign, /* in @implementation body, after +/- */
2118 omethodtag, /* after method name */
2119 omethodcolon, /* after method colon */
2120 omethodparm, /* after method parameter */
2121 oignore /* wait for @end */
2125 * Use this structure to keep info about the token read, and how it
2126 * should be tagged. Used by the make_C_tag function to build a tag.
2139 token tok; /* latest token read */
2142 * Set this to TRUE, and the next token considered is called a function.
2143 * Used only for GNU emacs's function-defining macros.
2145 bool next_token_is_func;
2148 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
2153 * methodlen is the length of the method name stored in token_name.
2159 oo_browser_clear_all_globals()
2161 /* Initialize globals so there is no carry over between files. */
2162 oo_browser_construct = C_NULL;
2163 fvdef = fvnone; typdef = tnone; structdef = snone;
2164 definedef = dnone; objdef = onone;
2165 structtype = st_none;
2166 next_token_is_func = yacc_rules = FALSE;
2170 oo_browser_clear_some_globals()
2172 oo_browser_construct = C_NULL;
2173 structtype = st_none;
2179 * checks to see if the current token is at the start of a
2180 * function or variable, or corresponds to a typedef, or
2181 * is a struct/union/enum tag, or #define, or an enum constant.
2183 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2184 * with args. C_EXT is which language we are looking at.
2186 * In the future we will need some way to adjust where the end of
2187 * the token is; for instance, implementing the C++ keyword
2188 * `operator' properly will adjust the end of the token to be after
2189 * whatever follows `operator'.
2197 * next_token_is_func IN OUT
2199 bool consider_token PP ((char *str, int len, int c, int c_ext,
2200 int cblev, int parlev, bool *is_func_or_var));
2202 consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var)
2203 register char *str; /* IN: token pointer */
2204 register int len; /* IN: token length */
2205 register int c; /* IN: first char after the token */
2206 int c_ext; /* IN: C extensions mask */
2207 int cblev; /* IN: curly brace level */
2208 int parlev; /* IN: parenthesis level */
2209 bool *is_func_or_var; /* OUT: function or variable found */
2211 enum sym_type toktype = C_symtype (str, len, c_ext);
2217 set_construct(C_STRUCTURE);
2220 set_construct(C_UNION);
2223 set_construct(C_CLASS);
2226 set_construct(C_ENUMERATION);
2229 set_construct(C_TYPE);
2232 set_construct(C_EXTERN);
2235 set_construct(C_FUNCTION);
2241 * Advance the definedef state machine.
2246 /* We're not on a preprocessor line. */
2249 if (toktype == st_C_define)
2251 definedef = ddefineseen;
2255 definedef = dignorerest;
2260 * Make a tag for any macro, unless it is a constant
2261 * and constantypedefs is FALSE.
2263 definedef = dignorerest;
2265 *is_func_or_var = (c == '(');
2268 char *p = str + len * sizeof(char);
2271 /* This must be a macro since there is no
2272 whitespace between the opening parenthesis
2273 and the definition name. */
2274 *is_func_or_var = TRUE;
2277 *is_func_or_var = FALSE;
2279 /* Handle possible whitespace between macro tag and opening
2280 parenthesis and ensure this is an actual macro.
2281 -- Bob Weiner, Altrasoft, 11/19/1997 */
2282 while (*p && isspace(*p)) p++;
2285 /* Skip over nested parentheses. */
2290 while (*++p && depth > 0 && *p != '\n')
2301 /* If this is a macro, we have just passed
2302 the arguments and there will be more on
2303 the line before the NULL character that marks
2304 the end of the line token. */
2305 while (*p == ' ' || *p == '\t') p++;
2306 if (*p) *is_func_or_var = TRUE;
2311 set_construct((*is_func_or_var) ? C_MACRO : C_CONSTANT);
2313 if (!*is_func_or_var && !constantypedefs)
2320 error ("internal error: definedef value.", (char *)NULL);
2329 if (toktype == st_C_typedef)
2332 typdef = ttypedseen;
2341 set_construct(C_CONSTANT);
2358 /* Do not return here, so the structdef stuff has a chance. */
2364 set_construct(C_CONSTANT);
2380 * This structdef business is currently only invoked when cblev==0.
2381 * It should be recursively invoked whatever the curly brace level,
2382 * and a stack of states kept, to allow for definitions of structs
2385 * This structdef business is NOT invoked when we are ctags and the
2386 * file is plain C. This is because a struct tag may have the same
2387 * name as another tag, and this loses with ctags.
2391 case st_C_javastruct:
2392 if (structdef == stagseen)
2393 structdef = scolonseen;
2402 if (typdef == ttypedseen
2403 || (typedefs_and_cplusplus && cblev == 0 && structdef == snone))
2405 structdef = skeyseen;
2406 structtype = toktype;
2411 if (structdef == skeyseen)
2413 /* Save the tag for struct/union/class, for functions and variables
2414 that may be defined inside. */
2416 if (structtype == st_C_struct)
2418 if (structtype == st_C_struct
2419 || structtype == st_C_union
2420 || structtype == st_C_class)
2422 structtag = savenstr (str, len);
2424 structtag = "<enum>";
2425 structdef = stagseen;
2429 /* Avoid entering fvdef stuff if typdef is going on. */
2430 if (typdef != tnone)
2436 /* Detect GNU macros.
2438 DEFUN note for writers of emacs C code:
2439 The DEFUN macro, used in emacs C source code, has a first arg
2440 that is a string (the lisp function name), and a second arg that
2441 is a C function name. Since etags skips strings, the second arg
2442 is tagged. This is unfortunate, as it would be better to tag the
2443 first arg. The simplest way to deal with this problem would be
2444 to name the tag with a name built from the function name, by
2445 removing the initial 'F' character and substituting '-' for '_'.
2446 Anyway, this assumes that the conventions of naming lisp
2447 functions will never change. Currently, this method is not
2448 implemented, so writers of emacs code are recommended to put the
2449 first two args of a DEFUN on the same line. */
2450 if (definedef == dnone && toktype == st_C_gnumacro)
2452 next_token_is_func = TRUE;
2455 if (next_token_is_func)
2457 next_token_is_func = FALSE;
2459 *is_func_or_var = TRUE;
2463 /* Detect Objective C constructs. */
2471 set_construct(C_OBJC);
2477 set_construct(C_OBJC);
2479 objdef = oimplementation;
2483 case oimplementation:
2484 /* Save the class tag for functions or variables defined inside. */
2485 objtag = savenstr (str, len);
2489 /* Save the class tag for categories. */
2490 objtag = savenstr (str, len);
2492 *is_func_or_var = TRUE;
2496 *is_func_or_var = TRUE;
2503 objdef = omethodtag;
2505 grow_linebuffer (&token_name, methodlen + 1);
2506 strncpy (token_name.buffer, str, len);
2507 token_name.buffer[methodlen] = '\0';
2508 token_name.len = methodlen;
2514 objdef = omethodparm;
2519 objdef = omethodtag;
2521 grow_linebuffer (&token_name, methodlen + 1);
2522 strncat (token_name.buffer, str, len);
2523 token_name.len = methodlen;
2528 if (toktype == st_C_objend)
2530 /* Memory leakage here: the string pointed by objtag is
2531 never released, because many tests would be needed to
2532 avoid breaking on incorrect input code. The amount of
2533 memory leaked here is the sum of the lengths of the
2541 /* A function, variable or enum constant? */
2545 set_construct(C_CONSTANT);
2551 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2552 fvdef = fvnone; /* should be useless */
2558 if (constantypedefs && structdef == sinbody && structtype == st_C_enum)
2561 oo_browser_construct = C_ENUM_LABEL;
2567 if (fvdef == fvnone)
2569 fvdef = fvnameseen; /* function or variable */
2570 *is_func_or_var = TRUE;
2580 * This routine finds functions, variables, typedefs,
2581 * #define's, enum constants and struct/union/enum definitions in
2582 * #C syntax and adds them to the list.
2584 #define current_lb_is_new (newndx == curndx)
2585 #define switch_line_buffers() (curndx = 1 - curndx)
2587 #define curlb (lbs[curndx].lb)
2588 #define othlb (lbs[1-curndx].lb)
2589 #define newlb (lbs[newndx].lb)
2590 #define curlinepos (lbs[curndx].linepos)
2591 #define othlinepos (lbs[1-curndx].linepos)
2592 #define newlinepos (lbs[newndx].linepos)
2594 #define CNL_SAVE_DEFINEDEF() \
2596 curlinepos = charno; \
2598 linecharno = charno; \
2599 charno += readline (&curlb, inf); \
2600 lp = curlb.buffer; \
2607 CNL_SAVE_DEFINEDEF(); \
2608 if (savetok.valid) \
2611 savetok.valid = FALSE; \
2613 definedef = dnone; \
2617 void make_C_tag PP ((bool isfun));
2622 /* This function should never be called when tok.valid is FALSE, but
2623 we must protect against invalid input or internal errors. */
2626 if (traditional_tag_style)
2628 /* This was the original code. Now we call new_pfnote instead,
2629 which uses the new method for naming tags (see new_pfnote). */
2632 if (CTAGS || tok.named)
2633 name = savestr (token_name.buffer);
2634 pfnote (name, isfun,
2635 tok.buffer, tok.linelen, tok.lineno, tok.linepos);
2638 new_pfnote (token_name.buffer, token_name.len, isfun,
2639 tok.buffer, tok.linelen, tok.lineno, tok.linepos);
2648 C_entries (c_ext, inf)
2649 int c_ext; /* extension of C */
2650 FILE *inf; /* input file */
2652 register char c; /* latest char read; '\0' for end of line */
2653 register char *lp; /* pointer one beyond the character `c' */
2654 int curndx, newndx; /* indices for current and new lb */
2655 register int tokoff; /* offset in line of start of current token */
2656 register int toklen; /* length of current token */
2657 char *qualifier; /* string used to qualify names */
2658 int qlen; /* length of qualifier */
2659 int cblev; /* current curly brace level */
2660 int parlev; /* current parenthesis level */
2661 bool incomm, inquote, inchar, quotednl, midtoken;
2663 token savetok; /* token saved during preprocessor handling */
2666 tokoff = toklen = 0; /* keep compiler quiet */
2667 curndx = newndx = 0;
2673 fvdef = fvnone; typdef = tnone; structdef = snone;
2674 definedef = dnone; objdef = onone;
2675 next_token_is_func = yacc_rules = FALSE;
2676 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2677 tok.valid = savetok.valid = FALSE;
2680 cplpl = (c_ext & C_PLPL) == C_PLPL;
2681 cjava = (c_ext & C_JAVA) == C_JAVA;
2683 { qualifier = "."; qlen = 1; }
2685 { qualifier = "::"; qlen = 2; }
2692 /* If we're at the end of the line, the next character is a
2693 '\0'; don't skip it, because it's the thing that tells us
2694 to read the next line. */
2715 /* Newlines inside comments do not end macro definitions in
2717 CNL_SAVE_DEFINEDEF ();
2730 /* Newlines inside strings do not end macro definitions
2731 in traditional cpp, even though compilers don't
2732 usually accept them. */
2733 CNL_SAVE_DEFINEDEF ();
2743 /* Hmmm, something went wrong. */
2757 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2762 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2772 else if (/* cplpl && */ *lp == '/')
2780 if ((c_ext & YACC) && *lp == '%')
2782 /* entering or exiting rules section in yacc file */
2784 definedef = dnone; fvdef = fvnone;
2785 typdef = tnone; structdef = snone;
2786 next_token_is_func = FALSE;
2787 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2789 yacc_rules = !yacc_rules;
2795 if (definedef == dnone)
2798 bool cpptoken = TRUE;
2800 /* Look back on this line. If all blanks, or nonblanks
2801 followed by an end of comment, this is a preprocessor
2803 for (cp = newlb.buffer; cp < lp-1; cp++)
2806 if (*cp == '*' && *(cp+1) == '/')
2815 definedef = dsharpseen;
2816 } /* if (definedef == dnone) */
2822 /* Consider token only if some complicated conditions are satisfied. */
2823 if ((definedef != dnone
2824 || (cblev == 0 && structdef != scolonseen)
2825 || (cblev == 1 && cplpl && structdef == sinbody)
2826 || (structdef == sinbody && structtype == st_C_enum))
2827 && typdef != tignore
2828 && definedef != dignorerest
2829 && fvdef != finlist)
2835 if (c == ':' && cplpl && *lp == ':' && begtoken(*(lp + 1)))
2838 * This handles :: in the middle, but not at the
2839 * beginning of an identifier.
2844 set_construct(C_METHOD);
2849 bool funorvar = FALSE;
2852 || consider_token (newlb.buffer + tokoff, toklen, c,
2853 c_ext, cblev, parlev, &funorvar))
2856 if (structdef == sinbody
2857 && definedef == dnone
2859 /* function or var defined in C++ class body */
2861 int len = strlen (structtag) + qlen + toklen;
2862 grow_linebuffer (&token_name, len + 1);
2863 strcpy (token_name.buffer, structtag);
2864 strcat (token_name.buffer, qualifier);
2865 strncat (token_name.buffer,
2866 newlb.buffer + tokoff, toklen);
2867 token_name.len = len;
2870 oo_browser_construct = C_METHOD;
2873 else if (objdef == ocatseen)
2874 /* Objective C category */
2876 int len = strlen (objtag) + 2 + toklen;
2877 grow_linebuffer (&token_name, len + 1);
2878 strcpy (token_name.buffer, objtag);
2879 strcat (token_name.buffer, "(");
2880 strncat (token_name.buffer,
2881 newlb.buffer + tokoff, toklen);
2882 strcat (token_name.buffer, ")");
2883 token_name.len = len;
2886 oo_browser_construct = C_OBJC;
2889 else if (objdef == omethodtag
2890 || objdef == omethodparm)
2891 /* Objective C method */
2895 oo_browser_construct = C_OBJC;
2900 grow_linebuffer (&token_name, toklen + 1);
2901 strncpy (token_name.buffer,
2902 newlb.buffer + tokoff, toklen);
2903 token_name.buffer[toklen] = '\0';
2904 token_name.len = toklen;
2907 = (structdef == stagseen
2910 /* Also name #define constants,
2911 enumerations and enum_labels.
2912 Conditionalize `funorvar' reference
2913 here or #defines will appear without
2915 -- Bob Weiner, Altrasoft, 4/25/1998 */
2916 || ((oo_browser_format || funorvar)
2917 && definedef == dignorerest)
2918 || (oo_browser_format
2919 && (oo_browser_construct == C_ENUMERATION
2920 || oo_browser_construct == C_ENUM_LABEL))
2923 && definedef == dignorerest)
2927 tok.lineno = lineno;
2928 tok.linelen = tokoff + toklen + 1;
2929 tok.buffer = newlb.buffer;
2930 tok.linepos = newlinepos;
2933 if (definedef == dnone
2934 && (fvdef == fvnameseen
2935 || structdef == stagseen
2937 || objdef != onone))
2939 if (current_lb_is_new)
2940 switch_line_buffers ();
2943 make_C_tag (funorvar);
2947 } /* if (endtoken (c)) */
2948 else if (intoken (c))
2953 } /* if (midtoken) */
2954 else if (begtoken (c))
2966 set_construct(C_MACRO);
2968 make_C_tag (TRUE); /* a function */
2975 if (structdef == stagseen && !cjava)
2981 if (!yacc_rules || lp == newlb.buffer + 1)
2983 tokoff = lp - 1 - newlb.buffer;
2988 } /* if (begtoken) */
2989 } /* if must look at token */
2992 /* Detect end of line, colon, comma, semicolon and various braces
2993 after having handled a token.*/
2997 if (definedef != dnone)
3003 make_C_tag (TRUE); /* an Objective C class */
3007 objdef = omethodcolon;
3009 grow_linebuffer (&token_name, methodlen + 1);
3010 strcat (token_name.buffer, ":");
3011 token_name.len = methodlen;
3014 if (structdef == stagseen)
3015 structdef = scolonseen;
3022 make_C_tag (FALSE); /* a yacc function */
3032 if (definedef != dnone)
3039 set_construct(C_TYPE);
3041 make_C_tag (FALSE); /* a typedef */
3051 if ((globals && cblev == 0) || (members && cblev == 1))
3053 make_C_tag (FALSE); /* a variable */
3055 /* if (constantypedefs && structdef == snone)*/
3061 set_construct(C_ENUMERATION);
3064 set_construct(C_CLASS);
3067 set_construct(C_VARIABLE);
3071 /* Force reset of st_C_enum structtype value. */
3072 structtype = st_none;
3078 /* The following instruction invalidates the token.
3079 Probably the token should be invalidated in all
3080 other cases where some state machine is reset. */
3083 if (structdef == stagseen)
3087 if (definedef != dnone)
3093 make_C_tag (TRUE); /* an Objective C method */
3104 if ((globals && cblev == 0) || (members && cblev == 1))
3105 make_C_tag (FALSE); /* a variable */
3110 if (structdef == stagseen)
3114 if (definedef != dnone)
3116 if (cblev == 0 && typdef == tend)
3119 set_construct(C_TYPE);
3122 make_C_tag (FALSE); /* a typedef */
3133 if ((globals && cblev == 0) || (members && cblev == 1))
3134 make_C_tag (FALSE); /* a variable */
3136 if (constantypedefs && structdef == snone)
3142 set_construct(C_ENUMERATION);
3145 set_construct(C_CLASS);
3148 set_construct(C_VARIABLE);
3152 /* Force reset of st_C_enum structtype value. */
3153 structtype = st_none;
3160 if (structdef == stagseen)
3164 if (definedef != dnone)
3166 if (objdef == otagseen && parlev == 0)
3167 objdef = oparenseen;
3175 if (tok.valid && *lp != '*')
3177 /* This handles constructs like:
3178 typedef void OperatorFun (int fun); */
3181 set_construct(C_TYPE);
3186 } /* switch (typdef) */
3198 if (definedef != dnone)
3200 if (objdef == ocatseen && parlev == 1)
3202 make_C_tag (TRUE); /* an Objective C category */
3214 if (cblev == 0 && typdef == tend)
3217 set_construct(C_TYPE);
3220 make_C_tag (FALSE); /* a typedef */
3223 else if (parlev < 0) /* can happen due to ill-conceived #if's. */
3227 if (definedef != dnone)
3229 if (typdef == ttypedseen)
3233 case skeyseen: /* unnamed struct */
3234 structdef = sinbody;
3235 structtag = "_anonymous_";
3238 case scolonseen: /* named struct */
3239 structdef = sinbody;
3240 make_C_tag (FALSE); /* a struct */
3247 set_construct(C_FUNCTION);
3248 /* Ensure function name is recorded.
3249 -- Bob Weiner, Altrasoft */
3252 make_C_tag (TRUE); /* a function */
3261 make_C_tag (TRUE); /* an Objective C class */
3266 make_C_tag (TRUE); /* an Objective C method */
3270 /* Neutralize `extern "C" {' grot. */
3271 if (cblev == 0 && structdef == snone && typdef == tnone)
3278 if (definedef != dnone)
3280 if (fvdef == fstartlist)
3281 fvdef = fvnone; /* avoid tagging `foo' in `foo (*bar()) ()' */
3284 if (definedef != dnone)
3286 if (!noindentypedefs && lp == newlb.buffer + 1)
3288 cblev = 0; /* reset curly brace level if first column */
3289 parlev = 0; /* also reset paren level, just in case... */
3295 if (typdef == tinbody)
3297 /* Memory leakage here: the string pointed by structtag is
3298 never released, because I fear to miss something and
3299 break things while freeing the area. The amount of
3300 memory leaked here is the sum of the lengths of the
3302 if (structdef == sinbody)
3303 free (structtag); */
3306 structtag = "<error>";
3308 /* Next line added to avoid any state carryover between
3309 functions. -- Bob Weiner, Altrasoft, 11/19/1997 */
3310 fvdef = fvnone; oo_browser_construct = C_NULL;
3315 if (definedef != dnone)
3328 if ((globals && cblev == 0) || (members && cblev == 1))
3330 make_C_tag (FALSE); /* a variable */
3337 set_construct(C_ENUMERATION);
3340 set_construct(C_CLASS);
3343 /* a global variable */
3344 set_construct(C_VARIABLE);
3348 /* ootags categorizes each tag found whereas etags doesn't.
3349 Set the is_method flag if this tag has been marked as
3350 such by an earlier section of code.
3351 -- Steve Baur, Altrasoft, 5/7/1998 */
3352 is_method = (oo_browser_construct == C_METHOD);
3355 /* Force reset of st_C_enum structtype value. */
3356 structtype = st_none;
3362 fvdef = is_method ? fignore : vignore;
3373 if (objdef == oinbody && cblev == 0)
3375 objdef = omethodsign;
3379 case '#': case '~': case '&': case '%': case '/': case '|':
3380 case '^': case '!': case '<': case '>': case '.': case '?': case ']':
3381 if (definedef != dnone)
3387 /* The above characters cannot follow a function tag in C, so
3388 unmark this as a function entry. For C++, these characters
3389 may follow an `operator' function construct, so skip the
3390 unmarking conditional below.
3391 -- Steve Baur, Altrasoft, 5/7/1998 */
3392 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
3399 if (objdef == otagseen)
3401 make_C_tag (TRUE); /* an Objective C class */
3404 /* If a macro spans multiple lines don't reset its state. */
3406 CNL_SAVE_DEFINEDEF ();
3412 } /* while not eof */
3416 * Process either a C++ file or a C file depending on the setting
3420 default_C_entries (inf)
3423 C_entries (cplusplus ? C_PLPL : 0, inf);
3426 /* Always do plain ANSI C. */
3428 plain_C_entries (inf)
3434 /* Always do C++. */
3436 Cplusplus_entries (inf)
3439 C_entries (C_PLPL, inf);
3442 /* Always do Java. */
3447 C_entries (C_JAVA, inf);
3455 C_entries (C_STAR, inf);
3458 /* Always do Yacc. */
3463 C_entries (YACC, inf);
3466 /* A useful macro. */
3467 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3468 for (lineno = charno = 0; /* loop initialization */ \
3469 !feof (file_pointer) /* loop test */ \
3470 && (lineno++, /* instructions at start of loop */ \
3471 linecharno = charno, \
3472 charno += readline (&line_buffer, file_pointer), \
3473 char_pointer = lb.buffer, \
3479 * Read a file, but do no processing. This is used to do regexp
3480 * matching on files that have no language defined.
3483 just_read_file (inf)
3486 register char *dummy;
3488 LOOP_ON_INPUT_LINES (inf, lb, dummy)
3492 /* Fortran parsing */
3494 bool tail PP ((char *cp));
3499 register int len = 0;
3501 while (*cp && lowcase(*cp) == lowcase(dbp[len]))
3503 if (*cp == '\0' && !intoken(dbp[len]))
3514 dbp = skip_spaces (dbp);
3518 dbp = skip_spaces (dbp);
3519 if (strneq (dbp, "(*)", 3))
3524 if (!isdigit (*dbp))
3526 --dbp; /* force failure */
3531 while (isdigit (*dbp));
3534 void getit PP ((FILE *inf));
3541 dbp = skip_spaces (dbp);
3545 linecharno = charno;
3546 charno += readline (&lb, inf);
3551 dbp = skip_spaces (dbp);
3557 for (cp = dbp + 1; *cp && intoken (*cp); cp++)
3559 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
3560 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3565 Fortran_functions (inf)
3568 LOOP_ON_INPUT_LINES (inf, lb, dbp)
3571 dbp++; /* Ratfor escape to fortran */
3572 dbp = skip_spaces (dbp);
3575 switch (lowcase (*dbp))
3578 if (tail ("integer"))
3586 if (tail ("logical"))
3590 if (tail ("complex") || tail ("character"))
3594 if (tail ("double"))
3596 dbp = skip_spaces (dbp);
3599 if (tail ("precision"))
3605 dbp = skip_spaces (dbp);
3608 switch (lowcase (*dbp))
3611 if (tail ("function"))
3615 if (tail ("subroutine"))
3623 if (tail ("program"))
3628 if (tail ("procedure"))
3636 * Bob Weiner, Motorola Inc., 4/3/94
3637 * Unix and microcontroller assembly tag handling
3638 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
3646 LOOP_ON_INPUT_LINES (inf, lb, cp)
3648 /* If first char is alphabetic or one of [_.$], test for colon
3649 following identifier. */
3650 if (isalpha (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3652 /* Read past label. */
3654 while (isalnum (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3656 if (*cp == ':' || isspace (*cp))
3658 /* Found end of label, so copy it and add it to the table. */
3659 pfnote ((CTAGS) ? savenstr(lb.buffer, cp-lb.buffer) : NULL, TRUE,
3660 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3667 * Perl support by Bart Robinson <lomew@cs.utah.edu>
3668 * enhanced by Michael Ernst <mernst@alum.mit.edu>
3669 * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/
3670 * Perl variable names: /^(my|local).../
3673 Perl_functions (inf)
3678 LOOP_ON_INPUT_LINES (inf, lb, cp)
3682 && *cp++ == 'b' && isspace (*cp++))
3684 cp = skip_spaces (cp);
3688 && !isspace (*cp) && *cp != '{' && *cp != '(')
3690 pfnote ((CTAGS) ? savenstr(lb.buffer, cp-lb.buffer) : NULL, TRUE,
3691 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3694 else if (globals /* only if tagging global vars is enabled */
3695 && ((cp = lb.buffer,
3704 && (*cp == '(' || isspace (*cp)))
3706 /* After "my" or "local", but before any following paren or space. */
3707 char *varname = NULL;
3709 cp = skip_spaces (cp);
3710 if (*cp == '$' || *cp == '@' || *cp == '%')
3712 char* varstart = ++cp;
3713 while (isalnum (*cp) || *cp == '_')
3715 varname = savenstr (varstart, cp-varstart);
3719 /* Should be examining a variable list at this point;
3720 could insist on seeing an open parenthesis. */
3721 while (*cp != '\0' && *cp != ';' && *cp != '=' && *cp != ')')
3725 /* Perhaps I should back cp up one character, so the TAGS table
3726 doesn't mention (and so depend upon) the following char. */
3727 pfnote ((CTAGS) ? savenstr (lb.buffer, cp-lb.buffer) : varname,
3728 FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3734 * Python support by Eric S. Raymond <esr@thyrsus.com>
3735 * Look for /^def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
3738 Python_functions (inf)
3743 LOOP_ON_INPUT_LINES (inf, lb, cp)
3747 && *cp++ == 'f' && isspace (*cp++))
3749 cp = skip_spaces (cp);
3750 while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':')
3752 pfnote ((char *) NULL, TRUE,
3753 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3761 && *cp++ == 's' && isspace (*cp++))
3763 cp = skip_spaces (cp);
3764 while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':')
3766 pfnote ((char *) NULL, TRUE,
3767 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3772 /* Idea by Corny de Souza
3773 * Cobol tag functions
3774 * We could look for anything that could be a paragraph name.
3775 * i.e. anything that starts in column 8 is one word and ends in a full stop.
3778 Cobol_paragraphs (inf)
3781 register char *bp, *ep;
3783 LOOP_ON_INPUT_LINES (inf, lb, bp)
3789 /* If eoln, compiler option or comment ignore whole line. */
3790 if (bp[-1] != ' ' || !isalnum (bp[0]))
3793 for (ep = bp; isalnum (*ep) || *ep == '-'; ep++)
3796 pfnote ((CTAGS) ? savenstr (bp, ep-bp) : NULL, TRUE,
3797 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
3801 /* Added by Mosur Mohan, 4/22/88 */
3802 /* Pascal parsing */
3805 * Locates tags for procedures & functions. Doesn't do any type- or
3806 * var-definitions. It does look for the keyword "extern" or
3807 * "forward" immediately following the procedure statement; if found,
3808 * the tag is skipped.
3811 Pascal_functions (inf)
3814 linebuffer tline; /* mostly copied from C_entries */
3816 int save_lineno, save_len;
3817 char c, *cp, *namebuf;
3819 bool /* each of these flags is TRUE iff: */
3820 incomment, /* point is inside a comment */
3821 inquote, /* point is inside '..' string */
3822 get_tagname, /* point is after PROCEDURE/FUNCTION
3823 keyword, so next item = potential tag */
3824 found_tag, /* point is after a potential tag */
3825 inparms, /* point is within parameter-list */
3826 verify_tag; /* point has passed the parm-list, so the
3827 next token will determine whether this
3828 is a FORWARD/EXTERN to be ignored, or
3829 whether it is a real tag */
3831 save_lcno = save_lineno = save_len = 0; /* keep compiler quiet */
3832 namebuf = NULL; /* keep compiler quiet */
3837 initbuffer (&tline);
3839 incomment = inquote = FALSE;
3840 found_tag = FALSE; /* have a proc name; check if extern */
3841 get_tagname = FALSE; /* have found "procedure" keyword */
3842 inparms = FALSE; /* found '(' after "proc" */
3843 verify_tag = FALSE; /* check if "extern" is ahead */
3846 while (!feof (inf)) /* long main loop to get next char */
3849 if (c == '\0') /* if end of line */
3852 linecharno = charno;
3853 charno += readline (&lb, inf);
3857 if (!((found_tag && verify_tag)
3859 c = *dbp++; /* only if don't need *dbp pointing
3860 to the beginning of the name of
3861 the procedure or function */
3865 if (c == '}') /* within { } comments */
3867 else if (c == '*' && *dbp == ')') /* within (* *) comments */
3884 inquote = TRUE; /* found first quote */
3886 case '{': /* found open { comment */
3890 if (*dbp == '*') /* found open (* comment */
3895 else if (found_tag) /* found '(' after tag, i.e., parm-list */
3898 case ')': /* end of parms list */
3903 if (found_tag && !inparms) /* end of proc or fn stmt */
3910 if (found_tag && verify_tag && (*dbp != ' '))
3912 /* check if this is an "extern" declaration */
3915 if (lowcase (*dbp == 'e'))
3917 if (tail ("extern")) /* superfluous, really! */
3923 else if (lowcase (*dbp) == 'f')
3925 if (tail ("forward")) /* check for forward reference */
3931 if (found_tag && verify_tag) /* not external proc, so make tag */
3935 pfnote (namebuf, TRUE,
3936 tline.buffer, save_len, save_lineno, save_lcno);
3940 if (get_tagname) /* grab name of proc or fn */
3945 /* save all values for later tagging */
3946 grow_linebuffer (&tline, lb.len + 1);
3947 strcpy (tline.buffer, lb.buffer);
3948 save_lineno = lineno;
3949 save_lcno = linecharno;
3951 /* grab block name */
3952 for (cp = dbp + 1; *cp != '\0' && !endtoken (*cp); cp++)
3954 namebuf = (CTAGS) ? savenstr (dbp, cp-dbp) : NULL;
3955 dbp = cp; /* set dbp to e-o-token */
3956 save_len = dbp - lb.buffer + 1;
3957 get_tagname = FALSE;
3961 /* and proceed to check for "extern" */
3963 else if (!incomment && !inquote && !found_tag)
3965 /* check for proc/fn keywords */
3966 switch (lowcase (c))
3969 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
3973 if (tail ("unction"))
3978 } /* while not eof */
3980 free (tline.buffer);
3984 * lisp tag functions
3985 * look for (def or (DEF, quote or QUOTE
3987 int L_isdef PP ((char *strp));
3990 register char *strp;
3992 return ((strp[1] == 'd' || strp[1] == 'D')
3993 && (strp[2] == 'e' || strp[2] == 'E')
3994 && (strp[3] == 'f' || strp[3] == 'F'));
3996 int L_isquote PP ((char *strp));
3999 register char *strp;
4001 return ((*++strp == 'q' || *strp == 'Q')
4002 && (*++strp == 'u' || *strp == 'U')
4003 && (*++strp == 'o' || *strp == 'O')
4004 && (*++strp == 't' || *strp == 'T')
4005 && (*++strp == 'e' || *strp == 'E')
4006 && isspace (*++strp));
4009 void L_getit PP ((void));
4015 if (*dbp == '\'') /* Skip prefix quote */
4017 else if (*dbp == '(')
4019 if (L_isquote (dbp))
4020 dbp += 7; /* Skip "(quote " */
4022 dbp += 1; /* Skip "(" before name in (defstruct (foo)) */
4023 dbp = skip_spaces (dbp);
4026 for (cp = dbp /*+1*/;
4027 *cp != '\0' && *cp != '(' && *cp != ' ' && *cp != ')';
4033 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
4034 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4038 Lisp_functions (inf)
4041 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4047 dbp = skip_non_spaces (dbp);
4048 dbp = skip_spaces (dbp);
4053 /* Check for (foo::defmumble name-defined ... */
4056 while (*dbp != '\0' && !isspace (*dbp)
4057 && *dbp != ':' && *dbp != '(' && *dbp != ')');
4062 while (*dbp == ':');
4064 if (L_isdef (dbp - 1))
4066 dbp = skip_non_spaces (dbp);
4067 dbp = skip_spaces (dbp);
4077 * Postscript tag functions
4078 * Just look for lines where the first character is '/'
4079 * Richard Mlynarik <mly@adoc.xerox.com>
4082 Postscript_functions (inf)
4085 register char *bp, *ep;
4087 LOOP_ON_INPUT_LINES (inf, lb, bp)
4092 *ep != '\0' && *ep != ' ' && *ep != '{';
4095 pfnote ((CTAGS) ? savenstr (bp, ep-bp) : NULL, TRUE,
4096 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
4103 * Scheme tag functions
4104 * look for (def... xyzzy
4105 * look for (def... (xyzzy
4106 * look for (def ... ((...(xyzzy ....
4107 * look for (set! xyzzy
4110 void get_scheme PP ((void));
4113 Scheme_functions (inf)
4116 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4119 && (dbp[1] == 'D' || dbp[1] == 'd')
4120 && (dbp[2] == 'E' || dbp[2] == 'e')
4121 && (dbp[3] == 'F' || dbp[3] == 'f'))
4123 dbp = skip_non_spaces (dbp);
4124 /* Skip over open parens and white space */
4125 while (isspace (*dbp) || *dbp == '(')
4130 && (dbp[1] == 'S' || dbp[1] == 's')
4131 && (dbp[2] == 'E' || dbp[2] == 'e')
4132 && (dbp[3] == 'T' || dbp[3] == 't')
4133 && (dbp[4] == '!' || dbp[4] == '!')
4134 && (isspace (dbp[5])))
4136 dbp = skip_non_spaces (dbp);
4137 dbp = skip_spaces (dbp);
4150 /* Go till you get to white space or a syntactic break */
4152 *cp != '\0' && *cp != '(' && *cp != ')' && !isspace (*cp);
4155 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
4156 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4159 /* Find tags in TeX and LaTeX input files. */
4161 /* TEX_toktab is a table of TeX control sequences that define tags.
4162 Each TEX_tabent records one such control sequence.
4163 CONVERT THIS TO USE THE Stab TYPE!! */
4170 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
4172 /* Default set of control sequences to put into TEX_toktab.
4173 The value of environment var TEXTAGS is prepended to this. */
4175 char *TEX_defenv = "\
4176 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4177 :part:appendix:entry:index";
4179 void TEX_mode PP ((FILE *inf));
4180 struct TEX_tabent *TEX_decode_env PP ((char *evarname, char *defenv));
4181 int TEX_Token PP ((char *cp));
4183 char TEX_esc = '\\';
4184 char TEX_opgrp = '{';
4185 char TEX_clgrp = '}';
4188 * TeX/LaTeX scanning loop.
4197 /* Select either \ or ! as escape character. */
4200 /* Initialize token table once from environment. */
4202 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
4204 LOOP_ON_INPUT_LINES (inf, lb, cp)
4207 /* Look at each esc in line. */
4208 while ((cp = etags_strchr (cp, TEX_esc)) != NULL)
4212 linecharno += cp - lasthit;
4214 i = TEX_Token (lasthit);
4217 /* We seem to include the TeX command in the tag name.
4219 for (p = lasthit + TEX_toktab[i].len;
4220 *p != '\0' && *p != TEX_clgrp;
4223 pfnote (/*savenstr (lasthit, p-lasthit)*/ (char *)NULL, TRUE,
4224 lb.buffer, lb.len, lineno, linecharno);
4225 break; /* We only tag a line once */
4231 #define TEX_LESC '\\'
4232 #define TEX_SESC '!'
4235 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4236 chars accordingly. */
4243 while ((c = getc (inf)) != EOF)
4245 /* Skip to next line if we hit the TeX comment char. */
4249 else if (c == TEX_LESC || c == TEX_SESC )
4268 /* Read environment and prepend it to the default string.
4269 Build token table. */
4271 TEX_decode_env (evarname, defenv)
4275 register char *env, *p;
4277 struct TEX_tabent *tab;
4280 /* Append default string to environment. */
4281 env = getenv (evarname);
4287 env = concat (oldenv, defenv, "");
4291 /* Allocate a token table */
4292 for (size = 1, p = env; p;)
4293 if ((p = etags_strchr (p, ':')) && *++p != '\0')
4295 /* Add 1 to leave room for null terminator. */
4296 tab = xnew (size + 1, struct TEX_tabent);
4298 /* Unpack environment string into token table. Be careful about */
4299 /* zero-length strings (leading ':', "::" and trailing ':') */
4302 p = etags_strchr (env, ':');
4303 if (!p) /* End of environment string. */
4304 p = env + strlen (env);
4306 { /* Only non-zero strings. */
4307 tab[i].name = savenstr (env, p - env);
4308 tab[i].len = strlen (tab[i].name);
4315 tab[i].name = NULL; /* Mark end of table. */
4323 /* If the text at CP matches one of the tag-defining TeX command names,
4324 return the pointer to the first occurrence of that command in TEX_toktab.
4325 Otherwise return -1.
4326 Keep the capital `T' in `token' for dumb truncating compilers
4327 (this distinguishes it from `TEX_toktab' */
4334 for (i = 0; TEX_toktab[i].len > 0; i++)
4335 if (strneq (TEX_toktab[i].name, cp, TEX_toktab[i].len))
4341 * Prolog support (rewritten) by Anders Lindgren, Mar. 96
4343 * Assumes that the predicate starts at column 0.
4344 * Only the first clause of a predicate is added.
4346 int prolog_pred PP ((char *s, char *last));
4347 void prolog_skip_comment PP ((linebuffer *plb, FILE *inf));
4348 int prolog_atom PP ((char *s, int pos));
4351 Prolog_functions (inf)
4362 LOOP_ON_INPUT_LINES (inf, lb, cp)
4364 if (cp[0] == '\0') /* Empty line */
4366 else if (isspace (cp[0])) /* Not a predicate */
4368 else if (cp[0] == '/' && cp[1] == '*') /* comment. */
4369 prolog_skip_comment (&lb, inf);
4370 else if ((len = prolog_pred (cp, last)) > 0)
4372 /* Predicate. Store the function name so that we only
4373 generate a tag for the first clause. */
4375 last = xnew(len + 1, char);
4376 else if (len + 1 > allocated)
4377 last = xrnew (last, len + 1, char);
4378 allocated = len + 1;
4379 strncpy (last, cp, len);
4387 prolog_skip_comment (plb, inf)
4395 for (cp = plb->buffer; *cp != '\0'; cp++)
4396 if (cp[0] == '*' && cp[1] == '/')
4399 linecharno += readline (plb, inf);
4405 * A predicate definition is added if it matches:
4406 * <beginning of line><Prolog Atom><whitespace>(
4408 * It is added to the tags database if it doesn't match the
4409 * name of the previous clause header.
4411 * Return the size of the name of the predicate, or 0 if no header
4415 prolog_pred (s, last)
4417 char *last; /* Name of last clause. */
4422 pos = prolog_atom (s, 0);
4427 pos = skip_spaces (s + pos) - s;
4429 if ((s[pos] == '(') || (s[pos] == '.'))
4434 /* Save only the first clause. */
4436 || len != strlen (last)
4437 || !strneq (s, last, len))
4439 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
4440 s, pos, lineno, linecharno);
4448 * Consume a Prolog atom.
4449 * Return the number of bytes consumed, or -1 if there was an error.
4451 * A prolog atom, in this context, could be one of:
4452 * - An alphanumeric sequence, starting with a lower case letter.
4453 * - A quoted arbitrary string. Single quotes can escape themselves.
4454 * Backslash quotes everything.
4457 prolog_atom (s, pos)
4465 if (islower(s[pos]) || (s[pos] == '_'))
4467 /* The atom is unquoted. */
4469 while (isalnum(s[pos]) || (s[pos] == '_'))
4473 return pos - origpos;
4475 else if (s[pos] == '\'')
4486 pos++; /* A double quote */
4488 else if (s[pos] == '\0')
4489 /* Multiline quoted atoms are ignored. */
4491 else if (s[pos] == '\\')
4493 if (s[pos+1] == '\0')
4500 return pos - origpos;
4507 * Support for Erlang -- Anders Lindgren, Feb 1996.
4509 * Generates tags for functions, defines, and records.
4511 * Assumes that Erlang functions start at column 0.
4513 int erlang_func PP ((char *s, char *last));
4514 void erlang_attribute PP ((char *s));
4515 int erlang_atom PP ((char *s, int pos));
4518 Erlang_functions (inf)
4529 LOOP_ON_INPUT_LINES (inf, lb, cp)
4531 if (cp[0] == '\0') /* Empty line */
4533 else if (isspace (cp[0])) /* Not function nor attribute */
4535 else if (cp[0] == '%') /* comment */
4537 else if (cp[0] == '"') /* Sometimes, strings start in column one */
4539 else if (cp[0] == '-') /* attribute, e.g. "-define" */
4541 erlang_attribute (cp);
4544 else if ((len = erlang_func (cp, last)) > 0)
4547 * Function. Store the function name so that we only
4548 * generates a tag for the first clause.
4551 last = xnew (len + 1, char);
4552 else if (len + 1 > allocated)
4553 last = xrnew (last, len + 1, char);
4554 allocated = len + 1;
4555 strncpy (last, cp, len);
4563 * A function definition is added if it matches:
4564 * <beginning of line><Erlang Atom><whitespace>(
4566 * It is added to the tags database if it doesn't match the
4567 * name of the previous clause header.
4569 * Return the size of the name of the function, or 0 if no function
4573 erlang_func (s, last)
4575 char *last; /* Name of last clause. */
4580 pos = erlang_atom (s, 0);
4585 pos = skip_spaces (s + pos) - s;
4587 /* Save only the first clause. */
4590 || len != strlen (last)
4591 || !strneq (s, last, len)))
4593 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
4594 s, pos, lineno, linecharno);
4603 * Handle attributes. Currently, tags are generated for defines
4606 * They are on the form:
4607 * -define(foo, bar).
4608 * -define(Foo(M, N), M+N).
4609 * -record(graph, {vtab = notable, cyclic = true}).
4612 erlang_attribute (s)
4618 if (strneq (s, "-define", 7) || strneq (s, "-record", 7))
4620 pos = skip_spaces (s + 7) - s;
4621 if (s[pos++] == '(')
4623 pos = skip_spaces (s + pos) - s;
4624 len = erlang_atom (s, pos);
4626 pfnote ((CTAGS) ? savenstr (& s[pos], len) : NULL, TRUE,
4627 s, pos + len, lineno, linecharno);
4635 * Consume an Erlang atom (or variable).
4636 * Return the number of bytes consumed, or -1 if there was an error.
4639 erlang_atom (s, pos)
4647 if (isalpha (s[pos]) || s[pos] == '_')
4649 /* The atom is unquoted. */
4651 while (isalnum (s[pos]) || s[pos] == '_')
4653 return pos - origpos;
4655 else if (s[pos] == '\'')
4666 else if (s[pos] == '\0')
4667 /* Multiline quoted atoms are ignored. */
4669 else if (s[pos] == '\\')
4671 if (s[pos+1] == '\0')
4678 return pos - origpos;
4684 #ifdef ETAGS_REGEXPS
4686 /* Take a string like "/blah/" and turn it into "blah", making sure
4687 that the first and last characters are the same, and handling
4688 quoted separator characters. Actually, stops on the occurrence of
4689 an unquoted separator. Also turns "\t" into a Tab character.
4690 Returns pointer to terminating separator. Works in place. Null
4691 terminates name string. */
4692 char * scan_separators PP ((char *name));
4694 scan_separators (name)
4698 char *copyto = name;
4699 bool quoted = FALSE;
4701 for (++name; *name != '\0'; ++name)
4707 else if (*name == sep)
4711 /* Something else is quoted, so preserve the quote. */
4717 else if (*name == '\\')
4719 else if (*name == sep)
4725 /* Terminate copied string. */
4730 /* Look at the argument of --regex or --no-regex and do the right
4731 thing. Same for each line of a regexp file. */
4733 analyse_regex (regex_arg)
4736 if (regex_arg == NULL)
4737 free_patterns (); /* --no-regex: remove existing regexps */
4739 /* A real --regexp option or a line in a regexp file. */
4740 switch (regex_arg[0])
4742 /* Comments in regexp file or null arg to --regex. */
4748 /* Read a regex file. This is recursive and may result in a
4749 loop, which will stop when the file descriptors are exhausted. */
4753 linebuffer regexbuf;
4754 char *regexfile = regex_arg + 1;
4756 /* regexfile is a file containing regexps, one per line. */
4757 regexfp = fopen (regexfile, "r");
4758 if (regexfp == NULL)
4763 initbuffer (®exbuf);
4764 while (readline_internal (®exbuf, regexfp) > 0)
4765 analyse_regex (regexbuf.buffer);
4766 free (regexbuf.buffer);
4771 /* Regexp to be used for a specific language only. */
4775 char *lang_name = regex_arg + 1;
4778 for (cp = lang_name; *cp != '}'; cp++)
4781 error ("unterminated language name in regex: %s", regex_arg);
4785 lang = get_language_from_name (lang_name);
4788 add_regex (cp + 1, lang);
4792 /* Regexp to be used for any language. */
4794 add_regex (regex_arg, NULL);
4799 /* Turn a name, which is an ed-style (but Emacs syntax) regular
4800 expression, into a real regular expression by compiling it. */
4802 add_regex (regexp_pattern, lang)
4803 char *regexp_pattern;
4808 struct re_pattern_buffer *patbuf;
4812 if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0])
4814 error ("%s: unterminated regexp", regexp_pattern);
4817 name = scan_separators (regexp_pattern);
4818 if (regexp_pattern[0] == '\0')
4820 error ("null regexp", (char *)NULL);
4823 (void) scan_separators (name);
4825 patbuf = xnew (1, struct re_pattern_buffer);
4826 patbuf->translate = NULL;
4827 patbuf->fastmap = NULL;
4828 patbuf->buffer = NULL;
4829 patbuf->allocated = 0;
4831 err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf);
4834 error ("%s while compiling pattern", err);
4839 p_head = xnew (1, pattern);
4840 p_head->regex = savestr (regexp_pattern);
4841 p_head->p_next = pp;
4842 p_head->language = lang;
4843 p_head->pattern = patbuf;
4844 p_head->name_pattern = savestr (name);
4845 p_head->error_signaled = FALSE;
4849 * Do the substitutions indicated by the regular expression and
4852 char * substitute PP ((char *in, char *out, struct re_registers *regs));
4854 substitute (in, out, regs)
4856 struct re_registers *regs;
4859 int size, dig, diglen;
4862 size = strlen (out);
4864 /* Pass 1: figure out how much to allocate by finding all \N strings. */
4865 if (out[size - 1] == '\\')
4866 fatal ("pattern error in \"%s\"", out);
4867 for (t = etags_strchr (out, '\\');
4869 t = etags_strchr (t + 2, '\\'))
4873 diglen = regs->end[dig] - regs->start[dig];
4879 /* Allocate space and do the substitutions. */
4880 result = xnew (size + 1, char);
4882 for (t = result; *out != '\0'; out++)
4883 if (*out == '\\' && isdigit (*++out))
4885 /* Using "dig2" satisfies my debugger. Bleah. */
4887 diglen = regs->end[dig] - regs->start[dig];
4888 strncpy (t, in + regs->start[dig], diglen);
4895 if (DEBUG && (t > result + size || t - result != strlen (result)))
4901 /* Deallocate all patterns. */
4906 while (p_head != NULL)
4908 pp = p_head->p_next;
4909 free (p_head->regex);
4910 free (p_head->name_pattern);
4917 #endif /* ETAGS_REGEXPS */
4918 /* Initialize a linebuffer for use */
4924 lbp->buffer = xnew (200, char);
4928 * Read a line of text from `stream' into `lbp', excluding the
4929 * newline or CR-NL, if any. Return the number of characters read from
4930 * `stream', which is the length of the line including the newline.
4932 * On DOS or Windows we do not count the CR character, if any, before the
4933 * NL, in the returned length; this mirrors the behavior of emacs on those
4934 * platforms (for text files, it translates CR-NL to NL as it reads in the
4938 readline_internal (lbp, stream)
4940 register FILE *stream;
4942 char *buffer = lbp->buffer;
4943 register char *p = lbp->buffer;
4944 register char *pend;
4947 pend = p + lbp->size; /* Separate to avoid 386/IX compiler bug. */
4951 register int c = getc (stream);
4954 /* We're at the end of linebuffer: expand it. */
4956 buffer = xrnew (buffer, lbp->size, char);
4957 p += buffer - lbp->buffer;
4958 pend = buffer + lbp->size;
4959 lbp->buffer = buffer;
4969 if (p > buffer && p[-1] == '\r')
4973 /* Assume CRLF->LF translation will be performed by Emacs
4974 when loading this file, so CRs won't appear in the buffer.
4975 It would be cleaner to compensate within Emacs;
4976 however, Emacs does not know how many CRs were deleted
4977 before any given point in the file. */
4992 lbp->len = p - buffer;
4994 return lbp->len + chars_deleted;
4998 * Like readline_internal, above, but in addition try to match the
4999 * input line against relevant regular expressions.
5002 readline (lbp, stream)
5006 /* Read new line. */
5007 long result = readline_internal (lbp, stream);
5008 #ifdef ETAGS_REGEXPS
5012 /* Match against relevant patterns. */
5014 for (pp = p_head; pp != NULL; pp = pp->p_next)
5016 /* Only use generic regexps or those for the current language. */
5017 if (pp->language != NULL && pp->language != curlang)
5020 match = re_match (pp->pattern, lbp->buffer, lbp->len, 0, &pp->regs);
5025 if (!pp->error_signaled)
5027 error ("error while matching \"%s\"", pp->regex);
5028 pp->error_signaled = TRUE;
5035 /* Match occurred. Construct a tag. */
5036 if (pp->name_pattern[0] != '\0')
5038 /* Make a named tag. */
5039 char *name = substitute (lbp->buffer,
5040 pp->name_pattern, &pp->regs);
5042 pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);
5046 /* Make an unnamed tag. */
5047 pfnote ((char *)NULL, TRUE,
5048 lbp->buffer, match, lineno, linecharno);
5053 #endif /* ETAGS_REGEXPS */
5059 * Return a pointer to a space of size strlen(cp)+1 allocated
5060 * with xnew where the string CP has been copied.
5066 return savenstr (cp, strlen (cp));
5070 * Return a pointer to a space of size LEN+1 allocated with xnew where
5071 * the string CP has been copied for at most the first LEN characters.
5080 dp = xnew (len + 1, char);
5081 strncpy (dp, cp, len);
5087 * Return the ptr in sp at which the character c last
5088 * appears; NULL if not found
5090 * Identical to System V strrchr, included for portability.
5093 etags_strrchr (sp, c)
5110 * Return the ptr in sp at which the character c first
5111 * appears; NULL if not found
5113 * Identical to System V strchr, included for portability.
5116 etags_strchr (sp, c)
5128 /* Skip spaces, return new pointer. */
5133 while (isspace (*cp)) /* isspace('\0')==FALSE */
5138 /* Skip non spaces, return new pointer. */
5140 skip_non_spaces (cp)
5143 while (!iswhite (*cp)) /* iswhite('\0')==TRUE */
5148 /* Print error message and exit. */
5166 suggest_asking_for_help ()
5168 fprintf (stderr, "\tTry `%s %s' for a complete list of options.\n",
5179 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
5182 const char *s1, *s2;
5184 fprintf (stderr, "%s: ", progname);
5185 fprintf (stderr, s1, s2);
5186 fprintf (stderr, "\n");
5189 /* Return a newly-allocated string whose contents
5190 concatenate those of s1, s2, s3. */
5195 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
5196 char *result = xnew (len1 + len2 + len3 + 1, char);
5198 strcpy (result, s1);
5199 strcpy (result + len1, s2);
5200 strcpy (result + len1 + len2, s3);
5201 result[len1 + len2 + len3] = '\0';
5206 /* Does the same work as the system V getcwd, but does not need to
5207 guess the buffer size in advance. */
5213 char *path = xnew (bufsize, char);
5215 while (getcwd (path, bufsize) == NULL)
5217 if (errno != ERANGE)
5221 path = xnew (bufsize, char);
5224 canonicalize_filename (path);
5227 #else /* not HAVE_GETCWD */
5229 char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */
5233 for (p = path; *p != '\0'; p++)
5239 return strdup (path);
5240 #else /* not MSDOS */
5245 pipe = (FILE *) popen ("pwd 2>/dev/null", "r");
5246 if (pipe == NULL || readline_internal (&path, pipe) == 0)
5251 #endif /* not MSDOS */
5252 #endif /* not HAVE_GETCWD */
5255 /* Return a newly allocated string containing the file name of FILE
5256 relative to the absolute directory DIR (which should end with a slash). */
5258 relative_filename (file, dir)
5261 char *fp, *dp, *afn, *res;
5264 /* Find the common root of file and dir (with a trailing slash). */
5265 afn = absolute_filename (file, cwd);
5268 while (*fp++ == *dp++)
5270 fp--, dp--; /* back to the first differing char */
5271 do /* look at the equal chars until '/' */
5275 /* Build a sequence of "../" strings for the resulting relative file name. */
5277 while ((dp = etags_strchr (dp + 1, '/')) != NULL)
5279 res = xnew (3*i + strlen (fp + 1) + 1, char);
5282 strcat (res, "../");
5284 /* Add the file name relative to the common root of file and dir. */
5285 strcat (res, fp + 1);
5291 /* Return a newly allocated string containing the absolute file name
5292 of FILE given DIR (which should end with a slash). */
5294 absolute_filename (file, dir)
5297 char *slashp, *cp, *res;
5299 if (filename_is_absolute (file))
5300 res = savestr (file);
5302 /* We don't support non-absolute file names with a drive
5303 letter, like `d:NAME' (it's too much hassle). */
5304 else if (file[1] == ':')
5305 fatal ("%s: relative file names with drive letters not supported", file);
5308 res = concat (dir, file, "");
5310 /* Delete the "/dirname/.." and "/." substrings. */
5311 slashp = etags_strchr (res, '/');
5312 while (slashp != NULL && slashp[0] != '\0')
5314 if (slashp[1] == '.')
5316 if (slashp[2] == '.'
5317 && (slashp[3] == '/' || slashp[3] == '\0'))
5322 while (cp >= res && !filename_is_absolute (cp));
5324 cp = slashp; /* the absolute name begins with "/.." */
5326 /* Under MSDOS and NT we get `d:/NAME' as absolute
5327 file name, so the luser could say `d:/../NAME'.
5328 We silently treat this as `d:/NAME'. */
5329 else if (cp[0] != '/')
5332 strcpy (cp, slashp + 3);
5336 else if (slashp[2] == '/' || slashp[2] == '\0')
5338 strcpy (slashp, slashp + 2);
5343 slashp = etags_strchr (slashp + 1, '/');
5347 return savestr ("/");
5352 /* Return a newly allocated string containing the absolute
5353 file name of dir where FILE resides given DIR (which should
5354 end with a slash). */
5356 absolute_dirname (file, dir)
5362 canonicalize_filename (file);
5363 slashp = etags_strrchr (file, '/');
5365 return savestr (dir);
5368 res = absolute_filename (file, dir);
5374 /* Whether the argument string is an absolute file name. The argument
5375 string must have been canonicalized with canonicalize_filename. */
5377 filename_is_absolute (fn)
5380 return (fn[0] == '/'
5382 || (isalpha(fn[0]) && fn[1] == ':' && fn[2] == '/')
5387 /* Translate backslashes into slashes. Works in place. */
5389 canonicalize_filename (fn)
5393 for (; *fn != '\0'; fn++)
5401 /* Increase the size of a linebuffer. */
5403 grow_linebuffer (lbp, toksize)
5407 while (lbp->size < toksize)
5409 lbp->buffer = xrnew (lbp->buffer, lbp->size, char);
5412 /* Like malloc but get fatal error if memory is exhausted. */
5417 long *result = (long *) malloc (size);
5419 fatal ("virtual memory exhausted", (char *)NULL);
5424 xrealloc (ptr, size)
5428 long *result = (long *) realloc (ptr, size);
5430 fatal ("virtual memory exhausted", (char *)NULL);