diff options
| author | Francesco Potortì | 1996-03-22 19:13:22 +0000 |
|---|---|---|
| committer | Francesco Potortì | 1996-03-22 19:13:22 +0000 |
| commit | 8dc7496c3f472a54d652c0725e2c015353c35bac (patch) | |
| tree | 48bc51ca436e7dc7b2bf9f02e6c5dee1bf47335b /lib-src | |
| parent | 6ccab458cc51e82ed10ba436e024a0eced858913 (diff) | |
| download | emacs-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.c | 500 |
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 | ||
| 34 | char pot_etags_version[] = "@(#) pot revision number is 11.53"; | 34 | char 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; | |||
| 156 | Lang_function C_entries; | 157 | Lang_function C_entries; |
| 157 | Lang_function Cplusplus_entries; | 158 | Lang_function Cplusplus_entries; |
| 158 | Lang_function Cstar_entries; | 159 | Lang_function Cstar_entries; |
| 160 | Lang_function Erlang_functions; | ||
| 159 | Lang_function Fortran_functions; | 161 | Lang_function Fortran_functions; |
| 160 | Lang_function Yacc_entries; | 162 | Lang_function Yacc_entries; |
| 161 | Lang_function Lisp_functions; | 163 | Lang_function Lisp_functions; |
| @@ -172,6 +174,7 @@ void default_C_entries (); | |||
| 172 | void plain_C_entries (); | 174 | void plain_C_entries (); |
| 173 | void Cplusplus_entries (); | 175 | void Cplusplus_entries (); |
| 174 | void Cstar_entries (); | 176 | void Cstar_entries (); |
| 177 | void Erlang_functions (); | ||
| 175 | void Fortran_functions (); | 178 | void Fortran_functions (); |
| 176 | void Yacc_entries (); | 179 | void Yacc_entries (); |
| 177 | void Lisp_functions (); | 180 | void Lisp_functions (); |
| @@ -347,6 +350,9 @@ char *Cplusplus_suffixes [] = | |||
| 347 | char *Cstar_suffixes [] = | 350 | char *Cstar_suffixes [] = |
| 348 | { "cs", "hs", NULL }; | 351 | { "cs", "hs", NULL }; |
| 349 | 352 | ||
| 353 | char *Erlang_suffixes [] = | ||
| 354 | { "erl", "hrl", NULL }; | ||
| 355 | |||
| 350 | char *Fortran_suffixes [] = | 356 | char *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\ |
| 455 | abbreviations for the long option names. A - as file name means read\n\ | 462 | abbreviations for the long option names. A - as file name means read\n\ |
| 456 | names from stdin.\n\n", progname); | 463 | names from stdin.", progname); |
| 464 | if (!CTAGS) | ||
| 465 | printf (" Absolute names are stored in the output file as they\n\ | ||
| 466 | are. 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 | */ | ||
| 3466 | void | ||
| 3467 | Prolog_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. */ | ||
| 3458 | void | 3513 | void |
| 3459 | prolog_getit (s) | 3514 | prolog_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 | */ | ||
| 3541 | int | ||
| 3542 | prolog_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 | */ | ||
| 3586 | int | ||
| 3587 | prolog_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. */ |
| 3637 | int | ||
| 3638 | prolog_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 | */ | ||
| 3509 | void | 3659 | void |
| 3510 | Prolog_functions (inf) | 3660 | Erlang_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 | */ | ||
| 3725 | int | ||
| 3726 | erlang_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 | */ | ||
| 3533 | void | 3768 | void |
| 3534 | skip_comment (plb, inf, plineno, plinecharno) | 3769 | erlang_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 | */ | ||
| 3803 | int | ||
| 3804 | erlang_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 */ | ||
| 3850 | int | ||
| 3851 | erlang_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 | |||
| 3843 | just_read_file (inf) | 4156 | just_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; |