aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorFrancesco Potortì1996-03-22 19:13:22 +0000
committerFrancesco Potortì1996-03-22 19:13:22 +0000
commit8dc7496c3f472a54d652c0725e2c015353c35bac (patch)
tree48bc51ca436e7dc7b2bf9f02e6c5dee1bf47335b /lib-src
parent6ccab458cc51e82ed10ba436e024a0eced858913 (diff)
downloademacs-8dc7496c3f472a54d652c0725e2c015353c35bac.tar.gz
emacs-8dc7496c3f472a54d652c0725e2c015353c35bac.zip
* etags.c (just_read_file): Reset lineno and charno on entry.
* etags.c: Prolog language totaly rewritten. (Prolog_functions): Rewritten from scratch. (skip_comment, prolog_getit): Removed. (prolog_skip_comment): New function, like old skip_comment. (prolog_pred, prolog_atom, prolog_white): New functions. (erlang_func, erlang_attributes): Forward declarations added. (erlang_atom): Check if backslash ends line inside quoted atom. * etags.c (absolutefn): DOS_NT version corrected. (main): Append "/" to the dir name only if not already there. (print_help): Explain the absolute/relative file name issue. * etags.c: New Languange Erlang added. (Erlang_functions, erlang_func, erlang_attribute, erlang_atom, erlang_white): New functions. (Erlang_suffixes): New suffix list. (lang_names): Erlang entry added. (prolog_getit): Accepts headers spanning several lines. Always name tags. (Prolog_functions): Removed incorrect compensation for newline characters. (readline_internal): Zero-terminate last line.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/etags.c500
1 files changed, 408 insertions, 92 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 213b959f675..5e6b7990d1c 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -28,10 +28,10 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
28 * Francesco Potorti` reorganised C and C++ based on work by Joe Wells. 28 * Francesco Potorti` reorganised C and C++ based on work by Joe Wells.
29 * Regexp tags by Tom Tromey. 29 * Regexp tags by Tom Tromey.
30 * 30 *
31 * Francesco Potorti` (pot@cnuce.cnr.it) is the current maintainer. 31 * Francesco Potorti` (F.Potorti@cnuce.cnr.it) is the current maintainer.
32 */ 32 */
33 33
34char pot_etags_version[] = "@(#) pot revision number is 11.53"; 34char pot_etags_version[] = "@(#) pot revision number is 11.59";
35 35
36#define TRUE 1 36#define TRUE 1
37#define FALSE 0 37#define FALSE 0
@@ -41,22 +41,22 @@ char pot_etags_version[] = "@(#) pot revision number is 11.53";
41#endif 41#endif
42 42
43#ifdef MSDOS 43#ifdef MSDOS
44#include <fcntl.h> 44# include <fcntl.h>
45#include <sys/param.h> 45# include <sys/param.h>
46#endif /* MSDOS */ 46#endif /* MSDOS */
47 47
48#ifdef WINDOWSNT 48#ifdef WINDOWSNT
49#include <stdlib.h> 49# include <stdlib.h>
50#include <fcntl.h> 50# include <fcntl.h>
51#include <string.h> 51# include <string.h>
52#define MAXPATHLEN _MAX_PATH 52# define MAXPATHLEN _MAX_PATH
53#endif 53#endif
54 54
55#ifdef HAVE_CONFIG_H 55#ifdef HAVE_CONFIG_H
56#include <config.h> 56# include <config.h>
57/* On some systems, Emacs defines static as nothing for the sake 57 /* On some systems, Emacs defines static as nothing for the sake
58 of unexec. We don't want that here since we don't use unexec. */ 58 of unexec. We don't want that here since we don't use unexec. */
59#undef static 59# undef static
60#endif 60#endif
61 61
62#include <stdio.h> 62#include <stdio.h>
@@ -75,7 +75,7 @@ extern int errno;
75#include <getopt.h> 75#include <getopt.h>
76 76
77#ifdef ETAGS_REGEXPS 77#ifdef ETAGS_REGEXPS
78#include <regex.h> 78# include <regex.h>
79#endif /* ETAGS_REGEXPS */ 79#endif /* ETAGS_REGEXPS */
80 80
81/* Define CTAGS to make the program "ctags" compatible with the usual one. 81/* Define CTAGS to make the program "ctags" compatible with the usual one.
@@ -90,11 +90,11 @@ extern int errno;
90 90
91/* Exit codes for success and failure. */ 91/* Exit codes for success and failure. */
92#ifdef VMS 92#ifdef VMS
93#define GOOD 1 93# define GOOD 1
94#define BAD 0 94# define BAD 0
95#else 95#else
96#define GOOD 0 96# define GOOD 0
97#define BAD 1 97# define BAD 1
98#endif 98#endif
99 99
100/* C extensions. */ 100/* C extensions. */
@@ -113,7 +113,8 @@ extern int errno;
113#define endtoken(arg) (_etk[arg]) /* T if char ends tokens */ 113#define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
114 114
115#ifdef DOS_NT 115#ifdef DOS_NT
116# define absolutefn(fn) (fn[0] == '/' || (isalpha (fn[0]) && fn[1] == ':')) 116# define absolutefn(fn) (fn[0] == '/' \
117 || (isalpha (fn[0]) && fn[1] == ':' && fn[2] == '/'))
117#else 118#else
118# define absolutefn(fn) (fn[0] == '/') 119# define absolutefn(fn) (fn[0] == '/')
119#endif 120#endif
@@ -156,6 +157,7 @@ Lang_function default_C_entries;
156Lang_function C_entries; 157Lang_function C_entries;
157Lang_function Cplusplus_entries; 158Lang_function Cplusplus_entries;
158Lang_function Cstar_entries; 159Lang_function Cstar_entries;
160Lang_function Erlang_functions;
159Lang_function Fortran_functions; 161Lang_function Fortran_functions;
160Lang_function Yacc_entries; 162Lang_function Yacc_entries;
161Lang_function Lisp_functions; 163Lang_function Lisp_functions;
@@ -172,6 +174,7 @@ void default_C_entries ();
172void plain_C_entries (); 174void plain_C_entries ();
173void Cplusplus_entries (); 175void Cplusplus_entries ();
174void Cstar_entries (); 176void Cstar_entries ();
177void Erlang_functions ();
175void Fortran_functions (); 178void Fortran_functions ();
176void Yacc_entries (); 179void Yacc_entries ();
177void Lisp_functions (); 180void Lisp_functions ();
@@ -347,6 +350,9 @@ char *Cplusplus_suffixes [] =
347char *Cstar_suffixes [] = 350char *Cstar_suffixes [] =
348 { "cs", "hs", NULL }; 351 { "cs", "hs", NULL };
349 352
353char *Erlang_suffixes [] =
354 { "erl", "hrl", NULL };
355
350char *Fortran_suffixes [] = 356char *Fortran_suffixes [] =
351 { "F", "f", "f90", "for", NULL }; 357 { "F", "f", "f90", "for", NULL };
352 358
@@ -398,6 +404,7 @@ struct lang_entry lang_names [] =
398 { "c", default_C_entries, default_C_suffixes, NULL }, 404 { "c", default_C_entries, default_C_suffixes, NULL },
399 { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL }, 405 { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL },
400 { "c*", Cstar_entries, Cstar_suffixes, NULL }, 406 { "c*", Cstar_entries, Cstar_suffixes, NULL },
407 { "erlang", Erlang_functions, Erlang_suffixes, NULL },
401 { "fortran", Fortran_functions, Fortran_suffixes, NULL }, 408 { "fortran", Fortran_functions, Fortran_suffixes, NULL },
402 { "lisp", Lisp_functions, Lisp_suffixes, NULL }, 409 { "lisp", Lisp_functions, Lisp_suffixes, NULL },
403 { "pascal", Pascal_functions, Pascal_suffixes, NULL }, 410 { "pascal", Pascal_functions, Pascal_suffixes, NULL },
@@ -453,7 +460,11 @@ print_help ()
453{ 460{
454 printf ("These are the options accepted by %s. You may use unambiguous\n\ 461 printf ("These are the options accepted by %s. You may use unambiguous\n\
455abbreviations for the long option names. A - as file name means read\n\ 462abbreviations for the long option names. A - as file name means read\n\
456names from stdin.\n\n", progname); 463names from stdin.", progname);
464 if (!CTAGS)
465 printf (" Absolute names are stored in the output file as they\n\
466are. Relative ones are stored relative to the output file's directory.");
467 puts ("\n");
457 468
458 puts ("-a, --append\n\ 469 puts ("-a, --append\n\
459 Append tag entries to existing tags file."); 470 Append tag entries to existing tags file.");
@@ -843,19 +854,14 @@ main (argc, argv)
843 } 854 }
844 855
845 if (tagfile == NULL) 856 if (tagfile == NULL)
846 { 857 tagfile = CTAGS ? "tags" : "TAGS";
847 tagfile = CTAGS ? "tags" : "TAGS";
848 }
849 cwd = etags_getcwd (); /* the current working directory */ 858 cwd = etags_getcwd (); /* the current working directory */
850 strcat (cwd, "/"); 859 if (cwd[strlen(cwd)-1] != '/')
860 strcat (cwd, "/");
851 if (streq (tagfile, "-")) 861 if (streq (tagfile, "-"))
852 { 862 tagfiledir = cwd;
853 tagfiledir = cwd;
854 }
855 else 863 else
856 { 864 tagfiledir = absolute_dirname (tagfile, cwd);
857 tagfiledir = absolute_dirname (tagfile, cwd);
858 }
859 865
860 init (); /* set up boolean "functions" */ 866 init (); /* set up boolean "functions" */
861 867
@@ -3451,103 +3457,409 @@ TEX_Token (cp)
3451 return -1; 3457 return -1;
3452} 3458}
3453 3459
3454/* Support for Prolog. */ 3460/*
3461 * Prolog support (rewritten) by Anders Lindgren, Mar. 96
3462 *
3463 * Assumes that the predicate starts at column 0.
3464 * Only the first clause of a predicate is added.
3465 */
3466void
3467Prolog_functions (inf)
3468 FILE *inf;
3469{
3470 int prolog_pred ();
3471 void prolog_skip_comment ();
3472
3473 char * last;
3474 int len;
3475 int allocated;
3476
3477 allocated = 0;
3478 len = 0;
3479 last = NULL;
3480
3481 lineno = 0;
3482 linecharno = 0;
3483 charno = 0;
3484
3485 while (!feof (inf))
3486 {
3487 lineno++;
3488 linecharno += charno;
3489 charno = readline (&lb, inf);
3490 dbp = lb.buffer;
3491 if (dbp[0] == '\0') /* Empty line */
3492 continue;
3493 else if (isspace (dbp[0])) /* Not a predicate */
3494 continue;
3495 else if (dbp[0] == '/' && dbp[1] == '*') /* comment. */
3496 prolog_skip_comment (&lb, inf, &lineno, &linecharno);
3497 else if (len = prolog_pred (dbp, last))
3498 {
3499 /* Predicate. Store the function name so that we only
3500 * generates a tag for the first clause. */
3501 if (last == NULL)
3502 last = xnew(len + 1, char);
3503 else if (len + 1 > allocated)
3504 last = (char *) xrealloc(last, len + 1);
3505 allocated = len + 1;
3506 strncpy (last, dbp, len);
3507 last[len] = '\0';
3508 }
3509 }
3510}
3511
3455 3512
3456/* Whole head (not only functor, but also arguments)
3457 is gotten in compound term. */
3458void 3513void
3459prolog_getit (s) 3514prolog_skip_comment (plb, inf)
3515 struct linebuffer *plb;
3516 FILE *inf;
3517{
3518 char *cp;
3519
3520 do
3521 {
3522 for (cp = plb->buffer; *cp != '\0'; cp++)
3523 if (cp[0] == '*' && cp[1] == '/')
3524 return;
3525 lineno++;
3526 linecharno += readline (plb, inf);
3527 }
3528 while (!feof(inf));
3529}
3530
3531/*
3532 * A predicate definition is added if it matches:
3533 * <beginning of line><Prolog Atom><whitespace>(
3534 *
3535 * It is added to the tags database if it doesn't match the
3536 * name of the previous clause header.
3537 *
3538 * Return the size of the name of the predicate, or 0 if no header
3539 * was found.
3540 */
3541int
3542prolog_pred (s, last)
3460 char *s; 3543 char *s;
3544 char *last; /* Name of last clause. */
3461{ 3545{
3462 char *save_s; 3546 int prolog_atom();
3463 int insquote, npar; 3547 int prolog_white();
3464 3548
3465 save_s = s; 3549 int pos;
3466 insquote = FALSE; 3550 int len;
3467 npar = 0; 3551
3468 while (1) 3552 pos = prolog_atom(s, 0);
3553 if (pos < 1)
3554 return 0;
3555
3556 len = pos;
3557 pos += prolog_white(s, pos);
3558
3559 if ((s[pos] == '(') || (s[pos] == '.'))
3469 { 3560 {
3470 if (s[0] == '\0') /* syntax error. */ 3561 if (s[pos] == '(')
3471 return; 3562 pos++;
3472 else if (insquote && s[0] == '\'' && s[1] == '\'') 3563
3473 s += 2; 3564 /* Save only the first clause. */
3474 else if (s[0] == '\'') 3565 if ((last == NULL) ||
3566 (len != strlen(last)) ||
3567 (strncmp(s, last, len) != 0))
3475 { 3568 {
3476 insquote = !insquote; 3569 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
3477 s++; 3570 s, pos, lineno, linecharno);
3571 return len;
3478 } 3572 }
3479 else if (!insquote && s[0] == '(') 3573 }
3574 return 0;
3575}
3576
3577/*
3578 * Consume a Prolog atom.
3579 * Return the number of bytes consumed, or -1 if there was an error.
3580 *
3581 * A prolog atom, in this context, could be one of:
3582 * - An alphanumeric sequence, starting with a lower case letter.
3583 * - A quoted arbitrary string. Single quotes can escape themselves.
3584 * Backslash quotes everything.
3585 */
3586int
3587prolog_atom (s, pos)
3588 char *s;
3589 int pos;
3590{
3591 int origpos;
3592
3593 origpos = pos;
3594
3595 if (islower(s[pos]) || (s[pos] == '_'))
3596 {
3597 /* The atom is unquoted. */
3598 pos++;
3599 while (isalnum(s[pos]) || (s[pos] == '_'))
3480 { 3600 {
3481 npar++; 3601 pos++;
3482 s++;
3483 } 3602 }
3484 else if (!insquote && s[0] == ')') 3603 return pos - origpos;
3604 }
3605 else if (s[pos] == '\'')
3606 {
3607 pos++;
3608
3609 while (1)
3485 { 3610 {
3486 npar--; 3611 if (s[pos] == '\'')
3487 s++; 3612 {
3488 if (npar == 0) 3613 pos++;
3489 break; 3614 if (s[pos] != '\'')
3490 else if (npar < 0) /* syntax error. */ 3615 break;
3491 return; 3616 pos++; /* A double quote */
3492 } 3617 }
3493 else if (!insquote && s[0] == '.' 3618 else if (s[pos] == '\0')
3494 && (isspace (s[1]) || s[1] == '\0')) 3619 /* Multiline quoted atoms are ignored. */
3495 { /* fullstop. */ 3620 return -1;
3496 if (npar != 0) /* syntax error. */ 3621 else if (s[pos] == '\\')
3497 return; 3622 {
3498 s++; 3623 if (s[pos+1] == '\0')
3499 break; 3624 return -1;
3625 pos += 2;
3626 }
3627 else
3628 pos++;
3500 } 3629 }
3501 else 3630 return pos - origpos;
3502 s++;
3503 } 3631 }
3504 pfnote ((CTAGS) ? savenstr (save_s, s-save_s) : NULL, TRUE, 3632 else
3505 save_s, s-save_s, lineno, linecharno); 3633 return -1;
3506} 3634}
3507 3635
3508/* It is assumed that prolog predicate starts from column 0. */ 3636/* Consume whitespace. Return the number of bytes eaten. */
3637int
3638prolog_white (s, pos)
3639 char *s;
3640 int pos;
3641{
3642 int origpos;
3643
3644 origpos = pos;
3645
3646 while (isspace(s[pos]))
3647 pos++;
3648
3649 return pos - origpos;
3650}
3651
3652/*
3653 * Support for Erlang -- Anders Lindgren, Feb 1996.
3654 *
3655 * Generates tags for functions, defines, and records.
3656 *
3657 * Assumes that Erlang functions start at column 0.
3658 */
3509void 3659void
3510Prolog_functions (inf) 3660Erlang_functions (inf)
3511 FILE *inf; 3661 FILE *inf;
3512{ 3662{
3513 void skip_comment (), prolog_getit (); 3663 int erlang_func ();
3664 void erlang_attribute ();
3665
3666 char * last;
3667 int len;
3668 int allocated;
3669
3670 allocated = 0;
3671 len = 0;
3672 last = NULL;
3673
3674 lineno = 0;
3675 linecharno = 0;
3676 charno = 0;
3514 3677
3515 lineno = linecharno = charno = 0;
3516 while (!feof (inf)) 3678 while (!feof (inf))
3517 { 3679 {
3518 lineno++; 3680 lineno++;
3519 linecharno += charno; 3681 linecharno += charno;
3520 charno = readline (&lb, inf) + 1; /* 1 for newline. */ 3682 charno = readline (&lb, inf);
3521 dbp = lb.buffer; 3683 dbp = lb.buffer;
3522 if (isspace (dbp[0])) /* not predicate header. */ 3684 if (dbp[0] == '\0') /* Empty line */
3523 continue; 3685 continue;
3524 else if (dbp[0] == '%') /* comment. */ 3686 else if (isspace (dbp[0])) /* Not function nor attribute */
3525 continue; 3687 continue;
3526 else if (dbp[0] == '/' && dbp[1] == '*') /* comment. */ 3688 else if (dbp[0] == '%') /* comment */
3527 skip_comment (&lb, inf, &lineno, &linecharno); 3689 continue;
3528 else /* found. */ 3690 else if (dbp[0] == '"') /* Sometimes, strings start in column one */
3529 prolog_getit (dbp); 3691 continue;
3692 else if (dbp[0] == '-') /* attribute, e.g. "-define" */
3693 {
3694 erlang_attribute(dbp);
3695 last = NULL;
3696 }
3697 else if (len = erlang_func (dbp, last))
3698 {
3699 /*
3700 * Function. Store the function name so that we only
3701 * generates a tag for the first clause.
3702 */
3703 if (last == NULL)
3704 last = xnew(len + 1, char);
3705 else if (len + 1 > allocated)
3706 last = (char *) xrealloc(last, len + 1);
3707 allocated = len + 1;
3708 strncpy (last, dbp, len);
3709 last[len] = '\0';
3710 }
3711 }
3712}
3713
3714
3715/*
3716 * A function definition is added if it matches:
3717 * <beginning of line><Erlang Atom><whitespace>(
3718 *
3719 * It is added to the tags database if it doesn't match the
3720 * name of the previous clause header.
3721 *
3722 * Return the size of the name of the function, or 0 if no function
3723 * was found.
3724 */
3725int
3726erlang_func (s, last)
3727 char *s;
3728 char *last; /* Name of last clause. */
3729{
3730 int erlang_atom ();
3731 int erlang_white ();
3732
3733 int pos;
3734 int len;
3735
3736 pos = erlang_atom(s, 0);
3737 if (pos < 1)
3738 return 0;
3739
3740 len = pos;
3741 pos += erlang_white(s, pos);
3742
3743 if (s[pos++] == '(')
3744 {
3745 /* Save only the first clause. */
3746 if ((last == NULL) ||
3747 (len != strlen(last)) ||
3748 (strncmp(s, last, len) != 0))
3749 {
3750 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
3751 s, pos, lineno, linecharno);
3752 return len;
3753 }
3530 } 3754 }
3755 return 0;
3531} 3756}
3532 3757
3758
3759/*
3760 * Handle attributes. Currently, tags are generated for defines
3761 * and records.
3762 *
3763 * They are on the form:
3764 * -define(foo, bar).
3765 * -define(Foo(M, N), M+N).
3766 * -record(graph, {vtab = notable, cyclic = true}).
3767 */
3533void 3768void
3534skip_comment (plb, inf, plineno, plinecharno) 3769erlang_attribute (s)
3535 struct linebuffer *plb; 3770 char *s;
3536 FILE *inf;
3537 int *plineno; /* result */
3538 long *plinecharno; /* result */
3539{ 3771{
3540 char *cp; 3772 int erlang_atom ();
3773 int erlang_white ();
3541 3774
3542 do 3775 int pos;
3776 int len;
3777
3778 if ((strncmp(s, "-define", 7) == 0) ||
3779 (strncmp(s, "-record", 7) == 0))
3543 { 3780 {
3544 for (cp = plb->buffer; *cp != '\0'; cp++) 3781 pos = 7;
3545 if (cp[0] == '*' && cp[1] == '/') 3782 pos += erlang_white(s, pos);
3546 return; 3783
3547 (*plineno)++; 3784 if (s[pos++] == '(')
3548 *plinecharno += readline (plb, inf) + 1; /* 1 for newline. */ 3785 {
3786 pos += erlang_white(s, pos);
3787
3788 if (len = erlang_atom(s, pos))
3789 {
3790 pfnote ((CTAGS) ? savenstr (& s[pos], len) : NULL, TRUE,
3791 s, pos + len, lineno, linecharno);
3792 }
3793 }
3549 } 3794 }
3550 while (!feof(inf)); 3795 return;
3796}
3797
3798
3799/*
3800 * Consume an Erlang atom (or variable).
3801 * Return the number of bytes consumed, or -1 if there was an error.
3802 */
3803int
3804erlang_atom (s, pos)
3805 char *s;
3806 int pos;
3807{
3808 int origpos;
3809
3810 origpos = pos;
3811
3812 if (isalpha (s[pos]) || s[pos] == '_')
3813 {
3814 /* The atom is unquoted. */
3815 pos++;
3816 while (isalnum (s[pos]) || s[pos] == '_')
3817 pos++;
3818 return pos - origpos;
3819 }
3820 else if (s[pos] == '\'')
3821 {
3822 pos++;
3823
3824 while (1)
3825 {
3826 if (s[pos] == '\'')
3827 {
3828 pos++;
3829 break;
3830 }
3831 else if (s[pos] == '\0')
3832 /* Multiline quoted atoms are ignored. */
3833 return -1;
3834 else if (s[pos] == '\\')
3835 {
3836 if (s[pos+1] == '\0')
3837 return -1;
3838 pos += 2;
3839 }
3840 else
3841 pos++;
3842 }
3843 return pos - origpos;
3844 }
3845 else
3846 return -1;
3847}
3848
3849/* Consume whitespace. Return the number of bytes eaten */
3850int
3851erlang_white (s, pos)
3852 char *s;
3853 int pos;
3854{
3855 int origpos;
3856
3857 origpos = pos;
3858
3859 while (isspace (s[pos]))
3860 pos++;
3861
3862 return pos - origpos;
3551} 3863}
3552 3864
3553#ifdef ETAGS_REGEXPS 3865#ifdef ETAGS_REGEXPS
@@ -3754,6 +4066,7 @@ readline_internal (linebuffer, stream)
3754 } 4066 }
3755 if (c == EOF) 4067 if (c == EOF)
3756 { 4068 {
4069 *p = '\0';
3757 chars_deleted = 0; 4070 chars_deleted = 0;
3758 break; 4071 break;
3759 } 4072 }
@@ -3843,6 +4156,9 @@ void
3843just_read_file (inf) 4156just_read_file (inf)
3844 FILE *inf; 4157 FILE *inf;
3845{ 4158{
4159 lineno = 0;
4160 charno = 0;
4161
3846 while (!feof (inf)) 4162 while (!feof (inf))
3847 { 4163 {
3848 ++lineno; 4164 ++lineno;