diff options
Diffstat (limited to 'lib-src/make-docfile.c')
| -rw-r--r-- | lib-src/make-docfile.c | 351 |
1 files changed, 197 insertions, 154 deletions
diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c index 1ec365f3446..68e7029ee85 100644 --- a/lib-src/make-docfile.c +++ b/lib-src/make-docfile.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | /* Generate doc-string file for GNU Emacs from source files. | 1 | /* Generate doc-string file for GNU Emacs from source files. |
| 2 | Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2011 | 2 | |
| 3 | Free Software Foundation, Inc. | 3 | Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2012 |
| 4 | Free Software Foundation, Inc. | ||
| 4 | 5 | ||
| 5 | This file is part of GNU Emacs. | 6 | This file is part of GNU Emacs. |
| 6 | 7 | ||
| @@ -35,57 +36,41 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 35 | 36 | ||
| 36 | #include <config.h> | 37 | #include <config.h> |
| 37 | 38 | ||
| 38 | /* defined to be emacs_main, sys_fopen, etc. in config.h */ | ||
| 39 | #undef main | ||
| 40 | #undef fopen | ||
| 41 | #undef chdir | ||
| 42 | |||
| 43 | #include <stdio.h> | 39 | #include <stdio.h> |
| 44 | #include <stdlib.h> | 40 | #include <stdlib.h> /* config.h unconditionally includes this anyway */ |
| 45 | #ifdef MSDOS | 41 | #ifdef MSDOS |
| 46 | #include <fcntl.h> | 42 | #include <fcntl.h> |
| 47 | #endif /* MSDOS */ | 43 | #endif /* MSDOS */ |
| 48 | #ifdef WINDOWSNT | 44 | #ifdef WINDOWSNT |
| 45 | /* Defined to be sys_fopen in ms-w32.h, but only #ifdef emacs, so this | ||
| 46 | is really just insurance. */ | ||
| 47 | #undef fopen | ||
| 49 | #include <fcntl.h> | 48 | #include <fcntl.h> |
| 50 | #include <direct.h> | 49 | #include <direct.h> |
| 51 | #endif /* WINDOWSNT */ | 50 | #endif /* WINDOWSNT */ |
| 52 | 51 | ||
| 53 | #ifdef DOS_NT | 52 | #ifdef DOS_NT |
| 53 | /* Defined to be sys_chdir in ms-w32.h, but only #ifdef emacs, so this | ||
| 54 | is really just insurance. | ||
| 55 | |||
| 56 | Similarly, msdos defines this as sys_chdir, but we're not linking with the | ||
| 57 | file where that function is defined. */ | ||
| 58 | #undef chdir | ||
| 54 | #define READ_TEXT "rt" | 59 | #define READ_TEXT "rt" |
| 55 | #define READ_BINARY "rb" | 60 | #define READ_BINARY "rb" |
| 61 | #define IS_SLASH(c) ((c) == '/' || (c) == '\\' || (c) == ':') | ||
| 56 | #else /* not DOS_NT */ | 62 | #else /* not DOS_NT */ |
| 57 | #define READ_TEXT "r" | 63 | #define READ_TEXT "r" |
| 58 | #define READ_BINARY "r" | 64 | #define READ_BINARY "r" |
| 65 | #define IS_SLASH(c) ((c) == '/') | ||
| 59 | #endif /* not DOS_NT */ | 66 | #endif /* not DOS_NT */ |
| 60 | 67 | ||
| 61 | #ifndef DIRECTORY_SEP | ||
| 62 | #define DIRECTORY_SEP '/' | ||
| 63 | #endif | ||
| 64 | |||
| 65 | #ifndef IS_DIRECTORY_SEP | ||
| 66 | #define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP) | ||
| 67 | #endif | ||
| 68 | |||
| 69 | /* Use this to suppress gcc's `...may be used before initialized' warnings. */ | ||
| 70 | #ifdef lint | ||
| 71 | # define IF_LINT(Code) Code | ||
| 72 | #else | ||
| 73 | # define IF_LINT(Code) /* empty */ | ||
| 74 | #endif | ||
| 75 | |||
| 76 | static int scan_file (char *filename); | 68 | static int scan_file (char *filename); |
| 77 | static int scan_lisp_file (const char *filename, const char *mode); | 69 | static int scan_lisp_file (const char *filename, const char *mode); |
| 78 | static int scan_c_file (char *filename, const char *mode); | 70 | static int scan_c_file (char *filename, const char *mode); |
| 79 | static void fatal (const char *s1, const char *s2) NO_RETURN; | ||
| 80 | static void start_globals (void); | 71 | static void start_globals (void); |
| 81 | static void write_globals (void); | 72 | static void write_globals (void); |
| 82 | 73 | ||
| 83 | #ifdef MSDOS | ||
| 84 | /* s/msdos.h defines this as sys_chdir, but we're not linking with the | ||
| 85 | file where that function is defined. */ | ||
| 86 | #undef chdir | ||
| 87 | #endif | ||
| 88 | |||
| 89 | #include <unistd.h> | 74 | #include <unistd.h> |
| 90 | 75 | ||
| 91 | /* Stdio stream for output to the DOC file. */ | 76 | /* Stdio stream for output to the DOC file. */ |
| @@ -111,7 +96,7 @@ error (const char *s1, const char *s2) | |||
| 111 | /* Print error message and exit. */ | 96 | /* Print error message and exit. */ |
| 112 | 97 | ||
| 113 | /* VARARGS1 */ | 98 | /* VARARGS1 */ |
| 114 | static void | 99 | static _Noreturn void |
| 115 | fatal (const char *s1, const char *s2) | 100 | fatal (const char *s1, const char *s2) |
| 116 | { | 101 | { |
| 117 | error (s1, s2); | 102 | error (s1, s2); |
| @@ -226,7 +211,7 @@ put_filename (char *filename) | |||
| 226 | 211 | ||
| 227 | for (tmp = filename; *tmp; tmp++) | 212 | for (tmp = filename; *tmp; tmp++) |
| 228 | { | 213 | { |
| 229 | if (IS_DIRECTORY_SEP(*tmp)) | 214 | if (IS_DIRECTORY_SEP (*tmp)) |
| 230 | filename = tmp + 1; | 215 | filename = tmp + 1; |
| 231 | } | 216 | } |
| 232 | 217 | ||
| @@ -541,8 +526,8 @@ write_c_args (FILE *out, char *func, char *buf, int minargs, int maxargs) | |||
| 541 | maxargs--; | 526 | maxargs--; |
| 542 | 527 | ||
| 543 | /* In C code, `default' is a reserved word, so we spell it | 528 | /* In C code, `default' is a reserved word, so we spell it |
| 544 | `defalt'; unmangle that here. */ | 529 | `defalt'; demangle that here. */ |
| 545 | if (ident_length == 6 && strncmp (ident_start, "defalt", 6) == 0) | 530 | if (ident_length == 6 && memcmp (ident_start, "defalt", 6) == 0) |
| 546 | fprintf (out, "DEFAULT"); | 531 | fprintf (out, "DEFAULT"); |
| 547 | else | 532 | else |
| 548 | while (ident_length-- > 0) | 533 | while (ident_length-- > 0) |
| @@ -562,13 +547,15 @@ write_c_args (FILE *out, char *func, char *buf, int minargs, int maxargs) | |||
| 562 | putc (')', out); | 547 | putc (')', out); |
| 563 | } | 548 | } |
| 564 | 549 | ||
| 565 | /* The types of globals. */ | 550 | /* The types of globals. These are sorted roughly in decreasing alignment |
| 551 | order to avoid allocation gaps, except that functions are last. */ | ||
| 566 | enum global_type | 552 | enum global_type |
| 567 | { | 553 | { |
| 554 | INVALID, | ||
| 555 | LISP_OBJECT, | ||
| 568 | EMACS_INTEGER, | 556 | EMACS_INTEGER, |
| 569 | BOOLEAN, | 557 | BOOLEAN, |
| 570 | LISP_OBJECT, | 558 | FUNCTION, |
| 571 | INVALID | ||
| 572 | }; | 559 | }; |
| 573 | 560 | ||
| 574 | /* A single global. */ | 561 | /* A single global. */ |
| @@ -576,6 +563,7 @@ struct global | |||
| 576 | { | 563 | { |
| 577 | enum global_type type; | 564 | enum global_type type; |
| 578 | char *name; | 565 | char *name; |
| 566 | int value; | ||
| 579 | }; | 567 | }; |
| 580 | 568 | ||
| 581 | /* All the variable names we saw while scanning C sources in `-g' | 569 | /* All the variable names we saw while scanning C sources in `-g' |
| @@ -585,7 +573,7 @@ int num_globals_allocated; | |||
| 585 | struct global *globals; | 573 | struct global *globals; |
| 586 | 574 | ||
| 587 | static void | 575 | static void |
| 588 | add_global (enum global_type type, char *name) | 576 | add_global (enum global_type type, char *name, int value) |
| 589 | { | 577 | { |
| 590 | /* Ignore the one non-symbol that can occur. */ | 578 | /* Ignore the one non-symbol that can occur. */ |
| 591 | if (strcmp (name, "...")) | 579 | if (strcmp (name, "...")) |
| @@ -606,6 +594,7 @@ add_global (enum global_type type, char *name) | |||
| 606 | 594 | ||
| 607 | globals[num_globals - 1].type = type; | 595 | globals[num_globals - 1].type = type; |
| 608 | globals[num_globals - 1].name = name; | 596 | globals[num_globals - 1].name = name; |
| 597 | globals[num_globals - 1].value = value; | ||
| 609 | } | 598 | } |
| 610 | } | 599 | } |
| 611 | 600 | ||
| @@ -614,13 +603,24 @@ compare_globals (const void *a, const void *b) | |||
| 614 | { | 603 | { |
| 615 | const struct global *ga = a; | 604 | const struct global *ga = a; |
| 616 | const struct global *gb = b; | 605 | const struct global *gb = b; |
| 606 | |||
| 607 | if (ga->type != gb->type) | ||
| 608 | return ga->type - gb->type; | ||
| 609 | |||
| 617 | return strcmp (ga->name, gb->name); | 610 | return strcmp (ga->name, gb->name); |
| 618 | } | 611 | } |
| 619 | 612 | ||
| 620 | static void | 613 | static void |
| 614 | close_emacs_globals (void) | ||
| 615 | { | ||
| 616 | fprintf (outfile, "};\n"); | ||
| 617 | fprintf (outfile, "extern struct emacs_globals globals;\n"); | ||
| 618 | } | ||
| 619 | |||
| 620 | static void | ||
| 621 | write_globals (void) | 621 | write_globals (void) |
| 622 | { | 622 | { |
| 623 | int i; | 623 | int i, seen_defun = 0; |
| 624 | qsort (globals, num_globals, sizeof (struct global), compare_globals); | 624 | qsort (globals, num_globals, sizeof (struct global), compare_globals); |
| 625 | for (i = 0; i < num_globals; ++i) | 625 | for (i = 0; i < num_globals; ++i) |
| 626 | { | 626 | { |
| @@ -632,25 +632,62 @@ write_globals (void) | |||
| 632 | type = "EMACS_INT"; | 632 | type = "EMACS_INT"; |
| 633 | break; | 633 | break; |
| 634 | case BOOLEAN: | 634 | case BOOLEAN: |
| 635 | type = "int"; | 635 | type = "bool"; |
| 636 | break; | 636 | break; |
| 637 | case LISP_OBJECT: | 637 | case LISP_OBJECT: |
| 638 | type = "Lisp_Object"; | 638 | type = "Lisp_Object"; |
| 639 | break; | 639 | break; |
| 640 | case FUNCTION: | ||
| 641 | if (!seen_defun) | ||
| 642 | { | ||
| 643 | close_emacs_globals (); | ||
| 644 | fprintf (outfile, "\n"); | ||
| 645 | seen_defun = 1; | ||
| 646 | } | ||
| 647 | break; | ||
| 640 | default: | 648 | default: |
| 641 | fatal ("not a recognized DEFVAR_", 0); | 649 | fatal ("not a recognized DEFVAR_", 0); |
| 642 | } | 650 | } |
| 643 | 651 | ||
| 644 | fprintf (outfile, " %s f_%s;\n", type, globals[i].name); | 652 | if (globals[i].type != FUNCTION) |
| 645 | fprintf (outfile, "#define %s globals.f_%s\n", | 653 | { |
| 646 | globals[i].name, globals[i].name); | 654 | fprintf (outfile, " %s f_%s;\n", type, globals[i].name); |
| 655 | fprintf (outfile, "#define %s globals.f_%s\n", | ||
| 656 | globals[i].name, globals[i].name); | ||
| 657 | } | ||
| 658 | else | ||
| 659 | { | ||
| 660 | /* It would be nice to have a cleaner way to deal with these | ||
| 661 | special hacks. */ | ||
| 662 | if (strcmp (globals[i].name, "Fthrow") == 0 | ||
| 663 | || strcmp (globals[i].name, "Ftop_level") == 0 | ||
| 664 | || strcmp (globals[i].name, "Fkill_emacs") == 0 | ||
| 665 | || strcmp (globals[i].name, "Fexit_recursive_edit") == 0 | ||
| 666 | || strcmp (globals[i].name, "Fabort_recursive_edit") == 0) | ||
| 667 | fprintf (outfile, "_Noreturn "); | ||
| 668 | fprintf (outfile, "EXFUN (%s, ", globals[i].name); | ||
| 669 | if (globals[i].value == -1) | ||
| 670 | fprintf (outfile, "MANY"); | ||
| 671 | else if (globals[i].value == -2) | ||
| 672 | fprintf (outfile, "UNEVALLED"); | ||
| 673 | else | ||
| 674 | fprintf (outfile, "%d", globals[i].value); | ||
| 675 | fprintf (outfile, ");\n"); | ||
| 676 | } | ||
| 677 | |||
| 647 | while (i + 1 < num_globals | 678 | while (i + 1 < num_globals |
| 648 | && !strcmp (globals[i].name, globals[i + 1].name)) | 679 | && !strcmp (globals[i].name, globals[i + 1].name)) |
| 649 | ++i; | 680 | { |
| 681 | if (globals[i].type == FUNCTION | ||
| 682 | && globals[i].value != globals[i + 1].value) | ||
| 683 | error ("function '%s' defined twice with differing signatures", | ||
| 684 | globals[i].name); | ||
| 685 | ++i; | ||
| 686 | } | ||
| 650 | } | 687 | } |
| 651 | 688 | ||
| 652 | fprintf (outfile, "};\n"); | 689 | if (!seen_defun) |
| 653 | fprintf (outfile, "extern struct emacs_globals globals;\n"); | 690 | close_emacs_globals (); |
| 654 | } | 691 | } |
| 655 | 692 | ||
| 656 | 693 | ||
| @@ -675,14 +712,14 @@ scan_c_file (char *filename, const char *mode) | |||
| 675 | 712 | ||
| 676 | if (infile == NULL && extension == 'o') | 713 | if (infile == NULL && extension == 'o') |
| 677 | { | 714 | { |
| 678 | /* try .m */ | 715 | /* Try .m. */ |
| 679 | filename[strlen (filename) - 1] = 'm'; | 716 | filename[strlen (filename) - 1] = 'm'; |
| 680 | infile = fopen (filename, mode); | 717 | infile = fopen (filename, mode); |
| 681 | if (infile == NULL) | 718 | if (infile == NULL) |
| 682 | filename[strlen (filename) - 1] = 'c'; /* don't confuse people */ | 719 | filename[strlen (filename) - 1] = 'c'; /* Don't confuse people. */ |
| 683 | } | 720 | } |
| 684 | 721 | ||
| 685 | /* No error if non-ex input file */ | 722 | /* No error if non-ex input file. */ |
| 686 | if (infile == NULL) | 723 | if (infile == NULL) |
| 687 | { | 724 | { |
| 688 | perror (filename); | 725 | perror (filename); |
| @@ -700,6 +737,7 @@ scan_c_file (char *filename, const char *mode) | |||
| 700 | int defvarperbufferflag = 0; | 737 | int defvarperbufferflag = 0; |
| 701 | int defvarflag = 0; | 738 | int defvarflag = 0; |
| 702 | enum global_type type = INVALID; | 739 | enum global_type type = INVALID; |
| 740 | char *name IF_LINT (= 0); | ||
| 703 | 741 | ||
| 704 | if (c != '\n' && c != '\r') | 742 | if (c != '\n' && c != '\r') |
| 705 | { | 743 | { |
| @@ -765,8 +803,9 @@ scan_c_file (char *filename, const char *mode) | |||
| 765 | } | 803 | } |
| 766 | else continue; | 804 | else continue; |
| 767 | 805 | ||
| 768 | if (generate_globals && (!defvarflag || defvarperbufferflag | 806 | if (generate_globals |
| 769 | || type == INVALID)) | 807 | && (!defvarflag || defvarperbufferflag || type == INVALID) |
| 808 | && !defunflag) | ||
| 770 | continue; | 809 | continue; |
| 771 | 810 | ||
| 772 | while (c != '(') | 811 | while (c != '(') |
| @@ -785,7 +824,6 @@ scan_c_file (char *filename, const char *mode) | |||
| 785 | if (generate_globals) | 824 | if (generate_globals) |
| 786 | { | 825 | { |
| 787 | int i = 0; | 826 | int i = 0; |
| 788 | char *name; | ||
| 789 | 827 | ||
| 790 | /* Skip "," and whitespace. */ | 828 | /* Skip "," and whitespace. */ |
| 791 | do | 829 | do |
| @@ -800,14 +838,18 @@ scan_c_file (char *filename, const char *mode) | |||
| 800 | input_buffer[i++] = c; | 838 | input_buffer[i++] = c; |
| 801 | c = getc (infile); | 839 | c = getc (infile); |
| 802 | } | 840 | } |
| 803 | while (! (c == ',' || c == ' ' || c == '\t' || | 841 | while (! (c == ',' || c == ' ' || c == '\t' |
| 804 | c == '\n' || c == '\r')); | 842 | || c == '\n' || c == '\r')); |
| 805 | input_buffer[i] = '\0'; | 843 | input_buffer[i] = '\0'; |
| 806 | 844 | ||
| 807 | name = xmalloc (i + 1); | 845 | name = xmalloc (i + 1); |
| 808 | memcpy (name, input_buffer, i + 1); | 846 | memcpy (name, input_buffer, i + 1); |
| 809 | add_global (type, name); | 847 | |
| 810 | continue; | 848 | if (!defunflag) |
| 849 | { | ||
| 850 | add_global (type, name, 0); | ||
| 851 | continue; | ||
| 852 | } | ||
| 811 | } | 853 | } |
| 812 | 854 | ||
| 813 | /* DEFVAR_LISP ("name", addr, "doc") | 855 | /* DEFVAR_LISP ("name", addr, "doc") |
| @@ -815,12 +857,12 @@ scan_c_file (char *filename, const char *mode) | |||
| 815 | DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */ | 857 | DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */ |
| 816 | 858 | ||
| 817 | if (defunflag) | 859 | if (defunflag) |
| 818 | commas = 5; | 860 | commas = generate_globals ? 4 : 5; |
| 819 | else if (defvarperbufferflag) | 861 | else if (defvarperbufferflag) |
| 820 | commas = 3; | 862 | commas = 3; |
| 821 | else if (defvarflag) | 863 | else if (defvarflag) |
| 822 | commas = 1; | 864 | commas = 1; |
| 823 | else /* For DEFSIMPLE and DEFPRED */ | 865 | else /* For DEFSIMPLE and DEFPRED. */ |
| 824 | commas = 2; | 866 | commas = 2; |
| 825 | 867 | ||
| 826 | while (commas) | 868 | while (commas) |
| @@ -838,11 +880,16 @@ scan_c_file (char *filename, const char *mode) | |||
| 838 | if (c < 0) | 880 | if (c < 0) |
| 839 | goto eof; | 881 | goto eof; |
| 840 | ungetc (c, infile); | 882 | ungetc (c, infile); |
| 841 | if (commas == 2) /* pick up minargs */ | 883 | if (commas == 2) /* Pick up minargs. */ |
| 842 | scanned = fscanf (infile, "%d", &minargs); | 884 | scanned = fscanf (infile, "%d", &minargs); |
| 843 | else /* pick up maxargs */ | 885 | else /* Pick up maxargs. */ |
| 844 | if (c == 'M' || c == 'U') /* MANY || UNEVALLED */ | 886 | if (c == 'M' || c == 'U') /* MANY || UNEVALLED */ |
| 845 | maxargs = -1; | 887 | { |
| 888 | if (generate_globals) | ||
| 889 | maxargs = (c == 'M') ? -1 : -2; | ||
| 890 | else | ||
| 891 | maxargs = -1; | ||
| 892 | } | ||
| 846 | else | 893 | else |
| 847 | scanned = fscanf (infile, "%d", &maxargs); | 894 | scanned = fscanf (infile, "%d", &maxargs); |
| 848 | if (scanned < 0) | 895 | if (scanned < 0) |
| @@ -855,6 +902,12 @@ scan_c_file (char *filename, const char *mode) | |||
| 855 | c = getc (infile); | 902 | c = getc (infile); |
| 856 | } | 903 | } |
| 857 | 904 | ||
| 905 | if (generate_globals) | ||
| 906 | { | ||
| 907 | add_global (FUNCTION, name, maxargs); | ||
| 908 | continue; | ||
| 909 | } | ||
| 910 | |||
| 858 | while (c == ' ' || c == '\n' || c == '\r' || c == '\t') | 911 | while (c == ' ' || c == '\n' || c == '\r' || c == '\t') |
| 859 | c = getc (infile); | 912 | c = getc (infile); |
| 860 | 913 | ||
| @@ -893,7 +946,7 @@ scan_c_file (char *filename, const char *mode) | |||
| 893 | fprintf (outfile, "%s\n", input_buffer); | 946 | fprintf (outfile, "%s\n", input_buffer); |
| 894 | 947 | ||
| 895 | if (comment) | 948 | if (comment) |
| 896 | getc (infile); /* Skip past `*' */ | 949 | getc (infile); /* Skip past `*'. */ |
| 897 | c = read_c_string_or_comment (infile, 1, comment, &saw_usage); | 950 | c = read_c_string_or_comment (infile, 1, comment, &saw_usage); |
| 898 | 951 | ||
| 899 | /* If this is a defun, find the arguments and print them. If | 952 | /* If this is a defun, find the arguments and print them. If |
| @@ -974,12 +1027,12 @@ scan_c_file (char *filename, const char *mode) | |||
| 974 | arglist, but the doc string must still have a backslash and newline | 1027 | arglist, but the doc string must still have a backslash and newline |
| 975 | immediately after the double quote. | 1028 | immediately after the double quote. |
| 976 | The only source files that must follow this convention are preloaded | 1029 | The only source files that must follow this convention are preloaded |
| 977 | uncompiled ones like loaddefs.el and bindings.el; aside | 1030 | uncompiled ones like loaddefs.el; aside from that, it is always the .elc |
| 978 | from that, it is always the .elc file that we look at, and they are no | 1031 | file that we should look at, and they are no problem because byte-compiler |
| 979 | problem because byte-compiler output follows this convention. | 1032 | output follows this convention. |
| 980 | The NAME and DOCSTRING are output. | 1033 | The NAME and DOCSTRING are output. |
| 981 | NAME is preceded by `F' for a function or `V' for a variable. | 1034 | NAME is preceded by `F' for a function or `V' for a variable. |
| 982 | An entry is output only if DOCSTRING has \ newline just after the opening " | 1035 | An entry is output only if DOCSTRING has \ newline just after the opening ". |
| 983 | */ | 1036 | */ |
| 984 | 1037 | ||
| 985 | static void | 1038 | static void |
| @@ -1020,20 +1073,83 @@ read_lisp_symbol (FILE *infile, char *buffer) | |||
| 1020 | } | 1073 | } |
| 1021 | 1074 | ||
| 1022 | static int | 1075 | static int |
| 1076 | search_lisp_doc_at_eol (FILE *infile) | ||
| 1077 | { | ||
| 1078 | char c = 0, c1 = 0, c2 = 0; | ||
| 1079 | |||
| 1080 | /* Skip until the end of line; remember two previous chars. */ | ||
| 1081 | while (c != '\n' && c != '\r' && c != EOF) | ||
| 1082 | { | ||
| 1083 | c2 = c1; | ||
| 1084 | c1 = c; | ||
| 1085 | c = getc (infile); | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | /* If two previous characters were " and \, | ||
| 1089 | this is a doc string. Otherwise, there is none. */ | ||
| 1090 | if (c2 != '"' || c1 != '\\') | ||
| 1091 | { | ||
| 1092 | #ifdef DEBUG | ||
| 1093 | fprintf (stderr, "## non-docstring in %s (%s)\n", | ||
| 1094 | buffer, filename); | ||
| 1095 | #endif | ||
| 1096 | if (c != EOF) | ||
| 1097 | ungetc (c, infile); | ||
| 1098 | return 0; | ||
| 1099 | } | ||
| 1100 | return 1; | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | #define DEF_ELISP_FILE(fn) { #fn, sizeof(#fn) - 1 } | ||
| 1104 | |||
| 1105 | static int | ||
| 1023 | scan_lisp_file (const char *filename, const char *mode) | 1106 | scan_lisp_file (const char *filename, const char *mode) |
| 1024 | { | 1107 | { |
| 1025 | FILE *infile; | 1108 | FILE *infile; |
| 1026 | register int c; | 1109 | register int c; |
| 1027 | char *saved_string = 0; | 1110 | char *saved_string = 0; |
| 1111 | /* These are the only files that are loaded uncompiled, and must | ||
| 1112 | follow the conventions of the doc strings expected by this | ||
| 1113 | function. These conventions are automatically followed by the | ||
| 1114 | byte compiler when it produces the .elc files. */ | ||
| 1115 | static struct { | ||
| 1116 | const char *fn; | ||
| 1117 | size_t fl; | ||
| 1118 | } const uncompiled[] = { | ||
| 1119 | DEF_ELISP_FILE (loaddefs.el), | ||
| 1120 | DEF_ELISP_FILE (loadup.el), | ||
| 1121 | DEF_ELISP_FILE (charprop.el), | ||
| 1122 | DEF_ELISP_FILE (cp51932.el), | ||
| 1123 | DEF_ELISP_FILE (eucjp-ms.el) | ||
| 1124 | }; | ||
| 1125 | int i, match; | ||
| 1126 | size_t flen = strlen (filename); | ||
| 1028 | 1127 | ||
| 1029 | if (generate_globals) | 1128 | if (generate_globals) |
| 1030 | fatal ("scanning lisp file when -g specified", 0); | 1129 | fatal ("scanning lisp file when -g specified", 0); |
| 1130 | if (flen > 3 && !strcmp (filename + flen - 3, ".el")) | ||
| 1131 | { | ||
| 1132 | for (i = 0, match = 0; i < sizeof (uncompiled) / sizeof (uncompiled[0]); | ||
| 1133 | i++) | ||
| 1134 | { | ||
| 1135 | if (uncompiled[i].fl <= flen | ||
| 1136 | && !strcmp (filename + flen - uncompiled[i].fl, uncompiled[i].fn) | ||
| 1137 | && (flen == uncompiled[i].fl | ||
| 1138 | || IS_SLASH (filename[flen - uncompiled[i].fl - 1]))) | ||
| 1139 | { | ||
| 1140 | match = 1; | ||
| 1141 | break; | ||
| 1142 | } | ||
| 1143 | } | ||
| 1144 | if (!match) | ||
| 1145 | fatal ("uncompiled lisp file %s is not supported", filename); | ||
| 1146 | } | ||
| 1031 | 1147 | ||
| 1032 | infile = fopen (filename, mode); | 1148 | infile = fopen (filename, mode); |
| 1033 | if (infile == NULL) | 1149 | if (infile == NULL) |
| 1034 | { | 1150 | { |
| 1035 | perror (filename); | 1151 | perror (filename); |
| 1036 | return 0; /* No error */ | 1152 | return 0; /* No error. */ |
| 1037 | } | 1153 | } |
| 1038 | 1154 | ||
| 1039 | c = '\n'; | 1155 | c = '\n'; |
| @@ -1110,7 +1226,7 @@ scan_lisp_file (const char *filename, const char *mode) | |||
| 1110 | type = 'F'; | 1226 | type = 'F'; |
| 1111 | read_lisp_symbol (infile, buffer); | 1227 | read_lisp_symbol (infile, buffer); |
| 1112 | 1228 | ||
| 1113 | /* Skip the arguments: either "nil" or a list in parens */ | 1229 | /* Skip the arguments: either "nil" or a list in parens. */ |
| 1114 | 1230 | ||
| 1115 | c = getc (infile); | 1231 | c = getc (infile); |
| 1116 | if (c == 'n') /* nil */ | 1232 | if (c == 'n') /* nil */ |
| @@ -1154,39 +1270,18 @@ scan_lisp_file (const char *filename, const char *mode) | |||
| 1154 | || ! strcmp (buffer, "defconst") | 1270 | || ! strcmp (buffer, "defconst") |
| 1155 | || ! strcmp (buffer, "defcustom")) | 1271 | || ! strcmp (buffer, "defcustom")) |
| 1156 | { | 1272 | { |
| 1157 | char c1 = 0, c2 = 0; | ||
| 1158 | type = 'V'; | 1273 | type = 'V'; |
| 1159 | read_lisp_symbol (infile, buffer); | 1274 | read_lisp_symbol (infile, buffer); |
| 1160 | 1275 | ||
| 1161 | if (saved_string == 0) | 1276 | if (saved_string == 0) |
| 1162 | { | 1277 | if (!search_lisp_doc_at_eol (infile)) |
| 1163 | 1278 | continue; | |
| 1164 | /* Skip until the end of line; remember two previous chars. */ | ||
| 1165 | while (c != '\n' && c != '\r' && c >= 0) | ||
| 1166 | { | ||
| 1167 | c2 = c1; | ||
| 1168 | c1 = c; | ||
| 1169 | c = getc (infile); | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | /* If two previous characters were " and \, | ||
| 1173 | this is a doc string. Otherwise, there is none. */ | ||
| 1174 | if (c2 != '"' || c1 != '\\') | ||
| 1175 | { | ||
| 1176 | #ifdef DEBUG | ||
| 1177 | fprintf (stderr, "## non-docstring in %s (%s)\n", | ||
| 1178 | buffer, filename); | ||
| 1179 | #endif | ||
| 1180 | continue; | ||
| 1181 | } | ||
| 1182 | } | ||
| 1183 | } | 1279 | } |
| 1184 | 1280 | ||
| 1185 | else if (! strcmp (buffer, "custom-declare-variable") | 1281 | else if (! strcmp (buffer, "custom-declare-variable") |
| 1186 | || ! strcmp (buffer, "defvaralias") | 1282 | || ! strcmp (buffer, "defvaralias") |
| 1187 | ) | 1283 | ) |
| 1188 | { | 1284 | { |
| 1189 | char c1 = 0, c2 = 0; | ||
| 1190 | type = 'V'; | 1285 | type = 'V'; |
| 1191 | 1286 | ||
| 1192 | c = getc (infile); | 1287 | c = getc (infile); |
| @@ -1221,31 +1316,12 @@ scan_lisp_file (const char *filename, const char *mode) | |||
| 1221 | } | 1316 | } |
| 1222 | 1317 | ||
| 1223 | if (saved_string == 0) | 1318 | if (saved_string == 0) |
| 1224 | { | 1319 | if (!search_lisp_doc_at_eol (infile)) |
| 1225 | /* Skip to end of line; remember the two previous chars. */ | 1320 | continue; |
| 1226 | while (c != '\n' && c != '\r' && c >= 0) | ||
| 1227 | { | ||
| 1228 | c2 = c1; | ||
| 1229 | c1 = c; | ||
| 1230 | c = getc (infile); | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | /* If two previous characters were " and \, | ||
| 1234 | this is a doc string. Otherwise, there is none. */ | ||
| 1235 | if (c2 != '"' || c1 != '\\') | ||
| 1236 | { | ||
| 1237 | #ifdef DEBUG | ||
| 1238 | fprintf (stderr, "## non-docstring in %s (%s)\n", | ||
| 1239 | buffer, filename); | ||
| 1240 | #endif | ||
| 1241 | continue; | ||
| 1242 | } | ||
| 1243 | } | ||
| 1244 | } | 1321 | } |
| 1245 | 1322 | ||
| 1246 | else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias")) | 1323 | else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias")) |
| 1247 | { | 1324 | { |
| 1248 | char c1 = 0, c2 = 0; | ||
| 1249 | type = 'F'; | 1325 | type = 'F'; |
| 1250 | 1326 | ||
| 1251 | c = getc (infile); | 1327 | c = getc (infile); |
| @@ -1278,26 +1354,8 @@ scan_lisp_file (const char *filename, const char *mode) | |||
| 1278 | } | 1354 | } |
| 1279 | 1355 | ||
| 1280 | if (saved_string == 0) | 1356 | if (saved_string == 0) |
| 1281 | { | 1357 | if (!search_lisp_doc_at_eol (infile)) |
| 1282 | /* Skip to end of line; remember the two previous chars. */ | 1358 | continue; |
| 1283 | while (c != '\n' && c != '\r' && c >= 0) | ||
| 1284 | { | ||
| 1285 | c2 = c1; | ||
| 1286 | c1 = c; | ||
| 1287 | c = getc (infile); | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | /* If two previous characters were " and \, | ||
| 1291 | this is a doc string. Otherwise, there is none. */ | ||
| 1292 | if (c2 != '"' || c1 != '\\') | ||
| 1293 | { | ||
| 1294 | #ifdef DEBUG | ||
| 1295 | fprintf (stderr, "## non-docstring in %s (%s)\n", | ||
| 1296 | buffer, filename); | ||
| 1297 | #endif | ||
| 1298 | continue; | ||
| 1299 | } | ||
| 1300 | } | ||
| 1301 | } | 1359 | } |
| 1302 | 1360 | ||
| 1303 | else if (! strcmp (buffer, "autoload")) | 1361 | else if (! strcmp (buffer, "autoload")) |
| @@ -1339,29 +1397,16 @@ scan_lisp_file (const char *filename, const char *mode) | |||
| 1339 | continue; | 1397 | continue; |
| 1340 | } | 1398 | } |
| 1341 | read_c_string_or_comment (infile, 0, 0, 0); | 1399 | read_c_string_or_comment (infile, 0, 0, 0); |
| 1342 | skip_white (infile); | ||
| 1343 | 1400 | ||
| 1344 | if (saved_string == 0) | 1401 | if (saved_string == 0) |
| 1345 | { | 1402 | if (!search_lisp_doc_at_eol (infile)) |
| 1346 | /* If the next three characters aren't `dquote bslash newline' | 1403 | continue; |
| 1347 | then we're not reading a docstring. */ | ||
| 1348 | if ((c = getc (infile)) != '"' | ||
| 1349 | || (c = getc (infile)) != '\\' | ||
| 1350 | || ((c = getc (infile)) != '\n' && c != '\r')) | ||
| 1351 | { | ||
| 1352 | #ifdef DEBUG | ||
| 1353 | fprintf (stderr, "## non-docstring in %s (%s)\n", | ||
| 1354 | buffer, filename); | ||
| 1355 | #endif | ||
| 1356 | continue; | ||
| 1357 | } | ||
| 1358 | } | ||
| 1359 | } | 1404 | } |
| 1360 | 1405 | ||
| 1361 | #ifdef DEBUG | 1406 | #ifdef DEBUG |
| 1362 | else if (! strcmp (buffer, "if") | 1407 | else if (! strcmp (buffer, "if") |
| 1363 | || ! strcmp (buffer, "byte-code")) | 1408 | || ! strcmp (buffer, "byte-code")) |
| 1364 | ; | 1409 | continue; |
| 1365 | #endif | 1410 | #endif |
| 1366 | 1411 | ||
| 1367 | else | 1412 | else |
| @@ -1373,12 +1418,10 @@ scan_lisp_file (const char *filename, const char *mode) | |||
| 1373 | continue; | 1418 | continue; |
| 1374 | } | 1419 | } |
| 1375 | 1420 | ||
| 1376 | /* At this point, we should either use the previous | 1421 | /* At this point, we should either use the previous dynamic doc string in |
| 1377 | dynamic doc string in saved_string | 1422 | saved_string or gobble a doc string from the input file. |
| 1378 | or gobble a doc string from the input file. | 1423 | In the latter case, the opening quote (and leading backslash-newline) |
| 1379 | 1424 | have already been read. */ | |
| 1380 | In the latter case, the opening quote (and leading | ||
| 1381 | backslash-newline) have already been read. */ | ||
| 1382 | 1425 | ||
| 1383 | putc (037, outfile); | 1426 | putc (037, outfile); |
| 1384 | putc (type, outfile); | 1427 | putc (type, outfile); |