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)))
177 #define xstrncpy(d_,s_,l_) \
181 strncat((dst_),(s_),(l_)-1); \
187 typedef void Lang_function(FILE *);
191 Lang_function *function;
196 typedef struct node_st { /* sorting structure */
197 char *name; /* function or type name */
199 short int construct; /* Construct type for the OO-Browser */
201 char *file; /* file name */
202 bool is_func; /* use pattern or line no */
203 bool been_warned; /* set if noticed dup */
204 int lno; /* line number tag is on */
205 long cno; /* character number line starts on */
206 char *pat; /* search pattern */
207 struct node_st *left, *right; /* left and right sons */
211 /* If you add to this array, you must add a corresponding entry to the
213 static char *oo_browser_default_classes[] =
214 /* Lack of square brackets around some of these entries are intentional. */
215 { "null", "class", "method", "[constant]", "[enumeration]", "[enum_label]",
216 "extern", "[function]", "[macro]", "objc", "[structure]", "[type]",
217 "[union]", "[variable]"
220 /* If you add to this enum, you must add a corresponding entry to the
222 enum oo_browser_constructs { C_NULL, C_CLASS, C_METHOD, C_CONSTANT,
224 C_ENUM_LABEL, C_EXTERN, C_FUNCTION, C_MACRO,
225 C_OBJC, C_STRUCTURE, C_TYPE, C_UNION, C_VARIABLE
228 enum oo_browser_constructs oo_browser_construct = C_NULL;
232 * A `linebuffer' is a structure which holds a line of text.
233 * `readline_internal' reads a line from a stream into a linebuffer
234 * and works regardless of the length of the line.
235 * SIZE is the size of BUFFER, LEN is the length of the string in
236 * BUFFER after readline reads it.
244 extern char *getenv PP((const char *envvar));
246 /* Many compilers barf on this:
247 Lang_function Asm_labels;
248 so let's write it this way */
249 void Asm_labels PP((FILE * inf));
250 void C_entries PP((int c_ext, FILE * inf));
251 void default_C_entries PP((FILE * inf));
252 void plain_C_entries PP((FILE * inf));
253 void Cjava_entries PP((FILE * inf));
254 void Cplusplus_entries PP((FILE * inf));
255 void Yacc_entries PP((FILE * inf));
256 void Cobol_paragraphs PP((FILE * inf));
257 void Cstar_entries PP((FILE * inf));
258 void Erlang_functions PP((FILE * inf));
259 void Fortran_functions PP((FILE * inf));
260 void Lisp_functions PP((FILE * inf));
261 void Pascal_functions PP((FILE * inf));
262 void Perl_functions PP((FILE * inf));
263 void Postscript_functions PP((FILE * inf));
264 void Prolog_functions PP((FILE * inf));
265 void Python_functions PP((FILE * inf));
266 void Scheme_functions PP((FILE * inf));
267 void TeX_functions PP((FILE * inf));
268 void just_read_file PP((FILE * inf));
270 void print_language_names PP((void));
271 void print_version PP((void));
272 void print_help PP((void));
274 language *get_language_from_name PP((char *name));
275 language *get_language_from_interpreter PP((char *interpreter));
276 language *get_language_from_suffix PP((char *suffix));
277 int total_size_of_entries PP((node * np));
278 long readline PP((linebuffer * lbp, FILE * stream));
279 long readline_internal PP((linebuffer * lbp, FILE * stream));
281 void analyse_regex PP((char *regex_arg));
282 void add_regex PP((char *regexp_pattern, language * lang));
283 void free_patterns PP((void));
284 #endif /* ETAGS_REGEXPS */
285 void error PP((const char *s1, const char *s2));
286 void suggest_asking_for_help PP((void));
287 void fatal PP((char *s1, char *s2));
288 void pfatal PP((char *s1));
289 void add_node PP((node * np, node ** cur_node_p));
291 void init PP((void));
292 void initbuffer PP((linebuffer * lbp));
293 void find_entries PP((char *file, FILE * inf));
294 void free_tree PP((node * np));
296 PP((char *name, bool is_func, char *linestart, int linelen, int lno, long cno));
298 PP((char *name, int namelen, bool is_func, char *linestart, int linelen,
300 void process_file PP((char *file));
301 void put_entries PP((node * np));
302 void takeprec PP((void));
304 char *concat PP((char *s1, char *s2, char *s3));
305 char *skip_spaces PP((char *cp));
306 char *skip_non_spaces PP((char *cp));
307 char *savenstr PP((char *cp, int len));
308 char *savestr PP((char *cp));
309 char *etags_strchr PP((char *sp, int c));
310 char *etags_strrchr PP((char *sp, int c));
311 char *etags_getcwd PP((void));
312 char *relative_filename PP((char *file, char *dir));
313 char *absolute_filename PP((char *file, char *dir));
314 char *absolute_dirname PP((char *file, char *dir));
315 bool filename_is_absolute PP((char *fn));
316 void canonicalize_filename PP((char *fn));
317 void grow_linebuffer PP((linebuffer * lbp, int toksize));
318 long *xmalloc PP((unsigned int size));
319 long *xrealloc PP((char *ptr, unsigned int size));
321 char searchar = '/'; /* use /.../ searches */
323 char *tagfile; /* output file */
324 char *progname; /* name this program was invoked with */
325 char *cwd; /* current working directory */
326 char *tagfiledir; /* directory of tagfile */
327 FILE *tagf; /* ioptr for tags file */
329 char *curfile; /* current input file name */
330 language *curlang; /* current language */
332 int lineno; /* line number of current line */
333 long charno; /* current character number */
334 long linecharno; /* charno of start of current line */
335 char *dbp; /* pointer to start of current tag */
336 node *head; /* the head of the binary tree of tags */
338 linebuffer lb; /* the current line */
339 linebuffer token_name; /* used by C_entries as a temporary area */
342 linebuffer lb; /* used by C_entries instead of lb */
345 /* boolean "functions" (see init) */
346 bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
349 *white = " \f\t\n\r",
351 *nonam = " \f\t\n\r(=,[;",
352 /* token ending chars */
353 *endtk = " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
354 /* token starting chars */
355 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
356 /* valid in-token chars */
357 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
359 bool append_to_tagfile; /* -a: append to tags */
360 /* The following four default to TRUE for etags, but to FALSE for ctags. */
361 bool typedefs; /* -t: create tags for C typedefs */
362 bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */
363 /* 0 struct/enum/union decls, and C++ */
364 /* member functions. */
365 bool constantypedefs; /* -d: create tags for C #define, enum */
366 /* constants and variables. */
367 /* -D: opposite of -d. Default under ctags. */
368 bool globals; /* create tags for global variables */
369 bool members; /* create tags for C member variables */
370 bool update; /* -u: update tags */
371 bool vgrind_style; /* -v: create vgrind style index output */
372 bool no_warnings; /* -w: suppress warnings */
373 bool cxref_style; /* -x: create cxref style output */
374 bool cplusplus; /* .[hc] means C++, not C */
375 bool noindentypedefs; /* -I: ignore indentation in C */
377 bool oo_browser_format; /* -O: OO-Browser tags format */
381 struct option longopts[] = {
382 {"append", no_argument, NULL, 'a'},
383 {"backward-search", no_argument, NULL, 'B'},
384 {"c++", no_argument, NULL, 'C'},
385 {"cxref", no_argument, NULL, 'x'},
386 {"defines", no_argument, NULL, 'd'},
387 {"no-defines", no_argument, NULL, 'D'},
388 {"globals", no_argument, &globals, TRUE},
389 {"no-globals", no_argument, &globals, FALSE},
390 {"help", no_argument, NULL, 'h'},
391 {"help", no_argument, NULL, 'H'},
392 {"ignore-indentation", no_argument, NULL, 'I'},
393 {"include", required_argument, NULL, 'i'},
394 {"language", required_argument, NULL, 'l'},
395 {"members", no_argument, &members, TRUE},
396 {"no-members", no_argument, &members, FALSE},
397 {"no-warn", no_argument, NULL, 'w'},
398 {"output", required_argument, NULL, 'o'},
400 {"oo-browser", no_argument, NULL, 'O'},
403 {"regex", required_argument, NULL, 'r'},
404 {"no-regex", no_argument, NULL, 'R'},
405 #endif /* ETAGS_REGEXPS */
406 {"typedefs", no_argument, NULL, 't'},
407 {"typedefs-and-c++", no_argument, NULL, 'T'},
408 {"update", no_argument, NULL, 'u'},
409 {"version", no_argument, NULL, 'V'},
410 {"vgrind", no_argument, NULL, 'v'},
413 #endif /* LONG_OPTIONS */
416 /* Structure defining a regular expression. Elements are
417 the compiled pattern, and the name string. */
418 typedef struct pattern {
419 struct pattern *p_next;
422 struct re_pattern_buffer *pattern;
423 struct re_registers regs;
428 /* Array of all regexps. */
429 pattern *p_head = NULL;
430 #endif /* ETAGS_REGEXPS */
436 /* Non-NULL if language fixed. */
437 language *forced_lang = NULL;
440 char *Asm_suffixes[] = { "a", /* Unix assembler */
441 "asm", /* Microcontroller assembly */
442 "def", /* BSO/Tasking definition includes */
443 "inc", /* Microcontroller include files */
444 "ins", /* Microcontroller include files */
445 "s", "sa", /* Unix assembler */
446 "src", /* BSO/Tasking C compiler output */
450 /* Note that .c and .h can be considered C++, if the --c++ flag was
451 given. That is why default_C_entries is called here. */
452 char *default_C_suffixes[] = { "c", "h", NULL };
454 char *Cplusplus_suffixes[] =
455 { "C", "H", "c++", "cc", "cpp", "cxx", "h++", "hh", "hpp", "hxx",
456 "M", /* Objective C++ */
457 "pdb", /* Postscript with C syntax */
461 char *Cjava_suffixes[] = { "java", NULL };
463 char *Cobol_suffixes[] = { "COB", "cob", NULL };
465 char *Cstar_suffixes[] = { "cs", "hs", NULL };
467 char *Erlang_suffixes[] = { "erl", "hrl", NULL };
469 char *Fortran_suffixes[] = { "F", "f", "f90", "for", NULL };
471 char *Lisp_suffixes[] = { "cl", "clisp", "el", "l", "lisp", "lsp", "ml", NULL };
473 char *Pascal_suffixes[] = { "p", "pas", NULL };
475 char *Perl_suffixes[] = { "pl", "pm", NULL };
476 char *Perl_interpreters[] = { "perl", "@PERL@", NULL };
478 char *plain_C_suffixes[] = { "pc", /* Pro*C file */
479 "m", /* Objective C file */
480 "lm", /* Objective lex file */
484 char *Postscript_suffixes[] = { "ps", NULL };
486 char *Prolog_suffixes[] = { "prolog", NULL };
488 char *Python_suffixes[] = { "py", NULL };
490 /* Can't do the `SCM' or `scm' prefix with a version number. */
491 char *Scheme_suffixes[] =
492 { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "ss", "t", NULL };
494 char *TeX_suffixes[] =
495 { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL };
497 char *Yacc_suffixes[] = { "y", "ym", NULL }; /* .ym is Objective yacc file */
500 * Table of languages.
502 * It is ok for a given function to be listed under more than one
503 * name. I just didn't.
506 language lang_names[] = {
507 {"asm", Asm_labels, Asm_suffixes, NULL},
508 {"c", default_C_entries, default_C_suffixes, NULL},
509 {"c++", Cplusplus_entries, Cplusplus_suffixes, NULL},
510 {"c*", Cstar_entries, Cstar_suffixes, NULL},
511 {"cobol", Cobol_paragraphs, Cobol_suffixes, NULL},
512 {"erlang", Erlang_functions, Erlang_suffixes, NULL},
513 {"fortran", Fortran_functions, Fortran_suffixes, NULL},
514 {"java", Cjava_entries, Cjava_suffixes, NULL},
515 {"lisp", Lisp_functions, Lisp_suffixes, NULL},
516 {"pascal", Pascal_functions, Pascal_suffixes, NULL},
517 {"perl", Perl_functions, Perl_suffixes, Perl_interpreters},
518 {"postscript", Postscript_functions, Postscript_suffixes, NULL},
519 {"proc", plain_C_entries, plain_C_suffixes, NULL},
520 {"prolog", Prolog_functions, Prolog_suffixes, NULL},
521 {"python", Python_functions, Python_suffixes, NULL},
522 {"scheme", Scheme_functions, Scheme_suffixes, NULL},
523 {"tex", TeX_functions, TeX_suffixes, NULL},
524 {"yacc", Yacc_entries, Yacc_suffixes, NULL},
525 {"auto", NULL}, /* default guessing scheme */
526 {"none", just_read_file}, /* regexp matching only */
527 {NULL, NULL} /* end of list */
530 void print_language_names()
535 puts("\nThese are the currently supported languages, along with the\n\
536 default file name suffixes:");
537 for (lang = lang_names; lang->name != NULL; lang++) {
538 printf("\t%s\t", lang->name);
539 if (lang->suffixes != NULL)
540 for (ext = lang->suffixes; *ext != NULL; ext++)
541 printf(" .%s", *ext);
544 puts("Where `auto' means use default language for files based on file\n\
545 name suffix, and `none' means only do regexp processing on files.\n\
546 If no language is specified and no matching suffix is found,\n\
547 the first line of the file is read for a sharp-bang (#!) sequence\n\
548 followed by the name of an interpreter. If no such sequence is found,\n\
549 Fortran is tried first; if no tags are found, C is tried next.");
553 # define VERSION "20"
557 printf("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION);
558 puts("Copyright (C) 1996 Free Software Foundation, Inc. and Ken Arnold");
559 puts("This program is distributed under the same terms as Emacs");
566 printf("Usage: %s [options] [[regex-option ...] file-name] ...\n\
568 These are the options accepted by %s.\n", progname, progname);
570 puts("You may use unambiguous abbreviations for the long option names.");
572 puts("Long option names do not work with this executable, as it is not\n\
573 linked with GNU getopt.");
574 #endif /* LONG_OPTIONS */
575 puts("A - as file name means read names from stdin (one per line).");
578 (" Absolute names are stored in the output file as they are.\n\
579 Relative ones are stored relative to the output file's directory.");
582 puts("-a, --append\n\
583 Append tag entries to existing tags file.");
586 puts("-B, --backward-search\n\
587 Write the search commands for the tag entries using '?', the\n\
588 backward-search command instead of '/', the forward-search command.");
591 Treat files whose name suffix defaults to C language as C++ files.");
594 puts("-d, --defines\n\
595 Create tag entries for C #define constants and enum constants, too.");
597 puts("-D, --no-defines\n\
598 Don't create tag entries for C #define constants and enum constants.\n\
599 This makes the tags file smaller.");
602 puts("-i FILE, --include=FILE\n\
603 Include a note in tag file indicating that, when searching for\n\
604 a tag, one should also consult the tags file FILE after\n\
605 checking the current file.");
606 puts("-l LANG, --language=LANG\n\
607 Force the following files to be considered as written in the\n\
608 named language up to the next --language=LANG option.");
613 Create tag entries for global variables in some languages.");
615 puts("--no-globals\n\
616 Do not create tag entries for global variables in some\n\
617 languages. This makes the tags file smaller.");
619 Create tag entries for member variables in C and derived languages.");
622 puts("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
623 Make a tag for each line matching pattern REGEXP in the\n\
624 following files. regexfile is a file containing one REGEXP\n\
625 per line. REGEXP is anchored (as if preceded by ^).\n\
626 The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
627 named tags can be created with:\n\
628 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
629 puts("-R, --no-regex\n\
630 Don't create tags from regexps for the following files.");
631 #endif /* ETAGS_REGEXPS */
632 puts("-o FILE, --output=FILE\n\
633 Write the tags to FILE.");
635 puts("-O, --oo-browser\n\
636 Generate a specialized tags format used only by the Altrasoft OO-Browser.");
638 puts("-I, --ignore-indentation\n\
639 Don't rely on indentation quite as much as normal. Currently,\n\
640 this means not to assume that a closing brace in the first\n\
641 column is the final brace of a function or structure\n\
642 definition in C and C++.");
645 puts("-t, --typedefs\n\
646 Generate tag entries for C typedefs.");
647 puts("-T, --typedefs-and-c++\n\
648 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
649 and C++ member functions.");
650 puts("-u, --update\n\
651 Update the tag entries for the given files, leaving tag\n\
652 entries for other files in place. Currently, this is\n\
653 implemented by deleting the existing entries for the given\n\
654 files and then rewriting the new entries at the end of the\n\
655 tags file. It is often faster to simply rebuild the entire\n\
656 tag file than to use this.");
657 puts("-v, --vgrind\n\
658 Generates an index of items intended for human consumption,\n\
659 similar to the output of vgrind. The index is sorted, and\n\
660 gives the page number of each item.");
661 puts("-w, --no-warn\n\
662 Suppress warning messages about entries defined in multiple\n\
665 Like --vgrind, but in the style of cxref, rather than vgrind.\n\
666 The output uses line numbers instead of page numbers, but\n\
667 beyond that the differences are cosmetic; try both to see\n\
671 puts("-V, --version\n\
672 Print the version of the program.\n\
674 Print this help message.");
676 print_language_names();
679 puts("Report bugs to bug-gnu-emacs@prep.ai.mit.edu");
690 /* This structure helps us allow mixing of --lang and file names. */
692 enum argument_type arg_type;
697 #ifdef VMS /* VMS specific functions */
701 /* This is a BUG! ANY arbitrary limit is a BUG!
702 Won't someone please fix this? */
703 #define MAX_FILE_SPEC_LEN 255
706 char body[MAX_FILE_SPEC_LEN + 1];
710 v1.05 nmm 26-Jun-86 fn_exp - expand specification of list of file names
711 returning in each successive call the next file name matching the input
712 spec. The function expects that each in_spec passed
713 to it will be processed to completion; in particular, up to and
714 including the call following that in which the last matching name
715 is returned, the function ignores the value of in_spec, and will
716 only start processing a new spec with the following call.
717 If an error occurs, on return out_spec contains the value
718 of in_spec when the error occurred.
720 With each successive file name returned in out_spec, the
721 function's return value is one. When there are no more matching
722 names the function returns zero. If on the first call no file
723 matches in_spec, or there is any other error, -1 is returned.
728 #define OUTSIZE MAX_FILE_SPEC_LEN
729 short fn_exp(out, in)
733 static long context = 0;
734 static struct dsc$descriptor_s o;
735 static struct dsc$descriptor_s i;
736 static bool pass1 = TRUE;
742 o.dsc$a_pointer = (char *)out;
743 o.dsc$w_length = (short)OUTSIZE;
744 i.dsc$a_pointer = in;
745 i.dsc$w_length = (short)strlen(in);
746 i.dsc$b_dtype = DSC$K_DTYPE_T;
747 i.dsc$b_class = DSC$K_CLASS_S;
748 o.dsc$b_dtype = DSC$K_DTYPE_VT;
749 o.dsc$b_class = DSC$K_CLASS_VS;
751 if ((status = lib$find_file(&i, &o, &context, 0, 0)) == RMS$_NORMAL) {
752 out->body[out->curlen] = EOS;
754 } else if (status == RMS$_NMF)
757 strcpy(out->body, in);
760 lib$find_file_end(&context);
766 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
767 name of each file specified by the provided arg expanding wildcards.
769 char *gfnames(arg, p_error)
773 static vspec filename = { MAX_FILE_SPEC_LEN, "\0" };
775 switch (fn_exp(&filename, arg)) {
778 return filename.body;
784 return filename.body;
788 #ifndef OLD /* Newer versions of VMS do provide `system'. */
792 error("%s", "system() function not implemented under VMS");
796 #define VERSION_DELIM ';'
797 char *massage_name(s)
803 if (*s == VERSION_DELIM) {
812 int main(int argc, char *argv[])
815 unsigned int nincluded_files;
816 char **included_files;
819 int current_arg, file_count;
820 linebuffer filename_lb;
827 included_files = xnew(argc, char *);
831 /* Allocate enough no matter what happens. Overkill, but each one
833 argbuffer = xnew(argc, argument);
836 /* Set syntax for regular expression routines. */
837 re_set_syntax(RE_SYNTAX_EMACS | RE_INTERVALS);
838 #endif /* ETAGS_REGEXPS */
841 * If etags, always find typedefs and structure tags. Why not?
842 * Also default is to find macro constants, enum constants and
846 typedefs = typedefs_and_cplusplus = constantypedefs = TRUE;
857 optstring = "-aCdDf:Il:o:r:RStTi:BuvxwVhH";
859 optstring = "-aCdDf:Il:o:r:RStTi:BOuvxwVhH";
863 optstring = "-aCdDf:Il:o:StTi:BuvxwVhH";
865 optstring = "-aCdDf:Il:o:StTi:BOuvxwVhH";
867 #endif /* ETAGS_REGEXPS */
870 optstring = optstring + 1;
871 #endif /* LONG_OPTIONS */
873 opt = getopt_long(argc, argv, optstring, longopts, 0);
879 /* If getopt returns 0, then it has already processed a
880 long-named option. We should do nothing. */
884 /* This means that a file name has been seen. Record it. */
885 argbuffer[current_arg].arg_type = at_filename;
886 argbuffer[current_arg].what = optarg;
891 /* Common options. */
893 append_to_tagfile = TRUE;
899 constantypedefs = TRUE;
902 constantypedefs = FALSE;
904 case 'f': /* for compatibility with old makefiles */
907 /* convert char to string, to call error with */
910 error("-%s option may only be given once.",
912 suggest_asking_for_help();
918 oo_browser_format = TRUE;
922 case 'S': /* for backward compatibility */
923 noindentypedefs = TRUE;
927 language *lang = get_language_from_name(optarg);
929 argbuffer[current_arg].lang = lang;
930 argbuffer[current_arg].arg_type =
938 argbuffer[current_arg].arg_type = at_regexp;
939 argbuffer[current_arg].what = optarg;
943 argbuffer[current_arg].arg_type = at_regexp;
944 argbuffer[current_arg].what = NULL;
947 #endif /* ETAGS_REGEXPS */
959 typedefs = typedefs_and_cplusplus = TRUE;
964 included_files[nincluded_files++] = optarg;
976 /*FALLTHRU*/ case 'x':
984 suggest_asking_for_help();
988 for (; optind < argc; ++optind) {
989 argbuffer[current_arg].arg_type = at_filename;
990 argbuffer[current_arg].what = argv[optind];
995 if (nincluded_files == 0 && file_count == 0) {
996 error("no input files specified.", 0);
997 suggest_asking_for_help();
1000 if (tagfile == NULL)
1001 tagfile = CTAGS ? "tags" : "TAGS";
1002 cwd = etags_getcwd(); /* the current working directory */
1003 if (cwd[strlen(cwd) - 1] != '/') {
1005 cwd = concat(oldcwd, "/", "");
1008 if (streq(tagfile, "-"))
1011 tagfiledir = absolute_dirname(tagfile, cwd);
1013 init(); /* set up boolean "functions" */
1016 initbuffer(&token_name);
1017 initbuffer(&lbs[0].lb);
1018 initbuffer(&lbs[1].lb);
1019 initbuffer(&filename_lb);
1022 if (streq(tagfile, "-")) {
1025 tagf = fopen(tagfile, append_to_tagfile ? "a" : "w");
1031 * Loop through files finding functions.
1033 for (i = 0; i < current_arg; ++i) {
1034 switch (argbuffer[i].arg_type) {
1036 forced_lang = argbuffer[i].lang;
1038 #ifdef ETAGS_REGEXPS
1040 analyse_regex(argbuffer[i].what);
1046 gfnames(argbuffer[i].what, &got_err)) != NULL) {
1048 error("can't find file %s\n",
1052 this_file = massage_name(this_file);
1055 this_file = argbuffer[i].what;
1058 oo_browser_clear_all_globals();
1060 /* Input file named "-" means read file names from stdin
1061 (one per line) and use them. */
1062 if (streq(this_file, "-"))
1063 while (readline_internal(&filename_lb, stdin) >
1067 oo_browser_clear_some_globals();
1069 process_file(filename_lb.buffer);
1074 process_file(this_file);
1084 #ifdef ETAGS_REGEXPS
1086 #endif /* ETAGS_REGEXPS */
1089 while (nincluded_files-- > 0)
1090 fprintf(tagf, "\f\n%s,include\n", *included_files++);
1096 /* If CTAGS, we are here. process_file did not write the tags yet,
1097 because we want them ordered. Let's do it now. */
1106 for (i = 0; i < current_arg; ++i) {
1107 if (argbuffer[i].arg_type != at_filename)
1109 sz = snprintf(cmd, sizeof(cmd),
1110 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
1111 tagfile, argbuffer[i].what, tagfile);
1112 if(sz >= 0 && (size_t)sz < sizeof(cmd))
1113 fatal("failed to build shell command line", (char *)NULL);
1114 if (system(cmd) != GOOD)
1115 fatal("failed to execute shell command", (char *)NULL);
1117 append_to_tagfile = TRUE;
1120 tagf = fopen(tagfile, append_to_tagfile ? "a" : "w");
1128 int sz = snprintf(cmd, sizeof(cmd), "sort %s -o %s", tagfile, tagfile);
1129 if(sz >= 0 && (size_t)sz < sizeof(cmd))
1130 fatal("failed to build sort command line", (char *)NULL);
1137 * Return a language given the name.
1139 language *get_language_from_name(name)
1145 error("empty language name", (char *)NULL);
1147 for (lang = lang_names; lang->name != NULL; lang++)
1148 if (streq(name, lang->name))
1150 error("unknown language \"%s\"", name);
1157 * Return a language given the interpreter name.
1159 language *get_language_from_interpreter(interpreter)
1165 if (interpreter == NULL)
1167 for (lang = lang_names; lang->name != NULL; lang++)
1168 if (lang->interpreters != NULL)
1169 for (iname = lang->interpreters; *iname != NULL;
1171 if (streq(*iname, interpreter))
1178 * Return a language given the file suffix.
1180 language *get_language_from_suffix(suffix)
1188 for (lang = lang_names; lang->name != NULL; lang++)
1189 if (lang->suffixes != NULL)
1190 for (ext = lang->suffixes; *ext != NULL; ext++)
1191 if (streq(*ext, suffix))
1198 * This routine is called on each file argument.
1200 void process_file(file)
1203 struct stat stat_buf;
1206 canonicalize_filename(file);
1207 if (streq(file, tagfile) && !streq(tagfile, "-")) {
1208 error("skipping inclusion of %s in self.", file);
1211 inf = fopen(file, "r");
1212 if (stat(file, &stat_buf) == 0 && !S_ISREG(stat_buf.st_mode)) {
1213 error("skipping %s: it is not a regular file.", file);
1223 find_entries(file, inf);
1228 if (filename_is_absolute(file)) {
1229 /* file is an absolute file name. Canonicalise it. */
1230 filename = absolute_filename(file, cwd);
1232 /* file is a file name relative to cwd. Make it relative
1233 to the directory of the tags file. */
1234 filename = relative_filename(file, tagfiledir);
1237 if (oo_browser_format)
1238 fprintf(tagf, "\f\n%s\n", filename);
1241 fprintf(tagf, "\f\n%s,%d\n", filename,
1242 total_size_of_entries(head));
1251 * This routine sets up the boolean pseudo-functions which work
1252 * by setting boolean flags dependent upon the corresponding character.
1253 * Every char which is NOT in that string is not a white char. Therefore,
1254 * all of the array "_wht" is set to FALSE, and then the elements
1255 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1256 * of a char is TRUE if it is the string "white", else FALSE.
1263 for (i = 0; i < CHARS; i++)
1264 iswhite(i) = notinname(i) = begtoken(i) = intoken(i) =
1265 endtoken(i) = FALSE;
1266 for (sp = white; *sp != '\0'; sp++)
1267 iswhite(*sp) = TRUE;
1268 for (sp = nonam; *sp != '\0'; sp++)
1269 notinname(*sp) = TRUE;
1270 for (sp = begtk; *sp != '\0'; sp++)
1271 begtoken(*sp) = TRUE;
1272 for (sp = midtk; *sp != '\0'; sp++)
1273 intoken(*sp) = TRUE;
1274 for (sp = endtk; *sp != '\0'; sp++)
1275 endtoken(*sp) = TRUE;
1276 iswhite('\0') = iswhite('\n');
1277 notinname('\0') = notinname('\n');
1278 begtoken('\0') = begtoken('\n');
1279 intoken('\0') = intoken('\n');
1280 endtoken('\0') = endtoken('\n');
1284 * This routine opens the specified file and calls the function
1285 * which finds the function and type definitions.
1287 node *last_node = NULL;
1289 void find_entries(file, inf)
1295 node *old_last_node;
1297 curfile = savestr(file);
1299 /* If user specified a language, use it. */
1301 if (lang != NULL && lang->function != NULL) {
1303 lang->function(inf);
1309 cp = etags_strrchr(file, '.');
1312 lang = get_language_from_suffix(cp);
1313 if (lang != NULL && lang->function != NULL) {
1315 lang->function(inf);
1322 /* Look for sharp-bang as the first two characters. */
1323 if (readline_internal(&lb, inf) > 0
1324 && lb.len >= 2 && lb.buffer[0] == '#' && lb.buffer[1] == '!') {
1327 /* Set lp to point at the first char after the last slash in the
1328 line or, if no slashes, at the first nonblank. Then set cp to
1329 the first successive blank and terminate the string. */
1330 lp = etags_strrchr(lb.buffer + 2, '/');
1334 lp = skip_spaces(lb.buffer + 2);
1335 cp = skip_non_spaces(lp);
1338 if (strlen(lp) > 0) {
1339 lang = get_language_from_interpreter(lp);
1340 if (lang != NULL && lang->function != NULL) {
1342 lang->function(inf);
1352 old_last_node = last_node;
1353 curlang = get_language_from_name("fortran");
1354 Fortran_functions(inf);
1356 /* No Fortran entries found. Try C. */
1357 if (old_last_node == last_node) {
1359 curlang = get_language_from_name(cplusplus ? "c++" : "c");
1360 default_C_entries(inf);
1368 void pfnote(name, is_func, linestart, linelen, lno, cno)
1369 char *name; /* tag name, or NULL if unnamed */
1370 bool is_func; /* tag is a function */
1371 char *linestart; /* start of the line where tag is */
1372 int linelen; /* length of the line where tag is */
1373 int lno; /* line number */
1374 long cno; /* character number */
1378 if (CTAGS && name == NULL)
1383 /* If ctags mode, change name "main" to M<thisfilename>. */
1384 if (CTAGS && !cxref_style && streq(name, "main")) {
1385 register char *fp = etags_strrchr(curfile, '/');
1386 np->name = concat("M", fp == 0 ? curfile : fp + 1, "");
1387 fp = etags_strrchr(np->name, '.');
1388 if (fp && fp[1] != '\0' && fp[2] == '\0')
1392 np->been_warned = FALSE;
1394 np->is_func = is_func;
1396 /* Our char numbers are 0-base, because of C language tradition?
1397 ctags compatibility? old versions compatibility? I don't know.
1398 Anyway, since emacs's are 1-base we expect etags.el to take care
1399 of the difference. If we wanted to have 1-based numbers, we would
1400 uncomment the +1 below. */
1401 np->cno = cno /* + 1 */ ;
1402 np->left = np->right = NULL;
1403 if (CTAGS && !cxref_style) {
1404 if (strlen(linestart) < 50)
1405 np->pat = concat(linestart, "$", "");
1407 np->pat = savenstr(linestart, 50);
1409 np->pat = savenstr(linestart, linelen);
1412 if (oo_browser_format)
1413 np->construct = oo_browser_construct;
1414 oo_browser_construct = C_NULL;
1415 oo_browser_check_and_clear_structtype();
1418 add_node(np, &head);
1421 /* Date: Wed, 22 Jan 1997 02:56:31 -0500 [last amended 18 Sep 1997]
1422 * From: Sam Kendall <kendall@mv.mv.com>
1423 * Subject: Proposal for firming up the TAGS format specification
1424 * To: F.Potorti@cnuce.cnr.it
1426 * pfnote should emit the optimized form [unnamed tag] only if:
1427 * 1. name does not contain any of the characters " \t\r\n(),;";
1428 * 2. linestart contains name as either a rightmost, or rightmost but
1429 * one character, substring;
1430 * 3. the character, if any, immediately before name in linestart must
1431 * be one of the characters " \t(),;";
1432 * 4. the character, if any, immediately after name in linestart must
1433 * also be one of the characters " \t(),;".
1435 * The real implementation uses the notinname() macro, which recognises
1436 * characters slightly different form " \t\r\n(),;". See the variable
1439 #define traditional_tag_style TRUE
1440 void new_pfnote(name, namelen, is_func, linestart, linelen, lno, cno)
1441 char *name; /* tag name, or NULL if unnamed */
1442 int namelen; /* tag length */
1443 bool is_func; /* tag is a function */
1444 char *linestart; /* start of the line where tag is */
1445 int linelen; /* length of the line where tag is */
1446 int lno; /* line number */
1447 long cno; /* character number */
1454 for (cp = name; !notinname(*cp); cp++)
1456 if (*cp == '\0') { /* rule #1 */
1457 cp = linestart + linelen - namelen;
1458 if (notinname(linestart[linelen - 1]))
1459 cp -= 1; /* rule #4 */
1461 if (!oo_browser_format && cp >= linestart /* rule #2 */
1463 if (cp >= linestart /* rule #2 */
1465 && (cp == linestart || notinname(cp[-1])) /* rule #3 */
1466 &&strneq(name, cp, namelen)) /* rule #2 */
1467 named = FALSE; /* use unnamed tag */
1472 name = savenstr(name, namelen);
1475 pfnote(name, is_func, linestart, linelen, lno, cno);
1480 * recurse on left children, iterate on right children.
1486 register node *node_right = np->right;
1487 free_tree(np->left);
1488 if (np->name != NULL)
1498 * Adds a node to the tree of nodes. In etags mode, we don't keep
1499 * it sorted; we just keep a linear list. In ctags mode, maintain
1500 * an ordered tree, with no attempt at balancing.
1502 * add_node is the only function allowed to add nodes, so it can
1505 void add_node(np, cur_node_p)
1506 node *np, **cur_node_p;
1509 register node *cur_node = *cur_node_p;
1511 if (cur_node == NULL) {
1519 if (last_node == NULL)
1520 fatal("internal error in add_node", (char *)NULL);
1521 last_node->right = np;
1525 dif = strcmp(np->name, cur_node->name);
1528 * If this tag name matches an existing one, then
1529 * do not add the node, but maybe print a warning.
1532 if (streq(np->file, cur_node->file)) {
1535 "Duplicate entry in file %s, line %d: %s\n",
1536 np->file, lineno, np->name);
1538 "Second entry ignored\n");
1540 } else if (!cur_node->been_warned && !no_warnings) {
1543 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1544 np->file, cur_node->file, np->name);
1545 cur_node->been_warned = TRUE;
1550 /* Actually add the node */
1551 add_node(np, dif < 0 ? &cur_node->left : &cur_node->right);
1556 /* Default class name for the current OO-Browser tag. */
1557 static char *oo_browser_class;
1558 /* Prefix character to use in OO-Browser listings for the current tag. */
1559 static char oo_browser_prefix;
1562 void put_entries(node * np)
1569 /* Output subentries that precede this one */
1570 put_entries(np->left);
1572 /* Output this entry */
1576 if (oo_browser_format) {
1577 /* Omit C++ `class' and `method' entries as well as Objective-C
1578 entries from this OO-Browser tags file since the browser handles
1579 them independently of this file. Omit `extern' variable declarations
1580 as they are unused by the OO-Browser. */
1581 if (np->construct != C_CLASS
1582 && np->construct != C_METHOD
1583 && np->construct != C_EXTERN
1584 && np->construct != C_OBJC) {
1586 oo_browser_default_classes[np->construct];
1587 switch (np->construct) {
1595 oo_browser_prefix = '=';
1599 oo_browser_prefix = '-';
1604 if (np->name != NULL)
1605 fprintf(tagf, "%s@%c %s@%s\n",
1607 oo_browser_prefix, np->name,
1610 fprintf(tagf, "%s@%c ???@%s\n",
1612 oo_browser_prefix, np->pat);
1616 if (np->name != NULL)
1617 fprintf(tagf, "%s\177%s\001%d,%ld\n",
1618 np->pat, np->name, np->lno, np->cno);
1620 fprintf(tagf, "%s\177%d,%ld\n",
1621 np->pat, np->lno, np->cno);
1626 if (np->name == NULL)
1627 error("internal error: NULL name in ctags mode.",
1632 fprintf(stdout, "%s %s %d\n",
1634 (np->lno + 63) / 64);
1636 fprintf(stdout, "%-16s %3d %-16s %s\n",
1637 np->name, np->lno, np->file, np->pat);
1639 fprintf(tagf, "%s\t%s\t", np->name, np->file);
1641 if (np->is_func) { /* a function */
1642 putc(searchar, tagf);
1645 for (sp = np->pat; *sp; sp++) {
1646 if (*sp == '\\' || *sp == searchar)
1650 putc(searchar, tagf);
1651 } else { /* a typedef; text pattern inadequate */
1652 fprintf(tagf, "%d", np->lno);
1658 /* Output subentries that follow this one */
1659 put_entries(np->right);
1662 /* Length of a number's decimal representation. */
1663 int number_len PP((long num));
1668 while ((num /= 10) > 0)
1674 * Return total number of characters that put_entries will output for
1675 * the nodes in the subtree of the specified node. Works only if
1676 * we are not ctags, but called only in that case. This count
1677 * is irrelevant with the new tags.el, but is still supplied for
1678 * backward compatibility.
1680 int total_size_of_entries(np)
1688 for (total = 0; np != NULL; np = np->right) {
1689 /* Count left subentries. */
1690 total += total_size_of_entries(np->left);
1692 /* Count this entry */
1693 total += strlen(np->pat) + 1;
1695 number_len((long)np->lno) + 1 + number_len(np->cno) + 1;
1696 if (np->name != NULL)
1697 total += 1 + strlen(np->name); /* \001name */
1704 * The C symbol tables.
1708 st_C_objprot, st_C_objimpl, st_C_objend,
1712 st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec,
1715 , st_C_union, st_C_class, st_C_extern, st_C_inline
1719 /* Feed stuff between (but not including) %[ and %] lines to:
1720 gperf -c -k 1,3 -o -p -r -t
1722 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1724 @interface, 0, st_C_objprot
1725 @protocol, 0, st_C_objprot
1726 @implementation,0, st_C_objimpl
1727 @end, 0, st_C_objend
1728 import, C_JAVA, st_C_ignore
1729 package, C_JAVA, st_C_ignore
1730 friend, C_PLPL, st_C_ignore
1731 extends, C_JAVA, st_C_javastruct
1732 implements, C_JAVA, st_C_javastruct
1733 interface, C_JAVA, st_C_struct
1734 class, C_PLPL, st_C_class
1735 namespace, C_PLPL, st_C_struct
1736 domain, C_STAR, st_C_struct
1737 union, 0, st_C_union
1738 struct, 0, st_C_struct
1740 typedef, 0, st_C_typedef
1741 define, 0, st_C_define
1742 inline, 0, st_C_inline
1743 bool, C_PLPL, st_C_typespec
1744 long, 0, st_C_typespec
1745 short, 0, st_C_typespec
1746 int, 0, st_C_typespec
1747 char, 0, st_C_typespec
1748 float, 0, st_C_typespec
1749 double, 0, st_C_typespec
1750 signed, 0, st_C_typespec
1751 unsigned, 0, st_C_typespec
1752 auto, 0, st_C_typespec
1753 void, 0, st_C_typespec
1754 extern, 0, st_C_extern
1755 static, 0, st_C_typespec
1756 const, 0, st_C_const
1757 volatile, 0, st_C_typespec
1758 explicit, C_PLPL, st_C_typespec
1759 mutable, C_PLPL, st_C_typespec
1760 typename, C_PLPL, st_C_typespec
1761 # DEFUN used in emacs, the next three used in glibc (SYSCALL only for mach).
1762 DEFUN, 0, st_C_gnumacro
1763 SYSCALL, 0, st_C_gnumacro
1764 ENTRY, 0, st_C_gnumacro
1765 PSEUDO, 0, st_C_gnumacro
1766 # These are defined inside C functions, so currently they are not met.
1767 # EXFUN used in glibc, DEFVAR_* in emacs.
1768 #EXFUN, 0, st_C_gnumacro
1769 #DEFVAR_, 0, st_C_gnumacro
1771 and replace lines between %< and %> with its output. */
1773 /* C code produced by gperf version 2.5 (GNU C++ version) */
1774 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
1775 struct C_stab_entry {
1781 #define TOTAL_KEYWORDS 41
1782 #define MIN_WORD_LENGTH 3
1783 #define MAX_WORD_LENGTH 15
1784 #define MIN_HASH_VALUE 13
1785 #define MAX_HASH_VALUE 129
1786 /* maximum key range = 117, duplicates = 0 */
1788 static unsigned int hash(char *str, unsigned int len)
1790 static unsigned char asso_values[] = {
1791 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1792 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1793 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1794 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1795 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1796 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1797 130, 130, 130, 130, 13, 130, 130, 130, 33, 32,
1798 47, 130, 130, 130, 130, 130, 130, 130, 130, 130,
1799 5, 130, 130, 20, 32, 130, 130, 130, 130, 130,
1800 130, 130, 130, 130, 130, 130, 130, 47, 55, 8,
1801 15, 33, 61, 38, 130, 60, 130, 130, 2, 9,
1802 10, 62, 59, 130, 28, 27, 50, 19, 3, 130,
1803 130, 130, 130, 130, 130, 130, 130, 130,
1806 asso_values[(unsigned char)str[2]] +
1807 asso_values[(unsigned char)str[0]];
1810 static struct C_stab_entry *in_word_set(char *str, unsigned int len)
1812 static struct C_stab_entry wordlist[] = {
1813 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1814 {"",}, {"",}, {"",}, {"",},
1815 {"volatile", 0, st_C_typespec},
1817 {"long", 0, st_C_typespec},
1818 {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1819 {"const", 0, st_C_const},
1820 {"",}, {"",}, {"",},
1821 {"@end", 0, st_C_objend},
1822 {"namespace", C_PLPL, st_C_struct},
1824 {"domain", C_STAR, st_C_struct},
1826 {"@interface", 0, st_C_objprot},
1827 {"",}, {"",}, {"",},
1828 {"@implementation", 0, st_C_objimpl},
1830 {"double", 0, st_C_typespec},
1832 {"PSEUDO", 0, st_C_gnumacro},
1833 {"",}, {"",}, {"",},
1834 {"SYSCALL", 0, st_C_gnumacro},
1836 {"@protocol", 0, st_C_objprot},
1837 {"",}, {"",}, {"",},
1838 {"unsigned", 0, st_C_typespec},
1840 {"enum", 0, st_C_enum},
1842 {"char", 0, st_C_typespec},
1843 {"class", C_PLPL, st_C_class},
1844 {"struct", 0, st_C_struct},
1845 {"",}, {"",}, {"",}, {"",},
1846 {"mutable", C_PLPL, st_C_typespec},
1847 {"void", 0, st_C_typespec},
1848 {"inline", 0, st_C_inline},
1849 {"ENTRY", 0, st_C_gnumacro},
1851 {"signed", 0, st_C_typespec},
1853 {"package", C_JAVA, st_C_ignore},
1854 {"",}, {"",}, {"",}, {"",}, {"",},
1855 {"static", 0, st_C_typespec},
1857 {"define", 0, st_C_define},
1859 {"union", 0, st_C_union},
1860 {"DEFUN", 0, st_C_gnumacro},
1861 {"",}, {"",}, {"",},
1862 {"extern", 0, st_C_extern},
1863 {"extends", C_JAVA, st_C_javastruct},
1864 {"",}, {"",}, {"",},
1865 {"short", 0, st_C_typespec},
1866 {"",}, {"",}, {"",}, {"",}, {"",},
1867 {"explicit", C_PLPL, st_C_typespec},
1868 {"auto", 0, st_C_typespec},
1869 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
1871 {"int", 0, st_C_typespec},
1873 {"typedef", 0, st_C_typedef},
1874 {"typename", C_PLPL, st_C_typespec},
1876 {"interface", C_JAVA, st_C_struct},
1878 {"bool", C_PLPL, st_C_typespec},
1879 {"",}, {"",}, {"",},
1880 {"import", C_JAVA, st_C_ignore},
1882 {"friend", C_PLPL, st_C_ignore},
1883 {"float", 0, st_C_typespec},
1884 {"implements", C_JAVA, st_C_javastruct},
1887 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) {
1888 register int key = hash(str, len);
1890 if (key <= MAX_HASH_VALUE && key >= 0) {
1891 register char *s = wordlist[key].name;
1893 if (*s == *str && !strncmp(str + 1, s + 1, len - 1))
1894 return &wordlist[key];
1902 enum sym_type C_symtype PP((char *str, int len, int c_ext));
1903 enum sym_type C_symtype(str, len, c_ext)
1908 register struct C_stab_entry *se = in_word_set(str, len);
1910 if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
1916 * C functions and variables are recognized using a simple
1917 * finite automaton. fvdef is its state variable.
1920 fvnone, /* nothing seen */
1921 fvnameseen, /* function or variable name seen */
1922 fstartlist, /* func: just after open parenthesis */
1923 finlist, /* func: in parameter list */
1924 flistseen, /* func: after parameter list */
1925 fignore, /* func: before open brace */
1926 vignore /* var-like: ignore until ';' */
1930 * typedefs are recognized using a simple finite automaton.
1931 * typdef is its state variable.
1934 tnone, /* nothing seen */
1935 ttypedseen, /* typedef keyword seen */
1936 tinbody, /* inside typedef body */
1937 tend, /* just before typedef tag */
1938 tignore /* junk after typedef tag */
1942 * struct-like structures (enum, struct and union) are recognized
1943 * using another simple finite automaton. `structdef' is its state
1947 snone, /* nothing seen yet */
1948 skeyseen, /* struct-like keyword seen */
1949 stagseen, /* struct-like tag seen */
1950 scolonseen, /* colon seen after struct-like tag */
1951 sinbody /* in struct body: recognize member func defs */
1955 * When structdef is stagseen, scolonseen, or sinbody, structtag is the
1956 * struct tag, and structtype is the type of the preceding struct-like
1959 char *structtag = "<uninited>";
1960 enum sym_type structtype;
1963 void oo_browser_check_and_clear_structtype(void)
1965 /* Allow for multiple enum_label tags. */
1966 if (structtype != st_C_enum)
1967 structtype = st_none;
1972 * When objdef is different from onone, objtag is the name of the class.
1974 char *objtag = "<uninited>";
1977 * Yet another little state machine to deal with preprocessor lines.
1980 dnone, /* nothing seen */
1981 dsharpseen, /* '#' seen as first char on line */
1982 ddefineseen, /* '#' and 'define' seen */
1983 dignorerest /* ignore rest of line */
1987 * State machine for Objective C protocols and implementations.
1988 * Tom R.Hageman <tom@basil.icce.rug.nl>
1991 onone, /* nothing seen */
1992 oprotocol, /* @interface or @protocol seen */
1993 oimplementation, /* @implementations seen */
1994 otagseen, /* class name seen */
1995 oparenseen, /* parenthesis before category seen */
1996 ocatseen, /* category name seen */
1997 oinbody, /* in @implementation body */
1998 omethodsign, /* in @implementation body, after +/- */
1999 omethodtag, /* after method name */
2000 omethodcolon, /* after method colon */
2001 omethodparm, /* after method parameter */
2002 oignore /* wait for @end */
2006 * Use this structure to keep info about the token read, and how it
2007 * should be tagged. Used by the make_C_tag function to build a tag.
2019 token tok; /* latest token read */
2022 * Set this to TRUE, and the next token considered is called a function.
2023 * Used only for GNU emacs's function-defining macros.
2025 bool next_token_is_func;
2028 * TRUE in the rules part of a yacc file, FALSE outside (parse as C).
2033 * methodlen is the length of the method name stored in token_name.
2038 void oo_browser_clear_all_globals(void)
2040 /* Initialize globals so there is no carry over between files. */
2041 oo_browser_construct = C_NULL;
2047 structtype = st_none;
2048 next_token_is_func = yacc_rules = FALSE;
2051 void oo_browser_clear_some_globals(void)
2053 oo_browser_construct = C_NULL;
2054 structtype = st_none;
2060 * checks to see if the current token is at the start of a
2061 * function or variable, or corresponds to a typedef, or
2062 * is a struct/union/enum tag, or #define, or an enum constant.
2064 * *IS_FUNC gets TRUE iff the token is a function or #define macro
2065 * with args. C_EXT is which language we are looking at.
2067 * In the future we will need some way to adjust where the end of
2068 * the token is; for instance, implementing the C++ keyword
2069 * `operator' properly will adjust the end of the token to be after
2070 * whatever follows `operator'.
2078 * next_token_is_func IN OUT
2080 bool consider_token PP((char *str, int len, int c, int c_ext,
2081 int cblev, int parlev, bool * is_func_or_var));
2082 bool consider_token(str, len, c, c_ext, cblev, parlev, is_func_or_var)
2083 register char *str; /* IN: token pointer */
2084 register int len; /* IN: token length */
2085 register int c; /* IN: first char after the token */
2086 int c_ext; /* IN: C extensions mask */
2087 int cblev; /* IN: curly brace level */
2088 int parlev; /* IN: parenthesis level */
2089 bool *is_func_or_var; /* OUT: function or variable found */
2091 enum sym_type toktype = C_symtype(str, len, c_ext);
2094 switch ((unsigned int)toktype) {
2096 set_construct(C_STRUCTURE);
2099 set_construct(C_UNION);
2102 set_construct(C_CLASS);
2105 set_construct(C_ENUMERATION);
2108 set_construct(C_TYPE);
2111 set_construct(C_EXTERN);
2114 set_construct(C_FUNCTION);
2124 * Advance the definedef state machine.
2126 switch (definedef) {
2128 /* We're not on a preprocessor line. */
2131 if (toktype == st_C_define) {
2132 definedef = ddefineseen;
2134 definedef = dignorerest;
2139 * Make a tag for any macro, unless it is a constant
2140 * and constantypedefs is FALSE.
2142 definedef = dignorerest;
2144 *is_func_or_var = (c == '(');
2147 char *p = str + len * sizeof(char);
2150 /* This must be a macro since there is no
2151 whitespace between the opening parenthesis
2152 and the definition name. */
2153 *is_func_or_var = TRUE;
2155 *is_func_or_var = FALSE;
2157 /* Handle possible whitespace between macro tag and opening
2158 parenthesis and ensure this is an actual macro.
2159 -- Bob Weiner, Altrasoft, 11/19/1997 */
2160 while (*p && isspace(*p))
2165 /* Skip over nested parentheses. */
2169 while (*++p && depth > 0 && *p != '\n') {
2182 /* If this is a macro, we have just passed
2183 the arguments and there will be more on
2184 the line before the NULL character that marks
2185 the end of the line token. */
2186 while (*p == ' ' || *p == '\t')
2189 *is_func_or_var = TRUE;
2194 set_construct((*is_func_or_var) ? C_MACRO : C_CONSTANT);
2196 if (!*is_func_or_var && !constantypedefs)
2203 error("internal error: definedef value.", (char *)NULL);
2211 if (toktype == st_C_typedef) {
2213 typdef = ttypedseen;
2219 switch ((unsigned int)toktype) {
2221 set_construct(C_CONSTANT);
2242 /* Do not return here, so the structdef stuff has a chance. */
2245 switch ((unsigned int)toktype) {
2247 set_construct(C_CONSTANT);
2273 * This structdef business is currently only invoked when cblev==0.
2274 * It should be recursively invoked whatever the curly brace level,
2275 * and a stack of states kept, to allow for definitions of structs
2278 * This structdef business is NOT invoked when we are ctags and the
2279 * file is plain C. This is because a struct tag may have the same
2280 * name as another tag, and this loses with ctags.
2282 switch ((unsigned int)toktype) {
2283 case st_C_javastruct:
2284 if (structdef == stagseen)
2285 structdef = scolonseen;
2294 if (typdef == ttypedseen
2295 || (typedefs_and_cplusplus && cblev == 0
2296 && structdef == snone)) {
2297 structdef = skeyseen;
2298 structtype = toktype;
2307 if (structdef == skeyseen) {
2308 /* Save the tag for struct/union/class, for functions and variables
2309 that may be defined inside. */
2311 if (structtype == st_C_struct)
2313 if (structtype == st_C_struct
2314 || structtype == st_C_union || structtype == st_C_class)
2316 structtag = savenstr(str, len);
2318 structtag = "<enum>";
2319 structdef = stagseen;
2323 /* Avoid entering fvdef stuff if typdef is going on. */
2324 if (typdef != tnone) {
2329 /* Detect GNU macros.
2331 DEFUN note for writers of emacs C code:
2332 The DEFUN macro, used in emacs C source code, has a first arg
2333 that is a string (the lisp function name), and a second arg that
2334 is a C function name. Since etags skips strings, the second arg
2335 is tagged. This is unfortunate, as it would be better to tag the
2336 first arg. The simplest way to deal with this problem would be
2337 to name the tag with a name built from the function name, by
2338 removing the initial 'F' character and substituting '-' for '_'.
2339 Anyway, this assumes that the conventions of naming lisp
2340 functions will never change. Currently, this method is not
2341 implemented, so writers of emacs code are recommended to put the
2342 first two args of a DEFUN on the same line. */
2343 if (definedef == dnone && toktype == st_C_gnumacro) {
2344 next_token_is_func = TRUE;
2347 if (next_token_is_func) {
2348 next_token_is_func = FALSE;
2350 *is_func_or_var = TRUE;
2354 /* Detect Objective C constructs. */
2357 switch ((unsigned int)toktype) {
2360 set_construct(C_OBJC);
2366 set_construct(C_OBJC);
2368 objdef = oimplementation;
2376 case oimplementation:
2377 /* Save the class tag for functions or variables defined inside. */
2378 objtag = savenstr(str, len);
2382 /* Save the class tag for categories. */
2383 objtag = savenstr(str, len);
2385 *is_func_or_var = TRUE;
2389 *is_func_or_var = TRUE;
2395 objdef = omethodtag;
2397 grow_linebuffer(&token_name, methodlen + 1);
2398 xstrncpy(token_name.buffer, str, len);
2399 token_name.buffer[methodlen] = '\0';
2400 token_name.len = methodlen;
2406 objdef = omethodparm;
2410 objdef = omethodtag;
2412 grow_linebuffer(&token_name, methodlen + 1);
2413 strncat(token_name.buffer, str, len);
2414 token_name.len = methodlen;
2419 if (toktype == st_C_objend) {
2420 /* Memory leakage here: the string pointed by objtag is
2421 never released, because many tests would be needed to
2422 avoid breaking on incorrect input code. The amount of
2423 memory leaked here is the sum of the lengths of the
2438 /* A function, variable or enum constant? */
2439 switch ((unsigned int)toktype) {
2441 set_construct(C_CONSTANT);
2447 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2448 fvdef = fvnone; /* should be useless */
2454 if (constantypedefs && structdef == sinbody
2455 && structtype == st_C_enum)
2458 oo_browser_construct = C_ENUM_LABEL;
2464 if (fvdef == fvnone) {
2465 fvdef = fvnameseen; /* function or variable */
2466 *is_func_or_var = TRUE;
2480 * This routine finds functions, variables, typedefs,
2481 * #define's, enum constants and struct/union/enum definitions in
2482 * #C syntax and adds them to the list.
2484 #define current_lb_is_new (newndx == curndx)
2485 #define switch_line_buffers() (curndx = 1 - curndx)
2487 #define curlb (lbs[curndx].lb)
2488 #define othlb (lbs[1-curndx].lb)
2489 #define newlb (lbs[newndx].lb)
2490 #define curlinepos (lbs[curndx].linepos)
2491 #define othlinepos (lbs[1-curndx].linepos)
2492 #define newlinepos (lbs[newndx].linepos)
2494 #define CNL_SAVE_DEFINEDEF() \
2496 curlinepos = charno; \
2498 linecharno = charno; \
2499 charno += readline (&curlb, inf); \
2500 lp = curlb.buffer; \
2507 CNL_SAVE_DEFINEDEF(); \
2508 if (savetok.valid) \
2511 savetok.valid = FALSE; \
2513 definedef = dnone; \
2516 void make_C_tag PP((bool isfun));
2517 void make_C_tag(isfun)
2520 /* This function should never be called when tok.valid is FALSE, but
2521 we must protect against invalid input or internal errors. */
2523 if (traditional_tag_style) {
2524 /* This was the original code. Now we call new_pfnote instead,
2525 which uses the new method for naming tags (see new_pfnote). */
2528 if (CTAGS || tok.named)
2529 name = savestr(token_name.buffer);
2531 tok.buffer, tok.linelen, tok.lineno,
2534 new_pfnote(token_name.buffer, token_name.len, isfun,
2535 tok.buffer, tok.linelen, tok.lineno,
2542 void C_entries(c_ext, inf)
2543 int c_ext; /* extension of C */
2544 FILE *inf; /* input file */
2546 register char c; /* latest char read; '\0' for end of line */
2547 register char *lp; /* pointer one beyond the character `c' */
2548 int curndx, newndx; /* indices for current and new lb */
2549 register int tokoff; /* offset in line of start of current token */
2550 register int toklen; /* length of current token */
2551 char *qualifier; /* string used to qualify names */
2552 int qlen; /* length of qualifier */
2553 int cblev; /* current curly brace level */
2554 int parlev; /* current parenthesis level */
2555 bool incomm, inquote, inchar, quotednl, midtoken;
2557 token savetok; /* token saved during preprocessor handling */
2559 /* initialise savetok */
2560 memset(&savetok, 0, sizeof(token));
2562 tokoff = toklen = 0; /* keep compiler quiet */
2563 curndx = newndx = 0;
2574 next_token_is_func = yacc_rules = FALSE;
2575 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2576 tok.valid = savetok.valid = FALSE;
2579 cplpl = (c_ext & C_PLPL) == C_PLPL;
2580 cjava = (c_ext & C_JAVA) == C_JAVA;
2589 while (!feof(inf)) {
2592 /* If we're at the end of the line, the next character is a
2593 '\0'; don't skip it, because it's the thing that tells us
2594 to read the next line. */
2601 } else if (incomm) {
2610 /* Newlines inside comments do not end macro definitions in
2612 CNL_SAVE_DEFINEDEF();
2618 } else if (inquote) {
2624 /* Newlines inside strings do not end macro definitions
2625 in traditional cpp, even though compilers don't
2626 usually accept them. */
2627 CNL_SAVE_DEFINEDEF();
2633 } else if (inchar) {
2636 /* Hmmm, something went wrong. */
2650 if (fvdef != finlist && fvdef != fignore
2651 && fvdef != vignore)
2656 if (fvdef != finlist && fvdef != fignore
2657 && fvdef != vignore)
2665 } else if ( /* cplpl && */ *lp == '/') {
2671 if ((c_ext & YACC) && *lp == '%') {
2672 /* entering or exiting rules section in yacc file */
2678 next_token_is_func = FALSE;
2679 midtoken = inquote = inchar = incomm =
2682 yacc_rules = !yacc_rules;
2687 if (definedef == dnone) {
2689 bool cpptoken = TRUE;
2691 /* Look back on this line. If all blanks, or nonblanks
2692 followed by an end of comment, this is a preprocessor
2694 for (cp = newlb.buffer; cp < lp - 1;
2696 if (!iswhite(*cp)) {
2707 definedef = dsharpseen;
2709 /* if (definedef == dnone) */
2715 /* Consider token only if some complicated conditions are satisfied. */
2716 if ((definedef != dnone
2717 || (cblev == 0 && structdef != scolonseen)
2718 || (cblev == 1 && cplpl && structdef == sinbody)
2719 || (structdef == sinbody && structtype == st_C_enum))
2720 && typdef != tignore
2721 && definedef != dignorerest && fvdef != finlist) {
2724 if (c == ':' && cplpl && *lp == ':'
2725 && begtoken(*(lp + 1))) {
2727 * This handles :: in the middle, but not at the
2728 * beginning of an identifier.
2733 set_construct(C_METHOD);
2736 bool funorvar = FALSE;
2739 || consider_token(newlb.
2749 if (structdef == sinbody
2752 /* function or var defined in C++ class body */
2782 oo_browser_construct
2785 } else if (objdef ==
2787 /* Objective C category */
2820 oo_browser_construct
2823 } else if (objdef ==
2827 /* Objective C method */
2832 oo_browser_construct
2861 /* Also name #define constants,
2862 enumerations and enum_labels.
2863 Conditionalize `funorvar' reference
2864 here or #defines will appear without
2866 -- Bob Weiner, Altrasoft, 4/25/1998 */
2868 ((oo_browser_format || funorvar)
2876 (oo_browser_construct
2880 oo_browser_construct
2893 tok.lineno = lineno;
2895 tokoff + toklen + 1;
2902 if (definedef == dnone
2911 if (current_lb_is_new)
2920 } /* if (endtoken (c)) */
2921 else if (intoken(c)) {
2925 } /* if (midtoken) */
2926 else if (begtoken(c)) {
2927 switch (definedef) {
2929 switch ((unsigned int)fvdef) {
2935 set_construct(C_MACRO);
2937 make_C_tag(TRUE); /* a function */
2948 if (structdef == stagseen && !cjava)
2960 if (!yacc_rules || lp == newlb.buffer + 1) {
2961 tokoff = lp - 1 - newlb.buffer;
2966 } /* if (begtoken) */
2969 /* if must look at token */
2970 /* Detect end of line, colon, comma, semicolon and various braces
2971 after having handled a token. */
2974 if (definedef != dnone)
2976 switch ((unsigned int)objdef) {
2979 make_C_tag(TRUE); /* an Objective C class */
2983 objdef = omethodcolon;
2985 grow_linebuffer(&token_name, methodlen + 1);
2986 strcat(token_name.buffer, ":");
2987 token_name.len = methodlen;
2994 if (structdef == stagseen)
2995 structdef = scolonseen;
2997 switch ((unsigned int)fvdef) {
3000 make_C_tag(FALSE); /* a yacc function */
3014 if (definedef != dnone)
3017 switch ((unsigned int)typdef) {
3020 set_construct(C_TYPE);
3022 make_C_tag(FALSE); /* a typedef */
3027 switch ((unsigned int)fvdef) {
3031 if ((globals && cblev == 0)
3032 || (members && cblev == 1))
3034 make_C_tag(FALSE); /* a variable */
3036 /* if (constantypedefs && structdef == snone)*/
3039 switch ((unsigned int)structtype) {
3041 set_construct(C_ENUMERATION);
3044 set_construct(C_CLASS);
3047 set_construct(C_VARIABLE);
3051 /* Force reset of st_C_enum structtype value. */
3052 structtype = st_none;
3058 /* The following instruction invalidates the token.
3059 Probably the token should be invalidated in all
3060 other cases where some state machine is reset. */
3063 if (structdef == stagseen)
3067 if (definedef != dnone)
3069 switch ((unsigned int)objdef) {
3072 make_C_tag(TRUE); /* an Objective C method */
3080 switch ((unsigned int)fvdef) {
3086 if ((globals && cblev == 0)
3087 || (members && cblev == 1))
3088 make_C_tag(FALSE); /* a variable */
3093 if (structdef == stagseen)
3097 if (definedef != dnone)
3099 if (cblev == 0 && typdef == tend) {
3101 set_construct(C_TYPE);
3104 make_C_tag(FALSE); /* a typedef */
3107 switch ((unsigned int)fvdef) {
3114 if ((globals && cblev == 0)
3115 || (members && cblev == 1))
3116 make_C_tag(FALSE); /* a variable */
3118 if (constantypedefs && structdef == snone) {
3120 switch ((unsigned int)structtype) {
3122 set_construct(C_ENUMERATION);
3125 set_construct(C_CLASS);
3128 set_construct(C_VARIABLE);
3132 /* Force reset of st_C_enum structtype value. */
3133 structtype = st_none;
3143 if (structdef == stagseen)
3147 if (definedef != dnone)
3149 if (objdef == otagseen && parlev == 0)
3150 objdef = oparenseen;
3151 switch ((unsigned int)fvdef) {
3156 if (tok.valid && *lp != '*') {
3157 /* This handles constructs like:
3158 typedef void OperatorFun (int fun); */
3161 set_construct(C_TYPE);
3173 } /* switch (typdef) */
3189 if (definedef != dnone)
3191 if (objdef == ocatseen && parlev == 1) {
3192 make_C_tag(TRUE); /* an Objective C category */
3195 if (--parlev == 0) {
3196 switch ((unsigned int)fvdef) {
3206 if (cblev == 0 && typdef == tend) {
3208 set_construct(C_TYPE);
3211 make_C_tag(FALSE); /* a typedef */
3213 } else if (parlev < 0) /* can happen due to ill-conceived #if's. */
3217 if (definedef != dnone)
3219 if (typdef == ttypedseen)
3221 switch (structdef) {
3222 case skeyseen: /* unnamed struct */
3223 structdef = sinbody;
3224 structtag = "_anonymous_";
3227 case scolonseen: /* named struct */
3228 structdef = sinbody;
3229 make_C_tag(FALSE); /* a struct */
3238 switch ((unsigned int)fvdef) {
3241 set_construct(C_FUNCTION);
3242 /* Ensure function name is recorded.
3243 -- Bob Weiner, Altrasoft */
3246 make_C_tag(TRUE); /* a function */
3252 switch ((unsigned int)objdef) {
3254 make_C_tag(TRUE); /* an Objective C class */
3259 make_C_tag(TRUE); /* an Objective C method */
3263 /* Neutralize `extern "C" {' grot. */
3264 if (cblev == 0 && structdef == snone
3276 if (definedef != dnone)
3278 if (fvdef == fstartlist)
3279 fvdef = fvnone; /* avoid tagging `foo' in `foo (*bar()) ()' */
3282 if (definedef != dnone)
3284 if (!noindentypedefs && lp == newlb.buffer + 1) {
3285 cblev = 0; /* reset curly brace level if first column */
3286 parlev = 0; /* also reset paren level, just in case... */
3287 } else if (cblev > 0)
3290 if (typdef == tinbody)
3292 /* Memory leakage here: the string pointed by structtag is
3293 never released, because I fear to miss something and
3294 break things while freeing the area. The amount of
3295 memory leaked here is the sum of the lengths of the
3297 if (structdef == sinbody)
3298 free (structtag); */
3301 structtag = "<error>";
3303 /* Next line added to avoid any state carryover between
3304 functions. -- Bob Weiner, Altrasoft, 11/19/1997 */
3306 oo_browser_construct = C_NULL;
3311 if (definedef != dnone)
3323 if ((globals && cblev == 0)
3324 || (members && cblev == 1))
3326 make_C_tag(FALSE); /* a variable */
3330 switch ((unsigned int)structtype) {
3336 set_construct(C_CLASS);
3339 /* a global variable */
3345 /* ootags categorizes each tag found whereas etags doesn't.
3346 Set the is_method flag if this tag has been marked as
3347 such by an earlier section of code.
3348 -- Steve Baur, Altrasoft, 5/7/1998 */
3350 (oo_browser_construct ==
3354 /* Force reset of st_C_enum structtype value. */
3355 structtype = st_none;
3364 fvdef = is_method ? fignore : vignore;
3375 if (objdef == oinbody && cblev == 0) {
3376 objdef = omethodsign;
3393 if (definedef != dnone)
3398 /* The above characters cannot follow a function tag in C, so
3399 unmark this as a function entry. For C++, these characters
3400 may follow an `operator' function construct, so skip the
3401 unmarking conditional below.
3402 -- Steve Baur, Altrasoft, 5/7/1998 */
3403 if (fvdef != finlist && fvdef != fignore
3404 && fvdef != vignore)
3411 if (objdef == otagseen) {
3412 make_C_tag(TRUE); /* an Objective C class */
3415 /* If a macro spans multiple lines don't reset its state. */
3417 CNL_SAVE_DEFINEDEF();
3427 } /* while not eof */
3431 * Process either a C++ file or a C file depending on the setting
3434 void default_C_entries(inf)
3437 C_entries(cplusplus ? C_PLPL : 0, inf);
3440 /* Always do plain ANSI C. */
3441 void plain_C_entries(inf)
3447 /* Always do C++. */
3448 void Cplusplus_entries(inf)
3451 C_entries(C_PLPL, inf);
3454 /* Always do Java. */
3455 void Cjava_entries(inf)
3458 C_entries(C_JAVA, inf);
3462 void Cstar_entries(inf)
3465 C_entries(C_STAR, inf);
3468 /* Always do Yacc. */
3469 void Yacc_entries(inf)
3472 C_entries(YACC, inf);
3475 /* A useful macro. */
3476 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3477 for (lineno = charno = 0; /* loop initialization */ \
3478 !feof (file_pointer) /* loop test */ \
3479 && (lineno++, /* instructions at start of loop */ \
3480 linecharno = charno, \
3481 charno += readline (&line_buffer, file_pointer), \
3482 char_pointer = lb.buffer, \
3487 * Read a file, but do no processing. This is used to do regexp
3488 * matching on files that have no language defined.
3490 void just_read_file(inf)
3493 register char *dummy;
3495 LOOP_ON_INPUT_LINES(inf, lb, dummy)
3499 /* Fortran parsing */
3501 bool tail PP((char *cp));
3505 register int len = 0;
3507 while (*cp && lowcase(*cp) == lowcase(dbp[len]))
3509 if (*cp == '\0' && !intoken(dbp[len])) {
3518 dbp = skip_spaces(dbp);
3522 dbp = skip_spaces(dbp);
3523 if (strneq(dbp, "(*)", 3)) {
3527 if (!isdigit(*dbp)) {
3528 --dbp; /* force failure */
3533 while (isdigit(*dbp));
3536 void getit PP((FILE * inf));
3542 dbp = skip_spaces(dbp);
3545 linecharno = charno;
3546 charno += readline(&lb, inf);
3551 dbp = skip_spaces(dbp);
3554 && *dbp != '_' && *dbp != '$')
3556 for (cp = dbp + 1; *cp && intoken(*cp); cp++)
3558 pfnote((CTAGS) ? savenstr(dbp, cp - dbp) : NULL, TRUE,
3559 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3562 void Fortran_functions(inf)
3565 LOOP_ON_INPUT_LINES(inf, lb, dbp) {
3567 dbp++; /* Ratfor escape to fortran */
3568 dbp = skip_spaces(dbp);
3571 switch (lowcase(*dbp)) {
3573 if (tail("integer"))
3581 if (tail("logical"))
3585 if (tail("complex") || tail("character"))
3589 if (tail("double")) {
3590 dbp = skip_spaces(dbp);
3593 if (tail("precision"))
3601 dbp = skip_spaces(dbp);
3604 switch (lowcase(*dbp)) {
3606 if (tail("function"))
3610 if (tail("subroutine"))
3618 if (tail("program")) {
3622 if (tail("procedure"))
3632 * Bob Weiner, Motorola Inc., 4/3/94
3633 * Unix and microcontroller assembly tag handling
3634 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
3636 void Asm_labels(FILE * inf)
3640 LOOP_ON_INPUT_LINES(inf, lb, cp) {
3641 /* If first char is alphabetic or one of [_.$], test for colon
3642 following identifier. */
3643 if (isalpha(*cp) || *cp == '_' || *cp == '.' || *cp == '$') {
3644 /* Read past label. */
3646 while (isalnum(*cp) || *cp == '_' || *cp == '.'
3649 if (*cp == ':' || isspace(*cp)) {
3650 /* Found end of label, so copy it and add it to the table. */
3653 cp - lb.buffer) : NULL, TRUE,
3654 lb.buffer, cp - lb.buffer + 1, lineno,
3662 * Perl support by Bart Robinson <lomew@cs.utah.edu>
3663 * enhanced by Michael Ernst <mernst@alum.mit.edu>
3664 * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/
3665 * Perl variable names: /^(my|local).../
3667 void Perl_functions(inf)
3672 LOOP_ON_INPUT_LINES(inf, lb, cp) {
3674 && *cp++ == 'u' && *cp++ == 'b' && isspace(*cp++)) {
3675 cp = skip_spaces(cp);
3678 && !isspace(*cp) && *cp != '{'
3683 cp - lb.buffer) : NULL, TRUE,
3684 lb.buffer, cp - lb.buffer + 1, lineno,
3687 } else if (globals /* only if tagging global vars is enabled */
3688 && ((cp = lb.buffer, *cp++ == 'm' && *cp++ == 'y')
3693 && *cp++ == 'a' && *cp++ == 'l'))
3694 && (*cp == '(' || isspace(*cp))) {
3695 /* After "my" or "local", but before any following paren or space. */
3696 char *varname = NULL;
3698 cp = skip_spaces(cp);
3699 if (*cp == '$' || *cp == '@' || *cp == '%') {
3700 char *varstart = ++cp;
3701 while (isalnum(*cp) || *cp == '_')
3703 varname = savenstr(varstart, cp - varstart);
3705 /* Should be examining a variable list at this point;
3706 could insist on seeing an open parenthesis. */
3707 while (*cp != '\0' && *cp != ';' && *cp != '='
3712 /* Perhaps I should back cp up one character, so the TAGS table
3713 doesn't mention (and so depend upon) the following char. */
3714 pfnote((CTAGS) ? savenstr(lb.buffer, cp - lb.buffer) :
3715 varname, FALSE, lb.buffer, cp - lb.buffer + 1,
3716 lineno, linecharno);
3722 * Python support by Eric S. Raymond <esr@thyrsus.com>
3723 * Look for /^def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
3725 void Python_functions(inf)
3730 LOOP_ON_INPUT_LINES(inf, lb, cp) {
3732 && *cp++ == 'e' && *cp++ == 'f' && isspace(*cp++)) {
3733 cp = skip_spaces(cp);
3734 while (*cp != '\0' && !isspace(*cp) && *cp != '('
3737 pfnote((char *)NULL, TRUE,
3738 lb.buffer, cp - lb.buffer + 1, lineno,
3746 && *cp++ == 's' && *cp++ == 's' && isspace(*cp++)) {
3747 cp = skip_spaces(cp);
3748 while (*cp != '\0' && !isspace(*cp) && *cp != '('
3751 pfnote((char *)NULL, TRUE,
3752 lb.buffer, cp - lb.buffer + 1, lineno,
3758 /* Idea by Corny de Souza
3759 * Cobol tag functions
3760 * We could look for anything that could be a paragraph name.
3761 * i.e. anything that starts in column 8 is one word and ends in a full stop.
3763 void Cobol_paragraphs(inf)
3766 register char *bp, *ep;
3768 LOOP_ON_INPUT_LINES(inf, lb, bp) {
3773 /* If eoln, compiler option or comment ignore whole line. */
3774 if (bp[-1] != ' ' || !isalnum(bp[0]))
3777 for (ep = bp; isalnum(*ep) || *ep == '-'; ep++)
3780 pfnote((CTAGS) ? savenstr(bp, ep - bp) : NULL, TRUE,
3781 lb.buffer, ep - lb.buffer + 1, lineno,
3786 /* Added by Mosur Mohan, 4/22/88 */
3787 /* Pascal parsing */
3790 * Locates tags for procedures & functions. Doesn't do any type- or
3791 * var-definitions. It does look for the keyword "extern" or
3792 * "forward" immediately following the procedure statement; if found,
3793 * the tag is skipped.
3795 void Pascal_functions(inf)
3798 linebuffer tline; /* mostly copied from C_entries */
3800 int save_lineno, save_len;
3801 char c, *cp, *namebuf;
3803 bool /* each of these flags is TRUE iff: */
3804 incomment, /* point is inside a comment */
3805 inquote, /* point is inside '..' string */
3806 get_tagname, /* point is after PROCEDURE/FUNCTION
3807 keyword, so next item = potential tag */
3808 found_tag, /* point is after a potential tag */
3809 inparms, /* point is within parameter-list */
3810 verify_tag; /* point has passed the parm-list, so the
3811 next token will determine whether this
3812 is a FORWARD/EXTERN to be ignored, or
3813 whether it is a real tag */
3815 save_lcno = save_lineno = save_len = 0; /* keep compiler quiet */
3816 namebuf = NULL; /* keep compiler quiet */
3823 incomment = inquote = FALSE;
3824 found_tag = FALSE; /* have a proc name; check if extern */
3825 get_tagname = FALSE; /* have found "procedure" keyword */
3826 inparms = FALSE; /* found '(' after "proc" */
3827 verify_tag = FALSE; /* check if "extern" is ahead */
3829 while (!feof(inf)) { /* long main loop to get next char */
3831 if (c == '\0') { /* if end of line */
3833 linecharno = charno;
3834 charno += readline(&lb, inf);
3838 if (!((found_tag && verify_tag)
3840 c = *dbp++; /* only if don't need *dbp pointing
3841 to the beginning of the name of
3842 the procedure or function */
3845 if (c == '}') /* within { } comments */
3847 else if (c == '*' && *dbp == ')') { /* within (* *) comments */
3852 } else if (inquote) {
3859 inquote = TRUE; /* found first quote */
3861 case '{': /* found open { comment */
3865 if (*dbp == '*') { /* found open (* comment */
3868 } else if (found_tag) /* found '(' after tag, i.e., parm-list */
3871 case ')': /* end of parms list */
3876 if (found_tag && !inparms) { /* end of proc or fn stmt */
3884 if (found_tag && verify_tag && (*dbp != ' ')) {
3885 /* check if this is an "extern" declaration */
3888 if (lowcase(*dbp == 'e')) {
3889 if (tail("extern")) { /* superfluous, really! */
3893 } else if (lowcase(*dbp) == 'f') {
3894 if (tail("forward")) { /* check for forward reference */
3899 if (found_tag && verify_tag) { /* not external proc, so make tag */
3902 pfnote(namebuf, TRUE,
3903 tline.buffer, save_len, save_lineno,
3908 if (get_tagname) { /* grab name of proc or fn */
3912 /* save all values for later tagging */
3913 grow_linebuffer(&tline, lb.len + 1);
3914 xstrncpy(tline.buffer, lb.buffer, lb.len);
3915 save_lineno = lineno;
3916 save_lcno = linecharno;
3918 /* grab block name */
3919 for (cp = dbp + 1; *cp != '\0' && !endtoken(*cp); cp++)
3921 namebuf = (CTAGS) ? savenstr(dbp, cp - dbp) : NULL;
3922 dbp = cp; /* set dbp to e-o-token */
3923 save_len = dbp - lb.buffer + 1;
3924 get_tagname = FALSE;
3928 /* and proceed to check for "extern" */
3929 } else if (!incomment && !inquote && !found_tag) {
3930 /* check for proc/fn keywords */
3931 switch (lowcase(c)) {
3933 if (tail("rocedure")) /* c = 'p', dbp has advanced */
3937 if (tail("unction"))
3944 } /* while not eof */
3950 * lisp tag functions
3951 * look for (def or (DEF, quote or QUOTE
3953 int L_isdef PP((char *strp));
3955 register char *strp;
3957 return ((strp[1] == 'd' || strp[1] == 'D')
3958 && (strp[2] == 'e' || strp[2] == 'E')
3959 && (strp[3] == 'f' || strp[3] == 'F'));
3961 int L_isquote PP((char *strp));
3963 register char *strp;
3965 return ((*++strp == 'q' || *strp == 'Q')
3966 && (*++strp == 'u' || *strp == 'U')
3967 && (*++strp == 'o' || *strp == 'O')
3968 && (*++strp == 't' || *strp == 'T')
3969 && (*++strp == 'e' || *strp == 'E')
3970 && isspace(*++strp));
3973 void L_getit PP((void));
3978 if (*dbp == '\'') /* Skip prefix quote */
3980 else if (*dbp == '(') {
3982 dbp += 7; /* Skip "(quote " */
3984 dbp += 1; /* Skip "(" before name in (defstruct (foo)) */
3985 dbp = skip_spaces(dbp);
3988 for (cp = dbp /*+1 */ ;
3989 *cp != '\0' && *cp != '(' && *cp != ' ' && *cp != ')'; cp++)
3994 pfnote((CTAGS) ? savenstr(dbp, cp - dbp) : NULL, TRUE,
3995 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3998 void Lisp_functions(inf)
4001 LOOP_ON_INPUT_LINES(inf, lb, dbp) {
4002 if (dbp[0] == '(') {
4004 dbp = skip_non_spaces(dbp);
4005 dbp = skip_spaces(dbp);
4008 /* Check for (foo::defmumble name-defined ... */
4011 while (*dbp != '\0' && !isspace(*dbp)
4012 && *dbp != ':' && *dbp != '('
4017 while (*dbp == ':');
4019 if (L_isdef(dbp - 1)) {
4020 dbp = skip_non_spaces(dbp);
4021 dbp = skip_spaces(dbp);
4031 * Postscript tag functions
4032 * Just look for lines where the first character is '/'
4033 * Richard Mlynarik <mly@adoc.xerox.com>
4035 void Postscript_functions(inf)
4038 register char *bp, *ep;
4040 LOOP_ON_INPUT_LINES(inf, lb, bp) {
4043 *ep != '\0' && *ep != ' ' && *ep != '{'; ep++)
4045 pfnote((CTAGS) ? savenstr(bp, ep - bp) : NULL, TRUE,
4046 lb.buffer, ep - lb.buffer + 1, lineno,
4053 * Scheme tag functions
4054 * look for (def... xyzzy
4055 * look for (def... (xyzzy
4056 * look for (def ... ((...(xyzzy ....
4057 * look for (set! xyzzy
4060 void get_scheme PP((void));
4062 void Scheme_functions(inf)
4065 LOOP_ON_INPUT_LINES(inf, lb, dbp) {
4066 if (dbp[0] == '(' && (dbp[1] == 'D' || dbp[1] == 'd')
4067 && (dbp[2] == 'E' || dbp[2] == 'e')
4068 && (dbp[3] == 'F' || dbp[3] == 'f')) {
4069 dbp = skip_non_spaces(dbp);
4070 /* Skip over open parens and white space */
4071 while (isspace(*dbp) || *dbp == '(')
4075 if (dbp[0] == '(' && (dbp[1] == 'S' || dbp[1] == 's')
4076 && (dbp[2] == 'E' || dbp[2] == 'e')
4077 && (dbp[3] == 'T' || dbp[3] == 't')
4078 && (dbp[4] == '!' || dbp[4] == '!')
4079 && (isspace(dbp[5]))) {
4080 dbp = skip_non_spaces(dbp);
4081 dbp = skip_spaces(dbp);
4093 /* Go till you get to white space or a syntactic break */
4095 *cp != '\0' && *cp != '(' && *cp != ')' && !isspace(*cp); cp++)
4097 pfnote((CTAGS) ? savenstr(dbp, cp - dbp) : NULL, TRUE,
4098 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4101 /* Find tags in TeX and LaTeX input files. */
4103 /* TEX_toktab is a table of TeX control sequences that define tags.
4104 Each TEX_tabent records one such control sequence.
4105 CONVERT THIS TO USE THE Stab TYPE!! */
4111 struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
4113 /* Default set of control sequences to put into TEX_toktab.
4114 The value of environment var TEXTAGS is prepended to this. */
4116 char *TEX_defenv = "\
4117 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4118 :part:appendix:entry:index";
4120 void TEX_mode PP((FILE * inf));
4121 struct TEX_tabent *TEX_decode_env PP((char *evarname, char *defenv));
4122 int TEX_Token PP((char *cp));
4124 char TEX_esc = '\\';
4125 char TEX_opgrp = '{';
4126 char TEX_clgrp = '}';
4129 * TeX/LaTeX scanning loop.
4131 void TeX_functions(inf)
4137 /* Select either \ or ! as escape character. */
4140 /* Initialize token table once from environment. */
4142 TEX_toktab = TEX_decode_env("TEXTAGS", TEX_defenv);
4144 LOOP_ON_INPUT_LINES(inf, lb, cp) {
4146 /* Look at each esc in line. */
4147 while ((cp = etags_strchr(cp, TEX_esc)) != NULL) {
4150 linecharno += cp - lasthit;
4152 i = TEX_Token(lasthit);
4154 /* We seem to include the TeX command in the tag name.
4156 for (p = lasthit + TEX_toktab[i].len;
4157 *p != '\0' && *p != TEX_clgrp;
4160 pfnote( /*savenstr (lasthit, p-lasthit) */
4162 lb.buffer, lb.len, lineno, linecharno);
4163 break; /* We only tag a line once */
4169 #define TEX_LESC '\\'
4170 #define TEX_SESC '!'
4173 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4174 chars accordingly. */
4180 while ((c = getc(inf)) != EOF) {
4181 /* Skip to next line if we hit the TeX comment char. */
4185 else if (c == TEX_LESC || c == TEX_SESC)
4189 if (c == TEX_LESC) {
4201 /* Read environment and prepend it to the default string.
4202 Build token table. */
4203 struct TEX_tabent *TEX_decode_env(evarname, defenv)
4207 register char *env, *p;
4209 struct TEX_tabent *tab;
4212 /* Append default string to environment. */
4213 env = getenv(evarname);
4218 env = concat(oldenv, defenv, "");
4222 /* Allocate a token table */
4223 for (size = 1, p = env; p;)
4224 if ((p = etags_strchr(p, ':')) && *++p != '\0')
4226 /* Add 1 to leave room for null terminator. */
4227 tab = xnew(size + 1, struct TEX_tabent);
4229 /* Unpack environment string into token table. Be careful about */
4230 /* zero-length strings (leading ':', "::" and trailing ':') */
4231 for (i = 0; *env;) {
4232 p = etags_strchr(env, ':');
4233 if (!p) /* End of environment string. */
4234 p = env + strlen(env);
4235 if (p - env > 0) { /* Only non-zero strings. */
4236 tab[i].name = savenstr(env, p - env);
4237 tab[i].len = strlen(tab[i].name);
4243 tab[i].name = NULL; /* Mark end of table. */
4251 /* If the text at CP matches one of the tag-defining TeX command names,
4252 return the pointer to the first occurrence of that command in TEX_toktab.
4253 Otherwise return -1.
4254 Keep the capital `T' in `token' for dumb truncating compilers
4255 (this distinguishes it from `TEX_toktab' */
4261 for (i = 0; TEX_toktab[i].len > 0; i++)
4262 if (strneq(TEX_toktab[i].name, cp, TEX_toktab[i].len))
4268 * Prolog support (rewritten) by Anders Lindgren, Mar. 96
4270 * Assumes that the predicate starts at column 0.
4271 * Only the first clause of a predicate is added.
4273 int prolog_pred PP((char *s, char *last));
4274 void prolog_skip_comment PP((linebuffer * plb, FILE * inf));
4275 int prolog_atom PP((char *s, int pos));
4277 void Prolog_functions(inf)
4288 LOOP_ON_INPUT_LINES(inf, lb, cp) {
4289 if (cp[0] == '\0') /* Empty line */
4291 else if (isspace(cp[0])) /* Not a predicate */
4293 else if (cp[0] == '/' && cp[1] == '*') /* comment. */
4294 prolog_skip_comment(&lb, inf);
4295 else if ((len = prolog_pred(cp, last)) > 0) {
4296 /* Predicate. Store the function name so that we only
4297 generate a tag for the first clause. */
4299 last = xnew(len + 1, char);
4300 else if (len + 1 > allocated)
4301 last = xrnew(last, len + 1, char);
4302 allocated = len + 1;
4303 xstrncpy(last, cp, len);
4310 void prolog_skip_comment(plb, inf)
4317 for (cp = plb->buffer; *cp != '\0'; cp++)
4318 if (cp[0] == '*' && cp[1] == '/')
4321 linecharno += readline(plb, inf);
4327 * A predicate definition is added if it matches:
4328 * <beginning of line><Prolog Atom><whitespace>(
4330 * It is added to the tags database if it doesn't match the
4331 * name of the previous clause header.
4333 * Return the size of the name of the predicate, or 0 if no header
4336 int prolog_pred(s, last)
4338 char *last; /* Name of last clause. */
4343 pos = prolog_atom(s, 0);
4348 pos = skip_spaces(s + pos) - s;
4350 if ((s[pos] == '(') || (s[pos] == '.')) {
4354 /* Save only the first clause. */
4355 if (last == NULL || len != (int)strlen(last)
4356 || !strneq(s, last, len)) {
4357 pfnote((CTAGS) ? savenstr(s, len) : NULL, TRUE,
4358 s, pos, lineno, linecharno);
4366 * Consume a Prolog atom.
4367 * Return the number of bytes consumed, or -1 if there was an error.
4369 * A prolog atom, in this context, could be one of:
4370 * - An alphanumeric sequence, starting with a lower case letter.
4371 * - A quoted arbitrary string. Single quotes can escape themselves.
4372 * Backslash quotes everything.
4374 int prolog_atom(s, pos)
4382 if (islower(s[pos]) || (s[pos] == '_')) {
4383 /* The atom is unquoted. */
4385 while (isalnum(s[pos]) || (s[pos] == '_')) {
4388 return pos - origpos;
4389 } else if (s[pos] == '\'') {
4393 if (s[pos] == '\'') {
4397 pos++; /* A double quote */
4398 } else if (s[pos] == '\0')
4399 /* Multiline quoted atoms are ignored. */
4401 else if (s[pos] == '\\') {
4402 if (s[pos + 1] == '\0')
4408 return pos - origpos;
4414 * Support for Erlang -- Anders Lindgren, Feb 1996.
4416 * Generates tags for functions, defines, and records.
4418 * Assumes that Erlang functions start at column 0.
4420 int erlang_func PP((char *s, char *last));
4421 void erlang_attribute PP((char *s));
4422 int erlang_atom PP((char *s, int pos));
4424 void Erlang_functions(inf)
4435 LOOP_ON_INPUT_LINES(inf, lb, cp) {
4436 if (cp[0] == '\0') /* Empty line */
4438 else if (isspace(cp[0])) /* Not function nor attribute */
4440 else if (cp[0] == '%') /* comment */
4442 else if (cp[0] == '"') /* Sometimes, strings start in column one */
4444 else if (cp[0] == '-') { /* attribute, e.g. "-define" */
4445 erlang_attribute(cp);
4448 } else if ((len = erlang_func(cp, last)) > 0) {
4450 * Function. Store the function name so that we only
4451 * generates a tag for the first clause.
4454 last = xnew(len + 1, char);
4455 else if (len + 1 > allocated)
4456 last = xrnew(last, len + 1, char);
4457 allocated = len + 1;
4458 xstrncpy(last, cp, len);
4466 * A function definition is added if it matches:
4467 * <beginning of line><Erlang Atom><whitespace>(
4469 * It is added to the tags database if it doesn't match the
4470 * name of the previous clause header.
4472 * Return the size of the name of the function, or 0 if no function
4475 int erlang_func(s, last)
4477 char *last; /* Name of last clause. */
4482 pos = erlang_atom(s, 0);
4487 pos = skip_spaces(s + pos) - s;
4489 /* Save only the first clause. */
4490 if (s[pos++] == '(' && (last == NULL || len != (int)strlen(last)
4491 || !strneq(s, last, len))) {
4492 pfnote((CTAGS) ? savenstr(s, len) : NULL, TRUE,
4493 s, pos, lineno, linecharno);
4501 * Handle attributes. Currently, tags are generated for defines
4504 * They are on the form:
4505 * -define(foo, bar).
4506 * -define(Foo(M, N), M+N).
4507 * -record(graph, {vtab = notable, cyclic = true}).
4509 void erlang_attribute(s)
4515 if (strneq(s, "-define", 7) || strneq(s, "-record", 7)) {
4516 pos = skip_spaces(s + 7) - s;
4517 if (s[pos++] == '(') {
4518 pos = skip_spaces(s + pos) - s;
4519 len = erlang_atom(s, pos);
4521 pfnote((CTAGS) ? savenstr(&s[pos], len) : NULL,
4522 TRUE, s, pos + len, lineno, linecharno);
4529 * Consume an Erlang atom (or variable).
4530 * Return the number of bytes consumed, or -1 if there was an error.
4532 int erlang_atom(s, pos)
4540 if (isalpha(s[pos]) || s[pos] == '_') {
4541 /* The atom is unquoted. */
4543 while (isalnum(s[pos]) || s[pos] == '_')
4545 return pos - origpos;
4546 } else if (s[pos] == '\'') {
4550 if (s[pos] == '\'') {
4553 } else if (s[pos] == '\0')
4554 /* Multiline quoted atoms are ignored. */
4556 else if (s[pos] == '\\') {
4557 if (s[pos + 1] == '\0')
4563 return pos - origpos;
4568 #ifdef ETAGS_REGEXPS
4570 /* Take a string like "/blah/" and turn it into "blah", making sure
4571 that the first and last characters are the same, and handling
4572 quoted separator characters. Actually, stops on the occurrence of
4573 an unquoted separator. Also turns "\t" into a Tab character.
4574 Returns pointer to terminating separator. Works in place. Null
4575 terminates name string. */
4576 char *scan_separators PP((char *name));
4577 char *scan_separators(name)
4581 char *copyto = name;
4582 bool quoted = FALSE;
4584 for (++name; *name != '\0'; ++name) {
4588 else if (*name == sep)
4591 /* Something else is quoted, so preserve the quote. */
4596 } else if (*name == '\\')
4598 else if (*name == sep)
4604 /* Terminate copied string. */
4609 /* Look at the argument of --regex or --no-regex and do the right
4610 thing. Same for each line of a regexp file. */
4611 void analyse_regex(regex_arg)
4614 if (regex_arg == NULL) {
4615 free_patterns(); /* --no-regex: remove existing regexps */
4618 /* A real --regexp option or a line in a regexp file. */
4619 switch (regex_arg[0]) {
4620 /* Comments in regexp file or null arg to --regex. */
4626 /* Read a regex file. This is recursive and may result in a
4627 loop, which will stop when the file descriptors are exhausted. */
4631 linebuffer regexbuf;
4632 char *regexfile = regex_arg + 1;
4634 /* regexfile is a file containing regexps, one per line. */
4635 regexfp = fopen(regexfile, "r");
4636 if (regexfp == NULL) {
4640 initbuffer(®exbuf);
4641 while (readline_internal(®exbuf, regexfp) > 0)
4642 analyse_regex(regexbuf.buffer);
4643 free(regexbuf.buffer);
4648 /* Regexp to be used for a specific language only. */
4652 char *lang_name = regex_arg + 1;
4655 for (cp = lang_name; *cp != '}'; cp++)
4658 ("unterminated language name in regex: %s",
4663 lang = get_language_from_name(lang_name);
4666 add_regex(cp + 1, lang);
4670 /* Regexp to be used for any language. */
4672 add_regex(regex_arg, NULL);
4677 /* Turn a name, which is an ed-style (but Emacs syntax) regular
4678 expression, into a real regular expression by compiling it. */
4679 void add_regex(regexp_pattern, lang)
4680 char *regexp_pattern;
4685 struct re_pattern_buffer *patbuf;
4688 if (regexp_pattern[strlen(regexp_pattern) - 1] != regexp_pattern[0]) {
4689 error("%s: unterminated regexp", regexp_pattern);
4692 name = scan_separators(regexp_pattern);
4693 if (regexp_pattern[0] == '\0') {
4694 error("null regexp", (char *)NULL);
4697 (void)scan_separators(name);
4699 patbuf = xnew(1, struct re_pattern_buffer);
4700 patbuf->translate = NULL;
4701 patbuf->fastmap = NULL;
4702 patbuf->buffer = NULL;
4703 patbuf->allocated = 0;
4706 re_compile_pattern(regexp_pattern, strlen(regexp_pattern), patbuf);
4708 error("%s while compiling pattern", err);
4713 p_head = xnew(1, pattern);
4714 p_head->regex = savestr(regexp_pattern);
4715 p_head->p_next = pp;
4716 p_head->language = lang;
4717 p_head->pattern = patbuf;
4718 p_head->name_pattern = savestr(name);
4719 p_head->error_signaled = FALSE;
4723 * Do the substitutions indicated by the regular expression and
4726 char *substitute PP((char *in, char *out, struct re_registers * regs));
4727 char *substitute(in, out, regs)
4729 struct re_registers *regs;
4732 int size, dig, diglen;
4737 /* Pass 1: figure out how much to allocate by finding all \N strings. */
4738 if (out[size - 1] == '\\')
4739 fatal("pattern error in \"%s\"", out);
4740 for (t = etags_strchr(out, '\\');
4741 t != NULL; t = etags_strchr(t + 2, '\\'))
4742 if (isdigit(t[1])) {
4744 diglen = regs->end[dig] - regs->start[dig];
4749 /* Allocate space and do the substitutions. */
4750 result = xnew(size + 1, char);
4752 for (t = result; *out != '\0'; out++)
4753 if (*out == '\\' && isdigit(*++out)) {
4754 /* Using "dig2" satisfies my debugger. Bleah. */
4756 diglen = regs->end[dig] - regs->start[dig];
4757 xstrncpy(t, in + regs->start[dig], diglen);
4763 if (DEBUG && (t > result + size || t - result != strlen(result)))
4769 /* Deallocate all patterns. */
4770 void free_patterns()
4773 while (p_head != NULL) {
4774 pp = p_head->p_next;
4775 free(p_head->regex);
4776 free(p_head->name_pattern);
4783 #endif /* ETAGS_REGEXPS */
4784 /* Initialize a linebuffer for use */
4785 void initbuffer(lbp)
4789 lbp->buffer = xnew(200, char);
4793 * Read a line of text from `stream' into `lbp', excluding the
4794 * newline or CR-NL, if any. Return the number of characters read from
4795 * `stream', which is the length of the line including the newline.
4797 * On DOS or Windows we do not count the CR character, if any, before the
4798 * NL, in the returned length; this mirrors the behavior of emacs on those
4799 * platforms (for text files, it translates CR-NL to NL as it reads in the
4802 long readline_internal(lbp, stream)
4804 register FILE *stream;
4806 char *buffer = lbp->buffer;
4807 register char *p = lbp->buffer;
4808 register char *pend;
4811 pend = p + lbp->size; /* Separate to avoid 386/IX compiler bug. */
4814 register int c = getc(stream);
4816 /* We're at the end of linebuffer: expand it. */
4818 buffer = xrnew(buffer, lbp->size, char);
4819 p += buffer - lbp->buffer;
4820 pend = buffer + lbp->size;
4821 lbp->buffer = buffer;
4829 if (p > buffer && p[-1] == '\r') {
4840 lbp->len = p - buffer;
4842 return lbp->len + chars_deleted;
4846 * Like readline_internal, above, but in addition try to match the
4847 * input line against relevant regular expressions.
4849 long readline(lbp, stream)
4853 /* Read new line. */
4854 long result = readline_internal(lbp, stream);
4855 #ifdef ETAGS_REGEXPS
4859 /* Match against relevant patterns. */
4861 for (pp = p_head; pp != NULL; pp = pp->p_next) {
4862 /* Only use generic regexps or those for the current language. */
4863 if (pp->language != NULL && pp->language != curlang)
4867 re_match(pp->pattern, lbp->buffer, lbp->len, 0,
4872 if (!pp->error_signaled) {
4873 error("error while matching \"%s\"",
4875 pp->error_signaled = TRUE;
4882 /* Match occurred. Construct a tag. */
4883 if (pp->name_pattern[0] != '\0') {
4884 /* Make a named tag. */
4885 char *name = substitute(lbp->buffer,
4890 pfnote(name, TRUE, lbp->buffer,
4894 /* Make an unnamed tag. */
4895 pfnote((char *)NULL, TRUE,
4896 lbp->buffer, match, lineno,
4902 #endif /* ETAGS_REGEXPS */
4908 * Return a pointer to a space of size strlen(cp)+1 allocated
4909 * with xnew where the string CP has been copied.
4914 return savenstr(cp, strlen(cp));
4918 * Return a pointer to a space of size LEN+1 allocated with xnew where
4919 * the string CP has been copied for at most the first LEN characters.
4921 char *savenstr(cp, len)
4927 dp = xnew(len + 1, char);
4928 xstrncpy(dp, cp, len);
4934 * Return the ptr in sp at which the character c last
4935 * appears; NULL if not found
4937 * Identical to System V strrchr, included for portability.
4939 char *etags_strrchr(sp, c)
4954 * Return the ptr in sp at which the character c first
4955 * appears; NULL if not found
4957 * Identical to System V strchr, included for portability.
4959 char *etags_strchr(sp, c)
4970 /* Skip spaces, return new pointer. */
4971 char *skip_spaces(cp)
4974 while (isspace(*cp)) /* isspace('\0')==FALSE */
4979 /* Skip non spaces, return new pointer. */
4980 char *skip_non_spaces(cp)
4983 while (!iswhite(*cp)) /* iswhite('\0')==TRUE */
4988 /* Print error message and exit. */
5003 void suggest_asking_for_help()
5005 fprintf(stderr, "\tTry `%s %s' for a complete list of options.\n",
5016 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
5018 const char *s1, *s2;
5020 fprintf(stderr, "%s: ", progname);
5021 fprintf(stderr, s1, s2);
5022 fprintf(stderr, "\n");
5025 /* Return a newly-allocated string whose contents
5026 concatenate those of s1, s2, s3. */
5027 char *concat(s1, s2, s3)
5030 int len1 = strlen(s1), len2 = strlen(s2), len3 = strlen(s3);
5031 char *result = xnew(len1 + len2 + len3 + 1, char);
5034 strcpy(result + len1, s2);
5035 strcpy(result + len1 + len2, s3);
5036 result[len1 + len2 + len3] = '\0';
5041 /* Does the same work as the system V getcwd, but does not need to
5042 guess the buffer size in advance. */
5043 char *etags_getcwd()
5047 char *path = xnew(bufsize, char);
5049 while (getcwd(path, bufsize) == NULL) {
5050 if (errno != ERANGE)
5054 path = xnew(bufsize, char);
5057 canonicalize_filename(path);
5060 #else /* not HAVE_GETCWD */
5065 pipe = (FILE *) popen("pwd 2>/dev/null", "r");
5066 if (pipe == NULL || readline_internal(&path, pipe) == 0)
5071 #endif /* not HAVE_GETCWD */
5074 /* Return a newly allocated string containing the file name of FILE
5075 relative to the absolute directory DIR (which should end with a slash). */
5076 char *relative_filename(file, dir)
5079 char *fp, *dp, *afn, *res;
5083 /* Find the common root of file and dir (with a trailing slash). */
5084 afn = absolute_filename(file, cwd);
5087 while (*fp++ == *dp++)
5089 fp--, dp--; /* back to the first differing char */
5090 do /* look at the equal chars until '/' */
5093 fp ++; /* Advance past the '/' */
5095 /* Build a sequence of "../" strings for the resulting relative file name. */
5097 while ((dp = etags_strchr(dp + 1, '/')) != NULL)
5099 res_left = 3 * i + strlen(fp);
5100 res = xnew( res_left + 1, char);
5102 for ( ; i-- > 0 ; res_left -= 4 )
5103 strncat(res, "../", res_left );
5105 /* Add the file name relative to the common root of file and dir. */
5106 strncat(res, fp, res_left);
5112 /* Return a newly allocated string containing the absolute file name
5113 of FILE given DIR (which should end with a slash). */
5114 char *absolute_filename(file, dir)
5117 char *slashp, *cp, *res;
5119 if (filename_is_absolute(file))
5120 res = savestr(file);
5122 res = concat(dir, file, "");
5124 /* Delete the "/dirname/.." and "/." substrings. */
5125 slashp = etags_strchr(res, '/');
5126 while (slashp != NULL && slashp[0] != '\0') {
5127 if (slashp[1] == '.') {
5128 if (slashp[2] == '.'
5129 && (slashp[3] == '/' || slashp[3] == '\0')) {
5133 while (cp >= res && !filename_is_absolute(cp));
5135 cp = slashp; /* the absolute name begins with "/.." */
5136 strcpy(cp, slashp + 3);
5139 } else if (slashp[2] == '/' || slashp[2] == '\0') {
5140 strcpy(slashp, slashp + 2);
5145 slashp = etags_strchr(slashp + 1, '/');
5149 return savestr("/");
5154 /* Return a newly allocated string containing the absolute
5155 file name of dir where FILE resides given DIR (which should
5156 end with a slash). */
5157 char *absolute_dirname(file, dir)
5163 canonicalize_filename(file);
5164 slashp = etags_strrchr(file, '/');
5166 return savestr(dir);
5169 res = absolute_filename(file, dir);
5175 /* Whether the argument string is an absolute file name. The argument
5176 string must have been canonicalized with canonicalize_filename. */
5177 bool filename_is_absolute(fn)
5180 return (fn[0] == '/');
5183 /* Translate backslashes into slashes. Works in place. */
5184 void canonicalize_filename(fn)
5190 /* Increase the size of a linebuffer. */
5191 void grow_linebuffer(lbp, toksize)
5195 while (lbp->size < toksize)
5197 lbp->buffer = xrnew(lbp->buffer, lbp->size, char);
5200 /* Like malloc but get fatal error if memory is exhausted. */
5204 long *result = (long *)malloc(size);
5206 fatal("virtual memory exhausted", (char *)NULL);
5210 long *xrealloc(ptr, size)
5214 long *result = (long *)realloc(ptr, size);
5216 fatal("virtual memory exhausted", (char *)NULL);