comparison lib-src/etags.c @ 42042:481d38f6aec2

* etags.c (PHP_functions): New function by Diez B. Roggisch, heavily adapted by me, for parsing PHP. (LOOKING_AT): New macro. (Perl_functions, Python_functions, PHP_functions) (Scheme_functions, Texinfo_nodes): Use it. (Perl_functions): Use strneq. (prolog_pred): Renamed to prolog_pr. (prolog_pr): Recognise Prolog rules (thanks to Geert Kloosterman) in addition to predicates. [ETAGS_REGEXPS] [!HAVE_CONFIG_H] [__CYGWIN__]: Prevent unmodified compile, as Cygwin's regex.h is incompatible with us (thanks to Markus Hoenicka). [!HAVE_CONFIG_H] [!__STDC__]: #define const as the empty string.
author Francesco Potortì <pot@gnu.org>
date Sat, 15 Dec 2001 16:07:31 +0000
parents a7f40b000353
children 7d2776273a81
comparison
equal deleted inserted replaced
42041:b4eeb5fd09f9 42042:481d38f6aec2
30 * 2001 Nested classes by Francesco Potort́ based on work by Mykola Dzyuba. 30 * 2001 Nested classes by Francesco Potort́ based on work by Mykola Dzyuba.
31 * 31 *
32 * Francesco Potort́ <pot@gnu.org> has maintained it since 1993. 32 * Francesco Potort́ <pot@gnu.org> has maintained it since 1993.
33 */ 33 */
34 34
35 char pot_etags_version[] = "@(#) pot revision number is 14.21"; 35 char pot_etags_version[] = "@(#) pot revision number is 14.26";
36 36
37 #define TRUE 1 37 #define TRUE 1
38 #define FALSE 0 38 #define FALSE 0
39 39
40 #ifdef DEBUG 40 #ifdef DEBUG
59 # define ETAGS_REGEXPS /* use the regexp features */ 59 # define ETAGS_REGEXPS /* use the regexp features */
60 # define LONG_OPTIONS /* accept long options */ 60 # define LONG_OPTIONS /* accept long options */
61 #else 61 #else
62 # ifndef __STDC__ 62 # ifndef __STDC__
63 # define static /* remove static for old compilers' sake */ 63 # define static /* remove static for old compilers' sake */
64 # define const /* same for const */
64 # endif 65 # endif
65 #endif /* !HAVE_CONFIG_H */ 66 #endif /* !HAVE_CONFIG_H */
66 67
67 #ifndef _GNU_SOURCE 68 #ifndef _GNU_SOURCE
68 # define _GNU_SOURCE 1 /* enables some compiler checks on GNU */ 69 # define _GNU_SOURCE 1 /* enables some compiler checks on GNU */
146 extern char *optarg; 147 extern char *optarg;
147 extern int optind, opterr; 148 extern int optind, opterr;
148 #endif /* LONG_OPTIONS */ 149 #endif /* LONG_OPTIONS */
149 150
150 #ifdef ETAGS_REGEXPS 151 #ifdef ETAGS_REGEXPS
152 # ifndef HAVE_CONFIG_H /* this is a standalone compilation */
153 # ifdef __CYGWIN__ /* compiling on Cygwin */
154 !!! NOTICE !!!
155 the regex.h distributed with Cygwin is not compatible with etags, alas!
156 If you want regular expression support, you should delete this notice and
157 arrange to use the GNU regex.h and regex.c.
158 # endif
159 # endif
151 # include <regex.h> 160 # include <regex.h>
152 #endif /* ETAGS_REGEXPS */ 161 #endif /* ETAGS_REGEXPS */
153 162
154 /* Define CTAGS to make the program "ctags" compatible with the usual one. 163 /* Define CTAGS to make the program "ctags" compatible with the usual one.
155 Leave it undefined to make the program "etags", which makes emacs-style 164 Leave it undefined to make the program "etags", which makes emacs-style
270 static void Yacc_entries P_((FILE *)); 279 static void Yacc_entries P_((FILE *));
271 static void Lisp_functions P_((FILE *)); 280 static void Lisp_functions P_((FILE *));
272 static void Makefile_targets P_((FILE *)); 281 static void Makefile_targets P_((FILE *));
273 static void Pascal_functions P_((FILE *)); 282 static void Pascal_functions P_((FILE *));
274 static void Perl_functions P_((FILE *)); 283 static void Perl_functions P_((FILE *));
284 static void PHP_functions P_((FILE *));
275 static void Postscript_functions P_((FILE *)); 285 static void Postscript_functions P_((FILE *));
276 static void Prolog_functions P_((FILE *)); 286 static void Prolog_functions P_((FILE *));
277 static void Python_functions P_((FILE *)); 287 static void Python_functions P_((FILE *));
278 static void Scheme_functions P_((FILE *)); 288 static void Scheme_functions P_((FILE *));
279 static void TeX_commands P_((FILE *)); 289 static void TeX_commands P_((FILE *));
519 char *Perl_suffixes [] = 529 char *Perl_suffixes [] =
520 { "pl", "pm", NULL }; 530 { "pl", "pm", NULL };
521 char *Perl_interpreters [] = 531 char *Perl_interpreters [] =
522 { "perl", "@PERL@", NULL }; 532 { "perl", "@PERL@", NULL };
523 533
534 char *PHP_suffixes [] =
535 { "php", "php3", "php4", NULL };
536
524 char *plain_C_suffixes [] = 537 char *plain_C_suffixes [] =
525 { "lm", /* Objective lex file */ 538 { "lm", /* Objective lex file */
526 "m", /* Objective C file */ 539 "m", /* Objective C file */
527 "pc", /* Pro*C file */ 540 "pc", /* Pro*C file */
528 NULL }; 541 NULL };
569 { "java", Cjava_entries, NULL, Cjava_suffixes, NULL }, 582 { "java", Cjava_entries, NULL, Cjava_suffixes, NULL },
570 { "lisp", Lisp_functions, NULL, Lisp_suffixes, NULL }, 583 { "lisp", Lisp_functions, NULL, Lisp_suffixes, NULL },
571 { "makefile", Makefile_targets, Makefile_filenames, NULL, NULL }, 584 { "makefile", Makefile_targets, Makefile_filenames, NULL, NULL },
572 { "pascal", Pascal_functions, NULL, Pascal_suffixes, NULL }, 585 { "pascal", Pascal_functions, NULL, Pascal_suffixes, NULL },
573 { "perl", Perl_functions, NULL, Perl_suffixes, Perl_interpreters }, 586 { "perl", Perl_functions, NULL, Perl_suffixes, Perl_interpreters },
587 { "php", PHP_functions, NULL, PHP_suffixes, NULL },
574 { "postscript", Postscript_functions, NULL, Postscript_suffixes, NULL }, 588 { "postscript", Postscript_functions, NULL, Postscript_suffixes, NULL },
575 { "proc", plain_C_entries, NULL, plain_C_suffixes, NULL }, 589 { "proc", plain_C_entries, NULL, plain_C_suffixes, NULL },
576 { "prolog", Prolog_functions, NULL, Prolog_suffixes, NULL }, 590 { "prolog", Prolog_functions, NULL, Prolog_suffixes, NULL },
577 { "python", Python_functions, NULL, Python_suffixes, NULL }, 591 { "python", Python_functions, NULL, Python_suffixes, NULL },
578 { "scheme", Scheme_functions, NULL, Scheme_suffixes, NULL }, 592 { "scheme", Scheme_functions, NULL, Scheme_suffixes, NULL },
3580 { 3594 {
3581 C_entries (YACC, inf); 3595 C_entries (YACC, inf);
3582 } 3596 }
3583 3597
3584 3598
3585 /* A useful macro. */ 3599 /* Useful macros. */
3586 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \ 3600 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3587 for (lineno = charno = 0; /* loop initialization */ \ 3601 for (lineno = charno = 0; /* loop initialization */ \
3588 !feof (file_pointer) /* loop test */ \ 3602 !feof (file_pointer) /* loop test */ \
3589 && (lineno++, /* instructions at start of loop */ \ 3603 && (lineno++, /* instructions at start of loop */ \
3590 linecharno = charno, \ 3604 linecharno = charno, \
3591 charno += readline (&line_buffer, file_pointer), \ 3605 charno += readline (&line_buffer, file_pointer), \
3592 char_pointer = lb.buffer, \ 3606 char_pointer = lb.buffer, \
3593 TRUE); \ 3607 TRUE); \
3594 ) 3608 )
3595 3609 #define LOOKING_AT(cp, keyword) /* keyword is a constant string */ \
3610 (strneq ((cp), keyword, sizeof(keyword)-1) /* cp points at kyword */ \
3611 && iswhite((cp)[sizeof(keyword)-1]) /* followed by a blank */ \
3612 && ((cp) = skip_spaces((cp)+sizeof(keyword)-1))) /* skip blanks */
3596 3613
3597 /* 3614 /*
3598 * Read a file, but do no processing. This is used to do regexp 3615 * Read a file, but do no processing. This is used to do regexp
3599 * matching on files that have no language defined. 3616 * matching on files that have no language defined.
3600 */ 3617 */
3969 { 3986 {
3970 register char *cp; 3987 register char *cp;
3971 3988
3972 LOOP_ON_INPUT_LINES (inf, lb, cp) 3989 LOOP_ON_INPUT_LINES (inf, lb, cp)
3973 { 3990 {
3974 if (*cp++ == 's' 3991 if (LOOKING_AT (cp, "sub"))
3975 && *cp++ == 'u' 3992 {
3976 && *cp++ == 'b' && iswhite (*cp++))
3977 {
3978 cp = skip_spaces (cp);
3979 if (*cp != '\0') 3993 if (*cp != '\0')
3980 { 3994 {
3981 char *sp = cp; 3995 char *sp = cp;
3982 while (*cp != '\0' 3996 while (*cp != '\0'
3983 && !iswhite (*cp) && *cp != '{' && *cp != '(') 3997 && !iswhite (*cp) && *cp != '{' && *cp != '(')
3985 pfnote (savenstr (sp, cp-sp), TRUE, 3999 pfnote (savenstr (sp, cp-sp), TRUE,
3986 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 4000 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3987 } 4001 }
3988 } 4002 }
3989 else if (globals /* only if tagging global vars is enabled */ 4003 else if (globals /* only if tagging global vars is enabled */
3990 && ((cp = lb.buffer, 4004 && ((strneq (cp, "my", 2) && (cp+=2))
3991 *cp++ == 'm' 4005 || (strneq (cp, "local", 5) && (cp+=5)))
3992 && *cp++ == 'y')
3993 || (cp = lb.buffer,
3994 *cp++ == 'l'
3995 && *cp++ == 'o'
3996 && *cp++ == 'c'
3997 && *cp++ == 'a'
3998 && *cp++ == 'l'))
3999 && (*cp == '(' || iswhite (*cp))) 4006 && (*cp == '(' || iswhite (*cp)))
4000 { 4007 {
4001 /* After "my" or "local", but before any following paren or space. */ 4008 /* After "my" or "local", but before any following paren or space. */
4002 char *varname = NULL; 4009 char *varname = NULL;
4003 4010
4023 FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 4030 FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4024 } 4031 }
4025 } 4032 }
4026 } 4033 }
4027 4034
4028 4035
4029 /* 4036 /*
4030 * Python support 4037 * Python support
4031 * Look for /^def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/ 4038 * Look for /^def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
4032 * Eric S. Raymond <esr@thyrsus.com> (1997) 4039 * Eric S. Raymond <esr@thyrsus.com> (1997)
4033 */ 4040 */
4036 FILE *inf; 4043 FILE *inf;
4037 { 4044 {
4038 register char *cp; 4045 register char *cp;
4039 4046
4040 LOOP_ON_INPUT_LINES (inf, lb, cp) 4047 LOOP_ON_INPUT_LINES (inf, lb, cp)
4041 { 4048 if (LOOKING_AT (cp, "def") || LOOKING_AT (cp, "class"))
4042 if (*cp++ == 'd' 4049 {
4043 && *cp++ == 'e' 4050 while (*cp != '\0' && !iswhite (*cp) && *cp != '(' && *cp != ':')
4044 && *cp++ == 'f' && iswhite (*cp++)) 4051 cp++;
4045 { 4052 pfnote (NULL, TRUE,
4046 cp = skip_spaces (cp); 4053 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4047 while (*cp != '\0' && !iswhite (*cp) && *cp != '(' && *cp != ':') 4054 }
4055 }
4056
4057
4058 /*
4059 * PHP support
4060 * Look for:
4061 * - /^[ \t]*function[ \t\n]+[^ \t\n(]+/
4062 * - /^[ \t]*class[ \t\n]+[^ \t\n]+/
4063 * - /^[ \t]*define\(\"[^\"]+/
4064 * Only with --members:
4065 * - /^[ \t]*var[ \t\n]+\$[^ \t\n=;]/
4066 * originally by Diez B. Roggisch 2001-06-06
4067 */
4068 static void
4069 PHP_functions (inf)
4070 FILE *inf;
4071 {
4072 register char *cp;
4073 bool search_identifier = FALSE;
4074
4075 LOOP_ON_INPUT_LINES (inf, lb, cp)
4076 {
4077 cp = skip_spaces (cp);
4078 if (search_identifier
4079 && *cp != '\0')
4080 {
4081 while (*cp != '\0' && !iswhite (*cp) && *cp != '(')
4048 cp++; 4082 cp++;
4049 pfnote (NULL, TRUE, 4083 pfnote (NULL, TRUE,
4050 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 4084 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4051 } 4085 search_identifier = FALSE;
4052 4086 }
4053 cp = lb.buffer; 4087 else if (LOOKING_AT (cp, "function"))
4054 if (*cp++ == 'c' 4088 {
4055 && *cp++ == 'l' 4089 if(*cp == '&')
4056 && *cp++ == 'a' 4090 cp = skip_spaces (cp+1);
4057 && *cp++ == 's' 4091 if(*cp != '\0')
4058 && *cp++ == 's' && iswhite (*cp++)) 4092 {
4059 { 4093 while (*cp != '\0' && !iswhite (*cp) && *cp != '(')
4060 cp = skip_spaces (cp); 4094 cp++;
4061 while (*cp != '\0' && !iswhite (*cp) && *cp != '(' && *cp != ':') 4095 pfnote (NULL, TRUE,
4096 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4097 }
4098 else
4099 search_identifier = TRUE;
4100 }
4101 else if (LOOKING_AT (cp, "class"))
4102 {
4103 if (*cp != '\0')
4104 {
4105 while (*cp != '\0' && !iswhite (*cp))
4106 cp++;
4107 pfnote (NULL, FALSE,
4108 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4109 }
4110 else
4111 search_identifier = TRUE;
4112 }
4113 else if (strneq (cp, "define", 6)
4114 && (cp = skip_spaces (cp+6))
4115 && *cp++ == '('
4116 && (*cp == '"' || *cp == '\''))
4117 {
4118 char quote = *cp++;
4119 while (*cp != quote && *cp != '\0')
4062 cp++; 4120 cp++;
4063 pfnote (NULL, TRUE, 4121 pfnote (NULL, FALSE,
4122 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4123 }
4124 else if (members
4125 && LOOKING_AT (cp, "var")
4126 && *cp == '$')
4127 {
4128 while (*cp != '=' && *cp != ';' && *cp != '\0' && !iswhite(*cp))
4129 cp++;
4130 pfnote (NULL, FALSE,
4064 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 4131 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4065 } 4132 }
4066 } 4133 }
4067 } 4134 }
4068 4135
4459 /* Skip over open parens and white space */ 4526 /* Skip over open parens and white space */
4460 while (iswhite (*bp) || *bp == '(') 4527 while (iswhite (*bp) || *bp == '(')
4461 bp++; 4528 bp++;
4462 get_tag (bp); 4529 get_tag (bp);
4463 } 4530 }
4464 if (bp[0] == '(' 4531 if (LOOKING_AT (bp, "(SET!") || LOOKING_AT (bp, "(set!"))
4465 && (bp[1] == 'S' || bp[1] == 's') 4532 get_tag (bp);
4466 && (bp[2] == 'E' || bp[2] == 'e')
4467 && (bp[3] == 'T' || bp[3] == 't')
4468 && (bp[4] == '!' || bp[4] == '!')
4469 && (iswhite (bp[5])))
4470 {
4471 bp = skip_non_spaces (bp);
4472 bp = skip_spaces (bp);
4473 get_tag (bp);
4474 }
4475 } 4533 }
4476 } 4534 }
4477 4535
4478 4536
4479 /* Find tags in TeX and LaTeX input files. */ 4537 /* Find tags in TeX and LaTeX input files. */
4664 Texinfo_nodes (inf) 4722 Texinfo_nodes (inf)
4665 FILE * inf; 4723 FILE * inf;
4666 { 4724 {
4667 char *cp, *start; 4725 char *cp, *start;
4668 LOOP_ON_INPUT_LINES (inf, lb, cp) 4726 LOOP_ON_INPUT_LINES (inf, lb, cp)
4669 { 4727 if (LOOKING_AT (cp, "@node"))
4670 if ((*cp++ == '@' 4728 {
4671 && *cp++ == 'n' 4729 start = cp;
4672 && *cp++ == 'o' 4730 while (*cp != '\0' && *cp != ',')
4673 && *cp++ == 'd' 4731 cp++;
4674 && *cp++ == 'e' && iswhite (*cp++))) 4732 pfnote (savenstr (start, cp - start), TRUE,
4675 { 4733 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4676 start = cp = skip_spaces(cp); 4734 }
4677 while (*cp != '\0' && *cp != ',')
4678 cp++;
4679 pfnote (savenstr (start, cp - start), TRUE,
4680 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4681 }
4682 }
4683 } 4735 }
4684 4736
4685 4737
4686 /* 4738 /*
4687 * Prolog support (rewritten) by Anders Lindgren, Mar. 96 4739 * Prolog support (rewritten) by Anders Lindgren, Mar. 96
4688 * 4740 *
4689 * Assumes that the predicate starts at column 0. 4741 * Assumes that the predicate starts at column 0.
4690 * Only the first clause of a predicate is added. 4742 * Only the first clause of a predicate is added.
4691 */ 4743 */
4692 static int prolog_pred P_((char *, char *)); 4744 static int prolog_pr P_((char *, char *));
4693 static void prolog_skip_comment P_((linebuffer *, FILE *)); 4745 static void prolog_skip_comment P_((linebuffer *, FILE *));
4694 static int prolog_atom P_((char *, int)); 4746 static int prolog_atom P_((char *, int));
4695 4747
4696 static void 4748 static void
4697 Prolog_functions (inf) 4749 Prolog_functions (inf)
4711 continue; 4763 continue;
4712 else if (iswhite (cp[0])) /* Not a predicate */ 4764 else if (iswhite (cp[0])) /* Not a predicate */
4713 continue; 4765 continue;
4714 else if (cp[0] == '/' && cp[1] == '*') /* comment. */ 4766 else if (cp[0] == '/' && cp[1] == '*') /* comment. */
4715 prolog_skip_comment (&lb, inf); 4767 prolog_skip_comment (&lb, inf);
4716 else if ((len = prolog_pred (cp, last)) > 0) 4768 else if ((len = prolog_pr (cp, last)) > 0)
4717 { 4769 {
4718 /* Predicate. Store the function name so that we only 4770 /* Predicate. Store the function name so that we only
4719 generate a tag for the first clause. */ 4771 generate a tag for the first clause. */
4720 if (last == NULL) 4772 if (last == NULL)
4721 last = xnew(len + 1, char); 4773 last = xnew(len + 1, char);
4746 } 4798 }
4747 while (!feof(inf)); 4799 while (!feof(inf));
4748 } 4800 }
4749 4801
4750 /* 4802 /*
4751 * A predicate definition is added if it matches: 4803 * A predicate or rule definition is added if it matches:
4752 * <beginning of line><Prolog Atom><whitespace>( 4804 * <beginning of line><Prolog Atom><whitespace>(
4805 * or <beginning of line><Prolog Atom><whitespace>:-
4753 * 4806 *
4754 * It is added to the tags database if it doesn't match the 4807 * It is added to the tags database if it doesn't match the
4755 * name of the previous clause header. 4808 * name of the previous clause header.
4756 * 4809 *
4757 * Return the size of the name of the predicate, or 0 if no header 4810 * Return the size of the name of the predicate or rule, or 0 if no
4758 * was found. 4811 * header was found.
4759 */ 4812 */
4760 static int 4813 static int
4761 prolog_pred (s, last) 4814 prolog_pr (s, last)
4762 char *s; 4815 char *s;
4763 char *last; /* Name of last clause. */ 4816 char *last; /* Name of last clause. */
4764 { 4817 {
4765 int pos; 4818 int pos;
4766 int len; 4819 int len;
4770 return 0; 4823 return 0;
4771 4824
4772 len = pos; 4825 len = pos;
4773 pos = skip_spaces (s + pos) - s; 4826 pos = skip_spaces (s + pos) - s;
4774 4827
4775 if ((s[pos] == '(') || (s[pos] == '.')) 4828 if ((s[pos] == '.'
4776 { 4829 || (s[pos] == '(' && (pos += 1))
4777 if (s[pos] == '(') 4830 || (s[pos] == ':' && s[pos + 1] == '-' && (pos += 2)))
4778 pos++; 4831 && (last == NULL /* save only the first clause */
4779 4832 || len != strlen (last)
4780 /* Save only the first clause. */ 4833 || !strneq (s, last, len)))
4781 if (last == NULL
4782 || len != (int)strlen (last)
4783 || !strneq (s, last, len))
4784 { 4834 {
4785 pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno); 4835 pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno);
4786 return len; 4836 return len;
4787 } 4837 }
4788 } 4838 else
4789 return 0; 4839 return 0;
4790 } 4840 }
4791 4841
4792 /* 4842 /*
4793 * Consume a Prolog atom. 4843 * Consume a Prolog atom.
4794 * Return the number of bytes consumed, or -1 if there was an error. 4844 * Return the number of bytes consumed, or -1 if there was an error.
5815 long *result = (long *) realloc (ptr, size); 5865 long *result = (long *) realloc (ptr, size);
5816 if (result == NULL) 5866 if (result == NULL)
5817 fatal ("virtual memory exhausted", (char *)NULL); 5867 fatal ("virtual memory exhausted", (char *)NULL);
5818 return result; 5868 return result;
5819 } 5869 }
5870
5871 /*
5872 * Local Variables:
5873 * c-indentation-style: gnu
5874 * indent-tabs-mode: t
5875 * tab-width: 8
5876 * c-font-lock-extra-types: ("FILE" "bool" "linebuffer")
5877 * End:
5878 */