aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src/make-docfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib-src/make-docfile.c')
-rw-r--r--lib-src/make-docfile.c289
1 files changed, 213 insertions, 76 deletions
diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c
index f74b3d516d1..bc5420ea939 100644
--- a/lib-src/make-docfile.c
+++ b/lib-src/make-docfile.c
@@ -36,6 +36,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
36 36
37#include <config.h> 37#include <config.h>
38 38
39#include <stdbool.h>
39#include <stdio.h> 40#include <stdio.h>
40#include <stdlib.h> /* config.h unconditionally includes this anyway */ 41#include <stdlib.h> /* config.h unconditionally includes this anyway */
41 42
@@ -63,6 +64,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
63static int scan_file (char *filename); 64static int scan_file (char *filename);
64static int scan_lisp_file (const char *filename, const char *mode); 65static int scan_lisp_file (const char *filename, const char *mode);
65static int scan_c_file (char *filename, const char *mode); 66static int scan_c_file (char *filename, const char *mode);
67static int scan_c_stream (FILE *infile);
66static void start_globals (void); 68static void start_globals (void);
67static void write_globals (void); 69static void write_globals (void);
68 70
@@ -106,6 +108,17 @@ xmalloc (unsigned int size)
106 return result; 108 return result;
107} 109}
108 110
111/* Like strdup, but get fatal error if memory is exhausted. */
112
113static char *
114xstrdup (char *s)
115{
116 char *result = strdup (s);
117 if (! result)
118 fatal ("virtual memory exhausted", 0);
119 return result;
120}
121
109/* Like realloc but get fatal error if memory is exhausted. */ 122/* Like realloc but get fatal error if memory is exhausted. */
110 123
111static void * 124static void *
@@ -123,7 +136,6 @@ main (int argc, char **argv)
123{ 136{
124 int i; 137 int i;
125 int err_count = 0; 138 int err_count = 0;
126 int first_infile;
127 139
128 progname = argv[0]; 140 progname = argv[0];
129 141
@@ -167,16 +179,21 @@ main (int argc, char **argv)
167 if (generate_globals) 179 if (generate_globals)
168 start_globals (); 180 start_globals ();
169 181
170 first_infile = i; 182 if (argc <= i)
171 for (; i < argc; i++) 183 scan_c_stream (stdin);
184 else
172 { 185 {
173 int j; 186 int first_infile = i;
174 /* Don't process one file twice. */ 187 for (; i < argc; i++)
175 for (j = first_infile; j < i; j++) 188 {
176 if (! strcmp (argv[i], argv[j])) 189 int j;
177 break; 190 /* Don't process one file twice. */
178 if (j == i) 191 for (j = first_infile; j < i; j++)
179 err_count += scan_file (argv[i]); 192 if (strcmp (argv[i], argv[j]) == 0)
193 break;
194 if (j == i)
195 err_count += scan_file (argv[i]);
196 }
180 } 197 }
181 198
182 if (err_count == 0 && generate_globals) 199 if (err_count == 0 && generate_globals)
@@ -528,13 +545,15 @@ write_c_args (char *func, char *buf, int minargs, int maxargs)
528} 545}
529 546
530/* The types of globals. These are sorted roughly in decreasing alignment 547/* The types of globals. These are sorted roughly in decreasing alignment
531 order to avoid allocation gaps, except that functions are last. */ 548 order to avoid allocation gaps, except that symbols and functions
549 are last. */
532enum global_type 550enum global_type
533{ 551{
534 INVALID, 552 INVALID,
535 LISP_OBJECT, 553 LISP_OBJECT,
536 EMACS_INTEGER, 554 EMACS_INTEGER,
537 BOOLEAN, 555 BOOLEAN,
556 SYMBOL,
538 FUNCTION 557 FUNCTION
539}; 558};
540 559
@@ -543,7 +562,11 @@ struct global
543{ 562{
544 enum global_type type; 563 enum global_type type;
545 char *name; 564 char *name;
546 int value; 565 union
566 {
567 int value;
568 char const *svalue;
569 } v;
547}; 570};
548 571
549/* All the variable names we saw while scanning C sources in `-g' 572/* All the variable names we saw while scanning C sources in `-g'
@@ -553,7 +576,7 @@ int num_globals_allocated;
553struct global *globals; 576struct global *globals;
554 577
555static void 578static void
556add_global (enum global_type type, char *name, int value) 579add_global (enum global_type type, char *name, int value, char const *svalue)
557{ 580{
558 /* Ignore the one non-symbol that can occur. */ 581 /* Ignore the one non-symbol that can occur. */
559 if (strcmp (name, "...")) 582 if (strcmp (name, "..."))
@@ -574,7 +597,10 @@ add_global (enum global_type type, char *name, int value)
574 597
575 globals[num_globals - 1].type = type; 598 globals[num_globals - 1].type = type;
576 globals[num_globals - 1].name = name; 599 globals[num_globals - 1].name = name;
577 globals[num_globals - 1].value = value; 600 if (svalue)
601 globals[num_globals - 1].v.svalue = svalue;
602 else
603 globals[num_globals - 1].v.value = value;
578 } 604 }
579} 605}
580 606
@@ -587,21 +613,58 @@ compare_globals (const void *a, const void *b)
587 if (ga->type != gb->type) 613 if (ga->type != gb->type)
588 return ga->type - gb->type; 614 return ga->type - gb->type;
589 615
616 /* Consider "nil" to be the least, so that iQnil is zero. That
617 way, Qnil's internal representation is zero, which is a bit faster. */
618 if (ga->type == SYMBOL)
619 {
620 bool a_nil = strcmp (ga->name, "Qnil") == 0;
621 bool b_nil = strcmp (gb->name, "Qnil") == 0;
622 if (a_nil | b_nil)
623 return b_nil - a_nil;
624 }
625
590 return strcmp (ga->name, gb->name); 626 return strcmp (ga->name, gb->name);
591} 627}
592 628
593static void 629static void
594close_emacs_globals (void) 630close_emacs_globals (int num_symbols)
595{ 631{
596 puts ("};"); 632 printf (("};\n"
597 puts ("extern struct emacs_globals globals;"); 633 "extern struct emacs_globals globals;\n"
634 "\n"
635 "#ifndef DEFINE_SYMBOLS\n"
636 "extern\n"
637 "#endif\n"
638 "struct Lisp_Symbol alignas (GCALIGNMENT) lispsym[%d];\n"),
639 num_symbols);
598} 640}
599 641
600static void 642static void
601write_globals (void) 643write_globals (void)
602{ 644{
603 int i, seen_defun = 0; 645 int i, j;
646 bool seen_defun = false;
647 int symnum = 0;
648 int num_symbols = 0;
604 qsort (globals, num_globals, sizeof (struct global), compare_globals); 649 qsort (globals, num_globals, sizeof (struct global), compare_globals);
650
651 j = 0;
652 for (i = 0; i < num_globals; i++)
653 {
654 while (i + 1 < num_globals
655 && strcmp (globals[i].name, globals[i + 1].name) == 0)
656 {
657 if (globals[i].type == FUNCTION
658 && globals[i].v.value != globals[i + 1].v.value)
659 error ("function '%s' defined twice with differing signatures",
660 globals[i].name);
661 i++;
662 }
663 num_symbols += globals[i].type == SYMBOL;
664 globals[j++] = globals[i];
665 }
666 num_globals = j;
667
605 for (i = 0; i < num_globals; ++i) 668 for (i = 0; i < num_globals; ++i)
606 { 669 {
607 char const *type = 0; 670 char const *type = 0;
@@ -617,12 +680,13 @@ write_globals (void)
617 case LISP_OBJECT: 680 case LISP_OBJECT:
618 type = "Lisp_Object"; 681 type = "Lisp_Object";
619 break; 682 break;
683 case SYMBOL:
620 case FUNCTION: 684 case FUNCTION:
621 if (!seen_defun) 685 if (!seen_defun)
622 { 686 {
623 close_emacs_globals (); 687 close_emacs_globals (num_symbols);
624 putchar ('\n'); 688 putchar ('\n');
625 seen_defun = 1; 689 seen_defun = true;
626 } 690 }
627 break; 691 break;
628 default: 692 default:
@@ -635,6 +699,13 @@ write_globals (void)
635 printf ("#define %s globals.f_%s\n", 699 printf ("#define %s globals.f_%s\n",
636 globals[i].name, globals[i].name); 700 globals[i].name, globals[i].name);
637 } 701 }
702 else if (globals[i].type == SYMBOL)
703 printf (("DEFINE_LISP_SYMBOL_BEGIN (%s)\n"
704 "#define i%s %d\n"
705 "#define %s builtin_lisp_symbol (i%s)\n"
706 "DEFINE_LISP_SYMBOL_END (%s)\n\n"),
707 globals[i].name, globals[i].name, symnum++,
708 globals[i].name, globals[i].name, globals[i].name);
638 else 709 else
639 { 710 {
640 /* It would be nice to have a cleaner way to deal with these 711 /* It would be nice to have a cleaner way to deal with these
@@ -647,39 +718,65 @@ write_globals (void)
647 fputs ("_Noreturn ", stdout); 718 fputs ("_Noreturn ", stdout);
648 719
649 printf ("EXFUN (%s, ", globals[i].name); 720 printf ("EXFUN (%s, ", globals[i].name);
650 if (globals[i].value == -1) 721 if (globals[i].v.value == -1)
651 fputs ("MANY", stdout); 722 fputs ("MANY", stdout);
652 else if (globals[i].value == -2) 723 else if (globals[i].v.value == -2)
653 fputs ("UNEVALLED", stdout); 724 fputs ("UNEVALLED", stdout);
654 else 725 else
655 printf ("%d", globals[i].value); 726 printf ("%d", globals[i].v.value);
656 putchar (')'); 727 putchar (')');
657 728
658 /* It would be nice to have a cleaner way to deal with these 729 /* It would be nice to have a cleaner way to deal with these
659 special hacks, too. */ 730 special hacks, too. */
660 if (strcmp (globals[i].name, "Fbyteorder") == 0 731 if (strcmp (globals[i].name, "Fatom") == 0
732 || strcmp (globals[i].name, "Fbyteorder") == 0
733 || strcmp (globals[i].name, "Fcharacterp") == 0
734 || strcmp (globals[i].name, "Fchar_or_string_p") == 0
735 || strcmp (globals[i].name, "Fconsp") == 0
736 || strcmp (globals[i].name, "Feq") == 0
737 || strcmp (globals[i].name, "Fface_attribute_relative_p") == 0
661 || strcmp (globals[i].name, "Fframe_windows_min_size") == 0 738 || strcmp (globals[i].name, "Fframe_windows_min_size") == 0
739 || strcmp (globals[i].name, "Fgnutls_errorp") == 0
662 || strcmp (globals[i].name, "Fidentity") == 0 740 || strcmp (globals[i].name, "Fidentity") == 0
741 || strcmp (globals[i].name, "Fintegerp") == 0
742 || strcmp (globals[i].name, "Finteractive") == 0
743 || strcmp (globals[i].name, "Ffloatp") == 0
744 || strcmp (globals[i].name, "Flistp") == 0
663 || strcmp (globals[i].name, "Fmax_char") == 0 745 || strcmp (globals[i].name, "Fmax_char") == 0
664 || strcmp (globals[i].name, "Ftool_bar_height") == 0) 746 || strcmp (globals[i].name, "Fnatnump") == 0
747 || strcmp (globals[i].name, "Fnlistp") == 0
748 || strcmp (globals[i].name, "Fnull") == 0
749 || strcmp (globals[i].name, "Fnumberp") == 0
750 || strcmp (globals[i].name, "Fstringp") == 0
751 || strcmp (globals[i].name, "Fsymbolp") == 0
752 || strcmp (globals[i].name, "Ftool_bar_height") == 0
753 || strcmp (globals[i].name, "Fwindow__sanitize_window_sizes") == 0
754#ifndef WINDOWSNT
755 || strcmp (globals[i].name, "Fgnutls_available_p") == 0
756 || strcmp (globals[i].name, "Fzlib_available_p") == 0
757#endif
758 || 0)
665 fputs (" ATTRIBUTE_CONST", stdout); 759 fputs (" ATTRIBUTE_CONST", stdout);
666 760
667 puts (";"); 761 puts (";");
668 } 762 }
669
670 while (i + 1 < num_globals
671 && !strcmp (globals[i].name, globals[i + 1].name))
672 {
673 if (globals[i].type == FUNCTION
674 && globals[i].value != globals[i + 1].value)
675 error ("function '%s' defined twice with differing signatures",
676 globals[i].name);
677 ++i;
678 }
679 } 763 }
680 764
681 if (!seen_defun) 765 if (!seen_defun)
682 close_emacs_globals (); 766 close_emacs_globals (num_symbols);
767
768 puts ("#ifdef DEFINE_SYMBOLS");
769 puts ("static char const *const defsym_name[] = {");
770 for (int i = 0; i < num_globals; i++)
771 {
772 if (globals[i].type == SYMBOL)
773 printf ("\t\"%s\",\n", globals[i].v.svalue);
774 while (i + 1 < num_globals
775 && strcmp (globals[i].name, globals[i + 1].name) == 0)
776 i++;
777 }
778 puts ("};");
779 puts ("#endif");
683} 780}
684 781
685 782
@@ -692,9 +789,6 @@ static int
692scan_c_file (char *filename, const char *mode) 789scan_c_file (char *filename, const char *mode)
693{ 790{
694 FILE *infile; 791 FILE *infile;
695 register int c;
696 register int commas;
697 int minargs, maxargs;
698 int extension = filename[strlen (filename) - 1]; 792 int extension = filename[strlen (filename) - 1];
699 793
700 if (extension == 'o') 794 if (extension == 'o')
@@ -720,8 +814,15 @@ scan_c_file (char *filename, const char *mode)
720 814
721 /* Reset extension to be able to detect duplicate files. */ 815 /* Reset extension to be able to detect duplicate files. */
722 filename[strlen (filename) - 1] = extension; 816 filename[strlen (filename) - 1] = extension;
817 return scan_c_stream (infile);
818}
819
820static int
821scan_c_stream (FILE *infile)
822{
823 int commas, minargs, maxargs;
824 int c = '\n';
723 825
724 c = '\n';
725 while (!feof (infile)) 826 while (!feof (infile))
726 { 827 {
727 int doc_keyword = 0; 828 int doc_keyword = 0;
@@ -750,37 +851,53 @@ scan_c_file (char *filename, const char *mode)
750 if (c != 'F') 851 if (c != 'F')
751 continue; 852 continue;
752 c = getc (infile); 853 c = getc (infile);
753 if (c != 'V') 854 if (c == 'S')
754 continue;
755 c = getc (infile);
756 if (c != 'A')
757 continue;
758 c = getc (infile);
759 if (c != 'R')
760 continue;
761 c = getc (infile);
762 if (c != '_')
763 continue;
764
765 defvarflag = 1;
766
767 c = getc (infile);
768 defvarperbufferflag = (c == 'P');
769 if (generate_globals)
770 { 855 {
771 if (c == 'I') 856 c = getc (infile);
772 type = EMACS_INTEGER; 857 if (c != 'Y')
773 else if (c == 'L') 858 continue;
774 type = LISP_OBJECT; 859 c = getc (infile);
775 else if (c == 'B') 860 if (c != 'M')
776 type = BOOLEAN; 861 continue;
862 c = getc (infile);
863 if (c != ' ' && c != '\t' && c != '(')
864 continue;
865 type = SYMBOL;
777 } 866 }
867 else if (c == 'V')
868 {
869 c = getc (infile);
870 if (c != 'A')
871 continue;
872 c = getc (infile);
873 if (c != 'R')
874 continue;
875 c = getc (infile);
876 if (c != '_')
877 continue;
778 878
779 c = getc (infile); 879 defvarflag = 1;
780 /* We need to distinguish between DEFVAR_BOOL and 880
781 DEFVAR_BUFFER_DEFAULTS. */ 881 c = getc (infile);
782 if (generate_globals && type == BOOLEAN && c != 'O') 882 defvarperbufferflag = (c == 'P');
783 type = INVALID; 883 if (generate_globals)
884 {
885 if (c == 'I')
886 type = EMACS_INTEGER;
887 else if (c == 'L')
888 type = LISP_OBJECT;
889 else if (c == 'B')
890 type = BOOLEAN;
891 }
892
893 c = getc (infile);
894 /* We need to distinguish between DEFVAR_BOOL and
895 DEFVAR_BUFFER_DEFAULTS. */
896 if (generate_globals && type == BOOLEAN && c != 'O')
897 type = INVALID;
898 }
899 else
900 continue;
784 } 901 }
785 else if (c == 'D') 902 else if (c == 'D')
786 { 903 {
@@ -797,7 +914,7 @@ scan_c_file (char *filename, const char *mode)
797 914
798 if (generate_globals 915 if (generate_globals
799 && (!defvarflag || defvarperbufferflag || type == INVALID) 916 && (!defvarflag || defvarperbufferflag || type == INVALID)
800 && !defunflag) 917 && !defunflag && type != SYMBOL)
801 continue; 918 continue;
802 919
803 while (c != '(') 920 while (c != '(')
@@ -807,15 +924,19 @@ scan_c_file (char *filename, const char *mode)
807 c = getc (infile); 924 c = getc (infile);
808 } 925 }
809 926
810 /* Lisp variable or function name. */ 927 if (type != SYMBOL)
811 c = getc (infile); 928 {
812 if (c != '"') 929 /* Lisp variable or function name. */
813 continue; 930 c = getc (infile);
814 c = read_c_string_or_comment (infile, -1, 0, 0); 931 if (c != '"')
932 continue;
933 c = read_c_string_or_comment (infile, -1, 0, 0);
934 }
815 935
816 if (generate_globals) 936 if (generate_globals)
817 { 937 {
818 int i = 0; 938 int i = 0;
939 char const *svalue = 0;
819 940
820 /* Skip "," and whitespace. */ 941 /* Skip "," and whitespace. */
821 do 942 do
@@ -827,6 +948,8 @@ scan_c_file (char *filename, const char *mode)
827 /* Read in the identifier. */ 948 /* Read in the identifier. */
828 do 949 do
829 { 950 {
951 if (c < 0)
952 goto eof;
830 input_buffer[i++] = c; 953 input_buffer[i++] = c;
831 c = getc (infile); 954 c = getc (infile);
832 } 955 }
@@ -837,13 +960,27 @@ scan_c_file (char *filename, const char *mode)
837 name = xmalloc (i + 1); 960 name = xmalloc (i + 1);
838 memcpy (name, input_buffer, i + 1); 961 memcpy (name, input_buffer, i + 1);
839 962
963 if (type == SYMBOL)
964 {
965 do
966 c = getc (infile);
967 while (c == ' ' || c == '\t' || c == '\n' || c == '\r');
968 if (c != '"')
969 continue;
970 c = read_c_string_or_comment (infile, -1, 0, 0);
971 svalue = xstrdup (input_buffer);
972 }
973
840 if (!defunflag) 974 if (!defunflag)
841 { 975 {
842 add_global (type, name, 0); 976 add_global (type, name, 0, svalue);
843 continue; 977 continue;
844 } 978 }
845 } 979 }
846 980
981 if (type == SYMBOL)
982 continue;
983
847 /* DEFVAR_LISP ("name", addr, "doc") 984 /* DEFVAR_LISP ("name", addr, "doc")
848 DEFVAR_LISP ("name", addr /\* doc *\/) 985 DEFVAR_LISP ("name", addr /\* doc *\/)
849 DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */ 986 DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */
@@ -896,7 +1033,7 @@ scan_c_file (char *filename, const char *mode)
896 1033
897 if (generate_globals) 1034 if (generate_globals)
898 { 1035 {
899 add_global (FUNCTION, name, maxargs); 1036 add_global (FUNCTION, name, maxargs, 0);
900 continue; 1037 continue;
901 } 1038 }
902 1039