1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 87, 88, 89, 93, 94, 95
3 Free Software Foundation, Inc. and Ken Arnold
5 This file is not considered part of SXEmacs.
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 * Ctags originally by Ken Arnold.
23 * Fortran added by Jim Kleckner.
24 * Ed Pelegri-Llopart added C typedefs.
25 * Gnu Emacs TAGS format and modifications by RMS?
26 * Sam Kendall added C++.
27 * Francesco Potorti` reorganised C and C++ based on work by Joe Wells.
28 * Regexp tags by Tom Tromey.
30 * Francesco Potorti` (F.Potorti@cnuce.cnr.it) is the current maintainer.
33 char pot_etags_version[] = "@(#) pot revision number is 12.28";
35 /* Prototyping magic snarfed from gmalloc.c */
36 #if defined (__cplusplus) || defined (__STDC__)
40 #define __ptr_t void *
41 #else /* Not C++ or ANSI C. */
47 #define __ptr_t char *
48 #endif /* C++ or ANSI C. */
52 /* On some systems, Emacs defines static as nothing for the sake
53 of unexec. We don't want that here since we don't use unexec. */
55 # define ETAGS_REGEXPS /* use the regexp features */
56 #endif /* HAVE_CONFIG_H */
65 #if defined (STDC_HEADERS)
74 extern char *getcwd();
76 #endif /* HAVE_UNISTD_H */
81 #include <sys/types.h>
84 #if !defined (S_ISREG) && defined (S_IFREG)
85 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
94 # define getopt_long(argc,argv,optstr,lopts,lind) getopt (argc, argv, optstr)
96 extern int optind, opterr;
98 # error "ootags cannot be built without getopt, preferably getopt_long"
99 #endif /* LONG_OPTIONS */
103 #endif /* ETAGS_REGEXPS */
105 /* Define CTAGS to make the program "ctags" compatible with the usual one.
106 Leave it undefined to make the program "etags", which makes emacs-style
107 tag tables and tags typedefs, #defines and struct/union/enum by default. */
115 /* Exit codes for success and failure. */
125 #define C_PLPL 0x00001 /* C++ */
126 #define C_STAR 0x00003 /* C* */
127 #define C_JAVA 0x00005 /* JAVA */
128 #define YACC 0x10000 /* yacc file */
130 #define streq(s,t) ((DEBUG && (s) == NULL && (t) == NULL \
131 && (abort (), 1)) || !strcmp (s, t))
132 #define strneq(s,t,n) ((DEBUG && (s) == NULL && (t) == NULL \
133 && (abort (), 1)) || !strncmp (s, t, n))
135 #define lowcase(c) tolower ((char)c)
137 #define CHARS 256 /* 2^sizeof(char) */
138 #define CHAR(x) ((unsigned int)x & (CHARS - 1))
139 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */
140 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
141 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
142 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
143 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
146 /*#undef OO_BROWSER*/
147 /* Due to the way this file is constructed, this unfortunately doesn't */
148 /* work except for documentation purposes. -slb */
153 #define set_construct(construct) \
154 if (!oo_browser_construct) oo_browser_construct = construct
155 void oo_browser_clear_all_globals(void);
156 void oo_browser_clear_some_globals(void);
157 void oo_browser_check_and_clear_structtype(void);
161 * xnew, xrnew -- allocate, reallocate storage
163 * SYNOPSIS: Type *xnew (int n, Type);
164 * Type *xrnew (OldPointer, int n, Type);
167 # include "chkmalloc.h"
168 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
169 (n) * sizeof (Type)))
170 # define xrnew(op,n,Type) ((Type *) trace_realloc (__FILE__, __LINE__, \
171 (op), (n) * sizeof (Type)))
173 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
174 # define xrnew(op,n,Type) ((Type *) xrealloc ((op), (n) * sizeof (Type)))
179 typedef void Lang_function(FILE *);
183 Lang_function *function;
188 typedef struct node_st { /* sorting structure */
189 char *name; /* function or type name */
191 short int construct; /* Construct type for the OO-Browser */
193 char *file; /* file name */
194 bool is_func; /* use pattern or line no */
195 bool been_warned; /* set if noticed dup */
196 int lno; /* line number tag is on */
197 long cno; /* character number line starts on */
198 char *pat; /* search pattern */
199 struct node_st *left, *right; /* left and right sons */
203 /* If you add to this array, you must add a corresponding entry to the
205 static char *oo_browser_default_classes[] =
206 /* Lack of square brackets around some of these entries are intentional. */
207 { "null", "class", "method", "[constant]", "[enumeration]", "[enum_label]",
208 "extern", "[function]", "[macro]", "objc", "[structure]", "[type]",
209 "[union]", "[variable]"
212 /* If you add to this enum, you must add a corresponding entry to the
214 enum oo_browser_constructs { C_NULL, C_CLASS, C_METHOD, C_CONSTANT,
216 C_ENUM_LABEL, C_EXTERN, C_FUNCTION, C_MACRO,
217 C_OBJC, C_STRUCTURE, C_TYPE, C_UNION, C_VARIABLE
220 enum oo_browser_constructs oo_browser_construct = C_NULL;
224 * A `linebuffer' is a structure which holds a line of text.
225 * `readline_internal' reads a line from a stream into a linebuffer
226 * and works regardless of the length of the line.
227 * SIZE is the size of BUFFER, LEN is the length of the string in
228 * BUFFER after readline reads it.
236 extern char *getenv PP((const char *envvar));
238 /* Many compilers barf on this:
239 Lang_function Asm_labels;
240 so let's write it this way */
241 void Asm_labels PP((FILE * inf));
242 void C_entries PP((int c_ext, FILE * inf));
243 void default_C_entries PP((FILE * inf));
244 void plain_C_entries PP((FILE * inf));
245 void Cjava_entries PP((FILE * inf));
246 void Cplusplus_entries PP((FILE * inf));
247 void Yacc_entries PP((FILE * inf));
248 void Cobol_paragraphs PP((FILE * inf));
249 void Cstar_entries PP((FILE * inf));
250 void Erlang_functions PP((FILE * inf));
251 void Fortran_functions PP((FILE * inf));
252 void Lisp_functions PP((FILE * inf));
253 void Pascal_functions PP((FILE * inf));
254 void Perl_functions PP((FILE * inf));
255 void Postscript_functions PP((FILE * inf));
256 void Prolog_functions PP((FILE * inf));
257 void Python_functions PP((FILE * inf));
258 void Scheme_functions PP((FILE * inf));
259 void TeX_functions PP((FILE * inf));
260 void just_read_file PP((FILE * inf));
262 void print_language_names PP((void));
263 void print_version PP((void));
264 void print_help PP((void));
266 language *get_language_from_name PP((char *name));
267 language *get_language_from_interpreter PP((char *interpreter));
268 language *get_language_from_suffix PP((char *suffix));
269 int total_size_of_entries PP((node * np));
270 long readline PP((linebuffer * lbp, FILE * stream));
271 long readline_internal PP((linebuffer * lbp, FILE * stream));
273 void analyse_regex PP((char *regex_arg));
274 void add_regex PP((char *regexp_pattern, language * lang));
275 void free_patterns PP((void));
276 #endif /* ETAGS_REGEXPS */
277 void error PP((const char *s1, const char *s2));
278 void suggest_asking_for_help PP((void));
279 void fatal PP((char *s1, char *s2));
280 void pfatal PP((char *s1));
281 void add_node PP((node * np, node ** cur_node_p));
283 void init PP((void));
284 void initbuffer PP((linebuffer * lbp));
285 void find_entries PP((char *file, FILE * inf));
286 void free_tree PP((node * np));
288 PP((char *name, bool is_func, char *linestart, int linelen, int lno, long cno));
290 PP((char *name, int namelen, bool is_func, char *linestart, int linelen,
292 void process_file PP((char *file));
293 void put_entries PP((node * np));
294 void takeprec PP((void));
296 char *concat PP((char *s1, char *s2, char *s3));
297 char *skip_spaces PP((char *cp));
298 char *skip_non_spaces PP((char *cp));
299 char *savenstr PP((char *cp, int len));
300 char *savestr PP((char *cp));
301 char *etags_strchr PP((char *sp, int c));
302 char *etags_strrchr PP((char *sp, int c));
303 char *etags_getcwd PP((void));
304 char *relative_filename PP((char *file, char *dir));
305 char *absolute_filename PP((char *file, char *dir));
306 char *absolute_dirname PP((char *file, char *dir));
307 bool filename_is_absolute PP((char *fn));
308 void canonicalize_filename PP((char *fn));
309 void grow_linebuffer PP((linebuffer * lbp, int toksize));
310 long *xmalloc PP((unsigned int size));
311 long *xrealloc PP((char *ptr, unsigned int size));
313 char searchar = '/'; /* use /.../ searches */
315 char *tagfile; /* output file */
316 char *progname; /* name this program was invoked with */
317 char *cwd; /* current working directory */
318 char *tagfiledir; /* directory of tagfile */
319 FILE *tagf; /* ioptr for tags file */
321 char *curfile; /* current input file name */
322 language *curlang; /* current language */
324 int lineno; /* line number of current line */
325 long charno; /* current character number */
326 long linecharno; /* charno of start of current line */
327 char *dbp; /* pointer to start of current tag */
328 node *head; /* the head of the binary tree of tags */
330 linebuffer lb; /* the current line */
331 linebuffer token_name; /* used by C_entries as a temporary area */
334 linebuffer lb; /* used by C_entries instead of lb */
337 /* boolean "functions" (see init) */
338 bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
341 *white = " \f\t\n\r",
343 *nonam = " \f\t\n\r(=,[;",
344 /* token ending chars */
345 *endtk = " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
346 /* token starting chars */
347 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
348 /* valid in-token chars */
349 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
351 bool append_to_tagfile; /* -a: append to tags */
352 /* The following four default to TRUE for etags, but to FALSE for ctags. */
353 bool typedefs; /* -t: create tags for C typedefs */
354 bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */
355 /* 0 struct/enum/union decls, and C++ */
356 /* member functions. */
357 bool constantypedefs; /* -d: create tags for C #define, enum */
358 /* constants and variables. */
359 /* -D: opposite of -d. Default under ctags. */
360 bool globals; /* create tags for global variables */
361 bool members; /* create tags for C member variables */
362 bool update; /* -u: update tags */
363 bool vgrind_style; /* -v: create vgrind style index output */
364 bool no_warnings; /* -w: suppress warnings */
365 bool cxref_style; /* -x: create cxref style output */
366 bool cplusplus; /* .[hc] means C++, not C */
367 bool noindentypedefs; /* -I: ignore indentation in C */
369 bool oo_browser_format; /* -O: OO-Browser tags format */
373 struct option longopts[] = {
374 {"append", no_argument, NULL, 'a'},
375 {"backward-search", no_argument, NULL, 'B'},
376 {"c++", no_argument, NULL, 'C'},
377 {"cxref", no_argument, NULL, 'x'},
378 {"defines", no_argument, NULL, 'd'},
379 {"no-defines", no_argument, NULL, 'D'},
380 {"globals", no_argument, &globals, TRUE},
381 {"no-globals", no_argument, &globals, FALSE},
382 {"help", no_argument, NULL, 'h'},
383 {"help", no_argument, NULL, 'H'},
384 {"ignore-indentation", no_argument, NULL, 'I'},
385 {"include", required_argument, NULL, 'i'},
386 {"language", required_argument, NULL, 'l'},
387 {"members", no_argument, &members, TRUE},
388 {"no-members", no_argument, &members, FALSE},
389 {"no-warn", no_argument, NULL, 'w'},
390 {"output", required_argument, NULL, 'o'},
392 {"oo-browser", no_argument, NULL, 'O'},
395 {"regex", required_argument, NULL, 'r'},
396 {"no-regex", no_argument, NULL, 'R'},
397 #endif /* ETAGS_REGEXPS */
398 {"typedefs", no_argument, NULL, 't'},
399 {"typedefs-and-c++", no_argument, NULL, 'T'},
400 {"update", no_argument, NULL, 'u'},
401 {"version", no_argument, NULL, 'V'},
402 {"vgrind", no_argument, NULL, 'v'},
405 #endif /* LONG_OPTIONS */
408 /* Structure defining a regular expression. Elements are
409 the compiled pattern, and the name string. */
410 typedef struct pattern {
411 struct pattern *p_next;
414 struct re_pattern_buffer *pattern;
415 struct re_registers regs;
420 /* Array of all regexps. */
421 pattern *p_head = NULL;
422 #endif /* ETAGS_REGEXPS */
428 /* Non-NULL if language fixed. */
429 language *forced_lang = NULL;
432 char *Asm_suffixes[] = { "a", /* Unix assembler */
433 "asm", /* Microcontroller assembly */
434 "def", /* BSO/Tasking definition includes */
435 "inc", /* Microcontroller include files */
436 "ins", /* Microcontroller include files */
437 "s", "sa", /* Unix assembler */
438 "src", /* BSO/Tasking C compiler output */
442 /* Note that .c and .h can be considered C++, if the --c++ flag was
443 given. That is why default_C_entries is called here. */
444 char *default_C_suffixes[] = { "c", "h", NULL };
446 char *Cplusplus_suffixes[] =
447 { "C", "H", "c++", "cc", "cpp", "cxx", "h++", "hh", "hpp", "hxx",
448 "M", /* Objective C++ */
449 "pdb", /* Postscript with C syntax */
453 char *Cjava_suffixes[] = { "java", NULL };
455 char *Cobol_suffixes[] = { "COB", "cob", NULL };
457 char *Cstar_suffixes[] = { "cs", "hs", NULL };
459 char *Erlang_suffixes[] = { "erl", "hrl", NULL };
461 char *Fortran_suffixes[] = { "F", "f", "f90", "for", NULL };
463 char *Lisp_suffixes[] = { "cl", "clisp", "el", "l", "lisp", "lsp", "ml", NULL };
465 char *Pascal_suffixes[] = { "p", "pas", NULL };
467 char *Perl_suffixes[] = { "pl", "pm", NULL };
468 char *Perl_interpreters[] = { "perl", "@PERL@", NULL };
470 char *plain_C_suffixes[] = { "pc", /* Pro*C file */
471 "m", /* Objective C file */
472 "lm", /* Objective lex file */
476 char *Postscript_suffixes[] = { "ps", NULL };
478 char *Prolog_suffixes[] = { "prolog", NULL };
480 char *Python_suffixes[] = { "py", NULL };
482 /* Can't do the `SCM' or `scm' prefix with a version number. */
483 char *Scheme_suffixes[] =
484 { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "ss", "t", NULL };
486 char *TeX_suffixes[] =
487 { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL };
489 char *Yacc_suffixes[] = { "y", "ym", NULL }; /* .ym is Objective yacc file */
492 * Table of languages.
494 * It is ok for a given function to be listed under more than one
495 * name. I just didn't.
498 language lang_names[] = {
499 {"asm", Asm_labels, Asm_suffixes, NULL},
500 {"c", default_C_entries, default_C_suffixes, NULL},
501 {"c++", Cplusplus_entries, Cplusplus_suffixes, NULL},
502 {"c*", Cstar_entries, Cstar_suffixes, NULL},
503 {"cobol", Cobol_paragraphs, Cobol_suffixes, NULL},
504 {"erlang", Erlang_functions, Erlang_suffixes, NULL},
505 {"fortran", Fortran_functions, Fortran_suffixes, NULL},
506 {"java", Cjava_entries, Cjava_suffixes, NULL},
507 {"lisp", Lisp_functions, Lisp_suffixes, NULL},
508 {"pascal", Pascal_functions, Pascal_suffixes, NULL},
509 {"perl", Perl_functions, Perl_suffixes, Perl_interpreters},
510 {"postscript", Postscript_functions, Postscript_suffixes, NULL},
511 {"proc", plain_C_entries, plain_C_suffixes, NULL},
512 {"prolog", Prolog_functions, Prolog_suffixes, NULL},
513 {"python", Python_functions, Python_suffixes, NULL},
514 {"scheme", Scheme_functions, Scheme_suffixes, NULL},
515 {"tex", TeX_functions, TeX_suffixes, NULL},
516 {"yacc", Yacc_entries, Yacc_suffixes, NULL},
517 {"auto", NULL}, /* default guessing scheme */
518 {"none", just_read_file}, /* regexp matching only */
519 {NULL, NULL} /* end of list */
522 void print_language_names()
527 puts("\nThese are the currently supported languages, along with the\n\
528 default file name suffixes:");
529 for (lang = lang_names; lang->name != NULL; lang++) {
530 printf("\t%s\t", lang->name);
531 if (lang->suffixes != NULL)
532 for (ext = lang->suffixes; *ext != NULL; ext++)
533 printf(" .%s", *ext);
536 puts("Where `auto' means use default language for files based on file\n\
537 name suffix, and `none' means only do regexp processing on files.\n\
538 If no language is specified and no matching suffix is found,\n\
539 the first line of the file is read for a sharp-bang (#!) sequence\n\
540 followed by the name of an interpreter. If no such sequence is found,\n\
541 Fortran is tried first; if no tags are found, C is tried next.");
545 # define VERSION "20"
549 printf("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION);
550 puts("Copyright (C) 1996 Free Software Foundation, Inc. and Ken Arnold");
551 puts("This program is distributed under the same terms as Emacs");
558 printf("Usage: %s [options] [[regex-option ...] file-name] ...\n\
560 These are the options accepted by %s.\n", progname, progname);
562 puts("You may use unambiguous abbreviations for the long option names.");
564 puts("Long option names do not work with this executable, as it is not\n\
565 linked with GNU getopt.");
566 #endif /* LONG_OPTIONS */
567 puts("A - as file name means read names from stdin (one per line).");
570 (" Absolute names are stored in the output file as they are.\n\
571 Relative ones are stored relative to the output file's directory.");
574 puts("-a, --append\n\
575 Append tag entries to existing tags file.");
578 puts("-B, --backward-search\n\
579 Write the search commands for the tag entries using '?', the\n\
580 backward-search command instead of '/', the forward-search command.");
583 Treat files whose name suffix defaults to C language as C++ files.");
586 puts("-d, --defines\n\
587 Create tag entries for C #define constants and enum constants, too.");
589 puts("-D, --no-defines\n\
590 Don't create tag entries for C #define constants and enum constants.\n\
591 This makes the tags file smaller.");
594 puts("-i FILE, --include=FILE\n\
595 Include a note in tag file indicating that, when searching for\n\
596 a tag, one should also consult the tags file FILE after\n\
597 checking the current file.");
598 puts("-l LANG, --language=LANG\n\
599 Force the following files to be considered as written in the\n\
600 named language up to the next --language=LANG option.");
605 Create tag entries for global variables in some languages.");
607 puts("--no-globals\n\
608 Do not create tag entries for global variables in some\n\
609 languages. This makes the tags file smaller.");
611 Create tag entries for member variables in C and derived languages.");
614 puts("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
615 Make a tag for each line matching pattern REGEXP in the\n\
616 following files. regexfile is a file containing one REGEXP\n\
617 per line. REGEXP is anchored (as if preceded by ^).\n\
618 The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
619 named tags can be created with:\n\
620 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
621 puts("-R, --no-regex\n\
622 Don't create tags from regexps for the following files.");
623 #endif /* ETAGS_REGEXPS */
624 puts("-o FILE, --output=FILE\n\
625 Write the tags to FILE.");
627 puts("-O, --oo-browser\n\
628 Generate a specialized tags format used only by the Altrasoft OO-Browser.");
630 puts("-I, --ignore-indentation\n\
631 Don't rely on indentation quite as much as normal. Currently,\n\
632 this means not to assume that a closing brace in the first\n\
633 column is the final brace of a function or structure\n\
634 definition in C and C++.");
637 puts("-t, --typedefs\n\
638 Generate tag entries for C typedefs.");
639 puts("-T, --typedefs-and-c++\n\
640 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
641 and C++ member functions.");
642 puts("-u, --update\n\
643 Update the tag entries for the given files, leaving tag\n\
644 entries for other files in place. Currently, this is\n\
645 implemented by deleting the existing entries for the given\n\
646 files and then rewriting the new entries at the end of the\n\
647 tags file. It is often faster to simply rebuild the entire\n\
648 tag file than to use this.");
649 puts("-v, --vgrind\n\
650 Generates an index of items intended for human consumption,\n\
651 similar to the output of vgrind. The index is sorted, and\n\
652 gives the page number of each item.");
653 puts("-w, --no-warn\n\
654 Suppress warning messages about entries defined in multiple\n\
657 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
658 The output uses line numbers instead of page numbers, but\n\
659 beyond that the differences are cosmetic; try both to see\n\
663 puts("-V, --version\n\
664 Print the version of the program.\n\
666 Print this help message.");
668 print_language_names();
671 puts("Report bugs to bug-gnu-emacs@prep.ai.mit.edu");
682 /* This structure helps us allow mixing of --lang and file names. */
684 enum argument_type arg_type;
689 #ifdef VMS /* VMS specific functions */
693 /* This is a BUG! ANY arbitrary limit is a BUG!
694 Won't someone please fix this? */
695 #define MAX_FILE_SPEC_LEN 255
698 char body[MAX_FILE_SPEC_LEN + 1];
702 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
703 returning in each successive call the next file name matching the input
704 spec. The function expects that each in_spec passed
705 to it will be processed to completion; in particular, up to and
706 including the call following that in which the last matching name
707 is returned, the function ignores the value of in_spec, and will
708 only start processing a new spec with the following call.
709 If an error occurs, on return out_spec contains the value
710 of in_spec when the error occurred.
712 With each successive file name returned in out_spec, the
713 function's return value is one. When there are no more matching
714 names the function returns zero. If on the first call no file
715 matches in_spec, or there is any other error, -1 is returned.
720 #define OUTSIZE MAX_FILE_SPEC_LEN
721 short fn_exp(out, in)
725 static long context = 0;
726 static struct dsc$descriptor_s o;
727 static struct dsc$descriptor_s i;
728 static bool pass1 = TRUE;
734 o.dsc$a_pointer = (char *)out;
735 o.dsc$w_length = (short)OUTSIZE;
736 i.dsc$a_pointer = in;
737 i.dsc$w_length = (short)strlen(in);
738 i.dsc$b_dtype = DSC$K_DTYPE_T;
739 i.dsc$b_class = DSC$K_CLASS_S;
740 o.dsc$b_dtype = DSC$K_DTYPE_VT;
741 o.dsc$b_class = DSC$K_CLASS_VS;
743 if ((status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL) {
744 out->body[out->curlen] = EOS;
746 } else if (status == RMS$_NMF)
749 strcpy(out->body, in);
752 lib$find_file_end(&context);
758 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
759 name of each file specified by the provided arg expanding wildcards.
761 char *gfnames(arg, p_error)
765 static vspec filename = { MAX_FILE_SPEC_LEN, "\0" };
767 switch (fn_exp(&filename, arg)) {
770 return filename.body;
776 return filename.body;
780 #ifndef OLD /* Newer versions of VMS do provide `system'. */
784 error("%s", "system() function not implemented under VMS");
788 #define VERSION_DELIM ';'
789 char *massage_name(s)
795 if (*s == VERSION_DELIM) {
804 int main(int argc, char *argv[])
807 unsigned int nincluded_files;
808 char **included_files;
811 int current_arg, file_count;
812 linebuffer filename_lb;
819 included_files = xnew(argc, char *);
823 /* Allocate enough no matter what happens. Overkill, but each one
825 argbuffer = xnew(argc, argument);
828 /* Set syntax for regular expression routines. */
829 re_set_syntax(RE_SYNTAX_EMACS | RE_INTERVALS);
830 #endif /* ETAGS_REGEXPS */
833 * If etags, always find typedefs and structure tags. Why not?
834 * Also default is to find macro constants, enum constants and
838 typedefs = typedefs_and_cplusplus = constantypedefs = TRUE;
849 optstring = "-aCdDf:Il:o:r:RStTi:BuvxwVhH";
851 optstring = "-aCdDf:Il:o:r:RStTi:BOuvxwVhH";
855 optstring = "-aCdDf:Il:o:StTi:BuvxwVhH";
857 optstring = "-aCdDf:Il:o:StTi:BOuvxwVhH";
859 #endif /* ETAGS_REGEXPS */
862 optstring = optstring + 1;
863 #endif /* LONG_OPTIONS */
865 opt = getopt_long(argc, argv, optstring, longopts, 0);
871 /* If getopt returns 0, then it has already processed a
872 long-named option. We should do nothing. */
876 /* This means that a file name has been seen. Record it. */
877 argbuffer[current_arg].arg_type = at_filename;
878 argbuffer[current_arg].what = optarg;
883 /* Common options. */
885 append_to_tagfile = TRUE;
891 constantypedefs = TRUE;
894 constantypedefs = FALSE;
896 case 'f': /* for compatibility with old makefiles */
899 /* convert char to string, to call error with */
902 error("-%s option may only be given once.",
904 suggest_asking_for_help();
910 oo_browser_format = TRUE;
914 case 'S': /* for backward compatibility */
915 noindentypedefs = TRUE;
919 language *lang = get_language_from_name(optarg);
921 argbuffer[current_arg].lang = lang;
922 argbuffer[current_arg].arg_type =
930 argbuffer[current_arg].arg_type = at_regexp;
931 argbuffer[current_arg].what = optarg;
935 argbuffer[current_arg].arg_type = at_regexp;
936 argbuffer[current_arg].what = NULL;
939 #endif /* ETAGS_REGEXPS */
951 typedefs = typedefs_and_cplusplus = TRUE;
956 included_files[nincluded_files++] = optarg;
968 /*FALLTHRU*/ case 'x':
976 suggest_asking_for_help();
980 for (; optind < argc; ++optind) {
981 argbuffer[current_arg].arg_type = at_filename;
982 argbuffer[current_arg].what = argv[optind];
987 if (nincluded_files == 0 && file_count == 0) {
988 error("no input files specified.", 0);
989 suggest_asking_for_help();
993 tagfile = CTAGS ? "tags" : "TAGS";
994 cwd = etags_getcwd(); /* the current working directory */
995 if (cwd[strlen(cwd) - 1] != '/') {
997 cwd = concat(oldcwd, "/", "");
1000 if (streq(tagfile, "-"))
1003 tagfiledir = absolute_dirname(tagfile, cwd);
1005 init(); /* set up boolean "functions" */
1008 initbuffer(&token_name);
1009 initbuffer(&lbs[0].lb);
1010 initbuffer(&lbs[1].lb);
1011 initbuffer(&filename_lb);
1014 if (streq(tagfile, "-")) {
1017 tagf = fopen(tagfile, append_to_tagfile ? "a" : "w");
1023 * Loop through files finding functions.
1025 for (i = 0; i < current_arg; ++i) {
1026 switch (argbuffer[i].arg_type) {
1028 forced_lang = argbuffer[i].lang;
1030 #ifdef ETAGS_REGEXPS
1032 analyse_regex(argbuffer[i].what);
1038 gfnames(argbuffer[i].what, &got_err)) != NULL) {
1040 error("can't find file %s\n",
1044 this_file = massage_name(this_file);
1047 this_file = argbuffer[i].what;
1050 oo_browser_clear_all_globals();
1052 /* Input file named "-" means read file names from stdin
1053 (one per line) and use them. */
1054 if (streq(this_file, "-"))
1055 while (readline_internal(&filename_lb, stdin) >
1059 oo_browser_clear_some_globals();
1061 process_file(filename_lb.buffer);
1066 process_file(this_file);
1076 #ifdef ETAGS_REGEXPS
1078 #endif /* ETAGS_REGEXPS */
1081 while (nincluded_files-- > 0)
1082 fprintf(tagf, "\f\n%s,include\n", *included_files++);
1088 /* If CTAGS, we are here. process_file did not write the tags yet,
1089 because we want them ordered. Let's do it now. */
1098 for (i = 0; i < current_arg; ++i) {
1099 if (argbuffer[i].arg_type != at_filename)
1101 sz = snprintf(cmd, sizeof(cmd),
1102 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1103 tagfile, argbuffer[i].what, tagfile);
1104 if(sz >= 0 && (size_t)sz < sizeof(cmd))
1105 fatal("failed to build shell command line", (char *)NULL);
1106 if (system(cmd) != GOOD)
1107 fatal("failed to execute shell command", (char *)NULL);
1109 append_to_tagfile = TRUE;
1112 tagf = fopen(tagfile, append_to_tagfile ? "a" : "w");
1120 int sz = snprintf(cmd, sizeof(cmd), "sort %s -o %s", tagfile, tagfile);
1121 if(sz >= 0 && (size_t)sz < sizeof(cmd))
1122 fatal("failed to build sort command line", (char *)NULL);
1129 * Return a language given the name.
1131 language *get_language_from_name(name)
1137 error("empty language name", (char *)NULL);
1139 for (lang = lang_names; lang->name != NULL; lang++)
1140 if (streq(name, lang->name))
1142 error("unknown language \"%s\"", name);
1149 * Return a language given the interpreter name.
1151 language *get_language_from_interpreter(interpreter)
1157 if (interpreter == NULL)
1159 for (lang = lang_names; lang->name != NULL; lang++)
1160 if (lang->interpreters != NULL)
1161 for (iname = lang->interpreters; *iname != NULL;
1163 if (streq(*iname, interpreter))
1170 * Return a language given the file suffix.
1172 language *get_language_from_suffix(suffix)
1180 for (lang = lang_names; lang->name != NULL; lang++)
1181 if (lang->suffixes != NULL)
1182 for (ext = lang->suffixes; *ext != NULL; ext++)
1183 if (streq(*ext, suffix))
1190 * This routine is called on each file argument.
1192 void process_file(file)
1195 struct stat stat_buf;
1198 canonicalize_filename(file);
1199 if (stat(file, &stat_buf) == 0 && !S_ISREG(stat_buf.st_mode)) {
1200 error("skipping %s: it is not a regular file.", file);
1203 if (streq(file, tagfile) && !streq(tagfile, "-")) {
1204 error("skipping inclusion of %s in self.", file);
1207 inf = fopen(file, "r");
1213 find_entries(file, inf);
1218 if (filename_is_absolute(file)) {
1219 /* file is an absolute file name. Canonicalise it. */
1220 filename = absolute_filename(file, cwd);
1222 /* file is a file name relative to cwd. Make it relative
1223 to the directory of the tags file. */
1224 filename = relative_filename(file, tagfiledir);
1227 if (oo_browser_format)
1228 fprintf(tagf, "\f\n%s\n", filename);
1231 fprintf(tagf, "\f\n%s,%d\n", filename,
1232 total_size_of_entries(head));
1241 * This routine sets up the boolean pseudo-functions which work
1242 * by setting boolean flags dependent upon the corresponding character.
1243 * Every char which is NOT in that string is not a white char. Therefore,
1244 * all of the array "_wht" is set to FALSE, and then the elements
1245 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1246 * of a char is TRUE if it is the string "white", else FALSE.
1253 for (i = 0; i < CHARS; i++)
1254 iswhite(i) = notinname(i) = begtoken(i) = intoken(i) =
1255 endtoken(i) = FALSE;
1256 for (sp = white; *sp != '\0'; sp++)
1257 iswhite(*sp) = TRUE;
1258 for (sp = nonam; *sp != '\0'; sp++)
1259 notinname(*sp) = TRUE;
1260 for (sp = begtk; *sp != '\0'; sp++)
1261 begtoken(*sp) = TRUE;
1262 for (sp = midtk; *sp != '\0'; sp++)
1263 intoken(*sp) = TRUE;
1264 for (sp = endtk; *sp != '\0'; sp++)
1265 endtoken(*sp) = TRUE;
1266 iswhite('\0') = iswhite('\n');
1267 notinname('\0') = notinname('\n');
1268 begtoken('\0') = begtoken('\n');
1269 intoken('\0') = intoken('\n');
1270 endtoken('\0') = endtoken('\n');
1274 * This routine opens the specified file and calls the function
1275 * which finds the function and type definitions.
1277 node *last_node = NULL;
1279 void find_entries(file, inf)
1285 node *old_last_node;
1287 curfile = savestr(file);
1289 /* If user specified a language, use it. */
1291 if (lang != NULL && lang->function != NULL) {
1293 lang->function(inf);
1299 cp = etags_strrchr(file, '.');
1302 lang = get_language_from_suffix(cp);
1303 if (lang != NULL && lang->function != NULL) {
1305 lang->function(inf);
1312 /* Look for sharp-bang as the first two characters. */
1313 if (readline_internal(&lb, inf) > 0
1314 && lb.len >= 2 && lb.buffer[0] == '#' && lb.buffer[1] == '!') {
1317 /* Set lp to point at the first char after the last slash in the
1318 line or, if no slashes, at the first nonblank. Then set cp to
1319 the first successive blank and terminate the string. */
1320 lp = etags_strrchr(lb.buffer + 2, '/');
1324 lp = skip_spaces(lb.buffer + 2);
1325 cp = skip_non_spaces(lp);
1328 if (strlen(lp) > 0) {
1329 lang = get_language_from_interpreter(lp);
1330 if (lang != NULL && lang->function != NULL) {
1332 lang->function(inf);
1342 old_last_node = last_node;
1343 curlang = get_language_from_name("fortran");
1344 Fortran_functions(inf);
1346 /* No Fortran entries found. Try C. */
1347 if (old_last_node == last_node) {
1349 curlang = get_language_from_name(cplusplus ? "c++" : "c");
1350 default_C_entries(inf);
1358 void pfnote(name, is_func, linestart, linelen, lno, cno)
1359 char *name; /* tag name, or NULL if unnamed */
1360 bool is_func; /* tag is a function */
1361 char *linestart; /* start of the line where tag is */
1362 int linelen; /* length of the line where tag is */
1363 int lno; /* line number */
1364 long cno; /* character number */
1368 if (CTAGS && name == NULL)
1373 /* If ctags mode, change name "main" to M<thisfilename>. */
1374 if (CTAGS && !cxref_style && streq(name, "main")) {
1375 register char *fp = etags_strrchr(curfile, '/');
1376 np->name = concat("M", fp == 0 ? curfile : fp + 1, "");
1377 fp = etags_strrchr(np->name, '.');
1378 if (fp && fp[1] != '\0' && fp[2] == '\0')
1382 np->been_warned = FALSE;
1384 np->is_func = is_func;
1386 /* Our char numbers are 0-base, because of C language tradition?
1387 ctags compatibility? old versions compatibility? I don't know.
1388 Anyway, since emacs's are 1-base we expect etags.el to take care
1389 of the difference. If we wanted to have 1-based numbers, we would
1390 uncomment the +1 below. */
1391 np->cno = cno /* + 1 */ ;
1392 np->left = np->right = NULL;
1393 if (CTAGS && !cxref_style) {
1394 if (strlen(linestart) < 50)
1395 np->pat = concat(linestart, "$", "");
1397 np->pat = savenstr(linestart, 50);
1399 np->pat = savenstr(linestart, linelen);
1402 if (oo_browser_format)
1403 np->construct = oo_browser_construct;
1404 oo_browser_construct = C_NULL;
1405 oo_browser_check_and_clear_structtype();
1408 add_node(np, &head);
1411 /* Date: Wed, 22 Jan 1997 02:56:31 -0500 [last amended 18 Sep 1997]
1412 * From: Sam Kendall <kendall@mv.mv.com>
1413 * Subject: Proposal for firming up the TAGS format specification
1414 * To: F.Potorti@cnuce.cnr.it
1416 * pfnote should emit the optimized form [unnamed tag] only if:
1417 * 1. name does not contain any of the characters " \t\r\n(),;";
1418 * 2. linestart contains name as either a rightmost, or rightmost but
1419 * one character, substring;
1420 * 3. the character, if any, immediately before name in linestart must
1421 * be one of the characters " \t(),;";
1422 * 4. the character, if any, immediately after name in linestart must
1423 * also be one of the characters " \t(),;".
1425 * The real implementation uses the notinname() macro, which recognises
1426 * characters slightly different form " \t\r\n(),;". See the variable
1429 #define traditional_tag_style TRUE
1430 void new_pfnote(name, namelen, is_func, linestart, linelen, lno, cno)
1431 char *name; /* tag name, or NULL if unnamed */
1432 int namelen; /* tag length */
1433 bool is_func; /* tag is a function */
1434 char *linestart; /* start of the line where tag is */
1435 int linelen; /* length of the line where tag is */
1436 int lno; /* line number */
1437 long cno; /* character number */
1444 for (cp = name; !notinname(*cp); cp++)
1446 if (*cp == '\0') { /* rule #1 */
1447 cp = linestart + linelen - namelen;
1448 if (notinname(linestart[linelen - 1]))
1449 cp -= 1; /* rule #4 */
1451 if (!oo_browser_format && cp >= linestart /* rule #2 */
1453 if (cp >= linestart /* rule #2 */
1455 && (cp == linestart || notinname(cp[-1])) /* rule #3 */
1456 &&strneq(name, cp, namelen)) /* rule #2 */
1457 named = FALSE; /* use unnamed tag */
1462 name = savenstr(name, namelen);
1465 pfnote(name, is_func, linestart, linelen, lno, cno);
1470 * recurse on left children, iterate on right children.
1476 register node *node_right = np->right;
1477 free_tree(np->left);
1478 if (np->name != NULL)
1488 * Adds a node to the tree of nodes. In etags mode, we don't keep
1489 * it sorted; we just keep a linear list. In ctags mode, maintain
1490 * an ordered tree, with no attempt at balancing.
1492 * add_node is the only function allowed to add nodes, so it can
1495 void add_node(np, cur_node_p)
1496 node *np, **cur_node_p;
1499 register node *cur_node = *cur_node_p;
1501 if (cur_node == NULL) {
1509 if (last_node == NULL)
1510 fatal("internal error in add_node", (char *)NULL);
1511 last_node->right = np;
1515 dif = strcmp(np->name, cur_node->name);
1518 * If this tag name matches an existing one, then
1519 * do not add the node, but maybe print a warning.
1522 if (streq(np->file, cur_node->file)) {
1525 "Duplicate entry in file %s, line %d: %s\n",
1526 np->file, lineno, np->name);
1528 "Second entry ignored\n");
1530 } else if (!cur_node->been_warned && !no_warnings) {
1533 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1534 np->file, cur_node->file, np->name);
1535 cur_node->been_warned = TRUE;
1540 /* Actually add the node */
1541 add_node(np, dif < 0 ? &cur_node->left : &cur_node->right);
1546 /* Default class name for the current OO-Browser tag. */
1547 static char *oo_browser_class;
1548 /* Prefix character to use in OO-Browser listings for the current tag. */
1549 static char oo_browser_prefix;
1552 void put_entries(node * np)
1559 /* Output subentries that precede this one */
1560 put_entries(np->left);
1562 /* Output this entry */
1566 if (oo_browser_format) {
1567 /* Omit C++ `class' and `method' entries as well as Objective-C
1568 entries from this OO-Browser tags file since the browser handles
1569 them independently of this file. Omit `extern' variable declarations
1570 as they are unused by the OO-Browser. */
1571 if (np->construct != C_CLASS
1572 && np->construct != C_METHOD
1573 && np->construct != C_EXTERN
1574 && np->construct != C_OBJC) {
1576 oo_browser_default_classes[np->construct];
1577 switch (np->construct) {
1585 oo_browser_prefix = '=';
1589 oo_browser_prefix = '-';
1594 if (np->name != NULL)
1595 fprintf(tagf, "%s@%c %s@%s\n",
1597 oo_browser_prefix, np->name,
1600 fprintf(tagf, "%s@%c ???@%s\n",
1602 oo_browser_prefix, np->pat);
1606 if (np->name != NULL)
1607 fprintf(tagf, "%s\177%s\001%d,%ld\n",
1608 np->pat, np->name, np->lno, np->cno);
1610 fprintf(tagf, "%s\177%d,%ld\n",
1611 np->pat, np->lno, np->cno);
1616 if (np->name == NULL)
1617 error("internal error: NULL name in ctags mode.",
1622 fprintf(stdout, "%s %s %d\n",
1624 (np->lno + 63) / 64);
1626 fprintf(stdout, "%-16s %3d %-16s %s\n",
1627 np->name, np->lno, np->file, np->pat);
1629 fprintf(tagf, "%s\t%s\t", np->name, np->file);
1631 if (np->is_func) { /* a function */
1632 putc(searchar, tagf);
1635 for (sp = np->pat; *sp; sp++) {
1636 if (*sp == '\\' || *sp == searchar)
1640 putc(searchar, tagf);
1641 } else { /* a typedef; text pattern inadequate */
1642 fprintf(tagf, "%d", np->lno);
1648 /* Output subentries that follow this one */
1649 put_entries(np->right);
1652 /* Length of a number's decimal representation. */
1653 int number_len PP((long num));
1658 while ((num /= 10) > 0)
1664 * Return total number of characters that put_entries will output for
1665 * the nodes in the subtree of the specified node. Works only if
1666 * we are not ctags, but called only in that case. This count
1667 * is irrelevant with the new tags.el, but is still supplied for
1668 * backward compatibility.
1670 int total_size_of_entries(np)
1678 for (total = 0; np != NULL; np = np->right) {
1679 /* Count left subentries. */
1680 total += total_size_of_entries(np->left);
1682 /* Count this entry */
1683 total += strlen(np->pat) + 1;
1685 number_len((long)np->lno) + 1 + number_len(np->cno) + 1;
1686 if (np->name != NULL)
1687 total += 1 + strlen(np->name); /* \001name */
1694 * The C symbol tables.
1698 st_C_objprot, st_C_objimpl, st_C_objend,
1702 st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec,
1705 , st_C_union, st_C_class, st_C_extern, st_C_inline
1709 /* Feed stuff between (but not including) %[ and %] lines to:
1710 gperf -c -k 1,3 -o -p -r -t
1712 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1714 @interface, 0, st_C_objprot
1715 @protocol, 0, st_C_objprot
1716 @implementation,0, st_C_objimpl
1717 @end, 0, st_C_objend
1718 import, C_JAVA, st_C_ignore
1719 package, C_JAVA, st_C_ignore
1720 friend, C_PLPL, st_C_ignore
1721 extends, C_JAVA, st_C_javastruct
1722 implements, C_JAVA, st_C_javastruct
1723 interface, C_JAVA, st_C_struct
1724 class, C_PLPL, st_C_class
1725 namespace, C_PLPL, st_C_struct
1726 domain, C_STAR, st_C_struct
1727 union, 0, st_C_union
1728 struct, 0, st_C_struct
1730 typedef, 0, st_C_typedef
1731 define, 0, st_C_define
1732 inline, 0, st_C_inline
1733 bool, C_PLPL, st_C_typespec
1734 long, 0, st_C_typespec
1735 short, 0, st_C_typespec
1736 int, 0, st_C_typespec
1737 char, 0, st_C_typespec
1738 float, 0, st_C_typespec
1739 double, 0, st_C_typespec
1740 signed, 0, st_C_typespec
1741 unsigned, 0, st_C_typespec
1742 auto, 0, st_C_typespec
1743 void, 0, st_C_typespec
1744 extern, 0, st_C_extern
1745 static, 0, st_C_typespec
1746 const, 0, st_C_const
1747 volatile, 0, st_C_typespec
1748 explicit, C_PLPL, st_C_typespec
1749 mutable, C_PLPL, st_C_typespec
1750 typename, C_PLPL, st_C_typespec
1751 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
1752 DEFUN, 0, st_C_gnumacro
1753 SYSCALL, 0, st_C_gnumacro
1754 ENTRY, 0, st_C_gnumacro
1755 PSEUDO, 0, st_C_gnumacro
1756 # These are defined inside C functions, so currently they are not met.
1757 # EXFUN used in glibc, DEFVAR_* in emacs.
1758 #EXFUN, 0, st_C_gnumacro
1759 #DEFVAR_, 0, st_C_gnumacro
1761 and replace lines between %< and %> with its output. */
1763 /* C code produced by gperf version 2.5 (GNU C++ version) */
1764 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
1765 struct C_stab_entry {
1771 #define TOTAL_KEYWORDS 41
1772 #define MIN_WORD_LENGTH 3
1773 #define MAX_WORD_LENGTH 15
1774 #define MIN_HASH_VALUE 13
1775 #define MAX_HASH_VALUE 129
1776 /* maximum key range = 117, duplicates = 0 */
1778 static unsigned int hash(char *str, unsigned int len)
1780 static unsigned char asso_values[] = {
1781 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1782 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1783 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1784 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1785 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1786 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1787 130, 130, 130, 130, 13, 130, 130, 130, 33, 32,
1788 47, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1789 5, 130, 130, 20, 32, 130, 130, 130, 130, 130,
1790 130, 130, 130, 130, 130, 130, 130, 47, 55, 8,
1791 15, 33, 61, 38, 130, 60, 130, 130, 2, 9,
1792 10, 62, 59, 130, 28, 27, 50, 19, 3, 130,
1793 130, 130, 130, 130, 130, 130, 130, 130,
1796 asso_values[(unsigned char)str[2]] +
1797 asso_values[(unsigned char)str[0]];
1800 static struct C_stab_entry *in_word_set(char *str, unsigned int len)
1802 static struct C_stab_entry wordlist[] = {
1803 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1804 {"",}, {"",}, {"",}, {"",},
1805 {"volatile", 0, st_C_typespec},
1807 {"long", 0, st_C_typespec},
1808 {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1809 {"const", 0, st_C_const},
1810 {"",}, {"",}, {"",},
1811 {"@end", 0, st_C_objend},
1812 {"namespace", C_PLPL, st_C_struct},
1814 {"domain", C_STAR, st_C_struct},
1816 {"@interface", 0, st_C_objprot},
1817 {"",}, {"",}, {"",},
1818 {"@implementation", 0, st_C_objimpl},
1820 {"double", 0, st_C_typespec},
1822 {"PSEUDO", 0, st_C_gnumacro},
1823 {"",}, {"",}, {"",},
1824 {"SYSCALL", 0, st_C_gnumacro},
1826 {"@protocol", 0, st_C_objprot},
1827 {"",}, {"",}, {"",},
1828 {"unsigned", 0, st_C_typespec},
1830 {"enum", 0, st_C_enum},
1832 {"char", 0, st_C_typespec},
1833 {"class", C_PLPL, st_C_class},
1834 {"struct", 0, st_C_struct},
1835 {"",}, {"",}, {"",}, {"",},
1836 {"mutable", C_PLPL, st_C_typespec},
1837 {"void", 0, st_C_typespec},
1838 {"inline", 0, st_C_inline},
1839 {"ENTRY", 0, st_C_gnumacro},
1841 {"signed", 0, st_C_typespec},
1843 {"package", C_JAVA, st_C_ignore},
1844 {"",}, {"",}, {"",}, {"",}, {"",},
1845 {"static", 0, st_C_typespec},
1847 {"define", 0, st_C_define},
1849 {"union", 0, st_C_union},
1850 {"DEFUN", 0, st_C_gnumacro},
1851 {"",}, {"",}, {"",},
1852 {"extern", 0, st_C_extern},
1853 {"extends", C_JAVA, st_C_javastruct},
1854 {"",}, {"",}, {"",},
1855 {"short", 0, st_C_typespec},
1856 {"",}, {"",}, {"",}, {"",}, {"",},
1857 {"explicit", C_PLPL, st_C_typespec},
1858 {"auto", 0, st_C_typespec},
1859 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1861 {"int", 0, st_C_typespec},
1863 {"typedef", 0, st_C_typedef},
1864 {"typename", C_PLPL, st_C_typespec},
1866 {"interface", C_JAVA, st_C_struct},
1868 {"bool", C_PLPL, st_C_typespec},
1869 {"",}, {"",}, {"",},
1870 {"import", C_JAVA, st_C_ignore},
1872 {"friend", C_PLPL, st_C_ignore},
1873 {"float", 0, st_C_typespec},
1874 {"implements", C_JAVA, st_C_javastruct},
1877 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) {
1878 register int key = hash(str, len);
1880 if (key <= MAX_HASH_VALUE && key >= 0) {
1881 register char *s = wordlist[key].name;
1883 if (*s == *str && !strncmp(str + 1, s + 1, len - 1))
1884 return &wordlist[key];
1892 enum sym_type C_symtype PP((char *str, int len, int c_ext));
1893 enum sym_type C_symtype(str, len, c_ext)
1898 register struct C_stab_entry *se = in_word_set(str, len);
1900 if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
1906 * C functions and variables are recognized using a simple
1907 * finite automaton. fvdef is its state variable.
1910 fvnone, /* nothing seen */
1911 fvnameseen, /* function or variable name seen */
1912 fstartlist, /* func: just after open parenthesis */
1913 finlist, /* func: in parameter list */
1914 flistseen, /* func: after parameter list */
1915 fignore, /* func: before open brace */
1916 vignore /* var-like: ignore until ';' */
1920 * typedefs are recognized using a simple finite automaton.
1921 * typdef is its state variable.
1924 tnone, /* nothing seen */
1925 ttypedseen, /* typedef keyword seen */
1926 tinbody, /* inside typedef body */
1927 tend, /* just before typedef tag */
1928 tignore /* junk after typedef tag */
1932 * struct-like structures (enum, struct and union) are recognized
1933 * using another simple finite automaton. `structdef' is its state
1937 snone, /* nothing seen yet */
1938 skeyseen, /* struct-like keyword seen */
1939 stagseen, /* struct-like tag seen */
1940 scolonseen, /* colon seen after struct-like tag */
1941 sinbody /* in struct body: recognize member func defs */
1945 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1946 * struct tag, and structtype is the type of the preceding struct-like
1949 char *structtag = "<uninited>";
1950 enum sym_type structtype;
1953 void oo_browser_check_and_clear_structtype(void)
1955 /* Allow for multiple enum_label tags. */
1956 if (structtype != st_C_enum)
1957 structtype = st_none;
1962 * When objdef is different from onone, objtag is the name of the class.
1964 char *objtag = "<uninited>";
1967 * Yet another little state machine to deal with preprocessor lines.
1970 dnone, /* nothing seen */
1971 dsharpseen, /* '#' seen as first char on line */
1972 ddefineseen, /* '#' and 'define' seen */
1973 dignorerest /* ignore rest of line */
1977 * State machine for Objective C protocols and implementations.
1978 * Tom R.Hageman <tom@basil.icce.rug.nl>
1981 onone, /* nothing seen */
1982 oprotocol, /* @interface or @protocol seen */
1983 oimplementation, /* @implementations seen */
1984 otagseen, /* class name seen */
1985 oparenseen, /* parenthesis before category seen */
1986 ocatseen, /* category name seen */
1987 oinbody, /* in @implementation body */
1988 omethodsign, /* in @implementation body, after +/- */
1989 omethodtag, /* after method name */
1990 omethodcolon, /* after method colon */
1991 omethodparm, /* after method parameter */
1992 oignore /* wait for @end */
1996 * Use this structure to keep info about the token read, and how it
1997 * should be tagged. Used by the make_C_tag function to build a tag.
2009 token tok; /* latest token read */
2012 * Set this to TRUE, and the next token considered is called a function.
2013 * Used only for GNU emacs's function-defining macros.
2015 bool next_token_is_func;
2018 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
2023 * methodlen is the length of the method name stored in token_name.
2028 void oo_browser_clear_all_globals(void)
2030 /* Initialize globals so there is no carry over between files. */
2031 oo_browser_construct = C_NULL;
2037 structtype = st_none;
2038 next_token_is_func = yacc_rules = FALSE;
2041 void oo_browser_clear_some_globals(void)
2043 oo_browser_construct = C_NULL;
2044 structtype = st_none;
2050 * checks to see if the current token is at the start of a
2051 * function or variable, or corresponds to a typedef, or
2052 * is a struct/union/enum tag, or #define, or an enum constant.
2054 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2055 * with args. C_EXT is which language we are looking at.
2057 * In the future we will need some way to adjust where the end of
2058 * the token is; for instance, implementing the C++ keyword
2059 * `operator' properly will adjust the end of the token to be after
2060 * whatever follows `operator'.
2068 * next_token_is_func IN OUT
2070 bool consider_token PP((char *str, int len, int c, int c_ext,
2071 int cblev, int parlev, bool * is_func_or_var));
2072 bool consider_token(str, len, c, c_ext, cblev, parlev, is_func_or_var)
2073 register char *str; /* IN: token pointer */
2074 register int len; /* IN: token length */
2075 register int c; /* IN: first char after the token */
2076 int c_ext; /* IN: C extensions mask */
2077 int cblev; /* IN: curly brace level */
2078 int parlev; /* IN: parenthesis level */
2079 bool *is_func_or_var; /* OUT: function or variable found */
2081 enum sym_type toktype = C_symtype(str, len, c_ext);
2084 switch ((unsigned int)toktype) {
2086 set_construct(C_STRUCTURE);
2089 set_construct(C_UNION);
2092 set_construct(C_CLASS);
2095 set_construct(C_ENUMERATION);
2098 set_construct(C_TYPE);
2101 set_construct(C_EXTERN);
2104 set_construct(C_FUNCTION);
2114 * Advance the definedef state machine.
2116 switch (definedef) {
2118 /* We're not on a preprocessor line. */
2121 if (toktype == st_C_define) {
2122 definedef = ddefineseen;
2124 definedef = dignorerest;
2129 * Make a tag for any macro, unless it is a constant
2130 * and constantypedefs is FALSE.
2132 definedef = dignorerest;
2134 *is_func_or_var = (c == '(');
2137 char *p = str + len * sizeof(char);
2140 /* This must be a macro since there is no
2141 whitespace between the opening parenthesis
2142 and the definition name. */
2143 *is_func_or_var = TRUE;
2145 *is_func_or_var = FALSE;
2147 /* Handle possible whitespace between macro tag and opening
2148 parenthesis and ensure this is an actual macro.
2149 -- Bob Weiner, Altrasoft, 11/19/1997 */
2150 while (*p && isspace(*p))
2155 /* Skip over nested parentheses. */
2159 while (*++p && depth > 0 && *p != '\n') {
2172 /* If this is a macro, we have just passed
2173 the arguments and there will be more on
2174 the line before the NULL character that marks
2175 the end of the line token. */
2176 while (*p == ' ' || *p == '\t')
2179 *is_func_or_var = TRUE;
2184 set_construct((*is_func_or_var) ? C_MACRO : C_CONSTANT);
2186 if (!*is_func_or_var && !constantypedefs)
2193 error("internal error: definedef value.", (char *)NULL);
2201 if (toktype == st_C_typedef) {
2203 typdef = ttypedseen;
2209 switch ((unsigned int)toktype) {
2211 set_construct(C_CONSTANT);
2232 /* Do not return here, so the structdef stuff has a chance. */
2235 switch ((unsigned int)toktype) {
2237 set_construct(C_CONSTANT);
2263 * This structdef business is currently only invoked when cblev==0.
2264 * It should be recursively invoked whatever the curly brace level,
2265 * and a stack of states kept, to allow for definitions of structs
2268 * This structdef business is NOT invoked when we are ctags and the
2269 * file is plain C. This is because a struct tag may have the same
2270 * name as another tag, and this loses with ctags.
2272 switch ((unsigned int)toktype) {
2273 case st_C_javastruct:
2274 if (structdef == stagseen)
2275 structdef = scolonseen;
2284 if (typdef == ttypedseen
2285 || (typedefs_and_cplusplus && cblev == 0
2286 && structdef == snone)) {
2287 structdef = skeyseen;
2288 structtype = toktype;
2297 if (structdef == skeyseen) {
2298 /* Save the tag for struct/union/class, for functions and variables
2299 that may be defined inside. */
2301 if (structtype == st_C_struct)
2303 if (structtype == st_C_struct
2304 || structtype == st_C_union || structtype == st_C_class)
2306 structtag = savenstr(str, len);
2308 structtag = "<enum>";
2309 structdef = stagseen;
2313 /* Avoid entering fvdef stuff if typdef is going on. */
2314 if (typdef != tnone) {
2319 /* Detect GNU macros.
2321 DEFUN note for writers of emacs C code:
2322 The DEFUN macro, used in emacs C source code, has a first arg
2323 that is a string (the lisp function name), and a second arg that
2324 is a C function name. Since etags skips strings, the second arg
2325 is tagged. This is unfortunate, as it would be better to tag the
2326 first arg. The simplest way to deal with this problem would be
2327 to name the tag with a name built from the function name, by
2328 removing the initial 'F' character and substituting '-' for '_'.
2329 Anyway, this assumes that the conventions of naming lisp
2330 functions will never change. Currently, this method is not
2331 implemented, so writers of emacs code are recommended to put the
2332 first two args of a DEFUN on the same line. */
2333 if (definedef == dnone && toktype == st_C_gnumacro) {
2334 next_token_is_func = TRUE;
2337 if (next_token_is_func) {
2338 next_token_is_func = FALSE;
2340 *is_func_or_var = TRUE;
2344 /* Detect Objective C constructs. */
2347 switch ((unsigned int)toktype) {
2350 set_construct(C_OBJC);
2356 set_construct(C_OBJC);
2358 objdef = oimplementation;
2366 case oimplementation:
2367 /* Save the class tag for functions or variables defined inside. */
2368 objtag = savenstr(str, len);
2372 /* Save the class tag for categories. */
2373 objtag = savenstr(str, len);
2375 *is_func_or_var = TRUE;
2379 *is_func_or_var = TRUE;
2385 objdef = omethodtag;
2387 grow_linebuffer(&token_name, methodlen + 1);
2388 strncpy(token_name.buffer, str, len);
2389 token_name.buffer[methodlen] = '\0';
2390 token_name.len = methodlen;
2396 objdef = omethodparm;
2400 objdef = omethodtag;
2402 grow_linebuffer(&token_name, methodlen + 1);
2403 strncat(token_name.buffer, str, len);
2404 token_name.len = methodlen;
2409 if (toktype == st_C_objend) {
2410 /* Memory leakage here: the string pointed by objtag is
2411 never released, because many tests would be needed to
2412 avoid breaking on incorrect input code. The amount of
2413 memory leaked here is the sum of the lengths of the
2428 /* A function, variable or enum constant? */
2429 switch ((unsigned int)toktype) {
2431 set_construct(C_CONSTANT);
2437 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2438 fvdef = fvnone; /* should be useless */
2444 if (constantypedefs && structdef == sinbody
2445 && structtype == st_C_enum)
2448 oo_browser_construct = C_ENUM_LABEL;
2454 if (fvdef == fvnone) {
2455 fvdef = fvnameseen; /* function or variable */
2456 *is_func_or_var = TRUE;
2470 * This routine finds functions, variables, typedefs,
2471 * #define's, enum constants and struct/union/enum definitions in
2472 * #C syntax and adds them to the list.
2474 #define current_lb_is_new (newndx == curndx)
2475 #define switch_line_buffers() (curndx = 1 - curndx)
2477 #define curlb (lbs[curndx].lb)
2478 #define othlb (lbs[1-curndx].lb)
2479 #define newlb (lbs[newndx].lb)
2480 #define curlinepos (lbs[curndx].linepos)
2481 #define othlinepos (lbs[1-curndx].linepos)
2482 #define newlinepos (lbs[newndx].linepos)
2484 #define CNL_SAVE_DEFINEDEF() \
2486 curlinepos = charno; \
2488 linecharno = charno; \
2489 charno += readline (&curlb, inf); \
2490 lp = curlb.buffer; \
2497 CNL_SAVE_DEFINEDEF(); \
2498 if (savetok.valid) \
2501 savetok.valid = FALSE; \
2503 definedef = dnone; \
2506 void make_C_tag PP((bool isfun));
2507 void make_C_tag(isfun)
2510 /* This function should never be called when tok.valid is FALSE, but
2511 we must protect against invalid input or internal errors. */
2513 if (traditional_tag_style) {
2514 /* This was the original code. Now we call new_pfnote instead,
2515 which uses the new method for naming tags (see new_pfnote). */
2518 if (CTAGS || tok.named)
2519 name = savestr(token_name.buffer);
2521 tok.buffer, tok.linelen, tok.lineno,
2524 new_pfnote(token_name.buffer, token_name.len, isfun,
2525 tok.buffer, tok.linelen, tok.lineno,
2532 void C_entries(c_ext, inf)
2533 int c_ext; /* extension of C */
2534 FILE *inf; /* input file */
2536 register char c; /* latest char read; '\0' for end of line */
2537 register char *lp; /* pointer one beyond the character `c' */
2538 int curndx, newndx; /* indices for current and new lb */
2539 register int tokoff; /* offset in line of start of current token */
2540 register int toklen; /* length of current token */
2541 char *qualifier; /* string used to qualify names */
2542 int qlen; /* length of qualifier */
2543 int cblev; /* current curly brace level */
2544 int parlev; /* current parenthesis level */
2545 bool incomm, inquote, inchar, quotednl, midtoken;
2547 token savetok; /* token saved during preprocessor handling */
2549 /* initialise savetok */
2550 memset(&savetok, 0, sizeof(token));
2552 tokoff = toklen = 0; /* keep compiler quiet */
2553 curndx = newndx = 0;
2564 next_token_is_func = yacc_rules = FALSE;
2565 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2566 tok.valid = savetok.valid = FALSE;
2569 cplpl = (c_ext & C_PLPL) == C_PLPL;
2570 cjava = (c_ext & C_JAVA) == C_JAVA;
2579 while (!feof(inf)) {
2582 /* If we're at the end of the line, the next character is a
2583 '\0'; don't skip it, because it's the thing that tells us
2584 to read the next line. */
2591 } else if (incomm) {
2600 /* Newlines inside comments do not end macro definitions in
2602 CNL_SAVE_DEFINEDEF();
2608 } else if (inquote) {
2614 /* Newlines inside strings do not end macro definitions
2615 in traditional cpp, even though compilers don't
2616 usually accept them. */
2617 CNL_SAVE_DEFINEDEF();
2623 } else if (inchar) {
2626 /* Hmmm, something went wrong. */
2640 if (fvdef != finlist && fvdef != fignore
2641 && fvdef != vignore)
2646 if (fvdef != finlist && fvdef != fignore
2647 && fvdef != vignore)
2655 } else if ( /* cplpl && */ *lp == '/') {
2661 if ((c_ext & YACC) && *lp == '%') {
2662 /* entering or exiting rules section in yacc file */
2668 next_token_is_func = FALSE;
2669 midtoken = inquote = inchar = incomm =
2672 yacc_rules = !yacc_rules;
2677 if (definedef == dnone) {
2679 bool cpptoken = TRUE;
2681 /* Look back on this line. If all blanks, or nonblanks
2682 followed by an end of comment, this is a preprocessor
2684 for (cp = newlb.buffer; cp < lp - 1;
2686 if (!iswhite(*cp)) {
2697 definedef = dsharpseen;
2699 /* if (definedef == dnone) */
2705 /* Consider token only if some complicated conditions are satisfied. */
2706 if ((definedef != dnone
2707 || (cblev == 0 && structdef != scolonseen)
2708 || (cblev == 1 && cplpl && structdef == sinbody)
2709 || (structdef == sinbody && structtype == st_C_enum))
2710 && typdef != tignore
2711 && definedef != dignorerest && fvdef != finlist) {
2714 if (c == ':' && cplpl && *lp == ':'
2715 && begtoken(*(lp + 1))) {
2717 * This handles :: in the middle, but not at the
2718 * beginning of an identifier.
2723 set_construct(C_METHOD);
2726 bool funorvar = FALSE;
2729 || consider_token(newlb.
2739 if (structdef == sinbody
2742 /* function or var defined in C++ class body */
2772 oo_browser_construct
2775 } else if (objdef ==
2777 /* Objective C category */
2810 oo_browser_construct
2813 } else if (objdef ==
2817 /* Objective C method */
2822 oo_browser_construct
2851 /* Also name #define constants,
2852 enumerations and enum_labels.
2853 Conditionalize `funorvar' reference
2854 here or #defines will appear without
2856 -- Bob Weiner, Altrasoft, 4/25/1998 */
2858 ((oo_browser_format || funorvar)
2866 (oo_browser_construct
2870 oo_browser_construct
2883 tok.lineno = lineno;
2885 tokoff + toklen + 1;
2892 if (definedef == dnone
2901 if (current_lb_is_new)
2910 } /* if (endtoken (c)) */
2911 else if (intoken(c)) {
2915 } /* if (midtoken) */
2916 else if (begtoken(c)) {
2917 switch (definedef) {
2919 switch ((unsigned int)fvdef) {
2925 set_construct(C_MACRO);
2927 make_C_tag(TRUE); /* a function */
2938 if (structdef == stagseen && !cjava)
2950 if (!yacc_rules || lp == newlb.buffer + 1) {
2951 tokoff = lp - 1 - newlb.buffer;
2956 } /* if (begtoken) */
2959 /* if must look at token */
2960 /* Detect end of line, colon, comma, semicolon and various braces
2961 after having handled a token. */
2964 if (definedef != dnone)
2966 switch ((unsigned int)objdef) {
2969 make_C_tag(TRUE); /* an Objective C class */
2973 objdef = omethodcolon;
2975 grow_linebuffer(&token_name, methodlen + 1);
2976 strcat(token_name.buffer, ":");
2977 token_name.len = methodlen;
2984 if (structdef == stagseen)
2985 structdef = scolonseen;
2987 switch ((unsigned int)fvdef) {
2990 make_C_tag(FALSE); /* a yacc function */
3004 if (definedef != dnone)
3007 switch ((unsigned int)typdef) {
3010 set_construct(C_TYPE);
3012 make_C_tag(FALSE); /* a typedef */
3017 switch ((unsigned int)fvdef) {
3021 if ((globals && cblev == 0)
3022 || (members && cblev == 1))
3024 make_C_tag(FALSE); /* a variable */
3026 /* if (constantypedefs && structdef == snone)*/
3029 switch ((unsigned int)structtype) {
3031 set_construct(C_ENUMERATION);
3034 set_construct(C_CLASS);
3037 set_construct(C_VARIABLE);
3041 /* Force reset of st_C_enum structtype value. */
3042 structtype = st_none;
3048 /* The following instruction invalidates the token.
3049 Probably the token should be invalidated in all
3050 other cases where some state machine is reset. */
3053 if (structdef == stagseen)
3057 if (definedef != dnone)
3059 switch ((unsigned int)objdef) {
3062 make_C_tag(TRUE); /* an Objective C method */
3070 switch ((unsigned int)fvdef) {
3076 if ((globals && cblev == 0)
3077 || (members && cblev == 1))
3078 make_C_tag(FALSE); /* a variable */
3083 if (structdef == stagseen)
3087 if (definedef != dnone)
3089 if (cblev == 0 && typdef == tend) {
3091 set_construct(C_TYPE);
3094 make_C_tag(FALSE); /* a typedef */
3097 switch ((unsigned int)fvdef) {
3104 if ((globals && cblev == 0)
3105 || (members && cblev == 1))
3106 make_C_tag(FALSE); /* a variable */
3108 if (constantypedefs && structdef == snone) {
3110 switch ((unsigned int)structtype) {
3112 set_construct(C_ENUMERATION);
3115 set_construct(C_CLASS);
3118 set_construct(C_VARIABLE);
3122 /* Force reset of st_C_enum structtype value. */
3123 structtype = st_none;
3133 if (structdef == stagseen)
3137 if (definedef != dnone)
3139 if (objdef == otagseen && parlev == 0)
3140 objdef = oparenseen;
3141 switch ((unsigned int)fvdef) {
3146 if (tok.valid && *lp != '*') {
3147 /* This handles constructs like:
3148 typedef void OperatorFun (int fun); */
3151 set_construct(C_TYPE);
3163 } /* switch (typdef) */
3179 if (definedef != dnone)
3181 if (objdef == ocatseen && parlev == 1) {
3182 make_C_tag(TRUE); /* an Objective C category */
3185 if (--parlev == 0) {
3186 switch ((unsigned int)fvdef) {
3196 if (cblev == 0 && typdef == tend) {
3198 set_construct(C_TYPE);
3201 make_C_tag(FALSE); /* a typedef */
3203 } else if (parlev < 0) /* can happen due to ill-conceived #if's. */
3207 if (definedef != dnone)
3209 if (typdef == ttypedseen)
3211 switch (structdef) {
3212 case skeyseen: /* unnamed struct */
3213 structdef = sinbody;
3214 structtag = "_anonymous_";
3217 case scolonseen: /* named struct */
3218 structdef = sinbody;
3219 make_C_tag(FALSE); /* a struct */
3228 switch ((unsigned int)fvdef) {
3231 set_construct(C_FUNCTION);
3232 /* Ensure function name is recorded.
3233 -- Bob Weiner, Altrasoft */
3236 make_C_tag(TRUE); /* a function */
3242 switch ((unsigned int)objdef) {
3244 make_C_tag(TRUE); /* an Objective C class */
3249 make_C_tag(TRUE); /* an Objective C method */
3253 /* Neutralize `extern "C" {' grot. */
3254 if (cblev == 0 && structdef == snone
3266 if (definedef != dnone)
3268 if (fvdef == fstartlist)
3269 fvdef = fvnone; /* avoid tagging `foo' in `foo (*bar()) ()' */
3272 if (definedef != dnone)
3274 if (!noindentypedefs && lp == newlb.buffer + 1) {
3275 cblev = 0; /* reset curly brace level if first column */
3276 parlev = 0; /* also reset paren level, just in case... */
3277 } else if (cblev > 0)
3280 if (typdef == tinbody)
3282 /* Memory leakage here: the string pointed by structtag is
3283 never released, because I fear to miss something and
3284 break things while freeing the area. The amount of
3285 memory leaked here is the sum of the lengths of the
3287 if (structdef == sinbody)
3288 free (structtag); */
3291 structtag = "<error>";
3293 /* Next line added to avoid any state carryover between
3294 functions. -- Bob Weiner, Altrasoft, 11/19/1997 */
3296 oo_browser_construct = C_NULL;
3301 if (definedef != dnone)
3313 if ((globals && cblev == 0)
3314 || (members && cblev == 1))
3316 make_C_tag(FALSE); /* a variable */
3320 switch ((unsigned int)structtype) {
3326 set_construct(C_CLASS);
3329 /* a global variable */
3335 /* ootags categorizes each tag found whereas etags doesn't.
3336 Set the is_method flag if this tag has been marked as
3337 such by an earlier section of code.
3338 -- Steve Baur, Altrasoft, 5/7/1998 */
3340 (oo_browser_construct ==
3344 /* Force reset of st_C_enum structtype value. */
3345 structtype = st_none;
3354 fvdef = is_method ? fignore : vignore;
3365 if (objdef == oinbody && cblev == 0) {
3366 objdef = omethodsign;
3383 if (definedef != dnone)
3388 /* The above characters cannot follow a function tag in C, so
3389 unmark this as a function entry. For C++, these characters
3390 may follow an `operator' function construct, so skip the
3391 unmarking conditional below.
3392 -- Steve Baur, Altrasoft, 5/7/1998 */
3393 if (fvdef != finlist && fvdef != fignore
3394 && fvdef != vignore)
3401 if (objdef == otagseen) {
3402 make_C_tag(TRUE); /* an Objective C class */
3405 /* If a macro spans multiple lines don't reset its state. */
3407 CNL_SAVE_DEFINEDEF();
3417 } /* while not eof */
3421 * Process either a C++ file or a C file depending on the setting
3424 void default_C_entries(inf)
3427 C_entries(cplusplus ? C_PLPL : 0, inf);
3430 /* Always do plain ANSI C. */
3431 void plain_C_entries(inf)
3437 /* Always do C++. */
3438 void Cplusplus_entries(inf)
3441 C_entries(C_PLPL, inf);
3444 /* Always do Java. */
3445 void Cjava_entries(inf)
3448 C_entries(C_JAVA, inf);
3452 void Cstar_entries(inf)
3455 C_entries(C_STAR, inf);
3458 /* Always do Yacc. */
3459 void Yacc_entries(inf)
3462 C_entries(YACC, inf);
3465 /* A useful macro. */
3466 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3467 for (lineno = charno = 0; /* loop initialization */ \
3468 !feof (file_pointer) /* loop test */ \
3469 && (lineno++, /* instructions at start of loop */ \
3470 linecharno = charno, \
3471 charno += readline (&line_buffer, file_pointer), \
3472 char_pointer = lb.buffer, \
3477 * Read a file, but do no processing. This is used to do regexp
3478 * matching on files that have no language defined.
3480 void just_read_file(inf)
3483 register char *dummy;
3485 LOOP_ON_INPUT_LINES(inf, lb, dummy)
3489 /* Fortran parsing */
3491 bool tail PP((char *cp));
3495 register int len = 0;
3497 while (*cp && lowcase(*cp) == lowcase(dbp[len]))
3499 if (*cp == '\0' && !intoken(dbp[len])) {
3508 dbp = skip_spaces(dbp);
3512 dbp = skip_spaces(dbp);
3513 if (strneq(dbp, "(*)", 3)) {
3517 if (!isdigit(*dbp)) {
3518 --dbp; /* force failure */
3523 while (isdigit(*dbp));
3526 void getit PP((FILE * inf));
3532 dbp = skip_spaces(dbp);
3535 linecharno = charno;
3536 charno += readline(&lb, inf);
3541 dbp = skip_spaces(dbp);
3544 && *dbp != '_' && *dbp != '$')
3546 for (cp = dbp + 1; *cp && intoken(*cp); cp++)
3548 pfnote((CTAGS) ? savenstr(dbp, cp - dbp) : NULL, TRUE,
3549 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3552 void Fortran_functions(inf)
3555 LOOP_ON_INPUT_LINES(inf, lb, dbp) {
3557 dbp++; /* Ratfor escape to fortran */
3558 dbp = skip_spaces(dbp);
3561 switch (lowcase(*dbp)) {
3563 if (tail("integer"))
3571 if (tail("logical"))
3575 if (tail("complex") || tail("character"))
3579 if (tail("double")) {
3580 dbp = skip_spaces(dbp);
3583 if (tail("precision"))
3591 dbp = skip_spaces(dbp);
3594 switch (lowcase(*dbp)) {
3596 if (tail("function"))
3600 if (tail("subroutine"))
3608 if (tail("program")) {
3612 if (tail("procedure"))
3622 * Bob Weiner, Motorola Inc., 4/3/94
3623 * Unix and microcontroller assembly tag handling
3624 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
3626 void Asm_labels(FILE * inf)
3630 LOOP_ON_INPUT_LINES(inf, lb, cp) {
3631 /* If first char is alphabetic or one of [_.$], test for colon
3632 following identifier. */
3633 if (isalpha(*cp) || *cp == '_' || *cp == '.' || *cp == '$') {
3634 /* Read past label. */
3636 while (isalnum(*cp) || *cp == '_' || *cp == '.'
3639 if (*cp == ':' || isspace(*cp)) {
3640 /* Found end of label, so copy it and add it to the table. */
3643 cp - lb.buffer) : NULL, TRUE,
3644 lb.buffer, cp - lb.buffer + 1, lineno,
3652 * Perl support by Bart Robinson <lomew@cs.utah.edu>
3653 * enhanced by Michael Ernst <mernst@alum.mit.edu>
3654 * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/
3655 * Perl variable names: /^(my|local).../
3657 void Perl_functions(inf)
3662 LOOP_ON_INPUT_LINES(inf, lb, cp) {
3664 && *cp++ == 'u' && *cp++ == 'b' && isspace(*cp++)) {
3665 cp = skip_spaces(cp);
3668 && !isspace(*cp) && *cp != '{'
3673 cp - lb.buffer) : NULL, TRUE,
3674 lb.buffer, cp - lb.buffer + 1, lineno,
3677 } else if (globals /* only if tagging global vars is enabled */
3678 && ((cp = lb.buffer, *cp++ == 'm' && *cp++ == 'y')
3683 && *cp++ == 'a' && *cp++ == 'l'))
3684 && (*cp == '(' || isspace(*cp))) {
3685 /* After "my" or "local", but before any following paren or space. */
3686 char *varname = NULL;
3688 cp = skip_spaces(cp);
3689 if (*cp == '$' || *cp == '@' || *cp == '%') {
3690 char *varstart = ++cp;
3691 while (isalnum(*cp) || *cp == '_')
3693 varname = savenstr(varstart, cp - varstart);
3695 /* Should be examining a variable list at this point;
3696 could insist on seeing an open parenthesis. */
3697 while (*cp != '\0' && *cp != ';' && *cp != '='
3702 /* Perhaps I should back cp up one character, so the TAGS table
3703 doesn't mention (and so depend upon) the following char. */
3704 pfnote((CTAGS) ? savenstr(lb.buffer, cp - lb.buffer) :
3705 varname, FALSE, lb.buffer, cp - lb.buffer + 1,
3706 lineno, linecharno);
3712 * Python support by Eric S. Raymond <esr@thyrsus.com>
3713 * Look for /^def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
3715 void Python_functions(inf)
3720 LOOP_ON_INPUT_LINES(inf, lb, cp) {
3722 && *cp++ == 'e' && *cp++ == 'f' && isspace(*cp++)) {
3723 cp = skip_spaces(cp);
3724 while (*cp != '\0' && !isspace(*cp) && *cp != '('
3727 pfnote((char *)NULL, TRUE,
3728 lb.buffer, cp - lb.buffer + 1, lineno,
3736 && *cp++ == 's' && *cp++ == 's' && isspace(*cp++)) {
3737 cp = skip_spaces(cp);
3738 while (*cp != '\0' && !isspace(*cp) && *cp != '('
3741 pfnote((char *)NULL, TRUE,
3742 lb.buffer, cp - lb.buffer + 1, lineno,
3748 /* Idea by Corny de Souza
3749 * Cobol tag functions
3750 * We could look for anything that could be a paragraph name.
3751 * i.e. anything that starts in column 8 is one word and ends in a full stop.
3753 void Cobol_paragraphs(inf)
3756 register char *bp, *ep;
3758 LOOP_ON_INPUT_LINES(inf, lb, bp) {
3763 /* If eoln, compiler option or comment ignore whole line. */
3764 if (bp[-1] != ' ' || !isalnum(bp[0]))
3767 for (ep = bp; isalnum(*ep) || *ep == '-'; ep++)
3770 pfnote((CTAGS) ? savenstr(bp, ep - bp) : NULL, TRUE,
3771 lb.buffer, ep - lb.buffer + 1, lineno,
3776 /* Added by Mosur Mohan, 4/22/88 */
3777 /* Pascal parsing */
3780 * Locates tags for procedures & functions. Doesn't do any type- or
3781 * var-definitions. It does look for the keyword "extern" or
3782 * "forward" immediately following the procedure statement; if found,
3783 * the tag is skipped.
3785 void Pascal_functions(inf)
3788 linebuffer tline; /* mostly copied from C_entries */
3790 int save_lineno, save_len;
3791 char c, *cp, *namebuf;
3793 bool /* each of these flags is TRUE iff: */
3794 incomment, /* point is inside a comment */
3795 inquote, /* point is inside '..' string */
3796 get_tagname, /* point is after PROCEDURE/FUNCTION
3797 keyword, so next item = potential tag */
3798 found_tag, /* point is after a potential tag */
3799 inparms, /* point is within parameter-list */
3800 verify_tag; /* point has passed the parm-list, so the
3801 next token will determine whether this
3802 is a FORWARD/EXTERN to be ignored, or
3803 whether it is a real tag */
3805 save_lcno = save_lineno = save_len = 0; /* keep compiler quiet */
3806 namebuf = NULL; /* keep compiler quiet */
3813 incomment = inquote = FALSE;
3814 found_tag = FALSE; /* have a proc name; check if extern */
3815 get_tagname = FALSE; /* have found "procedure" keyword */
3816 inparms = FALSE; /* found '(' after "proc" */
3817 verify_tag = FALSE; /* check if "extern" is ahead */
3819 while (!feof(inf)) { /* long main loop to get next char */
3821 if (c == '\0') { /* if end of line */
3823 linecharno = charno;
3824 charno += readline(&lb, inf);
3828 if (!((found_tag && verify_tag)
3830 c = *dbp++; /* only if don't need *dbp pointing
3831 to the beginning of the name of
3832 the procedure or function */
3835 if (c == '}') /* within { } comments */
3837 else if (c == '*' && *dbp == ')') { /* within (* *) comments */
3842 } else if (inquote) {
3849 inquote = TRUE; /* found first quote */
3851 case '{': /* found open { comment */
3855 if (*dbp == '*') { /* found open (* comment */
3858 } else if (found_tag) /* found '(' after tag, i.e., parm-list */
3861 case ')': /* end of parms list */
3866 if (found_tag && !inparms) { /* end of proc or fn stmt */
3874 if (found_tag && verify_tag && (*dbp != ' ')) {
3875 /* check if this is an "extern" declaration */
3878 if (lowcase(*dbp == 'e')) {
3879 if (tail("extern")) { /* superfluous, really! */
3883 } else if (lowcase(*dbp) == 'f') {
3884 if (tail("forward")) { /* check for forward reference */
3889 if (found_tag && verify_tag) { /* not external proc, so make tag */
3892 pfnote(namebuf, TRUE,
3893 tline.buffer, save_len, save_lineno,
3898 if (get_tagname) { /* grab name of proc or fn */
3902 /* save all values for later tagging */
3903 grow_linebuffer(&tline, lb.len + 1);
3904 strncpy(tline.buffer, lb.buffer, lb.len);
3905 save_lineno = lineno;
3906 save_lcno = linecharno;
3908 /* grab block name */
3909 for (cp = dbp + 1; *cp != '\0' && !endtoken(*cp); cp++)
3911 namebuf = (CTAGS) ? savenstr(dbp, cp - dbp) : NULL;
3912 dbp = cp; /* set dbp to e-o-token */
3913 save_len = dbp - lb.buffer + 1;
3914 get_tagname = FALSE;
3918 /* and proceed to check for "extern" */
3919 } else if (!incomment && !inquote && !found_tag) {
3920 /* check for proc/fn keywords */
3921 switch (lowcase(c)) {
3923 if (tail("rocedure")) /* c = 'p', dbp has advanced */
3927 if (tail("unction"))
3934 } /* while not eof */
3940 * lisp tag functions
3941 * look for (def or (DEF, quote or QUOTE
3943 int L_isdef PP((char *strp));
3945 register char *strp;
3947 return ((strp[1] == 'd' || strp[1] == 'D')
3948 && (strp[2] == 'e' || strp[2] == 'E')
3949 && (strp[3] == 'f' || strp[3] == 'F'));
3951 int L_isquote PP((char *strp));
3953 register char *strp;
3955 return ((*++strp == 'q' || *strp == 'Q')
3956 && (*++strp == 'u' || *strp == 'U')
3957 && (*++strp == 'o' || *strp == 'O')
3958 && (*++strp == 't' || *strp == 'T')
3959 && (*++strp == 'e' || *strp == 'E')
3960 && isspace(*++strp));
3963 void L_getit PP((void));
3968 if (*dbp == '\'') /* Skip prefix quote */
3970 else if (*dbp == '(') {
3972 dbp += 7; /* Skip "(quote " */
3974 dbp += 1; /* Skip "(" before name in (defstruct (foo)) */
3975 dbp = skip_spaces(dbp);
3978 for (cp = dbp /*+1 */ ;
3979 *cp != '\0' && *cp != '(' && *cp != ' ' && *cp != ')'; cp++)
3984 pfnote((CTAGS) ? savenstr(dbp, cp - dbp) : NULL, TRUE,
3985 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3988 void Lisp_functions(inf)
3991 LOOP_ON_INPUT_LINES(inf, lb, dbp) {
3992 if (dbp[0] == '(') {
3994 dbp = skip_non_spaces(dbp);
3995 dbp = skip_spaces(dbp);
3998 /* Check for (foo::defmumble name-defined ... */
4001 while (*dbp != '\0' && !isspace(*dbp)
4002 && *dbp != ':' && *dbp != '('
4007 while (*dbp == ':');
4009 if (L_isdef(dbp - 1)) {
4010 dbp = skip_non_spaces(dbp);
4011 dbp = skip_spaces(dbp);
4021 * Postscript tag functions
4022 * Just look for lines where the first character is '/'
4023 * Richard Mlynarik <mly@adoc.xerox.com>
4025 void Postscript_functions(inf)
4028 register char *bp, *ep;
4030 LOOP_ON_INPUT_LINES(inf, lb, bp) {
4033 *ep != '\0' && *ep != ' ' && *ep != '{'; ep++)
4035 pfnote((CTAGS) ? savenstr(bp, ep - bp) : NULL, TRUE,
4036 lb.buffer, ep - lb.buffer + 1, lineno,
4043 * Scheme tag functions
4044 * look for (def... xyzzy
4045 * look for (def... (xyzzy
4046 * look for (def ... ((...(xyzzy ....
4047 * look for (set! xyzzy
4050 void get_scheme PP((void));
4052 void Scheme_functions(inf)
4055 LOOP_ON_INPUT_LINES(inf, lb, dbp) {
4056 if (dbp[0] == '(' && (dbp[1] == 'D' || dbp[1] == 'd')
4057 && (dbp[2] == 'E' || dbp[2] == 'e')
4058 && (dbp[3] == 'F' || dbp[3] == 'f')) {
4059 dbp = skip_non_spaces(dbp);
4060 /* Skip over open parens and white space */
4061 while (isspace(*dbp) || *dbp == '(')
4065 if (dbp[0] == '(' && (dbp[1] == 'S' || dbp[1] == 's')
4066 && (dbp[2] == 'E' || dbp[2] == 'e')
4067 && (dbp[3] == 'T' || dbp[3] == 't')
4068 && (dbp[4] == '!' || dbp[4] == '!')
4069 && (isspace(dbp[5]))) {
4070 dbp = skip_non_spaces(dbp);
4071 dbp = skip_spaces(dbp);
4083 /* Go till you get to white space or a syntactic break */
4085 *cp != '\0' && *cp != '(' && *cp != ')' && !isspace(*cp); cp++)
4087 pfnote((CTAGS) ? savenstr(dbp, cp - dbp) : NULL, TRUE,
4088 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4091 /* Find tags in TeX and LaTeX input files. */
4093 /* TEX_toktab is a table of TeX control sequences that define tags.
4094 Each TEX_tabent records one such control sequence.
4095 CONVERT THIS TO USE THE Stab TYPE!! */
4101 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
4103 /* Default set of control sequences to put into TEX_toktab.
4104 The value of environment var TEXTAGS is prepended to this. */
4106 char *TEX_defenv = "\
4107 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4108 :part:appendix:entry:index";
4110 void TEX_mode PP((FILE * inf));
4111 struct TEX_tabent *TEX_decode_env PP((char *evarname, char *defenv));
4112 int TEX_Token PP((char *cp));
4114 char TEX_esc = '\\';
4115 char TEX_opgrp = '{';
4116 char TEX_clgrp = '}';
4119 * TeX/LaTeX scanning loop.
4121 void TeX_functions(inf)
4127 /* Select either \ or ! as escape character. */
4130 /* Initialize token table once from environment. */
4132 TEX_toktab = TEX_decode_env("TEXTAGS", TEX_defenv);
4134 LOOP_ON_INPUT_LINES(inf, lb, cp) {
4136 /* Look at each esc in line. */
4137 while ((cp = etags_strchr(cp, TEX_esc)) != NULL) {
4140 linecharno += cp - lasthit;
4142 i = TEX_Token(lasthit);
4144 /* We seem to include the TeX command in the tag name.
4146 for (p = lasthit + TEX_toktab[i].len;
4147 *p != '\0' && *p != TEX_clgrp;
4150 pfnote( /*savenstr (lasthit, p-lasthit) */
4152 lb.buffer, lb.len, lineno, linecharno);
4153 break; /* We only tag a line once */
4159 #define TEX_LESC '\\'
4160 #define TEX_SESC '!'
4163 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4164 chars accordingly. */
4170 while ((c = getc(inf)) != EOF) {
4171 /* Skip to next line if we hit the TeX comment char. */
4175 else if (c == TEX_LESC || c == TEX_SESC)
4179 if (c == TEX_LESC) {
4191 /* Read environment and prepend it to the default string.
4192 Build token table. */
4193 struct TEX_tabent *TEX_decode_env(evarname, defenv)
4197 register char *env, *p;
4199 struct TEX_tabent *tab;
4202 /* Append default string to environment. */
4203 env = getenv(evarname);
4208 env = concat(oldenv, defenv, "");
4212 /* Allocate a token table */
4213 for (size = 1, p = env; p;)
4214 if ((p = etags_strchr(p, ':')) && *++p != '\0')
4216 /* Add 1 to leave room for null terminator. */
4217 tab = xnew(size + 1, struct TEX_tabent);
4219 /* Unpack environment string into token table. Be careful about */
4220 /* zero-length strings (leading ':', "::" and trailing ':') */
4221 for (i = 0; *env;) {
4222 p = etags_strchr(env, ':');
4223 if (!p) /* End of environment string. */
4224 p = env + strlen(env);
4225 if (p - env > 0) { /* Only non-zero strings. */
4226 tab[i].name = savenstr(env, p - env);
4227 tab[i].len = strlen(tab[i].name);
4233 tab[i].name = NULL; /* Mark end of table. */
4241 /* If the text at CP matches one of the tag-defining TeX command names,
4242 return the pointer to the first occurrence of that command in TEX_toktab.
4243 Otherwise return -1.
4244 Keep the capital `T' in `token' for dumb truncating compilers
4245 (this distinguishes it from `TEX_toktab' */
4251 for (i = 0; TEX_toktab[i].len > 0; i++)
4252 if (strneq(TEX_toktab[i].name, cp, TEX_toktab[i].len))
4258 * Prolog support (rewritten) by Anders Lindgren, Mar. 96
4260 * Assumes that the predicate starts at column 0.
4261 * Only the first clause of a predicate is added.
4263 int prolog_pred PP((char *s, char *last));
4264 void prolog_skip_comment PP((linebuffer * plb, FILE * inf));
4265 int prolog_atom PP((char *s, int pos));
4267 void Prolog_functions(inf)
4278 LOOP_ON_INPUT_LINES(inf, lb, cp) {
4279 if (cp[0] == '\0') /* Empty line */
4281 else if (isspace(cp[0])) /* Not a predicate */
4283 else if (cp[0] == '/' && cp[1] == '*') /* comment. */
4284 prolog_skip_comment(&lb, inf);
4285 else if ((len = prolog_pred(cp, last)) > 0) {
4286 /* Predicate. Store the function name so that we only
4287 generate a tag for the first clause. */
4289 last = xnew(len + 1, char);
4290 else if (len + 1 > allocated)
4291 last = xrnew(last, len + 1, char);
4292 allocated = len + 1;
4293 strncpy(last, cp, len);
4300 void prolog_skip_comment(plb, inf)
4307 for (cp = plb->buffer; *cp != '\0'; cp++)
4308 if (cp[0] == '*' && cp[1] == '/')
4311 linecharno += readline(plb, inf);
4317 * A predicate definition is added if it matches:
4318 * <beginning of line><Prolog Atom><whitespace>(
4320 * It is added to the tags database if it doesn't match the
4321 * name of the previous clause header.
4323 * Return the size of the name of the predicate, or 0 if no header
4326 int prolog_pred(s, last)
4328 char *last; /* Name of last clause. */
4333 pos = prolog_atom(s, 0);
4338 pos = skip_spaces(s + pos) - s;
4340 if ((s[pos] == '(') || (s[pos] == '.')) {
4344 /* Save only the first clause. */
4345 if (last == NULL || len != (int)strlen(last)
4346 || !strneq(s, last, len)) {
4347 pfnote((CTAGS) ? savenstr(s, len) : NULL, TRUE,
4348 s, pos, lineno, linecharno);
4356 * Consume a Prolog atom.
4357 * Return the number of bytes consumed, or -1 if there was an error.
4359 * A prolog atom, in this context, could be one of:
4360 * - An alphanumeric sequence, starting with a lower case letter.
4361 * - A quoted arbitrary string. Single quotes can escape themselves.
4362 * Backslash quotes everything.
4364 int prolog_atom(s, pos)
4372 if (islower(s[pos]) || (s[pos] == '_')) {
4373 /* The atom is unquoted. */
4375 while (isalnum(s[pos]) || (s[pos] == '_')) {
4378 return pos - origpos;
4379 } else if (s[pos] == '\'') {
4383 if (s[pos] == '\'') {
4387 pos++; /* A double quote */
4388 } else if (s[pos] == '\0')
4389 /* Multiline quoted atoms are ignored. */
4391 else if (s[pos] == '\\') {
4392 if (s[pos + 1] == '\0')
4398 return pos - origpos;
4404 * Support for Erlang -- Anders Lindgren, Feb 1996.
4406 * Generates tags for functions, defines, and records.
4408 * Assumes that Erlang functions start at column 0.
4410 int erlang_func PP((char *s, char *last));
4411 void erlang_attribute PP((char *s));
4412 int erlang_atom PP((char *s, int pos));
4414 void Erlang_functions(inf)
4425 LOOP_ON_INPUT_LINES(inf, lb, cp) {
4426 if (cp[0] == '\0') /* Empty line */
4428 else if (isspace(cp[0])) /* Not function nor attribute */
4430 else if (cp[0] == '%') /* comment */
4432 else if (cp[0] == '"') /* Sometimes, strings start in column one */
4434 else if (cp[0] == '-') { /* attribute, e.g. "-define" */
4435 erlang_attribute(cp);
4438 } else if ((len = erlang_func(cp, last)) > 0) {
4440 * Function. Store the function name so that we only
4441 * generates a tag for the first clause.
4444 last = xnew(len + 1, char);
4445 else if (len + 1 > allocated)
4446 last = xrnew(last, len + 1, char);
4447 allocated = len + 1;
4448 strncpy(last, cp, len);
4456 * A function definition is added if it matches:
4457 * <beginning of line><Erlang Atom><whitespace>(
4459 * It is added to the tags database if it doesn't match the
4460 * name of the previous clause header.
4462 * Return the size of the name of the function, or 0 if no function
4465 int erlang_func(s, last)
4467 char *last; /* Name of last clause. */
4472 pos = erlang_atom(s, 0);
4477 pos = skip_spaces(s + pos) - s;
4479 /* Save only the first clause. */
4480 if (s[pos++] == '(' && (last == NULL || len != (int)strlen(last)
4481 || !strneq(s, last, len))) {
4482 pfnote((CTAGS) ? savenstr(s, len) : NULL, TRUE,
4483 s, pos, lineno, linecharno);
4491 * Handle attributes. Currently, tags are generated for defines
4494 * They are on the form:
4495 * -define(foo, bar).
4496 * -define(Foo(M, N), M+N).
4497 * -record(graph, {vtab = notable, cyclic = true}).
4499 void erlang_attribute(s)
4505 if (strneq(s, "-define", 7) || strneq(s, "-record", 7)) {
4506 pos = skip_spaces(s + 7) - s;
4507 if (s[pos++] == '(') {
4508 pos = skip_spaces(s + pos) - s;
4509 len = erlang_atom(s, pos);
4511 pfnote((CTAGS) ? savenstr(&s[pos], len) : NULL,
4512 TRUE, s, pos + len, lineno, linecharno);
4519 * Consume an Erlang atom (or variable).
4520 * Return the number of bytes consumed, or -1 if there was an error.
4522 int erlang_atom(s, pos)
4530 if (isalpha(s[pos]) || s[pos] == '_') {
4531 /* The atom is unquoted. */
4533 while (isalnum(s[pos]) || s[pos] == '_')
4535 return pos - origpos;
4536 } else if (s[pos] == '\'') {
4540 if (s[pos] == '\'') {
4543 } else if (s[pos] == '\0')
4544 /* Multiline quoted atoms are ignored. */
4546 else if (s[pos] == '\\') {
4547 if (s[pos + 1] == '\0')
4553 return pos - origpos;
4558 #ifdef ETAGS_REGEXPS
4560 /* Take a string like "/blah/" and turn it into "blah", making sure
4561 that the first and last characters are the same, and handling
4562 quoted separator characters. Actually, stops on the occurrence of
4563 an unquoted separator. Also turns "\t" into a Tab character.
4564 Returns pointer to terminating separator. Works in place. Null
4565 terminates name string. */
4566 char *scan_separators PP((char *name));
4567 char *scan_separators(name)
4571 char *copyto = name;
4572 bool quoted = FALSE;
4574 for (++name; *name != '\0'; ++name) {
4578 else if (*name == sep)
4581 /* Something else is quoted, so preserve the quote. */
4586 } else if (*name == '\\')
4588 else if (*name == sep)
4594 /* Terminate copied string. */
4599 /* Look at the argument of --regex or --no-regex and do the right
4600 thing. Same for each line of a regexp file. */
4601 void analyse_regex(regex_arg)
4604 if (regex_arg == NULL) {
4605 free_patterns(); /* --no-regex: remove existing regexps */
4608 /* A real --regexp option or a line in a regexp file. */
4609 switch (regex_arg[0]) {
4610 /* Comments in regexp file or null arg to --regex. */
4616 /* Read a regex file. This is recursive and may result in a
4617 loop, which will stop when the file descriptors are exhausted. */
4621 linebuffer regexbuf;
4622 char *regexfile = regex_arg + 1;
4624 /* regexfile is a file containing regexps, one per line. */
4625 regexfp = fopen(regexfile, "r");
4626 if (regexfp == NULL) {
4630 initbuffer(®exbuf);
4631 while (readline_internal(®exbuf, regexfp) > 0)
4632 analyse_regex(regexbuf.buffer);
4633 free(regexbuf.buffer);
4638 /* Regexp to be used for a specific language only. */
4642 char *lang_name = regex_arg + 1;
4645 for (cp = lang_name; *cp != '}'; cp++)
4648 ("unterminated language name in regex: %s",
4653 lang = get_language_from_name(lang_name);
4656 add_regex(cp + 1, lang);
4660 /* Regexp to be used for any language. */
4662 add_regex(regex_arg, NULL);
4667 /* Turn a name, which is an ed-style (but Emacs syntax) regular
4668 expression, into a real regular expression by compiling it. */
4669 void add_regex(regexp_pattern, lang)
4670 char *regexp_pattern;
4675 struct re_pattern_buffer *patbuf;
4678 if (regexp_pattern[strlen(regexp_pattern) - 1] != regexp_pattern[0]) {
4679 error("%s: unterminated regexp", regexp_pattern);
4682 name = scan_separators(regexp_pattern);
4683 if (regexp_pattern[0] == '\0') {
4684 error("null regexp", (char *)NULL);
4687 (void)scan_separators(name);
4689 patbuf = xnew(1, struct re_pattern_buffer);
4690 patbuf->translate = NULL;
4691 patbuf->fastmap = NULL;
4692 patbuf->buffer = NULL;
4693 patbuf->allocated = 0;
4696 re_compile_pattern(regexp_pattern, strlen(regexp_pattern), patbuf);
4698 error("%s while compiling pattern", err);
4703 p_head = xnew(1, pattern);
4704 p_head->regex = savestr(regexp_pattern);
4705 p_head->p_next = pp;
4706 p_head->language = lang;
4707 p_head->pattern = patbuf;
4708 p_head->name_pattern = savestr(name);
4709 p_head->error_signaled = FALSE;
4713 * Do the substitutions indicated by the regular expression and
4716 char *substitute PP((char *in, char *out, struct re_registers * regs));
4717 char *substitute(in, out, regs)
4719 struct re_registers *regs;
4722 int size, dig, diglen;
4727 /* Pass 1: figure out how much to allocate by finding all \N strings. */
4728 if (out[size - 1] == '\\')
4729 fatal("pattern error in \"%s\"", out);
4730 for (t = etags_strchr(out, '\\');
4731 t != NULL; t = etags_strchr(t + 2, '\\'))
4732 if (isdigit(t[1])) {
4734 diglen = regs->end[dig] - regs->start[dig];
4739 /* Allocate space and do the substitutions. */
4740 result = xnew(size + 1, char);
4742 for (t = result; *out != '\0'; out++)
4743 if (*out == '\\' && isdigit(*++out)) {
4744 /* Using "dig2" satisfies my debugger. Bleah. */
4746 diglen = regs->end[dig] - regs->start[dig];
4747 strncpy(t, in + regs->start[dig], diglen);
4753 if (DEBUG && (t > result + size || t - result != strlen(result)))
4759 /* Deallocate all patterns. */
4760 void free_patterns()
4763 while (p_head != NULL) {
4764 pp = p_head->p_next;
4765 free(p_head->regex);
4766 free(p_head->name_pattern);
4773 #endif /* ETAGS_REGEXPS */
4774 /* Initialize a linebuffer for use */
4775 void initbuffer(lbp)
4779 lbp->buffer = xnew(200, char);
4783 * Read a line of text from `stream' into `lbp', excluding the
4784 * newline or CR-NL, if any. Return the number of characters read from
4785 * `stream', which is the length of the line including the newline.
4787 * On DOS or Windows we do not count the CR character, if any, before the
4788 * NL, in the returned length; this mirrors the behavior of emacs on those
4789 * platforms (for text files, it translates CR-NL to NL as it reads in the
4792 long readline_internal(lbp, stream)
4794 register FILE *stream;
4796 char *buffer = lbp->buffer;
4797 register char *p = lbp->buffer;
4798 register char *pend;
4801 pend = p + lbp->size; /* Separate to avoid 386/IX compiler bug. */
4804 register int c = getc(stream);
4806 /* We're at the end of linebuffer: expand it. */
4808 buffer = xrnew(buffer, lbp->size, char);
4809 p += buffer - lbp->buffer;
4810 pend = buffer + lbp->size;
4811 lbp->buffer = buffer;
4819 if (p > buffer && p[-1] == '\r') {
4830 lbp->len = p - buffer;
4832 return lbp->len + chars_deleted;
4836 * Like readline_internal, above, but in addition try to match the
4837 * input line against relevant regular expressions.
4839 long readline(lbp, stream)
4843 /* Read new line. */
4844 long result = readline_internal(lbp, stream);
4845 #ifdef ETAGS_REGEXPS
4849 /* Match against relevant patterns. */
4851 for (pp = p_head; pp != NULL; pp = pp->p_next) {
4852 /* Only use generic regexps or those for the current language. */
4853 if (pp->language != NULL && pp->language != curlang)
4857 re_match(pp->pattern, lbp->buffer, lbp->len, 0,
4862 if (!pp->error_signaled) {
4863 error("error while matching \"%s\"",
4865 pp->error_signaled = TRUE;
4872 /* Match occurred. Construct a tag. */
4873 if (pp->name_pattern[0] != '\0') {
4874 /* Make a named tag. */
4875 char *name = substitute(lbp->buffer,
4880 pfnote(name, TRUE, lbp->buffer,
4884 /* Make an unnamed tag. */
4885 pfnote((char *)NULL, TRUE,
4886 lbp->buffer, match, lineno,
4892 #endif /* ETAGS_REGEXPS */
4898 * Return a pointer to a space of size strlen(cp)+1 allocated
4899 * with xnew where the string CP has been copied.
4904 return savenstr(cp, strlen(cp));
4908 * Return a pointer to a space of size LEN+1 allocated with xnew where
4909 * the string CP has been copied for at most the first LEN characters.
4911 char *savenstr(cp, len)
4917 dp = xnew(len + 1, char);
4918 strncpy(dp, cp, len);
4924 * Return the ptr in sp at which the character c last
4925 * appears; NULL if not found
4927 * Identical to System V strrchr, included for portability.
4929 char *etags_strrchr(sp, c)
4944 * Return the ptr in sp at which the character c first
4945 * appears; NULL if not found
4947 * Identical to System V strchr, included for portability.
4949 char *etags_strchr(sp, c)
4960 /* Skip spaces, return new pointer. */
4961 char *skip_spaces(cp)
4964 while (isspace(*cp)) /* isspace('\0')==FALSE */
4969 /* Skip non spaces, return new pointer. */
4970 char *skip_non_spaces(cp)
4973 while (!iswhite(*cp)) /* iswhite('\0')==TRUE */
4978 /* Print error message and exit. */
4993 void suggest_asking_for_help()
4995 fprintf(stderr, "\tTry `%s %s' for a complete list of options.\n",
5006 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
5008 const char *s1, *s2;
5010 fprintf(stderr, "%s: ", progname);
5011 fprintf(stderr, s1, s2);
5012 fprintf(stderr, "\n");
5015 /* Return a newly-allocated string whose contents
5016 concatenate those of s1, s2, s3. */
5017 char *concat(s1, s2, s3)
5020 int len1 = strlen(s1), len2 = strlen(s2), len3 = strlen(s3);
5021 char *result = xnew(len1 + len2 + len3 + 1, char);
5024 strcpy(result + len1, s2);
5025 strcpy(result + len1 + len2, s3);
5026 result[len1 + len2 + len3] = '\0';
5031 /* Does the same work as the system V getcwd, but does not need to
5032 guess the buffer size in advance. */
5033 char *etags_getcwd()
5037 char *path = xnew(bufsize, char);
5039 while (getcwd(path, bufsize) == NULL) {
5040 if (errno != ERANGE)
5044 path = xnew(bufsize, char);
5047 canonicalize_filename(path);
5050 #else /* not HAVE_GETCWD */
5055 pipe = (FILE *) popen("pwd 2>/dev/null", "r");
5056 if (pipe == NULL || readline_internal(&path, pipe) == 0)
5061 #endif /* not HAVE_GETCWD */
5064 /* Return a newly allocated string containing the file name of FILE
5065 relative to the absolute directory DIR (which should end with a slash). */
5066 char *relative_filename(file, dir)
5069 char *fp, *dp, *afn, *res;
5073 /* Find the common root of file and dir (with a trailing slash). */
5074 afn = absolute_filename(file, cwd);
5077 while (*fp++ == *dp++)
5079 fp--, dp--; /* back to the first differing char */
5080 do /* look at the equal chars until '/' */
5083 fp ++; /* Advance past the '/' */
5085 /* Build a sequence of "../" strings for the resulting relative file name. */
5087 while ((dp = etags_strchr(dp + 1, '/')) != NULL)
5089 res_left = 3 * i + strlen(fp);
5090 res = xnew( res_left + 1, char);
5092 for ( ; i-- > 0 ; res_left -= 4 )
5093 strncat(res, "../", res_left );
5095 /* Add the file name relative to the common root of file and dir. */
5096 strncat(res, fp, res_left);
5102 /* Return a newly allocated string containing the absolute file name
5103 of FILE given DIR (which should end with a slash). */
5104 char *absolute_filename(file, dir)
5107 char *slashp, *cp, *res;
5109 if (filename_is_absolute(file))
5110 res = savestr(file);
5112 res = concat(dir, file, "");
5114 /* Delete the "/dirname/.." and "/." substrings. */
5115 slashp = etags_strchr(res, '/');
5116 while (slashp != NULL && slashp[0] != '\0') {
5117 if (slashp[1] == '.') {
5118 if (slashp[2] == '.'
5119 && (slashp[3] == '/' || slashp[3] == '\0')) {
5123 while (cp >= res && !filename_is_absolute(cp));
5125 cp = slashp; /* the absolute name begins with "/.." */
5126 strcpy(cp, slashp + 3);
5129 } else if (slashp[2] == '/' || slashp[2] == '\0') {
5130 strcpy(slashp, slashp + 2);
5135 slashp = etags_strchr(slashp + 1, '/');
5139 return savestr("/");
5144 /* Return a newly allocated string containing the absolute
5145 file name of dir where FILE resides given DIR (which should
5146 end with a slash). */
5147 char *absolute_dirname(file, dir)
5153 canonicalize_filename(file);
5154 slashp = etags_strrchr(file, '/');
5156 return savestr(dir);
5159 res = absolute_filename(file, dir);
5165 /* Whether the argument string is an absolute file name. The argument
5166 string must have been canonicalized with canonicalize_filename. */
5167 bool filename_is_absolute(fn)
5170 return (fn[0] == '/');
5173 /* Translate backslashes into slashes. Works in place. */
5174 void canonicalize_filename(fn)
5180 /* Increase the size of a linebuffer. */
5181 void grow_linebuffer(lbp, toksize)
5185 while (lbp->size < toksize)
5187 lbp->buffer = xrnew(lbp->buffer, lbp->size, char);
5190 /* Like malloc but get fatal error if memory is exhausted. */
5194 long *result = (long *)malloc(size);
5196 fatal("virtual memory exhausted", (char *)NULL);
5200 long *xrealloc(ptr, size)
5204 long *result = (long *)realloc(ptr, size);
5206 fatal("virtual memory exhausted", (char *)NULL);