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 part of the OO-Browser.
6 It is derived from the etags.c program included with (but not considered
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
25 * Ctags originally by Ken Arnold.
26 * Fortran added by Jim Kleckner.
27 * Ed Pelegri-Llopart added C typedefs.
28 * Gnu Emacs TAGS format and modifications by RMS?
29 * Sam Kendall added C++.
30 * Francesco Potorti` reorganised C and C++ based on work by Joe Wells.
31 * Regexp tags by Tom Tromey.
33 * Modified for use as ootags.c by Bob Weiner and Steve Baur, BeOpen.com
35 * Francesco Potorti` (F.Potorti@cnuce.cnr.it) is the current maintainer.
38 char pot_etags_version[] = "@(#) pot revision number is 12.28";
40 /* Prototyping magic snarfed from gmalloc.c */
41 #if defined (__cplusplus) || defined (__STDC__)
45 #define __ptr_t void *
46 #else /* Not C++ or ANSI C. */
52 #define __ptr_t char *
53 #endif /* C++ or ANSI C. */
57 /* On some systems, Emacs defines static as nothing for the sake
58 of unexec. We don't want that here since we don't use unexec. */
60 # define ETAGS_REGEXPS /* use the regexp features */
61 # define LONG_OPTIONS /* accept long options */
62 #endif /* HAVE_CONFIG_H */
73 # include <sys/param.h>
75 # ifndef HAVE_CONFIG_H
77 # include <sys/config.h>
86 # define MAXPATHLEN _MAX_PATH
92 # endif /* not HAVE_CONFIG_H */
93 #endif /* WINDOWSNT */
95 #if !defined (WINDOWSNT) && defined (STDC_HEADERS)
104 extern char *getcwd ();
106 #endif /* HAVE_UNISTD_H */
114 #include <sys/types.h>
115 #include <sys/stat.h>
117 #if !defined (S_ISREG) && defined (S_IFREG)
118 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
124 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
126 extern int optind, opterr;
127 #endif /* LONG_OPTIONS */
131 #endif /* ETAGS_REGEXPS */
133 /* Define CTAGS to make the program "ctags" compatible with the usual one.
134 Leave it undefined to make the program "etags", which makes emacs-style
135 tag tables and tags typedefs, #defines and struct/union/enum by default. */
143 /* Exit codes for success and failure. */
153 #define C_PLPL 0x00001 /* C++ */
154 #define C_STAR 0x00003 /* C* */
155 #define C_JAVA 0x00005 /* JAVA */
156 #define YACC 0x10000 /* yacc file */
158 #define streq(s,t) ((DEBUG && (s) == NULL && (t) == NULL \
159 && (abort (), 1)) || !strcmp (s, t))
160 #define strneq(s,t,n) ((DEBUG && (s) == NULL && (t) == NULL \
161 && (abort (), 1)) || !strncmp (s, t, n))
163 #define lowcase(c) tolower ((char)c)
165 #define CHARS 256 /* 2^sizeof(char) */
166 #define CHAR(x) ((unsigned int)x & (CHARS - 1))
167 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */
168 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
169 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
170 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
171 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
174 /*#undef OO_BROWSER*/
175 /* Due to the way this file is constructed, this unfortunately doesn't */
176 /* work except for documentation purposes. -slb */
181 #define set_construct(construct) \
182 if (!oo_browser_construct) oo_browser_construct = construct
183 void oo_browser_clear_all_globals();
184 void oo_browser_clear_some_globals();
185 void oo_browser_check_and_clear_structtype();
189 * xnew, xrnew -- allocate, reallocate storage
191 * SYNOPSIS: Type *xnew (int n, Type);
192 * Type *xrnew (OldPointer, int n, Type);
195 # include "chkmalloc.h"
196 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
197 (n) * sizeof (Type)))
198 # define xrnew(op,n,Type) ((Type *) trace_realloc (__FILE__, __LINE__, \
199 (op), (n) * sizeof (Type)))
201 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
202 # define xrnew(op,n,Type) ((Type *) xrealloc ((op), (n) * sizeof (Type)))
207 typedef void Lang_function ();
212 Lang_function *function;
217 typedef struct node_st
218 { /* sorting structure */
219 char *name; /* function or type name */
221 short int construct; /* Construct type for the OO-Browser */
223 char *file; /* file name */
224 bool is_func; /* use pattern or line no */
225 bool been_warned; /* set if noticed dup */
226 int lno; /* line number tag is on */
227 long cno; /* character number line starts on */
228 char *pat; /* search pattern */
229 struct node_st *left, *right; /* left and right sons */
233 /* If you add to this array, you must add a corresponding entry to the
235 static char *oo_browser_default_classes[] =
236 /* Lack of square brackets around some of these entries are intentional. */
237 {"null", "class", "method", "[constant]", "[enumeration]", "[enum_label]",
238 "extern", "[function]", "[macro]", "objc", "[structure]", "[type]",
239 "[union]", "[variable]"};
241 /* If you add to this enum, you must add a corresponding entry to the
243 enum oo_browser_constructs {C_NULL, C_CLASS, C_METHOD, C_CONSTANT, C_ENUMERATION,
244 C_ENUM_LABEL, C_EXTERN, C_FUNCTION, C_MACRO,
245 C_OBJC, C_STRUCTURE, C_TYPE, C_UNION, C_VARIABLE};
247 enum oo_browser_constructs oo_browser_construct = C_NULL;
251 * A `linebuffer' is a structure which holds a line of text.
252 * `readline_internal' reads a line from a stream into a linebuffer
253 * and works regardless of the length of the line.
254 * SIZE is the size of BUFFER, LEN is the length of the string in
255 * BUFFER after readline reads it.
264 extern char *getenv PP ((const char *envvar));
266 /* Many compilers barf on this:
267 Lang_function Asm_labels;
268 so let's write it this way */
269 void Asm_labels PP ((FILE *inf));
270 void C_entries PP ((int c_ext, FILE *inf));
271 void default_C_entries PP ((FILE *inf));
272 void plain_C_entries PP ((FILE *inf));
273 void Cjava_entries PP ((FILE *inf));
274 void Cplusplus_entries PP ((FILE *inf));
275 void Yacc_entries PP ((FILE *inf));
276 void Cobol_paragraphs PP ((FILE *inf));
277 void Cstar_entries PP ((FILE *inf));
278 void Erlang_functions PP ((FILE *inf));
279 void Fortran_functions PP ((FILE *inf));
280 void Lisp_functions PP ((FILE *inf));
281 void Pascal_functions PP ((FILE *inf));
282 void Perl_functions PP ((FILE *inf));
283 void Postscript_functions PP ((FILE *inf));
284 void Prolog_functions PP ((FILE *inf));
285 void Python_functions PP ((FILE *inf));
286 void Scheme_functions PP ((FILE *inf));
287 void TeX_functions PP ((FILE *inf));
288 void just_read_file PP ((FILE *inf));
290 void print_language_names PP ((void));
291 void print_version PP ((void));
292 void print_help PP ((void));
294 language *get_language_from_name PP ((char *name));
295 language *get_language_from_interpreter PP ((char *interpreter));
296 language *get_language_from_suffix PP ((char *suffix));
297 int total_size_of_entries PP ((node *np));
298 long readline PP ((linebuffer *lbp, FILE *stream));
299 long readline_internal PP ((linebuffer *lbp, FILE *stream));
301 void analyse_regex PP ((char *regex_arg));
302 void add_regex PP ((char *regexp_pattern, language *lang));
303 void free_patterns PP ((void));
304 #endif /* ETAGS_REGEXPS */
305 void error PP ((const char *s1, const char *s2));
306 void suggest_asking_for_help PP ((void));
307 void fatal PP ((char *s1, char *s2));
308 void pfatal PP ((char *s1));
309 void add_node PP ((node *np, node **cur_node_p));
311 void init PP ((void));
312 void initbuffer PP ((linebuffer *lbp));
313 void find_entries PP ((char *file, FILE *inf));
314 void free_tree PP ((node *np));
315 void pfnote PP ((char *name, bool is_func, char *linestart, int linelen, int lno, long cno));
316 void new_pfnote PP ((char *name, int namelen, bool is_func, char *linestart, int linelen, int lno, long cno));
317 void process_file PP ((char *file));
318 void put_entries PP ((node *np));
319 void takeprec PP ((void));
321 char *concat PP ((char *s1, char *s2, char *s3));
322 char *skip_spaces PP ((char *cp));
323 char *skip_non_spaces PP ((char *cp));
324 char *savenstr PP ((char *cp, int len));
325 char *savestr PP ((char *cp));
326 char *etags_strchr PP ((char *sp, int c));
327 char *etags_strrchr PP ((char *sp, int c));
328 char *etags_getcwd PP ((void));
329 char *relative_filename PP ((char *file, char *dir));
330 char *absolute_filename PP ((char *file, char *dir));
331 char *absolute_dirname PP ((char *file, char *dir));
332 bool filename_is_absolute PP ((char *fn));
333 void canonicalize_filename PP ((char *fn));
334 void grow_linebuffer PP ((linebuffer *lbp, int toksize));
335 long *xmalloc PP ((unsigned int size));
336 long *xrealloc PP ((char *ptr, unsigned int size));
339 char searchar = '/'; /* use /.../ searches */
341 char *tagfile; /* output file */
342 char *progname; /* name this program was invoked with */
343 char *cwd; /* current working directory */
344 char *tagfiledir; /* directory of tagfile */
345 FILE *tagf; /* ioptr for tags file */
347 char *curfile; /* current input file name */
348 language *curlang; /* current language */
350 int lineno; /* line number of current line */
351 long charno; /* current character number */
352 long linecharno; /* charno of start of current line */
353 char *dbp; /* pointer to start of current tag */
354 node *head; /* the head of the binary tree of tags */
356 linebuffer lb; /* the current line */
357 linebuffer token_name; /* used by C_entries as a temporary area */
361 linebuffer lb; /* used by C_entries instead of lb */
364 /* boolean "functions" (see init) */
365 bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
368 *white = " \f\t\n\r",
370 *nonam = " \f\t\n\r(=,[;",
371 /* token ending chars */
372 *endtk = " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
373 /* token starting chars */
374 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
375 /* valid in-token chars */
376 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
378 bool append_to_tagfile; /* -a: append to tags */
379 /* The following four default to TRUE for etags, but to FALSE for ctags. */
380 bool typedefs; /* -t: create tags for C typedefs */
381 bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */
382 /* 0 struct/enum/union decls, and C++ */
383 /* member functions. */
384 bool constantypedefs; /* -d: create tags for C #define, enum */
385 /* constants and variables. */
386 /* -D: opposite of -d. Default under ctags. */
387 bool globals; /* create tags for global variables */
388 bool members; /* create tags for C member variables */
389 bool update; /* -u: update tags */
390 bool vgrind_style; /* -v: create vgrind style index output */
391 bool no_warnings; /* -w: suppress warnings */
392 bool cxref_style; /* -x: create cxref style output */
393 bool cplusplus; /* .[hc] means C++, not C */
394 bool noindentypedefs; /* -I: ignore indentation in C */
396 bool oo_browser_format; /* -O: OO-Browser tags format */
400 struct option longopts[] =
402 { "append", no_argument, NULL, 'a' },
403 { "backward-search", no_argument, NULL, 'B' },
404 { "c++", no_argument, NULL, 'C' },
405 { "cxref", no_argument, NULL, 'x' },
406 { "defines", no_argument, NULL, 'd' },
407 { "no-defines", no_argument, NULL, 'D' },
408 { "globals", no_argument, &globals, TRUE },
409 { "no-globals", no_argument, &globals, FALSE },
410 { "help", no_argument, NULL, 'h' },
411 { "help", no_argument, NULL, 'H' },
412 { "ignore-indentation", no_argument, NULL, 'I' },
413 { "include", required_argument, NULL, 'i' },
414 { "language", required_argument, NULL, 'l' },
415 { "members", no_argument, &members, TRUE },
416 { "no-members", no_argument, &members, FALSE },
417 { "no-warn", no_argument, NULL, 'w' },
418 { "output", required_argument, NULL, 'o' },
420 { "oo-browser", no_argument, NULL, 'O' },
423 { "regex", required_argument, NULL, 'r' },
424 { "no-regex", no_argument, NULL, 'R' },
425 #endif /* ETAGS_REGEXPS */
426 { "typedefs", no_argument, NULL, 't' },
427 { "typedefs-and-c++", no_argument, NULL, 'T' },
428 { "update", no_argument, NULL, 'u' },
429 { "version", no_argument, NULL, 'V' },
430 { "vgrind", no_argument, NULL, 'v' },
433 #endif /* LONG_OPTIONS */
436 /* Structure defining a regular expression. Elements are
437 the compiled pattern, and the name string. */
438 typedef struct pattern
440 struct pattern *p_next;
443 struct re_pattern_buffer *pattern;
444 struct re_registers regs;
449 /* Array of all regexps. */
450 pattern *p_head = NULL;
451 #endif /* ETAGS_REGEXPS */
457 /* Non-NULL if language fixed. */
458 language *forced_lang = NULL;
461 char *Asm_suffixes [] = { "a", /* Unix assembler */
462 "asm", /* Microcontroller assembly */
463 "def", /* BSO/Tasking definition includes */
464 "inc", /* Microcontroller include files */
465 "ins", /* Microcontroller include files */
466 "s", "sa", /* Unix assembler */
467 "src", /* BSO/Tasking C compiler output */
471 /* Note that .c and .h can be considered C++, if the --c++ flag was
472 given. That is why default_C_entries is called here. */
473 char *default_C_suffixes [] =
476 char *Cplusplus_suffixes [] =
477 { "C", "H", "c++", "cc", "cpp", "cxx", "h++", "hh", "hpp", "hxx",
478 "M", /* Objective C++ */
479 "pdb", /* Postscript with C syntax */
482 char *Cjava_suffixes [] =
485 char *Cobol_suffixes [] =
486 { "COB", "cob", NULL };
488 char *Cstar_suffixes [] =
489 { "cs", "hs", NULL };
491 char *Erlang_suffixes [] =
492 { "erl", "hrl", NULL };
494 char *Fortran_suffixes [] =
495 { "F", "f", "f90", "for", NULL };
497 char *Lisp_suffixes [] =
498 { "cl", "clisp", "el", "l", "lisp", "lsp", "ml", NULL };
500 char *Pascal_suffixes [] =
501 { "p", "pas", NULL };
503 char *Perl_suffixes [] =
504 { "pl", "pm", NULL };
505 char *Perl_interpreters [] =
506 { "perl", "@PERL@", NULL };
508 char *plain_C_suffixes [] =
509 { "pc", /* Pro*C file */
510 "m", /* Objective C file */
511 "lm", /* Objective lex file */
514 char *Postscript_suffixes [] =
517 char *Prolog_suffixes [] =
520 char *Python_suffixes [] =
523 /* Can't do the `SCM' or `scm' prefix with a version number. */
524 char *Scheme_suffixes [] =
525 { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "ss", "t", NULL };
527 char *TeX_suffixes [] =
528 { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL };
530 char *Yacc_suffixes [] =
531 { "y", "ym", NULL }; /* .ym is Objective yacc file */
534 * Table of languages.
536 * It is ok for a given function to be listed under more than one
537 * name. I just didn't.
540 language lang_names [] =
542 { "asm", Asm_labels, Asm_suffixes, NULL },
543 { "c", default_C_entries, default_C_suffixes, NULL },
544 { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL },
545 { "c*", Cstar_entries, Cstar_suffixes, NULL },
546 { "cobol", Cobol_paragraphs, Cobol_suffixes, NULL },
547 { "erlang", Erlang_functions, Erlang_suffixes, NULL },
548 { "fortran", Fortran_functions, Fortran_suffixes, NULL },
549 { "java", Cjava_entries, Cjava_suffixes, NULL },
550 { "lisp", Lisp_functions, Lisp_suffixes, NULL },
551 { "pascal", Pascal_functions, Pascal_suffixes, NULL },
552 { "perl", Perl_functions, Perl_suffixes, Perl_interpreters },
553 { "postscript", Postscript_functions, Postscript_suffixes, NULL },
554 { "proc", plain_C_entries, plain_C_suffixes, NULL },
555 { "prolog", Prolog_functions, Prolog_suffixes, NULL },
556 { "python", Python_functions, Python_suffixes, NULL },
557 { "scheme", Scheme_functions, Scheme_suffixes, NULL },
558 { "tex", TeX_functions, TeX_suffixes, NULL },
559 { "yacc", Yacc_entries, Yacc_suffixes, NULL },
560 { "auto", NULL }, /* default guessing scheme */
561 { "none", just_read_file }, /* regexp matching only */
562 { NULL, NULL } /* end of list */
567 print_language_names ()
572 puts ("\nThese are the currently supported languages, along with the\n\
573 default file name suffixes:");
574 for (lang = lang_names; lang->name != NULL; lang++)
576 printf ("\t%s\t", lang->name);
577 if (lang->suffixes != NULL)
578 for (ext = lang->suffixes; *ext != NULL; ext++)
579 printf (" .%s", *ext);
582 puts ("Where `auto' means use default language for files based on file\n\
583 name suffix, and `none' means only do regexp processing on files.\n\
584 If no language is specified and no matching suffix is found,\n\
585 the first line of the file is read for a sharp-bang (#!) sequence\n\
586 followed by the name of an interpreter. If no such sequence is found,\n\
587 Fortran is tried first; if no tags are found, C is tried next.");
591 # define VERSION "20"
596 printf ("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION);
597 puts ("Copyright (C) 1996 Free Software Foundation, Inc. and Ken Arnold");
598 puts ("This program is distributed under the same terms as Emacs");
606 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
608 These are the options accepted by %s.\n", progname, progname);
610 puts ("You may use unambiguous abbreviations for the long option names.");
612 puts ("Long option names do not work with this executable, as it is not\n\
613 linked with GNU getopt.");
614 #endif /* LONG_OPTIONS */
615 puts ("A - as file name means read names from stdin (one per line).");
617 printf (" Absolute names are stored in the output file as they are.\n\
618 Relative ones are stored relative to the output file's directory.");
621 puts ("-a, --append\n\
622 Append tag entries to existing tags file.");
625 puts ("-B, --backward-search\n\
626 Write the search commands for the tag entries using '?', the\n\
627 backward-search command instead of '/', the forward-search command.");
630 Treat files whose name suffix defaults to C language as C++ files.");
633 puts ("-d, --defines\n\
634 Create tag entries for C #define constants and enum constants, too.");
636 puts ("-D, --no-defines\n\
637 Don't create tag entries for C #define constants and enum constants.\n\
638 This makes the tags file smaller.");
642 puts ("-i FILE, --include=FILE\n\
643 Include a note in tag file indicating that, when searching for\n\
644 a tag, one should also consult the tags file FILE after\n\
645 checking the current file.");
646 puts ("-l LANG, --language=LANG\n\
647 Force the following files to be considered as written in the\n\
648 named language up to the next --language=LANG option.");
653 Create tag entries for global variables in some languages.");
655 puts ("--no-globals\n\
656 Do not create tag entries for global variables in some\n\
657 languages. This makes the tags file smaller.");
659 Create tag entries for member variables in C and derived languages.");
662 puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
663 Make a tag for each line matching pattern REGEXP in the\n\
664 following files. regexfile is a file containing one REGEXP\n\
665 per line. REGEXP is anchored (as if preceded by ^).\n\
666 The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
667 named tags can be created with:\n\
668 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
669 puts ("-R, --no-regex\n\
670 Don't create tags from regexps for the following files.");
671 #endif /* ETAGS_REGEXPS */
672 puts ("-o FILE, --output=FILE\n\
673 Write the tags to FILE.");
675 puts ("-O, --oo-browser\n\
676 Generate a specialized tags format used only by the BeOpen.com OO-Browser.");
678 puts ("-I, --ignore-indentation\n\
679 Don't rely on indentation quite as much as normal. Currently,\n\
680 this means not to assume that a closing brace in the first\n\
681 column is the final brace of a function or structure\n\
682 definition in C and C++.");
686 puts ("-t, --typedefs\n\
687 Generate tag entries for C typedefs.");
688 puts ("-T, --typedefs-and-c++\n\
689 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
690 and C++ member functions.");
691 puts ("-u, --update\n\
692 Update the tag entries for the given files, leaving tag\n\
693 entries for other files in place. Currently, this is\n\
694 implemented by deleting the existing entries for the given\n\
695 files and then rewriting the new entries at the end of the\n\
696 tags file. It is often faster to simply rebuild the entire\n\
697 tag file than to use this.");
698 puts ("-v, --vgrind\n\
699 Generates an index of items intended for human consumption,\n\
700 similar to the output of vgrind. The index is sorted, and\n\
701 gives the page number of each item.");
702 puts ("-w, --no-warn\n\
703 Suppress warning messages about entries defined in multiple\n\
705 puts ("-x, --cxref\n\
706 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
707 The output uses line numbers instead of page numbers, but\n\
708 beyond that the differences are cosmetic; try both to see\n\
712 puts ("-V, --version\n\
713 Print the version of the program.\n\
715 Print this help message.");
717 print_language_names ();
720 puts ("Report bugs to bug-gnu-emacs@prep.ai.mit.edu");
733 /* This structure helps us allow mixing of --lang and file names. */
736 enum argument_type arg_type;
741 #ifdef VMS /* VMS specific functions */
745 /* This is a BUG! ANY arbitrary limit is a BUG!
746 Won't someone please fix this? */
747 #define MAX_FILE_SPEC_LEN 255
750 char body[MAX_FILE_SPEC_LEN + 1];
754 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
755 returning in each successive call the next file name matching the input
756 spec. The function expects that each in_spec passed
757 to it will be processed to completion; in particular, up to and
758 including the call following that in which the last matching name
759 is returned, the function ignores the value of in_spec, and will
760 only start processing a new spec with the following call.
761 If an error occurs, on return out_spec contains the value
762 of in_spec when the error occurred.
764 With each successive file name returned in out_spec, the
765 function's return value is one. When there are no more matching
766 names the function returns zero. If on the first call no file
767 matches in_spec, or there is any other error, -1 is returned.
772 #define OUTSIZE MAX_FILE_SPEC_LEN
778 static long context = 0;
779 static struct dsc$descriptor_s o;
780 static struct dsc$descriptor_s i;
781 static bool pass1 = TRUE;
788 o.dsc$a_pointer = (char *) out;
789 o.dsc$w_length = (short)OUTSIZE;
790 i.dsc$a_pointer = in;
791 i.dsc$w_length = (short)strlen(in);
792 i.dsc$b_dtype = DSC$K_DTYPE_T;
793 i.dsc$b_class = DSC$K_CLASS_S;
794 o.dsc$b_dtype = DSC$K_DTYPE_VT;
795 o.dsc$b_class = DSC$K_CLASS_VS;
797 if ((status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL)
799 out->body[out->curlen] = EOS;
802 else if (status == RMS$_NMF)
806 strcpy(out->body, in);
809 lib$find_file_end(&context);
815 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
816 name of each file specified by the provided arg expanding wildcards.
819 gfnames (arg, p_error)
823 static vspec filename = {MAX_FILE_SPEC_LEN, "\0"};
825 switch (fn_exp (&filename, arg))
829 return filename.body;
835 return filename.body;
839 #ifndef OLD /* Newer versions of VMS do provide `system'. */
843 error ("%s", "system() function not implemented under VMS");
847 #define VERSION_DELIM ';'
848 char *massage_name (s)
854 if (*s == VERSION_DELIM)
872 unsigned int nincluded_files;
873 char **included_files;
876 int current_arg, file_count;
877 linebuffer filename_lb;
883 _fmode = O_BINARY; /* all of files are treated as binary files */
888 included_files = xnew (argc, char *);
892 /* Allocate enough no matter what happens. Overkill, but each one
894 argbuffer = xnew (argc, argument);
897 /* Set syntax for regular expression routines. */
898 re_set_syntax (RE_SYNTAX_EMACS | RE_INTERVALS);
899 #endif /* ETAGS_REGEXPS */
902 * If etags, always find typedefs and structure tags. Why not?
903 * Also default is to find macro constants, enum constants and
908 typedefs = typedefs_and_cplusplus = constantypedefs = TRUE;
920 optstring = "-aCdDf:Il:o:r:RStTi:BuvxwVhH";
922 optstring = "-aCdDf:Il:o:r:RStTi:BOuvxwVhH";
926 optstring = "-aCdDf:Il:o:StTi:BuvxwVhH";
928 optstring = "-aCdDf:Il:o:StTi:BOuvxwVhH";
930 #endif /* ETAGS_REGEXPS */
933 optstring = optstring + 1;
934 #endif /* LONG_OPTIONS */
936 opt = getopt_long (argc, argv, optstring, longopts, 0);
943 /* If getopt returns 0, then it has already processed a
944 long-named option. We should do nothing. */
948 /* This means that a file name has been seen. Record it. */
949 argbuffer[current_arg].arg_type = at_filename;
950 argbuffer[current_arg].what = optarg;
955 /* Common options. */
956 case 'a': append_to_tagfile = TRUE; break;
957 case 'C': cplusplus = TRUE; break;
958 case 'd': constantypedefs = TRUE; break;
959 case 'D': constantypedefs = FALSE; break;
960 case 'f': /* for compatibility with old makefiles */
964 /* convert char to string, to call error with */
966 sprintf (buf, "%c", opt);
967 error ("-%s option may only be given once.", buf);
968 suggest_asking_for_help ();
974 oo_browser_format = TRUE;
978 case 'S': /* for backward compatibility */
979 noindentypedefs = TRUE;
983 language *lang = get_language_from_name (optarg);
986 argbuffer[current_arg].lang = lang;
987 argbuffer[current_arg].arg_type = at_language;
994 argbuffer[current_arg].arg_type = at_regexp;
995 argbuffer[current_arg].what = optarg;
999 argbuffer[current_arg].arg_type = at_regexp;
1000 argbuffer[current_arg].what = NULL;
1003 #endif /* ETAGS_REGEXPS */
1015 typedefs = typedefs_and_cplusplus = TRUE;
1020 included_files[nincluded_files++] = optarg;
1023 /* Ctags options. */
1024 case 'B': searchar = '?'; break;
1025 case 'u': update = TRUE; break;
1026 case 'v': vgrind_style = TRUE; /*FALLTHRU*/
1027 case 'x': cxref_style = TRUE; break;
1028 case 'w': no_warnings = TRUE; break;
1031 suggest_asking_for_help ();
1035 for (; optind < argc; ++optind)
1037 argbuffer[current_arg].arg_type = at_filename;
1038 argbuffer[current_arg].what = argv[optind];
1043 if (nincluded_files == 0 && file_count == 0)
1045 error ("no input files specified.", 0);
1046 suggest_asking_for_help ();
1049 if (tagfile == NULL)
1050 tagfile = CTAGS ? "tags" : "TAGS";
1051 cwd = etags_getcwd (); /* the current working directory */
1052 if (cwd[strlen (cwd) - 1] != '/')
1055 cwd = concat (oldcwd, "/", "");
1058 if (streq (tagfile, "-"))
1061 tagfiledir = absolute_dirname (tagfile, cwd);
1063 init (); /* set up boolean "functions" */
1066 initbuffer (&token_name);
1067 initbuffer (&lbs[0].lb);
1068 initbuffer (&lbs[1].lb);
1069 initbuffer (&filename_lb);
1073 if (streq (tagfile, "-"))
1077 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1078 doesn't take effect until after `stdout' is already open). */
1079 if (!isatty (fileno (stdout)))
1080 setmode (fileno (stdout), O_BINARY);
1084 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1090 * Loop through files finding functions.
1092 for (i = 0; i < current_arg; ++i)
1094 switch (argbuffer[i].arg_type)
1097 forced_lang = argbuffer[i].lang;
1099 #ifdef ETAGS_REGEXPS
1101 analyse_regex (argbuffer[i].what);
1106 while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL)
1110 error ("can't find file %s\n", this_file);
1115 this_file = massage_name (this_file);
1118 this_file = argbuffer[i].what;
1121 oo_browser_clear_all_globals();
1123 /* Input file named "-" means read file names from stdin
1124 (one per line) and use them. */
1125 if (streq (this_file, "-"))
1126 while (readline_internal (&filename_lb, stdin) > 0)
1129 oo_browser_clear_some_globals();
1131 process_file (filename_lb.buffer);
1136 process_file (this_file);
1144 #ifdef ETAGS_REGEXPS
1146 #endif /* ETAGS_REGEXPS */
1150 while (nincluded_files-- > 0)
1151 fprintf (tagf, "\f\n%s,include\n", *included_files++);
1157 /* If CTAGS, we are here. process_file did not write the tags yet,
1158 because we want them ordered. Let's do it now. */
1168 for (i = 0; i < current_arg; ++i)
1170 if (argbuffer[i].arg_type != at_filename)
1173 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1174 tagfile, argbuffer[i].what, tagfile);
1175 if (system (cmd) != GOOD)
1176 fatal ("failed to execute shell command", (char *)NULL);
1178 append_to_tagfile = TRUE;
1181 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1190 sprintf (cmd, "sort %s -o %s", tagfile, tagfile);
1191 exit (system (cmd));
1198 * Return a language given the name.
1201 get_language_from_name (name)
1207 error ("empty language name", (char *)NULL);
1210 for (lang = lang_names; lang->name != NULL; lang++)
1211 if (streq (name, lang->name))
1213 error ("unknown language \"%s\"", name);
1221 * Return a language given the interpreter name.
1224 get_language_from_interpreter (interpreter)
1230 if (interpreter == NULL)
1232 for (lang = lang_names; lang->name != NULL; lang++)
1233 if (lang->interpreters != NULL)
1234 for (iname = lang->interpreters; *iname != NULL; iname++)
1235 if (streq (*iname, interpreter))
1244 * Return a language given the file suffix.
1247 get_language_from_suffix (suffix)
1255 for (lang = lang_names; lang->name != NULL; lang++)
1256 if (lang->suffixes != NULL)
1257 for (ext = lang->suffixes; *ext != NULL; ext++)
1258 if (streq (*ext, suffix))
1266 * This routine is called on each file argument.
1272 struct stat stat_buf;
1275 canonicalize_filename (file);
1276 if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode))
1278 error ("skipping %s: it is not a regular file.", file);
1281 if (streq (file, tagfile) && !streq (tagfile, "-"))
1283 error ("skipping inclusion of %s in self.", file);
1286 inf = fopen (file, "r");
1293 find_entries (file, inf);
1299 if (filename_is_absolute (file))
1301 /* file is an absolute file name. Canonicalise it. */
1302 filename = absolute_filename (file, cwd);
1306 /* file is a file name relative to cwd. Make it relative
1307 to the directory of the tags file. */
1308 filename = relative_filename (file, tagfiledir);
1311 if (oo_browser_format)
1312 fprintf (tagf, "\f\n%s\n", filename);
1315 fprintf (tagf, "\f\n%s,%d\n", filename, total_size_of_entries (head));
1324 * This routine sets up the boolean pseudo-functions which work
1325 * by setting boolean flags dependent upon the corresponding character.
1326 * Every char which is NOT in that string is not a white char. Therefore,
1327 * all of the array "_wht" is set to FALSE, and then the elements
1328 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1329 * of a char is TRUE if it is the string "white", else FALSE.
1337 for (i = 0; i < CHARS; i++)
1338 iswhite(i) = notinname(i) = begtoken(i) = intoken(i) = endtoken(i) = FALSE;
1339 for (sp = white; *sp != '\0'; sp++) iswhite (*sp) = TRUE;
1340 for (sp = nonam; *sp != '\0'; sp++) notinname (*sp) = TRUE;
1341 for (sp = begtk; *sp != '\0'; sp++) begtoken (*sp) = TRUE;
1342 for (sp = midtk; *sp != '\0'; sp++) intoken (*sp) = TRUE;
1343 for (sp = endtk; *sp != '\0'; sp++) endtoken (*sp) = TRUE;
1344 iswhite('\0') = iswhite('\n');
1345 notinname('\0') = notinname('\n');
1346 begtoken('\0') = begtoken('\n');
1347 intoken('\0') = intoken('\n');
1348 endtoken('\0') = endtoken('\n');
1352 * This routine opens the specified file and calls the function
1353 * which finds the function and type definitions.
1355 node *last_node = NULL;
1358 find_entries (file, inf)
1364 node *old_last_node;
1366 curfile = savestr (file);
1368 /* If user specified a language, use it. */
1370 if (lang != NULL && lang->function != NULL)
1373 lang->function (inf);
1379 cp = etags_strrchr (file, '.');
1383 lang = get_language_from_suffix (cp);
1384 if (lang != NULL && lang->function != NULL)
1387 lang->function (inf);
1394 /* Look for sharp-bang as the first two characters. */
1395 if (readline_internal (&lb, inf) > 0
1397 && lb.buffer[0] == '#'
1398 && lb.buffer[1] == '!')
1402 /* Set lp to point at the first char after the last slash in the
1403 line or, if no slashes, at the first nonblank. Then set cp to
1404 the first successive blank and terminate the string. */
1405 lp = etags_strrchr (lb.buffer+2, '/');
1409 lp = skip_spaces (lb.buffer + 2);
1410 cp = skip_non_spaces (lp);
1413 if (strlen (lp) > 0)
1415 lang = get_language_from_interpreter (lp);
1416 if (lang != NULL && lang->function != NULL)
1419 lang->function (inf);
1429 old_last_node = last_node;
1430 curlang = get_language_from_name ("fortran");
1431 Fortran_functions (inf);
1433 /* No Fortran entries found. Try C. */
1434 if (old_last_node == last_node)
1437 curlang = get_language_from_name (cplusplus ? "c++" : "c");
1438 default_C_entries (inf);
1447 pfnote (name, is_func, linestart, linelen, lno, cno)
1448 char *name; /* tag name, or NULL if unnamed */
1449 bool is_func; /* tag is a function */
1450 char *linestart; /* start of the line where tag is */
1451 int linelen; /* length of the line where tag is */
1452 int lno; /* line number */
1453 long cno; /* character number */
1457 if (CTAGS && name == NULL)
1460 np = xnew (1, node);
1462 /* If ctags mode, change name "main" to M<thisfilename>. */
1463 if (CTAGS && !cxref_style && streq (name, "main"))
1465 register char *fp = etags_strrchr (curfile, '/');
1466 np->name = concat ("M", fp == 0 ? curfile : fp + 1, "");
1467 fp = etags_strrchr (np->name, '.');
1468 if (fp && fp[1] != '\0' && fp[2] == '\0')
1473 np->been_warned = FALSE;
1475 np->is_func = is_func;
1477 /* Our char numbers are 0-base, because of C language tradition?
1478 ctags compatibility? old versions compatibility? I don't know.
1479 Anyway, since emacs's are 1-base we expect etags.el to take care
1480 of the difference. If we wanted to have 1-based numbers, we would
1481 uncomment the +1 below. */
1482 np->cno = cno /* + 1 */ ;
1483 np->left = np->right = NULL;
1484 if (CTAGS && !cxref_style)
1486 if (strlen (linestart) < 50)
1487 np->pat = concat (linestart, "$", "");
1489 np->pat = savenstr (linestart, 50);
1492 np->pat = savenstr (linestart, linelen);
1495 if (oo_browser_format)
1496 np->construct = oo_browser_construct;
1497 oo_browser_construct = C_NULL;
1498 oo_browser_check_and_clear_structtype();
1501 add_node (np, &head);
1504 /* Date: Wed, 22 Jan 1997 02:56:31 -0500 [last amended 18 Sep 1997]
1505 * From: Sam Kendall <kendall@mv.mv.com>
1506 * Subject: Proposal for firming up the TAGS format specification
1507 * To: F.Potorti@cnuce.cnr.it
1509 * pfnote should emit the optimized form [unnamed tag] only if:
1510 * 1. name does not contain any of the characters " \t\r\n(),;";
1511 * 2. linestart contains name as either a rightmost, or rightmost but
1512 * one character, substring;
1513 * 3. the character, if any, immediately before name in linestart must
1514 * be one of the characters " \t(),;";
1515 * 4. the character, if any, immediately after name in linestart must
1516 * also be one of the characters " \t(),;".
1518 * The real implementation uses the notinname() macro, which recognises
1519 * characters slightly different form " \t\r\n(),;". See the variable
1522 #define traditional_tag_style TRUE
1524 new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno)
1525 char *name; /* tag name, or NULL if unnamed */
1526 int namelen; /* tag length */
1527 bool is_func; /* tag is a function */
1528 char *linestart; /* start of the line where tag is */
1529 int linelen; /* length of the line where tag is */
1530 int lno; /* line number */
1531 long cno; /* character number */
1539 for (cp = name; !notinname (*cp); cp++)
1541 if (*cp == '\0') /* rule #1 */
1543 cp = linestart + linelen - namelen;
1544 if (notinname (linestart[linelen-1]))
1545 cp -= 1; /* rule #4 */
1547 if (!oo_browser_format
1548 && cp >= linestart /* rule #2 */
1550 if (cp >= linestart /* rule #2 */
1553 || notinname (cp[-1])) /* rule #3 */
1554 && strneq (name, cp, namelen)) /* rule #2 */
1555 named = FALSE; /* use unnamed tag */
1560 name = savenstr (name, namelen);
1563 pfnote (name, is_func, linestart, linelen, lno, cno);
1568 * recurse on left children, iterate on right children.
1576 register node *node_right = np->right;
1577 free_tree (np->left);
1578 if (np->name != NULL)
1588 * Adds a node to the tree of nodes. In etags mode, we don't keep
1589 * it sorted; we just keep a linear list. In ctags mode, maintain
1590 * an ordered tree, with no attempt at balancing.
1592 * add_node is the only function allowed to add nodes, so it can
1596 add_node (np, cur_node_p)
1597 node *np, **cur_node_p;
1600 register node *cur_node = *cur_node_p;
1602 if (cur_node == NULL)
1612 if (last_node == NULL)
1613 fatal ("internal error in add_node", (char *)NULL);
1614 last_node->right = np;
1620 dif = strcmp (np->name, cur_node->name);
1623 * If this tag name matches an existing one, then
1624 * do not add the node, but maybe print a warning.
1628 if (streq (np->file, cur_node->file))
1632 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1633 np->file, lineno, np->name);
1634 fprintf (stderr, "Second entry ignored\n");
1637 else if (!cur_node->been_warned && !no_warnings)
1641 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1642 np->file, cur_node->file, np->name);
1643 cur_node->been_warned = TRUE;
1648 /* Actually add the node */
1649 add_node (np, dif < 0 ? &cur_node->left : &cur_node->right);
1654 /* Default class name for the current OO-Browser tag. */
1655 static char *oo_browser_class;
1656 /* Prefix character to use in OO-Browser listings for the current tag. */
1657 static char oo_browser_prefix;
1669 /* Output subentries that precede this one */
1670 put_entries (np->left);
1672 /* Output this entry */
1677 if (oo_browser_format)
1679 /* Omit C++ `class' and `method' entries as well as Objective-C
1680 entries from this OO-Browser tags file since the browser handles
1681 them independently of this file. Omit `extern' variable declarations
1682 as they are unused by the OO-Browser. */
1683 if (np->construct != C_CLASS
1684 && np->construct != C_METHOD
1685 && np->construct != C_EXTERN
1686 && np->construct != C_OBJC)
1688 oo_browser_class = oo_browser_default_classes[np->construct];
1689 switch (np->construct)
1698 oo_browser_prefix = '=';
1702 oo_browser_prefix = '-';
1705 if (np->name != NULL)
1706 fprintf (tagf, "%s@%c %s@%s\n",
1707 oo_browser_class, oo_browser_prefix,
1710 fprintf (tagf, "%s@%c ???@%s\n",
1711 oo_browser_class, oo_browser_prefix, np->pat);
1717 if (np->name != NULL)
1718 fprintf (tagf, "%s\177%s\001%d,%ld\n",
1719 np->pat, np->name, np->lno, np->cno);
1721 fprintf (tagf, "%s\177%d,%ld\n",
1722 np->pat, np->lno, np->cno);
1729 if (np->name == NULL)
1730 error ("internal error: NULL name in ctags mode.", (char *)NULL);
1735 fprintf (stdout, "%s %s %d\n",
1736 np->name, np->file, (np->lno + 63) / 64);
1738 fprintf (stdout, "%-16s %3d %-16s %s\n",
1739 np->name, np->lno, np->file, np->pat);
1743 fprintf (tagf, "%s\t%s\t", np->name, np->file);
1747 putc (searchar, tagf);
1750 for (sp = np->pat; *sp; sp++)
1752 if (*sp == '\\' || *sp == searchar)
1756 putc (searchar, tagf);
1759 { /* a typedef; text pattern inadequate */
1760 fprintf (tagf, "%d", np->lno);
1766 /* Output subentries that follow this one */
1767 put_entries (np->right);
1770 /* Length of a number's decimal representation. */
1771 int number_len PP ((long num));
1777 while ((num /= 10) > 0)
1783 * Return total number of characters that put_entries will output for
1784 * the nodes in the subtree of the specified node. Works only if
1785 * we are not ctags, but called only in that case. This count
1786 * is irrelevant with the new tags.el, but is still supplied for
1787 * backward compatibility.
1790 total_size_of_entries (np)
1798 for (total = 0; np != NULL; np = np->right)
1800 /* Count left subentries. */
1801 total += total_size_of_entries (np->left);
1803 /* Count this entry */
1804 total += strlen (np->pat) + 1;
1805 total += number_len ((long) np->lno) + 1 + number_len (np->cno) + 1;
1806 if (np->name != NULL)
1807 total += 1 + strlen (np->name); /* \001name */
1814 * The C symbol tables.
1819 st_C_objprot, st_C_objimpl, st_C_objend,
1823 st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec,
1826 , st_C_union, st_C_class, st_C_extern, st_C_inline
1830 /* Feed stuff between (but not including) %[ and %] lines to:
1831 gperf -c -k 1,3 -o -p -r -t
1833 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1835 @interface, 0, st_C_objprot
1836 @protocol, 0, st_C_objprot
1837 @implementation,0, st_C_objimpl
1838 @end, 0, st_C_objend
1839 import, C_JAVA, st_C_ignore
1840 package, C_JAVA, st_C_ignore
1841 friend, C_PLPL, st_C_ignore
1842 extends, C_JAVA, st_C_javastruct
1843 implements, C_JAVA, st_C_javastruct
1844 interface, C_JAVA, st_C_struct
1845 class, C_PLPL, st_C_class
1846 namespace, C_PLPL, st_C_struct
1847 domain, C_STAR, st_C_struct
1848 union, 0, st_C_union
1849 struct, 0, st_C_struct
1851 typedef, 0, st_C_typedef
1852 define, 0, st_C_define
1853 inline, 0, st_C_inline
1854 bool, C_PLPL, st_C_typespec
1855 long, 0, st_C_typespec
1856 short, 0, st_C_typespec
1857 int, 0, st_C_typespec
1858 char, 0, st_C_typespec
1859 float, 0, st_C_typespec
1860 double, 0, st_C_typespec
1861 signed, 0, st_C_typespec
1862 unsigned, 0, st_C_typespec
1863 auto, 0, st_C_typespec
1864 void, 0, st_C_typespec
1865 extern, 0, st_C_extern
1866 static, 0, st_C_typespec
1867 const, 0, st_C_const
1868 volatile, 0, st_C_typespec
1869 explicit, C_PLPL, st_C_typespec
1870 mutable, C_PLPL, st_C_typespec
1871 typename, C_PLPL, st_C_typespec
1872 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
1873 DEFUN, 0, st_C_gnumacro
1874 SYSCALL, 0, st_C_gnumacro
1875 ENTRY, 0, st_C_gnumacro
1876 PSEUDO, 0, st_C_gnumacro
1877 # These are defined inside C functions, so currently they are not met.
1878 # EXFUN used in glibc, DEFVAR_* in emacs.
1879 #EXFUN, 0, st_C_gnumacro
1880 #DEFVAR_, 0, st_C_gnumacro
1882 and replace lines between %< and %> with its output. */
1884 /* C code produced by gperf version 2.5 (GNU C++ version) */
1885 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
1886 struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
1888 #define TOTAL_KEYWORDS 41
1889 #define MIN_WORD_LENGTH 3
1890 #define MAX_WORD_LENGTH 15
1891 #define MIN_HASH_VALUE 13
1892 #define MAX_HASH_VALUE 129
1893 /* maximum key range = 117, duplicates = 0 */
1898 register int unsigned len;
1900 static unsigned char asso_values[] =
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, 130, 130, 130, 130, 130, 130,
1905 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1906 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1907 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1908 130, 130, 130, 130, 13, 130, 130, 130, 33, 32,
1909 47, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1910 5, 130, 130, 20, 32, 130, 130, 130, 130, 130,
1911 130, 130, 130, 130, 130, 130, 130, 47, 55, 8,
1912 15, 33, 61, 38, 130, 60, 130, 130, 2, 9,
1913 10, 62, 59, 130, 28, 27, 50, 19, 3, 130,
1914 130, 130, 130, 130, 130, 130, 130, 130,
1916 return len + asso_values[str[2]] + asso_values[str[0]];
1919 struct C_stab_entry *
1920 in_word_set (str, len)
1922 register unsigned int len;
1924 static struct C_stab_entry wordlist[] =
1926 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1927 {"",}, {"",}, {"",}, {"",},
1928 {"volatile", 0, st_C_typespec},
1930 {"long", 0, st_C_typespec},
1931 {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1932 {"const", 0, st_C_const},
1933 {"",}, {"",}, {"",},
1934 {"@end", 0, st_C_objend},
1935 {"namespace", C_PLPL, st_C_struct},
1937 {"domain", C_STAR, st_C_struct},
1939 {"@interface", 0, st_C_objprot},
1940 {"",}, {"",}, {"",},
1941 {"@implementation", 0, st_C_objimpl},
1943 {"double", 0, st_C_typespec},
1945 {"PSEUDO", 0, st_C_gnumacro},
1946 {"",}, {"",}, {"",},
1947 {"SYSCALL", 0, st_C_gnumacro},
1949 {"@protocol", 0, st_C_objprot},
1950 {"",}, {"",}, {"",},
1951 {"unsigned", 0, st_C_typespec},
1953 {"enum", 0, st_C_enum},
1955 {"char", 0, st_C_typespec},
1956 {"class", C_PLPL, st_C_class},
1957 {"struct", 0, st_C_struct},
1958 {"",}, {"",}, {"",}, {"",},
1959 {"mutable", C_PLPL, st_C_typespec},
1960 {"void", 0, st_C_typespec},
1961 {"inline", 0, st_C_inline},
1962 {"ENTRY", 0, st_C_gnumacro},
1964 {"signed", 0, st_C_typespec},
1966 {"package", C_JAVA, st_C_ignore},
1967 {"",}, {"",}, {"",}, {"",}, {"",},
1968 {"static", 0, st_C_typespec},
1970 {"define", 0, st_C_define},
1972 {"union", 0, st_C_union},
1973 {"DEFUN", 0, st_C_gnumacro},
1974 {"",}, {"",}, {"",},
1975 {"extern", 0, st_C_extern},
1976 {"extends", C_JAVA, st_C_javastruct},
1977 {"",}, {"",}, {"",},
1978 {"short", 0, st_C_typespec},
1979 {"",}, {"",}, {"",}, {"",}, {"",},
1980 {"explicit", C_PLPL, st_C_typespec},
1981 {"auto", 0, st_C_typespec},
1982 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1984 {"int", 0, st_C_typespec},
1986 {"typedef", 0, st_C_typedef},
1987 {"typename", C_PLPL, st_C_typespec},
1989 {"interface", C_JAVA, st_C_struct},
1991 {"bool", C_PLPL, st_C_typespec},
1992 {"",}, {"",}, {"",},
1993 {"import", C_JAVA, st_C_ignore},
1995 {"friend", C_PLPL, st_C_ignore},
1996 {"float", 0, st_C_typespec},
1997 {"implements", C_JAVA, st_C_javastruct},
2000 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
2002 register int key = hash (str, len);
2004 if (key <= MAX_HASH_VALUE && key >= 0)
2006 register char *s = wordlist[key].name;
2008 if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
2009 return &wordlist[key];
2016 enum sym_type C_symtype PP ((char *str, int len, int c_ext));
2018 C_symtype (str, len, c_ext)
2023 register struct C_stab_entry *se = in_word_set (str, len);
2025 if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
2031 * C functions and variables are recognized using a simple
2032 * finite automaton. fvdef is its state variable.
2036 fvnone, /* nothing seen */
2037 fvnameseen, /* function or variable name seen */
2038 fstartlist, /* func: just after open parenthesis */
2039 finlist, /* func: in parameter list */
2040 flistseen, /* func: after parameter list */
2041 fignore, /* func: before open brace */
2042 vignore /* var-like: ignore until ';' */
2047 * typedefs are recognized using a simple finite automaton.
2048 * typdef is its state variable.
2052 tnone, /* nothing seen */
2053 ttypedseen, /* typedef keyword seen */
2054 tinbody, /* inside typedef body */
2055 tend, /* just before typedef tag */
2056 tignore /* junk after typedef tag */
2061 * struct-like structures (enum, struct and union) are recognized
2062 * using another simple finite automaton. `structdef' is its state
2067 snone, /* nothing seen yet */
2068 skeyseen, /* struct-like keyword seen */
2069 stagseen, /* struct-like tag seen */
2070 scolonseen, /* colon seen after struct-like tag */
2071 sinbody /* in struct body: recognize member func defs*/
2075 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
2076 * struct tag, and structtype is the type of the preceding struct-like
2079 char *structtag = "<uninited>";
2080 enum sym_type structtype;
2084 oo_browser_check_and_clear_structtype()
2086 /* Allow for multiple enum_label tags. */
2087 if (structtype != st_C_enum)
2088 structtype = st_none;
2093 * When objdef is different from onone, objtag is the name of the class.
2095 char *objtag = "<uninited>";
2098 * Yet another little state machine to deal with preprocessor lines.
2102 dnone, /* nothing seen */
2103 dsharpseen, /* '#' seen as first char on line */
2104 ddefineseen, /* '#' and 'define' seen */
2105 dignorerest /* ignore rest of line */
2109 * State machine for Objective C protocols and implementations.
2110 * Tom R.Hageman <tom@basil.icce.rug.nl>
2114 onone, /* nothing seen */
2115 oprotocol, /* @interface or @protocol seen */
2116 oimplementation, /* @implementations seen */
2117 otagseen, /* class name seen */
2118 oparenseen, /* parenthesis before category seen */
2119 ocatseen, /* category name seen */
2120 oinbody, /* in @implementation body */
2121 omethodsign, /* in @implementation body, after +/- */
2122 omethodtag, /* after method name */
2123 omethodcolon, /* after method colon */
2124 omethodparm, /* after method parameter */
2125 oignore /* wait for @end */
2129 * Use this structure to keep info about the token read, and how it
2130 * should be tagged. Used by the make_C_tag function to build a tag.
2143 token tok; /* latest token read */
2146 * Set this to TRUE, and the next token considered is called a function.
2147 * Used only for GNU emacs's function-defining macros.
2149 bool next_token_is_func;
2152 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
2157 * methodlen is the length of the method name stored in token_name.
2163 oo_browser_clear_all_globals()
2165 /* Initialize globals so there is no carry over between files. */
2166 oo_browser_construct = C_NULL;
2167 fvdef = fvnone; typdef = tnone; structdef = snone;
2168 definedef = dnone; objdef = onone;
2169 structtype = st_none;
2170 next_token_is_func = yacc_rules = FALSE;
2174 oo_browser_clear_some_globals()
2176 oo_browser_construct = C_NULL;
2177 structtype = st_none;
2183 * checks to see if the current token is at the start of a
2184 * function or variable, or corresponds to a typedef, or
2185 * is a struct/union/enum tag, or #define, or an enum constant.
2187 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2188 * with args. C_EXT is which language we are looking at.
2190 * In the future we will need some way to adjust where the end of
2191 * the token is; for instance, implementing the C++ keyword
2192 * `operator' properly will adjust the end of the token to be after
2193 * whatever follows `operator'.
2201 * next_token_is_func IN OUT
2203 bool consider_token PP ((char *str, int len, int c, int c_ext,
2204 int cblev, int parlev, bool *is_func_or_var));
2206 consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var)
2207 register char *str; /* IN: token pointer */
2208 register int len; /* IN: token length */
2209 register int c; /* IN: first char after the token */
2210 int c_ext; /* IN: C extensions mask */
2211 int cblev; /* IN: curly brace level */
2212 int parlev; /* IN: parenthesis level */
2213 bool *is_func_or_var; /* OUT: function or variable found */
2215 enum sym_type toktype = C_symtype (str, len, c_ext);
2221 set_construct(C_STRUCTURE);
2224 set_construct(C_UNION);
2227 set_construct(C_CLASS);
2230 set_construct(C_ENUMERATION);
2233 set_construct(C_TYPE);
2236 set_construct(C_EXTERN);
2239 set_construct(C_FUNCTION);
2245 * Advance the definedef state machine.
2250 /* We're not on a preprocessor line. */
2253 if (toktype == st_C_define)
2255 definedef = ddefineseen;
2259 definedef = dignorerest;
2264 * Make a tag for any macro, unless it is a constant
2265 * and constantypedefs is FALSE.
2267 definedef = dignorerest;
2269 *is_func_or_var = (c == '(');
2272 char *p = str + len * sizeof(char);
2275 /* This must be a macro since there is no
2276 whitespace between the opening parenthesis
2277 and the definition name. */
2278 *is_func_or_var = TRUE;
2281 *is_func_or_var = FALSE;
2283 /* Handle possible whitespace between macro tag and opening
2284 parenthesis and ensure this is an actual macro.
2285 -- Bob Weiner, BeOpen.com, 11/19/1997 */
2286 while (*p && isspace(*p)) p++;
2289 /* Skip over nested parentheses. */
2294 while (*++p && depth > 0 && *p != '\n')
2305 /* If this is a macro, we have just passed
2306 the arguments and there will be more on
2307 the line before the NULL character that marks
2308 the end of the line token. */
2309 while (*p == ' ' || *p == '\t') p++;
2310 if (*p) *is_func_or_var = TRUE;
2315 set_construct((*is_func_or_var) ? C_MACRO : C_CONSTANT);
2317 if (!*is_func_or_var && !constantypedefs)
2324 error ("internal error: definedef value.", (char *)NULL);
2333 if (toktype == st_C_typedef)
2336 typdef = ttypedseen;
2345 set_construct(C_CONSTANT);
2362 /* Do not return here, so the structdef stuff has a chance. */
2368 set_construct(C_CONSTANT);
2384 * This structdef business is currently only invoked when cblev==0.
2385 * It should be recursively invoked whatever the curly brace level,
2386 * and a stack of states kept, to allow for definitions of structs
2389 * This structdef business is NOT invoked when we are ctags and the
2390 * file is plain C. This is because a struct tag may have the same
2391 * name as another tag, and this loses with ctags.
2395 case st_C_javastruct:
2396 if (structdef == stagseen)
2397 structdef = scolonseen;
2406 if (typdef == ttypedseen
2407 || (typedefs_and_cplusplus && cblev == 0 && structdef == snone))
2409 structdef = skeyseen;
2410 structtype = toktype;
2415 if (structdef == skeyseen)
2417 /* Save the tag for struct/union/class, for functions and variables
2418 that may be defined inside. */
2420 if (structtype == st_C_struct)
2422 if (structtype == st_C_struct
2423 || structtype == st_C_union
2424 || structtype == st_C_class)
2426 structtag = savenstr (str, len);
2428 structtag = "<enum>";
2429 structdef = stagseen;
2433 /* Avoid entering fvdef stuff if typdef is going on. */
2434 if (typdef != tnone)
2440 /* Detect GNU macros.
2442 DEFUN note for writers of emacs C code:
2443 The DEFUN macro, used in emacs C source code, has a first arg
2444 that is a string (the lisp function name), and a second arg that
2445 is a C function name. Since etags skips strings, the second arg
2446 is tagged. This is unfortunate, as it would be better to tag the
2447 first arg. The simplest way to deal with this problem would be
2448 to name the tag with a name built from the function name, by
2449 removing the initial 'F' character and substituting '-' for '_'.
2450 Anyway, this assumes that the conventions of naming lisp
2451 functions will never change. Currently, this method is not
2452 implemented, so writers of emacs code are recommended to put the
2453 first two args of a DEFUN on the same line. */
2454 if (definedef == dnone && toktype == st_C_gnumacro)
2456 next_token_is_func = TRUE;
2459 if (next_token_is_func)
2461 next_token_is_func = FALSE;
2463 *is_func_or_var = TRUE;
2467 /* Detect Objective C constructs. */
2475 set_construct(C_OBJC);
2481 set_construct(C_OBJC);
2483 objdef = oimplementation;
2487 case oimplementation:
2488 /* Save the class tag for functions or variables defined inside. */
2489 objtag = savenstr (str, len);
2493 /* Save the class tag for categories. */
2494 objtag = savenstr (str, len);
2496 *is_func_or_var = TRUE;
2500 *is_func_or_var = TRUE;
2507 objdef = omethodtag;
2509 grow_linebuffer (&token_name, methodlen + 1);
2510 strncpy (token_name.buffer, str, len);
2511 token_name.buffer[methodlen] = '\0';
2512 token_name.len = methodlen;
2518 objdef = omethodparm;
2523 objdef = omethodtag;
2525 grow_linebuffer (&token_name, methodlen + 1);
2526 strncat (token_name.buffer, str, len);
2527 token_name.len = methodlen;
2532 if (toktype == st_C_objend)
2534 /* Memory leakage here: the string pointed by objtag is
2535 never released, because many tests would be needed to
2536 avoid breaking on incorrect input code. The amount of
2537 memory leaked here is the sum of the lengths of the
2545 /* A function, variable or enum constant? */
2549 set_construct(C_CONSTANT);
2555 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2556 fvdef = fvnone; /* should be useless */
2562 if (constantypedefs && structdef == sinbody && structtype == st_C_enum)
2565 oo_browser_construct = C_ENUM_LABEL;
2571 if (fvdef == fvnone)
2573 fvdef = fvnameseen; /* function or variable */
2574 *is_func_or_var = TRUE;
2584 * This routine finds functions, variables, typedefs,
2585 * #define's, enum constants and struct/union/enum definitions in
2586 * #C syntax and adds them to the list.
2588 #define current_lb_is_new (newndx == curndx)
2589 #define switch_line_buffers() (curndx = 1 - curndx)
2591 #define curlb (lbs[curndx].lb)
2592 #define othlb (lbs[1-curndx].lb)
2593 #define newlb (lbs[newndx].lb)
2594 #define curlinepos (lbs[curndx].linepos)
2595 #define othlinepos (lbs[1-curndx].linepos)
2596 #define newlinepos (lbs[newndx].linepos)
2598 #define CNL_SAVE_DEFINEDEF() \
2600 curlinepos = charno; \
2602 linecharno = charno; \
2603 charno += readline (&curlb, inf); \
2604 lp = curlb.buffer; \
2611 CNL_SAVE_DEFINEDEF(); \
2612 if (savetok.valid) \
2615 savetok.valid = FALSE; \
2617 definedef = dnone; \
2621 void make_C_tag PP ((bool isfun));
2626 /* This function should never be called when tok.valid is FALSE, but
2627 we must protect against invalid input or internal errors. */
2630 if (traditional_tag_style)
2632 /* This was the original code. Now we call new_pfnote instead,
2633 which uses the new method for naming tags (see new_pfnote). */
2636 if (CTAGS || tok.named)
2637 name = savestr (token_name.buffer);
2638 pfnote (name, isfun,
2639 tok.buffer, tok.linelen, tok.lineno, tok.linepos);
2642 new_pfnote (token_name.buffer, token_name.len, isfun,
2643 tok.buffer, tok.linelen, tok.lineno, tok.linepos);
2652 C_entries (c_ext, inf)
2653 int c_ext; /* extension of C */
2654 FILE *inf; /* input file */
2656 register char c; /* latest char read; '\0' for end of line */
2657 register char *lp; /* pointer one beyond the character `c' */
2658 int curndx, newndx; /* indices for current and new lb */
2659 register int tokoff; /* offset in line of start of current token */
2660 register int toklen; /* length of current token */
2661 char *qualifier; /* string used to qualify names */
2662 int qlen; /* length of qualifier */
2663 int cblev; /* current curly brace level */
2664 int parlev; /* current parenthesis level */
2665 bool incomm, inquote, inchar, quotednl, midtoken;
2667 token savetok; /* token saved during preprocessor handling */
2670 tokoff = toklen = 0; /* keep compiler quiet */
2671 curndx = newndx = 0;
2677 fvdef = fvnone; typdef = tnone; structdef = snone;
2678 definedef = dnone; objdef = onone;
2679 next_token_is_func = yacc_rules = FALSE;
2680 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2681 tok.valid = savetok.valid = FALSE;
2684 cplpl = (c_ext & C_PLPL) == C_PLPL;
2685 cjava = (c_ext & C_JAVA) == C_JAVA;
2687 { qualifier = "."; qlen = 1; }
2689 { qualifier = "::"; qlen = 2; }
2696 /* If we're at the end of the line, the next character is a
2697 '\0'; don't skip it, because it's the thing that tells us
2698 to read the next line. */
2719 /* Newlines inside comments do not end macro definitions in
2721 CNL_SAVE_DEFINEDEF ();
2734 /* Newlines inside strings do not end macro definitions
2735 in traditional cpp, even though compilers don't
2736 usually accept them. */
2737 CNL_SAVE_DEFINEDEF ();
2747 /* Hmmm, something went wrong. */
2761 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2766 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2776 else if (/* cplpl && */ *lp == '/')
2784 if ((c_ext & YACC) && *lp == '%')
2786 /* entering or exiting rules section in yacc file */
2788 definedef = dnone; fvdef = fvnone;
2789 typdef = tnone; structdef = snone;
2790 next_token_is_func = FALSE;
2791 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2793 yacc_rules = !yacc_rules;
2799 if (definedef == dnone)
2802 bool cpptoken = TRUE;
2804 /* Look back on this line. If all blanks, or nonblanks
2805 followed by an end of comment, this is a preprocessor
2807 for (cp = newlb.buffer; cp < lp-1; cp++)
2810 if (*cp == '*' && *(cp+1) == '/')
2819 definedef = dsharpseen;
2820 } /* if (definedef == dnone) */
2826 /* Consider token only if some complicated conditions are satisfied. */
2827 if ((definedef != dnone
2828 || (cblev == 0 && structdef != scolonseen)
2829 || (cblev == 1 && cplpl && structdef == sinbody)
2830 || (structdef == sinbody && structtype == st_C_enum))
2831 && typdef != tignore
2832 && definedef != dignorerest
2833 && fvdef != finlist)
2839 if (c == ':' && cplpl && *lp == ':' && begtoken(*(lp + 1)))
2842 * This handles :: in the middle, but not at the
2843 * beginning of an identifier.
2848 set_construct(C_METHOD);
2853 bool funorvar = FALSE;
2856 || consider_token (newlb.buffer + tokoff, toklen, c,
2857 c_ext, cblev, parlev, &funorvar))
2860 if (structdef == sinbody
2861 && definedef == dnone
2863 /* function or var defined in C++ class body */
2865 int len = strlen (structtag) + qlen + toklen;
2866 grow_linebuffer (&token_name, len + 1);
2867 strcpy (token_name.buffer, structtag);
2868 strcat (token_name.buffer, qualifier);
2869 strncat (token_name.buffer,
2870 newlb.buffer + tokoff, toklen);
2871 token_name.len = len;
2874 oo_browser_construct = C_METHOD;
2877 else if (objdef == ocatseen)
2878 /* Objective C category */
2880 int len = strlen (objtag) + 2 + toklen;
2881 grow_linebuffer (&token_name, len + 1);
2882 strcpy (token_name.buffer, objtag);
2883 strcat (token_name.buffer, "(");
2884 strncat (token_name.buffer,
2885 newlb.buffer + tokoff, toklen);
2886 strcat (token_name.buffer, ")");
2887 token_name.len = len;
2890 oo_browser_construct = C_OBJC;
2893 else if (objdef == omethodtag
2894 || objdef == omethodparm)
2895 /* Objective C method */
2899 oo_browser_construct = C_OBJC;
2904 grow_linebuffer (&token_name, toklen + 1);
2905 strncpy (token_name.buffer,
2906 newlb.buffer + tokoff, toklen);
2907 token_name.buffer[toklen] = '\0';
2908 token_name.len = toklen;
2911 = (structdef == stagseen
2914 /* Also name #define constants,
2915 enumerations and enum_labels.
2916 Conditionalize `funorvar' reference
2917 here or #defines will appear without
2919 -- Bob Weiner, BeOpen.com, 4/25/1998 */
2920 || ((oo_browser_format || funorvar)
2921 && definedef == dignorerest)
2922 || (oo_browser_format
2923 && (oo_browser_construct == C_ENUMERATION
2924 || oo_browser_construct == C_ENUM_LABEL))
2927 && definedef == dignorerest)
2931 tok.lineno = lineno;
2932 tok.linelen = tokoff + toklen + 1;
2933 tok.buffer = newlb.buffer;
2934 tok.linepos = newlinepos;
2937 if (definedef == dnone
2938 && (fvdef == fvnameseen
2939 || structdef == stagseen
2941 || objdef != onone))
2943 if (current_lb_is_new)
2944 switch_line_buffers ();
2947 make_C_tag (funorvar);
2951 } /* if (endtoken (c)) */
2952 else if (intoken (c))
2957 } /* if (midtoken) */
2958 else if (begtoken (c))
2970 set_construct(C_MACRO);
2972 make_C_tag (TRUE); /* a function */
2979 if (structdef == stagseen && !cjava)
2985 if (!yacc_rules || lp == newlb.buffer + 1)
2987 tokoff = lp - 1 - newlb.buffer;
2992 } /* if (begtoken) */
2993 } /* if must look at token */
2996 /* Detect end of line, colon, comma, semicolon and various braces
2997 after having handled a token.*/
3001 if (definedef != dnone)
3007 make_C_tag (TRUE); /* an Objective C class */
3011 objdef = omethodcolon;
3013 grow_linebuffer (&token_name, methodlen + 1);
3014 strcat (token_name.buffer, ":");
3015 token_name.len = methodlen;
3018 if (structdef == stagseen)
3019 structdef = scolonseen;
3026 make_C_tag (FALSE); /* a yacc function */
3036 if (definedef != dnone)
3043 set_construct(C_TYPE);
3045 make_C_tag (FALSE); /* a typedef */
3055 if ((globals && cblev == 0) || (members && cblev == 1))
3057 make_C_tag (FALSE); /* a variable */
3059 /* if (constantypedefs && structdef == snone)*/
3065 set_construct(C_ENUMERATION);
3068 set_construct(C_CLASS);
3071 set_construct(C_VARIABLE);
3075 /* Force reset of st_C_enum structtype value. */
3076 structtype = st_none;
3082 /* The following instruction invalidates the token.
3083 Probably the token should be invalidated in all
3084 other cases where some state machine is reset. */
3087 if (structdef == stagseen)
3091 if (definedef != dnone)
3097 make_C_tag (TRUE); /* an Objective C method */
3108 if ((globals && cblev == 0) || (members && cblev == 1))
3109 make_C_tag (FALSE); /* a variable */
3114 if (structdef == stagseen)
3118 if (definedef != dnone)
3120 if (cblev == 0 && typdef == tend)
3123 set_construct(C_TYPE);
3126 make_C_tag (FALSE); /* a typedef */
3137 if ((globals && cblev == 0) || (members && cblev == 1))
3138 make_C_tag (FALSE); /* a variable */
3140 if (constantypedefs && structdef == snone)
3146 set_construct(C_ENUMERATION);
3149 set_construct(C_CLASS);
3152 set_construct(C_VARIABLE);
3156 /* Force reset of st_C_enum structtype value. */
3157 structtype = st_none;
3164 if (structdef == stagseen)
3168 if (definedef != dnone)
3170 if (objdef == otagseen && parlev == 0)
3171 objdef = oparenseen;
3179 if (tok.valid && *lp != '*')
3181 /* This handles constructs like:
3182 typedef void OperatorFun (int fun); */
3185 set_construct(C_TYPE);
3190 } /* switch (typdef) */
3202 if (definedef != dnone)
3204 if (objdef == ocatseen && parlev == 1)
3206 make_C_tag (TRUE); /* an Objective C category */
3218 if (cblev == 0 && typdef == tend)
3221 set_construct(C_TYPE);
3224 make_C_tag (FALSE); /* a typedef */
3227 else if (parlev < 0) /* can happen due to ill-conceived #if's. */
3231 if (definedef != dnone)
3233 if (typdef == ttypedseen)
3237 case skeyseen: /* unnamed struct */
3238 structdef = sinbody;
3239 structtag = "_anonymous_";
3242 case scolonseen: /* named struct */
3243 structdef = sinbody;
3244 make_C_tag (FALSE); /* a struct */
3251 set_construct(C_FUNCTION);
3252 /* Ensure function name is recorded.
3253 -- Bob Weiner, BeOpen.com */
3256 make_C_tag (TRUE); /* a function */
3265 make_C_tag (TRUE); /* an Objective C class */
3270 make_C_tag (TRUE); /* an Objective C method */
3274 /* Neutralize `extern "C" {' grot. */
3275 if (cblev == 0 && structdef == snone && typdef == tnone)
3282 if (definedef != dnone)
3284 if (fvdef == fstartlist)
3285 fvdef = fvnone; /* avoid tagging `foo' in `foo (*bar()) ()' */
3288 if (definedef != dnone)
3290 if (!noindentypedefs && lp == newlb.buffer + 1)
3292 cblev = 0; /* reset curly brace level if first column */
3293 parlev = 0; /* also reset paren level, just in case... */
3299 if (typdef == tinbody)
3301 /* Memory leakage here: the string pointed by structtag is
3302 never released, because I fear to miss something and
3303 break things while freeing the area. The amount of
3304 memory leaked here is the sum of the lengths of the
3306 if (structdef == sinbody)
3307 free (structtag); */
3310 structtag = "<error>";
3312 /* Next line added to avoid any state carryover between
3313 functions. -- Bob Weiner, BeOpen.com, 11/19/1997 */
3314 fvdef = fvnone; oo_browser_construct = C_NULL;
3319 if (definedef != dnone)
3332 if ((globals && cblev == 0) || (members && cblev == 1))
3334 make_C_tag (FALSE); /* a variable */
3341 set_construct(C_ENUMERATION);
3344 set_construct(C_CLASS);
3347 /* a global variable */
3348 set_construct(C_VARIABLE);
3352 /* ootags categorizes each tag found whereas etags doesn't.
3353 Set the is_method flag if this tag has been marked as
3354 such by an earlier section of code.
3355 -- Steve Baur, BeOpen.com, 5/7/1998 */
3356 is_method = (oo_browser_construct == C_METHOD);
3359 /* Force reset of st_C_enum structtype value. */
3360 structtype = st_none;
3366 fvdef = is_method ? fignore : vignore;
3377 if (objdef == oinbody && cblev == 0)
3379 objdef = omethodsign;
3383 case '#': case '~': case '&': case '%': case '/': case '|':
3384 case '^': case '!': case '<': case '>': case '.': case '?': case ']':
3385 if (definedef != dnone)
3391 /* The above characters cannot follow a function tag in C, so
3392 unmark this as a function entry. For C++, these characters
3393 may follow an `operator' function construct, so skip the
3394 unmarking conditional below.
3395 -- Steve Baur, BeOpen.com, 5/7/1998 */
3396 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
3403 if (objdef == otagseen)
3405 make_C_tag (TRUE); /* an Objective C class */
3408 /* If a macro spans multiple lines don't reset its state. */
3410 CNL_SAVE_DEFINEDEF ();
3416 } /* while not eof */
3420 * Process either a C++ file or a C file depending on the setting
3424 default_C_entries (inf)
3427 C_entries (cplusplus ? C_PLPL : 0, inf);
3430 /* Always do plain ANSI C. */
3432 plain_C_entries (inf)
3438 /* Always do C++. */
3440 Cplusplus_entries (inf)
3443 C_entries (C_PLPL, inf);
3446 /* Always do Java. */
3451 C_entries (C_JAVA, inf);
3459 C_entries (C_STAR, inf);
3462 /* Always do Yacc. */
3467 C_entries (YACC, inf);
3470 /* A useful macro. */
3471 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3472 for (lineno = charno = 0; /* loop initialization */ \
3473 !feof (file_pointer) /* loop test */ \
3474 && (lineno++, /* instructions at start of loop */ \
3475 linecharno = charno, \
3476 charno += readline (&line_buffer, file_pointer), \
3477 char_pointer = lb.buffer, \
3483 * Read a file, but do no processing. This is used to do regexp
3484 * matching on files that have no language defined.
3487 just_read_file (inf)
3490 register char *dummy;
3492 LOOP_ON_INPUT_LINES (inf, lb, dummy)
3496 /* Fortran parsing */
3498 bool tail PP ((char *cp));
3503 register int len = 0;
3505 while (*cp && lowcase(*cp) == lowcase(dbp[len]))
3507 if (*cp == '\0' && !intoken(dbp[len]))
3518 dbp = skip_spaces (dbp);
3522 dbp = skip_spaces (dbp);
3523 if (strneq (dbp, "(*)", 3))
3528 if (!isdigit (*dbp))
3530 --dbp; /* force failure */
3535 while (isdigit (*dbp));
3538 void getit PP ((FILE *inf));
3545 dbp = skip_spaces (dbp);
3549 linecharno = charno;
3550 charno += readline (&lb, inf);
3555 dbp = skip_spaces (dbp);
3561 for (cp = dbp + 1; *cp && intoken (*cp); cp++)
3563 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
3564 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3569 Fortran_functions (inf)
3572 LOOP_ON_INPUT_LINES (inf, lb, dbp)
3575 dbp++; /* Ratfor escape to fortran */
3576 dbp = skip_spaces (dbp);
3579 switch (lowcase (*dbp))
3582 if (tail ("integer"))
3590 if (tail ("logical"))
3594 if (tail ("complex") || tail ("character"))
3598 if (tail ("double"))
3600 dbp = skip_spaces (dbp);
3603 if (tail ("precision"))
3609 dbp = skip_spaces (dbp);
3612 switch (lowcase (*dbp))
3615 if (tail ("function"))
3619 if (tail ("subroutine"))
3627 if (tail ("program"))
3632 if (tail ("procedure"))
3640 * Bob Weiner, Motorola Inc., 4/3/94
3641 * Unix and microcontroller assembly tag handling
3642 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
3650 LOOP_ON_INPUT_LINES (inf, lb, cp)
3652 /* If first char is alphabetic or one of [_.$], test for colon
3653 following identifier. */
3654 if (isalpha (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3656 /* Read past label. */
3658 while (isalnum (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3660 if (*cp == ':' || isspace (*cp))
3662 /* Found end of label, so copy it and add it to the table. */
3663 pfnote ((CTAGS) ? savenstr(lb.buffer, cp-lb.buffer) : NULL, TRUE,
3664 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3671 * Perl support by Bart Robinson <lomew@cs.utah.edu>
3672 * enhanced by Michael Ernst <mernst@alum.mit.edu>
3673 * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/
3674 * Perl variable names: /^(my|local).../
3677 Perl_functions (inf)
3682 LOOP_ON_INPUT_LINES (inf, lb, cp)
3686 && *cp++ == 'b' && isspace (*cp++))
3688 cp = skip_spaces (cp);
3692 && !isspace (*cp) && *cp != '{' && *cp != '(')
3694 pfnote ((CTAGS) ? savenstr(lb.buffer, cp-lb.buffer) : NULL, TRUE,
3695 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3698 else if (globals /* only if tagging global vars is enabled */
3699 && ((cp = lb.buffer,
3708 && (*cp == '(' || isspace (*cp)))
3710 /* After "my" or "local", but before any following paren or space. */
3711 char *varname = NULL;
3713 cp = skip_spaces (cp);
3714 if (*cp == '$' || *cp == '@' || *cp == '%')
3716 char* varstart = ++cp;
3717 while (isalnum (*cp) || *cp == '_')
3719 varname = savenstr (varstart, cp-varstart);
3723 /* Should be examining a variable list at this point;
3724 could insist on seeing an open parenthesis. */
3725 while (*cp != '\0' && *cp != ';' && *cp != '=' && *cp != ')')
3729 /* Perhaps I should back cp up one character, so the TAGS table
3730 doesn't mention (and so depend upon) the following char. */
3731 pfnote ((CTAGS) ? savenstr (lb.buffer, cp-lb.buffer) : varname,
3732 FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3738 * Python support by Eric S. Raymond <esr@thyrsus.com>
3739 * Look for /^def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
3742 Python_functions (inf)
3747 LOOP_ON_INPUT_LINES (inf, lb, cp)
3751 && *cp++ == 'f' && isspace (*cp++))
3753 cp = skip_spaces (cp);
3754 while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':')
3756 pfnote ((char *) NULL, TRUE,
3757 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3765 && *cp++ == 's' && isspace (*cp++))
3767 cp = skip_spaces (cp);
3768 while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':')
3770 pfnote ((char *) NULL, TRUE,
3771 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3776 /* Idea by Corny de Souza
3777 * Cobol tag functions
3778 * We could look for anything that could be a paragraph name.
3779 * i.e. anything that starts in column 8 is one word and ends in a full stop.
3782 Cobol_paragraphs (inf)
3785 register char *bp, *ep;
3787 LOOP_ON_INPUT_LINES (inf, lb, bp)
3793 /* If eoln, compiler option or comment ignore whole line. */
3794 if (bp[-1] != ' ' || !isalnum (bp[0]))
3797 for (ep = bp; isalnum (*ep) || *ep == '-'; ep++)
3800 pfnote ((CTAGS) ? savenstr (bp, ep-bp) : NULL, TRUE,
3801 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
3805 /* Added by Mosur Mohan, 4/22/88 */
3806 /* Pascal parsing */
3809 * Locates tags for procedures & functions. Doesn't do any type- or
3810 * var-definitions. It does look for the keyword "extern" or
3811 * "forward" immediately following the procedure statement; if found,
3812 * the tag is skipped.
3815 Pascal_functions (inf)
3818 linebuffer tline; /* mostly copied from C_entries */
3820 int save_lineno, save_len;
3821 char c, *cp, *namebuf;
3823 bool /* each of these flags is TRUE iff: */
3824 incomment, /* point is inside a comment */
3825 inquote, /* point is inside '..' string */
3826 get_tagname, /* point is after PROCEDURE/FUNCTION
3827 keyword, so next item = potential tag */
3828 found_tag, /* point is after a potential tag */
3829 inparms, /* point is within parameter-list */
3830 verify_tag; /* point has passed the parm-list, so the
3831 next token will determine whether this
3832 is a FORWARD/EXTERN to be ignored, or
3833 whether it is a real tag */
3835 save_lcno = save_lineno = save_len = 0; /* keep compiler quiet */
3836 namebuf = NULL; /* keep compiler quiet */
3841 initbuffer (&tline);
3843 incomment = inquote = FALSE;
3844 found_tag = FALSE; /* have a proc name; check if extern */
3845 get_tagname = FALSE; /* have found "procedure" keyword */
3846 inparms = FALSE; /* found '(' after "proc" */
3847 verify_tag = FALSE; /* check if "extern" is ahead */
3850 while (!feof (inf)) /* long main loop to get next char */
3853 if (c == '\0') /* if end of line */
3856 linecharno = charno;
3857 charno += readline (&lb, inf);
3861 if (!((found_tag && verify_tag)
3863 c = *dbp++; /* only if don't need *dbp pointing
3864 to the beginning of the name of
3865 the procedure or function */
3869 if (c == '}') /* within { } comments */
3871 else if (c == '*' && *dbp == ')') /* within (* *) comments */
3888 inquote = TRUE; /* found first quote */
3890 case '{': /* found open { comment */
3894 if (*dbp == '*') /* found open (* comment */
3899 else if (found_tag) /* found '(' after tag, i.e., parm-list */
3902 case ')': /* end of parms list */
3907 if (found_tag && !inparms) /* end of proc or fn stmt */
3914 if (found_tag && verify_tag && (*dbp != ' '))
3916 /* check if this is an "extern" declaration */
3919 if (lowcase (*dbp == 'e'))
3921 if (tail ("extern")) /* superfluous, really! */
3927 else if (lowcase (*dbp) == 'f')
3929 if (tail ("forward")) /* check for forward reference */
3935 if (found_tag && verify_tag) /* not external proc, so make tag */
3939 pfnote (namebuf, TRUE,
3940 tline.buffer, save_len, save_lineno, save_lcno);
3944 if (get_tagname) /* grab name of proc or fn */
3949 /* save all values for later tagging */
3950 grow_linebuffer (&tline, lb.len + 1);
3951 strcpy (tline.buffer, lb.buffer);
3952 save_lineno = lineno;
3953 save_lcno = linecharno;
3955 /* grab block name */
3956 for (cp = dbp + 1; *cp != '\0' && !endtoken (*cp); cp++)
3958 namebuf = (CTAGS) ? savenstr (dbp, cp-dbp) : NULL;
3959 dbp = cp; /* set dbp to e-o-token */
3960 save_len = dbp - lb.buffer + 1;
3961 get_tagname = FALSE;
3965 /* and proceed to check for "extern" */
3967 else if (!incomment && !inquote && !found_tag)
3969 /* check for proc/fn keywords */
3970 switch (lowcase (c))
3973 if (tail ("rocedure")) /* c = 'p', dbp has advanced */
3977 if (tail ("unction"))
3982 } /* while not eof */
3984 free (tline.buffer);
3988 * lisp tag functions
3989 * look for (def or (DEF, quote or QUOTE
3991 int L_isdef PP ((char *strp));
3994 register char *strp;
3996 return ((strp[1] == 'd' || strp[1] == 'D')
3997 && (strp[2] == 'e' || strp[2] == 'E')
3998 && (strp[3] == 'f' || strp[3] == 'F'));
4000 int L_isquote PP ((char *strp));
4003 register char *strp;
4005 return ((*++strp == 'q' || *strp == 'Q')
4006 && (*++strp == 'u' || *strp == 'U')
4007 && (*++strp == 'o' || *strp == 'O')
4008 && (*++strp == 't' || *strp == 'T')
4009 && (*++strp == 'e' || *strp == 'E')
4010 && isspace (*++strp));
4013 void L_getit PP ((void));
4019 if (*dbp == '\'') /* Skip prefix quote */
4021 else if (*dbp == '(')
4023 if (L_isquote (dbp))
4024 dbp += 7; /* Skip "(quote " */
4026 dbp += 1; /* Skip "(" before name in (defstruct (foo)) */
4027 dbp = skip_spaces (dbp);
4030 for (cp = dbp /*+1*/;
4031 *cp != '\0' && *cp != '(' && *cp != ' ' && *cp != ')';
4037 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
4038 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4042 Lisp_functions (inf)
4045 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4051 dbp = skip_non_spaces (dbp);
4052 dbp = skip_spaces (dbp);
4057 /* Check for (foo::defmumble name-defined ... */
4060 while (*dbp != '\0' && !isspace (*dbp)
4061 && *dbp != ':' && *dbp != '(' && *dbp != ')');
4066 while (*dbp == ':');
4068 if (L_isdef (dbp - 1))
4070 dbp = skip_non_spaces (dbp);
4071 dbp = skip_spaces (dbp);
4081 * Postscript tag functions
4082 * Just look for lines where the first character is '/'
4083 * Richard Mlynarik <mly@adoc.xerox.com>
4086 Postscript_functions (inf)
4089 register char *bp, *ep;
4091 LOOP_ON_INPUT_LINES (inf, lb, bp)
4096 *ep != '\0' && *ep != ' ' && *ep != '{';
4099 pfnote ((CTAGS) ? savenstr (bp, ep-bp) : NULL, TRUE,
4100 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
4107 * Scheme tag functions
4108 * look for (def... xyzzy
4109 * look for (def... (xyzzy
4110 * look for (def ... ((...(xyzzy ....
4111 * look for (set! xyzzy
4114 void get_scheme PP ((void));
4117 Scheme_functions (inf)
4120 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4123 && (dbp[1] == 'D' || dbp[1] == 'd')
4124 && (dbp[2] == 'E' || dbp[2] == 'e')
4125 && (dbp[3] == 'F' || dbp[3] == 'f'))
4127 dbp = skip_non_spaces (dbp);
4128 /* Skip over open parens and white space */
4129 while (isspace (*dbp) || *dbp == '(')
4134 && (dbp[1] == 'S' || dbp[1] == 's')
4135 && (dbp[2] == 'E' || dbp[2] == 'e')
4136 && (dbp[3] == 'T' || dbp[3] == 't')
4137 && (dbp[4] == '!' || dbp[4] == '!')
4138 && (isspace (dbp[5])))
4140 dbp = skip_non_spaces (dbp);
4141 dbp = skip_spaces (dbp);
4154 /* Go till you get to white space or a syntactic break */
4156 *cp != '\0' && *cp != '(' && *cp != ')' && !isspace (*cp);
4159 pfnote ((CTAGS) ? savenstr (dbp, cp-dbp) : NULL, TRUE,
4160 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4163 /* Find tags in TeX and LaTeX input files. */
4165 /* TEX_toktab is a table of TeX control sequences that define tags.
4166 Each TEX_tabent records one such control sequence.
4167 CONVERT THIS TO USE THE Stab TYPE!! */
4174 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
4176 /* Default set of control sequences to put into TEX_toktab.
4177 The value of environment var TEXTAGS is prepended to this. */
4179 char *TEX_defenv = "\
4180 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4181 :part:appendix:entry:index";
4183 void TEX_mode PP ((FILE *inf));
4184 struct TEX_tabent *TEX_decode_env PP ((char *evarname, char *defenv));
4185 int TEX_Token PP ((char *cp));
4187 char TEX_esc = '\\';
4188 char TEX_opgrp = '{';
4189 char TEX_clgrp = '}';
4192 * TeX/LaTeX scanning loop.
4201 /* Select either \ or ! as escape character. */
4204 /* Initialize token table once from environment. */
4206 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
4208 LOOP_ON_INPUT_LINES (inf, lb, cp)
4211 /* Look at each esc in line. */
4212 while ((cp = etags_strchr (cp, TEX_esc)) != NULL)
4216 linecharno += cp - lasthit;
4218 i = TEX_Token (lasthit);
4221 /* We seem to include the TeX command in the tag name.
4223 for (p = lasthit + TEX_toktab[i].len;
4224 *p != '\0' && *p != TEX_clgrp;
4227 pfnote (/*savenstr (lasthit, p-lasthit)*/ (char *)NULL, TRUE,
4228 lb.buffer, lb.len, lineno, linecharno);
4229 break; /* We only tag a line once */
4235 #define TEX_LESC '\\'
4236 #define TEX_SESC '!'
4239 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4240 chars accordingly. */
4247 while ((c = getc (inf)) != EOF)
4249 /* Skip to next line if we hit the TeX comment char. */
4253 else if (c == TEX_LESC || c == TEX_SESC )
4272 /* Read environment and prepend it to the default string.
4273 Build token table. */
4275 TEX_decode_env (evarname, defenv)
4279 register char *env, *p;
4281 struct TEX_tabent *tab;
4284 /* Append default string to environment. */
4285 env = getenv (evarname);
4291 env = concat (oldenv, defenv, "");
4295 /* Allocate a token table */
4296 for (size = 1, p = env; p;)
4297 if ((p = etags_strchr (p, ':')) && *++p != '\0')
4299 /* Add 1 to leave room for null terminator. */
4300 tab = xnew (size + 1, struct TEX_tabent);
4302 /* Unpack environment string into token table. Be careful about */
4303 /* zero-length strings (leading ':', "::" and trailing ':') */
4306 p = etags_strchr (env, ':');
4307 if (!p) /* End of environment string. */
4308 p = env + strlen (env);
4310 { /* Only non-zero strings. */
4311 tab[i].name = savenstr (env, p - env);
4312 tab[i].len = strlen (tab[i].name);
4319 tab[i].name = NULL; /* Mark end of table. */
4327 /* If the text at CP matches one of the tag-defining TeX command names,
4328 return the pointer to the first occurrence of that command in TEX_toktab.
4329 Otherwise return -1.
4330 Keep the capital `T' in `token' for dumb truncating compilers
4331 (this distinguishes it from `TEX_toktab' */
4338 for (i = 0; TEX_toktab[i].len > 0; i++)
4339 if (strneq (TEX_toktab[i].name, cp, TEX_toktab[i].len))
4345 * Prolog support (rewritten) by Anders Lindgren, Mar. 96
4347 * Assumes that the predicate starts at column 0.
4348 * Only the first clause of a predicate is added.
4350 int prolog_pred PP ((char *s, char *last));
4351 void prolog_skip_comment PP ((linebuffer *plb, FILE *inf));
4352 int prolog_atom PP ((char *s, int pos));
4355 Prolog_functions (inf)
4366 LOOP_ON_INPUT_LINES (inf, lb, cp)
4368 if (cp[0] == '\0') /* Empty line */
4370 else if (isspace (cp[0])) /* Not a predicate */
4372 else if (cp[0] == '/' && cp[1] == '*') /* comment. */
4373 prolog_skip_comment (&lb, inf);
4374 else if ((len = prolog_pred (cp, last)) > 0)
4376 /* Predicate. Store the function name so that we only
4377 generate a tag for the first clause. */
4379 last = xnew(len + 1, char);
4380 else if (len + 1 > allocated)
4381 last = xrnew (last, len + 1, char);
4382 allocated = len + 1;
4383 strncpy (last, cp, len);
4391 prolog_skip_comment (plb, inf)
4399 for (cp = plb->buffer; *cp != '\0'; cp++)
4400 if (cp[0] == '*' && cp[1] == '/')
4403 linecharno += readline (plb, inf);
4409 * A predicate definition is added if it matches:
4410 * <beginning of line><Prolog Atom><whitespace>(
4412 * It is added to the tags database if it doesn't match the
4413 * name of the previous clause header.
4415 * Return the size of the name of the predicate, or 0 if no header
4419 prolog_pred (s, last)
4421 char *last; /* Name of last clause. */
4426 pos = prolog_atom (s, 0);
4431 pos = skip_spaces (s + pos) - s;
4433 if ((s[pos] == '(') || (s[pos] == '.'))
4438 /* Save only the first clause. */
4440 || len != strlen (last)
4441 || !strneq (s, last, len))
4443 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
4444 s, pos, lineno, linecharno);
4452 * Consume a Prolog atom.
4453 * Return the number of bytes consumed, or -1 if there was an error.
4455 * A prolog atom, in this context, could be one of:
4456 * - An alphanumeric sequence, starting with a lower case letter.
4457 * - A quoted arbitrary string. Single quotes can escape themselves.
4458 * Backslash quotes everything.
4461 prolog_atom (s, pos)
4469 if (islower(s[pos]) || (s[pos] == '_'))
4471 /* The atom is unquoted. */
4473 while (isalnum(s[pos]) || (s[pos] == '_'))
4477 return pos - origpos;
4479 else if (s[pos] == '\'')
4490 pos++; /* A double quote */
4492 else if (s[pos] == '\0')
4493 /* Multiline quoted atoms are ignored. */
4495 else if (s[pos] == '\\')
4497 if (s[pos+1] == '\0')
4504 return pos - origpos;
4511 * Support for Erlang -- Anders Lindgren, Feb 1996.
4513 * Generates tags for functions, defines, and records.
4515 * Assumes that Erlang functions start at column 0.
4517 int erlang_func PP ((char *s, char *last));
4518 void erlang_attribute PP ((char *s));
4519 int erlang_atom PP ((char *s, int pos));
4522 Erlang_functions (inf)
4533 LOOP_ON_INPUT_LINES (inf, lb, cp)
4535 if (cp[0] == '\0') /* Empty line */
4537 else if (isspace (cp[0])) /* Not function nor attribute */
4539 else if (cp[0] == '%') /* comment */
4541 else if (cp[0] == '"') /* Sometimes, strings start in column one */
4543 else if (cp[0] == '-') /* attribute, e.g. "-define" */
4545 erlang_attribute (cp);
4548 else if ((len = erlang_func (cp, last)) > 0)
4551 * Function. Store the function name so that we only
4552 * generates a tag for the first clause.
4555 last = xnew (len + 1, char);
4556 else if (len + 1 > allocated)
4557 last = xrnew (last, len + 1, char);
4558 allocated = len + 1;
4559 strncpy (last, cp, len);
4567 * A function definition is added if it matches:
4568 * <beginning of line><Erlang Atom><whitespace>(
4570 * It is added to the tags database if it doesn't match the
4571 * name of the previous clause header.
4573 * Return the size of the name of the function, or 0 if no function
4577 erlang_func (s, last)
4579 char *last; /* Name of last clause. */
4584 pos = erlang_atom (s, 0);
4589 pos = skip_spaces (s + pos) - s;
4591 /* Save only the first clause. */
4594 || len != strlen (last)
4595 || !strneq (s, last, len)))
4597 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
4598 s, pos, lineno, linecharno);
4607 * Handle attributes. Currently, tags are generated for defines
4610 * They are on the form:
4611 * -define(foo, bar).
4612 * -define(Foo(M, N), M+N).
4613 * -record(graph, {vtab = notable, cyclic = true}).
4616 erlang_attribute (s)
4622 if (strneq (s, "-define", 7) || strneq (s, "-record", 7))
4624 pos = skip_spaces (s + 7) - s;
4625 if (s[pos++] == '(')
4627 pos = skip_spaces (s + pos) - s;
4628 len = erlang_atom (s, pos);
4630 pfnote ((CTAGS) ? savenstr (& s[pos], len) : NULL, TRUE,
4631 s, pos + len, lineno, linecharno);
4639 * Consume an Erlang atom (or variable).
4640 * Return the number of bytes consumed, or -1 if there was an error.
4643 erlang_atom (s, pos)
4651 if (isalpha (s[pos]) || s[pos] == '_')
4653 /* The atom is unquoted. */
4655 while (isalnum (s[pos]) || s[pos] == '_')
4657 return pos - origpos;
4659 else if (s[pos] == '\'')
4670 else if (s[pos] == '\0')
4671 /* Multiline quoted atoms are ignored. */
4673 else if (s[pos] == '\\')
4675 if (s[pos+1] == '\0')
4682 return pos - origpos;
4688 #ifdef ETAGS_REGEXPS
4690 /* Take a string like "/blah/" and turn it into "blah", making sure
4691 that the first and last characters are the same, and handling
4692 quoted separator characters. Actually, stops on the occurrence of
4693 an unquoted separator. Also turns "\t" into a Tab character.
4694 Returns pointer to terminating separator. Works in place. Null
4695 terminates name string. */
4696 char * scan_separators PP ((char *name));
4698 scan_separators (name)
4702 char *copyto = name;
4703 bool quoted = FALSE;
4705 for (++name; *name != '\0'; ++name)
4711 else if (*name == sep)
4715 /* Something else is quoted, so preserve the quote. */
4721 else if (*name == '\\')
4723 else if (*name == sep)
4729 /* Terminate copied string. */
4734 /* Look at the argument of --regex or --no-regex and do the right
4735 thing. Same for each line of a regexp file. */
4737 analyse_regex (regex_arg)
4740 if (regex_arg == NULL)
4741 free_patterns (); /* --no-regex: remove existing regexps */
4743 /* A real --regexp option or a line in a regexp file. */
4744 switch (regex_arg[0])
4746 /* Comments in regexp file or null arg to --regex. */
4752 /* Read a regex file. This is recursive and may result in a
4753 loop, which will stop when the file descriptors are exhausted. */
4757 linebuffer regexbuf;
4758 char *regexfile = regex_arg + 1;
4760 /* regexfile is a file containing regexps, one per line. */
4761 regexfp = fopen (regexfile, "r");
4762 if (regexfp == NULL)
4767 initbuffer (®exbuf);
4768 while (readline_internal (®exbuf, regexfp) > 0)
4769 analyse_regex (regexbuf.buffer);
4770 free (regexbuf.buffer);
4775 /* Regexp to be used for a specific language only. */
4779 char *lang_name = regex_arg + 1;
4782 for (cp = lang_name; *cp != '}'; cp++)
4785 error ("unterminated language name in regex: %s", regex_arg);
4789 lang = get_language_from_name (lang_name);
4792 add_regex (cp + 1, lang);
4796 /* Regexp to be used for any language. */
4798 add_regex (regex_arg, NULL);
4803 /* Turn a name, which is an ed-style (but Emacs syntax) regular
4804 expression, into a real regular expression by compiling it. */
4806 add_regex (regexp_pattern, lang)
4807 char *regexp_pattern;
4812 struct re_pattern_buffer *patbuf;
4816 if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0])
4818 error ("%s: unterminated regexp", regexp_pattern);
4821 name = scan_separators (regexp_pattern);
4822 if (regexp_pattern[0] == '\0')
4824 error ("null regexp", (char *)NULL);
4827 (void) scan_separators (name);
4829 patbuf = xnew (1, struct re_pattern_buffer);
4830 patbuf->translate = NULL;
4831 patbuf->fastmap = NULL;
4832 patbuf->buffer = NULL;
4833 patbuf->allocated = 0;
4835 err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf);
4838 error ("%s while compiling pattern", err);
4843 p_head = xnew (1, pattern);
4844 p_head->regex = savestr (regexp_pattern);
4845 p_head->p_next = pp;
4846 p_head->language = lang;
4847 p_head->pattern = patbuf;
4848 p_head->name_pattern = savestr (name);
4849 p_head->error_signaled = FALSE;
4853 * Do the substitutions indicated by the regular expression and
4856 char * substitute PP ((char *in, char *out, struct re_registers *regs));
4858 substitute (in, out, regs)
4860 struct re_registers *regs;
4863 int size, dig, diglen;
4866 size = strlen (out);
4868 /* Pass 1: figure out how much to allocate by finding all \N strings. */
4869 if (out[size - 1] == '\\')
4870 fatal ("pattern error in \"%s\"", out);
4871 for (t = etags_strchr (out, '\\');
4873 t = etags_strchr (t + 2, '\\'))
4877 diglen = regs->end[dig] - regs->start[dig];
4883 /* Allocate space and do the substitutions. */
4884 result = xnew (size + 1, char);
4886 for (t = result; *out != '\0'; out++)
4887 if (*out == '\\' && isdigit (*++out))
4889 /* Using "dig2" satisfies my debugger. Bleah. */
4891 diglen = regs->end[dig] - regs->start[dig];
4892 strncpy (t, in + regs->start[dig], diglen);
4899 if (DEBUG && (t > result + size || t - result != strlen (result)))
4905 /* Deallocate all patterns. */
4910 while (p_head != NULL)
4912 pp = p_head->p_next;
4913 free (p_head->regex);
4914 free (p_head->name_pattern);
4921 #endif /* ETAGS_REGEXPS */
4922 /* Initialize a linebuffer for use */
4928 lbp->buffer = xnew (200, char);
4932 * Read a line of text from `stream' into `lbp', excluding the
4933 * newline or CR-NL, if any. Return the number of characters read from
4934 * `stream', which is the length of the line including the newline.
4936 * On DOS or Windows we do not count the CR character, if any, before the
4937 * NL, in the returned length; this mirrors the behavior of emacs on those
4938 * platforms (for text files, it translates CR-NL to NL as it reads in the
4942 readline_internal (lbp, stream)
4944 register FILE *stream;
4946 char *buffer = lbp->buffer;
4947 register char *p = lbp->buffer;
4948 register char *pend;
4951 pend = p + lbp->size; /* Separate to avoid 386/IX compiler bug. */
4955 register int c = getc (stream);
4958 /* We're at the end of linebuffer: expand it. */
4960 buffer = xrnew (buffer, lbp->size, char);
4961 p += buffer - lbp->buffer;
4962 pend = buffer + lbp->size;
4963 lbp->buffer = buffer;
4973 if (p > buffer && p[-1] == '\r')
4977 /* Assume CRLF->LF translation will be performed by Emacs
4978 when loading this file, so CRs won't appear in the buffer.
4979 It would be cleaner to compensate within Emacs;
4980 however, Emacs does not know how many CRs were deleted
4981 before any given point in the file. */
4996 lbp->len = p - buffer;
4998 return lbp->len + chars_deleted;
5002 * Like readline_internal, above, but in addition try to match the
5003 * input line against relevant regular expressions.
5006 readline (lbp, stream)
5010 /* Read new line. */
5011 long result = readline_internal (lbp, stream);
5012 #ifdef ETAGS_REGEXPS
5016 /* Match against relevant patterns. */
5018 for (pp = p_head; pp != NULL; pp = pp->p_next)
5020 /* Only use generic regexps or those for the current language. */
5021 if (pp->language != NULL && pp->language != curlang)
5024 match = re_match (pp->pattern, lbp->buffer, lbp->len, 0, &pp->regs);
5029 if (!pp->error_signaled)
5031 error ("error while matching \"%s\"", pp->regex);
5032 pp->error_signaled = TRUE;
5039 /* Match occurred. Construct a tag. */
5040 if (pp->name_pattern[0] != '\0')
5042 /* Make a named tag. */
5043 char *name = substitute (lbp->buffer,
5044 pp->name_pattern, &pp->regs);
5046 pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);
5050 /* Make an unnamed tag. */
5051 pfnote ((char *)NULL, TRUE,
5052 lbp->buffer, match, lineno, linecharno);
5057 #endif /* ETAGS_REGEXPS */
5063 * Return a pointer to a space of size strlen(cp)+1 allocated
5064 * with xnew where the string CP has been copied.
5070 return savenstr (cp, strlen (cp));
5074 * Return a pointer to a space of size LEN+1 allocated with xnew where
5075 * the string CP has been copied for at most the first LEN characters.
5084 dp = xnew (len + 1, char);
5085 strncpy (dp, cp, len);
5091 * Return the ptr in sp at which the character c last
5092 * appears; NULL if not found
5094 * Identical to System V strrchr, included for portability.
5097 etags_strrchr (sp, c)
5114 * Return the ptr in sp at which the character c first
5115 * appears; NULL if not found
5117 * Identical to System V strchr, included for portability.
5120 etags_strchr (sp, c)
5132 /* Skip spaces, return new pointer. */
5137 while (isspace (*cp)) /* isspace('\0')==FALSE */
5142 /* Skip non spaces, return new pointer. */
5144 skip_non_spaces (cp)
5147 while (!iswhite (*cp)) /* iswhite('\0')==TRUE */
5152 /* Print error message and exit. */
5170 suggest_asking_for_help ()
5172 fprintf (stderr, "\tTry `%s %s' for a complete list of options.\n",
5183 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
5186 const char *s1, *s2;
5188 fprintf (stderr, "%s: ", progname);
5189 fprintf (stderr, s1, s2);
5190 fprintf (stderr, "\n");
5193 /* Return a newly-allocated string whose contents
5194 concatenate those of s1, s2, s3. */
5199 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
5200 char *result = xnew (len1 + len2 + len3 + 1, char);
5202 strcpy (result, s1);
5203 strcpy (result + len1, s2);
5204 strcpy (result + len1 + len2, s3);
5205 result[len1 + len2 + len3] = '\0';
5210 /* Does the same work as the system V getcwd, but does not need to
5211 guess the buffer size in advance. */
5217 char *path = xnew (bufsize, char);
5219 while (getcwd (path, bufsize) == NULL)
5221 if (errno != ERANGE)
5225 path = xnew (bufsize, char);
5228 canonicalize_filename (path);
5231 #else /* not HAVE_GETCWD */
5233 char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */
5237 for (p = path; *p != '\0'; p++)
5243 return strdup (path);
5244 #else /* not MSDOS */
5249 pipe = (FILE *) popen ("pwd 2>/dev/null", "r");
5250 if (pipe == NULL || readline_internal (&path, pipe) == 0)
5255 #endif /* not MSDOS */
5256 #endif /* not HAVE_GETCWD */
5259 /* Return a newly allocated string containing the file name of FILE
5260 relative to the absolute directory DIR (which should end with a slash). */
5262 relative_filename (file, dir)
5265 char *fp, *dp, *afn, *res;
5268 /* Find the common root of file and dir (with a trailing slash). */
5269 afn = absolute_filename (file, cwd);
5272 while (*fp++ == *dp++)
5274 fp--, dp--; /* back to the first differing char */
5275 do /* look at the equal chars until '/' */
5279 /* Build a sequence of "../" strings for the resulting relative file name. */
5281 while ((dp = etags_strchr (dp + 1, '/')) != NULL)
5283 res = xnew (3*i + strlen (fp + 1) + 1, char);
5286 strcat (res, "../");
5288 /* Add the file name relative to the common root of file and dir. */
5289 strcat (res, fp + 1);
5295 /* Return a newly allocated string containing the absolute file name
5296 of FILE given DIR (which should end with a slash). */
5298 absolute_filename (file, dir)
5301 char *slashp, *cp, *res;
5303 if (filename_is_absolute (file))
5304 res = savestr (file);
5306 /* We don't support non-absolute file names with a drive
5307 letter, like `d:NAME' (it's too much hassle). */
5308 else if (file[1] == ':')
5309 fatal ("%s: relative file names with drive letters not supported", file);
5312 res = concat (dir, file, "");
5314 /* Delete the "/dirname/.." and "/." substrings. */
5315 slashp = etags_strchr (res, '/');
5316 while (slashp != NULL && slashp[0] != '\0')
5318 if (slashp[1] == '.')
5320 if (slashp[2] == '.'
5321 && (slashp[3] == '/' || slashp[3] == '\0'))
5326 while (cp >= res && !filename_is_absolute (cp));
5328 cp = slashp; /* the absolute name begins with "/.." */
5330 /* Under MSDOS and NT we get `d:/NAME' as absolute
5331 file name, so the luser could say `d:/../NAME'.
5332 We silently treat this as `d:/NAME'. */
5333 else if (cp[0] != '/')
5336 strcpy (cp, slashp + 3);
5340 else if (slashp[2] == '/' || slashp[2] == '\0')
5342 strcpy (slashp, slashp + 2);
5347 slashp = etags_strchr (slashp + 1, '/');
5351 return savestr ("/");
5356 /* Return a newly allocated string containing the absolute
5357 file name of dir where FILE resides given DIR (which should
5358 end with a slash). */
5360 absolute_dirname (file, dir)
5366 canonicalize_filename (file);
5367 slashp = etags_strrchr (file, '/');
5369 return savestr (dir);
5372 res = absolute_filename (file, dir);
5378 /* Whether the argument string is an absolute file name. The argument
5379 string must have been canonicalized with canonicalize_filename. */
5381 filename_is_absolute (fn)
5384 return (fn[0] == '/'
5386 || (isalpha(fn[0]) && fn[1] == ':' && fn[2] == '/')
5391 /* Translate backslashes into slashes. Works in place. */
5393 canonicalize_filename (fn)
5397 for (; *fn != '\0'; fn++)
5405 /* Increase the size of a linebuffer. */
5407 grow_linebuffer (lbp, toksize)
5411 while (lbp->size < toksize)
5413 lbp->buffer = xrnew (lbp->buffer, lbp->size, char);
5416 /* Like malloc but get fatal error if memory is exhausted. */
5421 long *result = (long *) malloc (size);
5423 fatal ("virtual memory exhausted", (char *)NULL);
5428 xrealloc (ptr, size)
5432 long *result = (long *) realloc (ptr, size);
5434 fatal ("virtual memory exhausted", (char *)NULL);