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.c246
1 files changed, 215 insertions, 31 deletions
diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c
index 8addbda0489..ba54202954b 100644
--- a/lib-src/make-docfile.c
+++ b/lib-src/make-docfile.c
@@ -41,11 +41,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
41#undef chdir 41#undef chdir
42 42
43#include <stdio.h> 43#include <stdio.h>
44#include <stdlib.h>
44#ifdef MSDOS 45#ifdef MSDOS
45#include <fcntl.h> 46#include <fcntl.h>
46#endif /* MSDOS */ 47#endif /* MSDOS */
47#ifdef WINDOWSNT 48#ifdef WINDOWSNT
48#include <stdlib.h>
49#include <fcntl.h> 49#include <fcntl.h>
50#include <direct.h> 50#include <direct.h>
51#endif /* WINDOWSNT */ 51#endif /* WINDOWSNT */
@@ -66,10 +66,19 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
66#define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP) 66#define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
67#endif 67#endif
68 68
69int scan_file (char *filename); 69/* Use this to suppress gcc's `...may be used before initialized' warnings. */
70int scan_lisp_file (const char *filename, const char *mode); 70#ifdef lint
71int scan_c_file (char *filename, const char *mode); 71# define IF_LINT(Code) Code
72void fatal (const char *s1, const char *s2) NO_RETURN; 72#else
73# define IF_LINT(Code) /* empty */
74#endif
75
76static int scan_file (char *filename);
77static int scan_lisp_file (const char *filename, const char *mode);
78static int scan_c_file (char *filename, const char *mode);
79static void fatal (const char *s1, const char *s2) NO_RETURN;
80static void start_globals (void);
81static void write_globals (void);
73 82
74#ifdef MSDOS 83#ifdef MSDOS
75/* s/msdos.h defines this as sys_chdir, but we're not linking with the 84/* s/msdos.h defines this as sys_chdir, but we're not linking with the
@@ -85,10 +94,13 @@ FILE *outfile;
85/* Name this program was invoked with. */ 94/* Name this program was invoked with. */
86char *progname; 95char *progname;
87 96
97/* Nonzero if this invocation is generating globals.h. */
98int generate_globals;
99
88/* Print error message. `s1' is printf control string, `s2' is arg for it. */ 100/* Print error message. `s1' is printf control string, `s2' is arg for it. */
89 101
90/* VARARGS1 */ 102/* VARARGS1 */
91void 103static void
92error (const char *s1, const char *s2) 104error (const char *s1, const char *s2)
93{ 105{
94 fprintf (stderr, "%s: ", progname); 106 fprintf (stderr, "%s: ", progname);
@@ -99,7 +111,7 @@ error (const char *s1, const char *s2)
99/* Print error message and exit. */ 111/* Print error message and exit. */
100 112
101/* VARARGS1 */ 113/* VARARGS1 */
102void 114static void
103fatal (const char *s1, const char *s2) 115fatal (const char *s1, const char *s2)
104{ 116{
105 error (s1, s2); 117 error (s1, s2);
@@ -108,7 +120,7 @@ fatal (const char *s1, const char *s2)
108 120
109/* Like malloc but get fatal error if memory is exhausted. */ 121/* Like malloc but get fatal error if memory is exhausted. */
110 122
111void * 123static void *
112xmalloc (unsigned int size) 124xmalloc (unsigned int size)
113{ 125{
114 void *result = (void *) malloc (size); 126 void *result = (void *) malloc (size);
@@ -116,6 +128,18 @@ xmalloc (unsigned int size)
116 fatal ("virtual memory exhausted", 0); 128 fatal ("virtual memory exhausted", 0);
117 return result; 129 return result;
118} 130}
131
132/* Like realloc but get fatal error if memory is exhausted. */
133
134static void *
135xrealloc (void *arg, unsigned int size)
136{
137 void *result = (void *) realloc (arg, size);
138 if (result == NULL)
139 fatal ("virtual memory exhausted", 0);
140 return result;
141}
142
119 143
120int 144int
121main (int argc, char **argv) 145main (int argc, char **argv)
@@ -164,10 +188,18 @@ main (int argc, char **argv)
164 } 188 }
165 i += 2; 189 i += 2;
166 } 190 }
191 if (argc > i && !strcmp (argv[i], "-g"))
192 {
193 generate_globals = 1;
194 ++i;
195 }
167 196
168 if (outfile == 0) 197 if (outfile == 0)
169 fatal ("No output file specified", ""); 198 fatal ("No output file specified", "");
170 199
200 if (generate_globals)
201 start_globals ();
202
171 first_infile = i; 203 first_infile = i;
172 for (; i < argc; i++) 204 for (; i < argc; i++)
173 { 205 {
@@ -179,11 +211,15 @@ main (int argc, char **argv)
179 if (j == i) 211 if (j == i)
180 err_count += scan_file (argv[i]); 212 err_count += scan_file (argv[i]);
181 } 213 }
214
215 if (err_count == 0 && generate_globals)
216 write_globals ();
217
182 return (err_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS); 218 return (err_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
183} 219}
184 220
185/* Add a source file name boundary marker in the output file. */ 221/* Add a source file name boundary marker in the output file. */
186void 222static void
187put_filename (char *filename) 223put_filename (char *filename)
188{ 224{
189 char *tmp; 225 char *tmp;
@@ -202,13 +238,14 @@ put_filename (char *filename)
202/* Read file FILENAME and output its doc strings to outfile. */ 238/* Read file FILENAME and output its doc strings to outfile. */
203/* Return 1 if file is not found, 0 if it is found. */ 239/* Return 1 if file is not found, 0 if it is found. */
204 240
205int 241static int
206scan_file (char *filename) 242scan_file (char *filename)
207{ 243{
208 244
209 size_t len = strlen (filename); 245 size_t len = strlen (filename);
210 246
211 put_filename (filename); 247 if (!generate_globals)
248 put_filename (filename);
212 if (len > 4 && !strcmp (filename + len - 4, ".elc")) 249 if (len > 4 && !strcmp (filename + len - 4, ".elc"))
213 return scan_lisp_file (filename, READ_BINARY); 250 return scan_lisp_file (filename, READ_BINARY);
214 else if (len > 3 && !strcmp (filename + len - 3, ".el")) 251 else if (len > 3 && !strcmp (filename + len - 3, ".el"))
@@ -216,8 +253,16 @@ scan_file (char *filename)
216 else 253 else
217 return scan_c_file (filename, READ_TEXT); 254 return scan_c_file (filename, READ_TEXT);
218} 255}
256
257static void
258start_globals (void)
259{
260 fprintf (outfile, "/* This file was auto-generated by make-docfile. */\n");
261 fprintf (outfile, "/* DO NOT EDIT. */\n");
262 fprintf (outfile, "struct emacs_globals {\n");
263}
219 264
220char buf[128]; 265static char input_buffer[128];
221 266
222/* Some state during the execution of `read_c_string_or_comment'. */ 267/* Some state during the execution of `read_c_string_or_comment'. */
223struct rcsoc_state 268struct rcsoc_state
@@ -246,7 +291,7 @@ struct rcsoc_state
246/* Output CH to the file or buffer in STATE. Any pending newlines or 291/* Output CH to the file or buffer in STATE. Any pending newlines or
247 spaces are output first. */ 292 spaces are output first. */
248 293
249static INLINE void 294static inline void
250put_char (int ch, struct rcsoc_state *state) 295put_char (int ch, struct rcsoc_state *state)
251{ 296{
252 int out_ch; 297 int out_ch;
@@ -350,14 +395,14 @@ scan_keyword_or_put_char (int ch, struct rcsoc_state *state)
350 at the beginning of a line will be removed, and *SAW_USAGE set to 395 at the beginning of a line will be removed, and *SAW_USAGE set to
351 true if any were encountered. */ 396 true if any were encountered. */
352 397
353int 398static int
354read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usage) 399read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usage)
355{ 400{
356 register int c; 401 register int c;
357 struct rcsoc_state state; 402 struct rcsoc_state state;
358 403
359 state.in_file = infile; 404 state.in_file = infile;
360 state.buf_ptr = (printflag < 0 ? buf : 0); 405 state.buf_ptr = (printflag < 0 ? input_buffer : 0);
361 state.out_file = (printflag > 0 ? outfile : 0); 406 state.out_file = (printflag > 0 ? outfile : 0);
362 state.pending_spaces = 0; 407 state.pending_spaces = 0;
363 state.pending_newlines = 0; 408 state.pending_newlines = 0;
@@ -438,12 +483,12 @@ read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usa
438/* Write to file OUT the argument names of function FUNC, whose text is in BUF. 483/* Write to file OUT the argument names of function FUNC, whose text is in BUF.
439 MINARGS and MAXARGS are the minimum and maximum number of arguments. */ 484 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
440 485
441void 486static void
442write_c_args (FILE *out, char *func, char *buf, int minargs, int maxargs) 487write_c_args (FILE *out, char *func, char *buf, int minargs, int maxargs)
443{ 488{
444 register char *p; 489 register char *p;
445 int in_ident = 0; 490 int in_ident = 0;
446 char *ident_start; 491 char *ident_start IF_LINT (= NULL);
447 size_t ident_length = 0; 492 size_t ident_length = 0;
448 493
449 fprintf (out, "(fn"); 494 fprintf (out, "(fn");
@@ -517,20 +562,109 @@ write_c_args (FILE *out, char *func, char *buf, int minargs, int maxargs)
517 putc (')', out); 562 putc (')', out);
518} 563}
519 564
565/* The types of globals. */
566enum global_type
567{
568 EMACS_INTEGER,
569 BOOLEAN,
570 LISP_OBJECT,
571 INVALID
572};
573
574/* A single global. */
575struct global
576{
577 enum global_type type;
578 char *name;
579};
580
581/* All the variable names we saw while scanning C sources in `-g'
582 mode. */
583int num_globals;
584int num_globals_allocated;
585struct global *globals;
586
587static void
588add_global (enum global_type type, char *name)
589{
590 /* Ignore the one non-symbol that can occur. */
591 if (strcmp (name, "..."))
592 {
593 ++num_globals;
594
595 if (num_globals_allocated == 0)
596 {
597 num_globals_allocated = 100;
598 globals = xmalloc (num_globals_allocated * sizeof (struct global));
599 }
600 else if (num_globals == num_globals_allocated)
601 {
602 num_globals_allocated *= 2;
603 globals = xrealloc (globals,
604 num_globals_allocated * sizeof (struct global));
605 }
606
607 globals[num_globals - 1].type = type;
608 globals[num_globals - 1].name = name;
609 }
610}
611
612static int
613compare_globals (const void *a, const void *b)
614{
615 const struct global *ga = a;
616 const struct global *gb = b;
617 return strcmp (ga->name, gb->name);
618}
619
620static void
621write_globals (void)
622{
623 int i;
624 qsort (globals, num_globals, sizeof (struct global), compare_globals);
625 for (i = 0; i < num_globals; ++i)
626 {
627 char const *type;
628
629 switch (globals[i].type)
630 {
631 case EMACS_INTEGER:
632 type = "EMACS_INT";
633 break;
634 case BOOLEAN:
635 type = "int";
636 break;
637 case LISP_OBJECT:
638 type = "Lisp_Object";
639 break;
640 default:
641 fatal ("not a recognized DEFVAR_", 0);
642 }
643
644 fprintf (outfile, " %s f_%s;\n", type, globals[i].name);
645 fprintf (outfile, "#define %s globals.f_%s\n",
646 globals[i].name, globals[i].name);
647 while (i + 1 < num_globals
648 && !strcmp (globals[i].name, globals[i + 1].name))
649 ++i;
650 }
651
652 fprintf (outfile, "};\n");
653 fprintf (outfile, "extern struct emacs_globals globals;\n");
654}
655
656
520/* Read through a c file. If a .o file is named, 657/* Read through a c file. If a .o file is named,
521 the corresponding .c or .m file is read instead. 658 the corresponding .c or .m file is read instead.
522 Looks for DEFUN constructs such as are defined in ../src/lisp.h. 659 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
523 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */ 660 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
524 661
525int 662static int
526scan_c_file (char *filename, const char *mode) 663scan_c_file (char *filename, const char *mode)
527{ 664{
528 FILE *infile; 665 FILE *infile;
529 register int c; 666 register int c;
530 register int commas; 667 register int commas;
531 register int defunflag;
532 register int defvarperbufferflag;
533 register int defvarflag;
534 int minargs, maxargs; 668 int minargs, maxargs;
535 int extension = filename[strlen (filename) - 1]; 669 int extension = filename[strlen (filename) - 1];
536 670
@@ -562,6 +696,10 @@ scan_c_file (char *filename, const char *mode)
562 while (!feof (infile)) 696 while (!feof (infile))
563 { 697 {
564 int doc_keyword = 0; 698 int doc_keyword = 0;
699 int defunflag = 0;
700 int defvarperbufferflag = 0;
701 int defvarflag = 0;
702 enum global_type type = INVALID;
565 703
566 if (c != '\n' && c != '\r') 704 if (c != '\n' && c != '\r')
567 { 705 {
@@ -595,12 +733,24 @@ scan_c_file (char *filename, const char *mode)
595 continue; 733 continue;
596 734
597 defvarflag = 1; 735 defvarflag = 1;
598 defunflag = 0;
599 736
600 c = getc (infile); 737 c = getc (infile);
601 defvarperbufferflag = (c == 'P'); 738 defvarperbufferflag = (c == 'P');
739 if (generate_globals)
740 {
741 if (c == 'I')
742 type = EMACS_INTEGER;
743 else if (c == 'L')
744 type = LISP_OBJECT;
745 else if (c == 'B')
746 type = BOOLEAN;
747 }
602 748
603 c = getc (infile); 749 c = getc (infile);
750 /* We need to distinguish between DEFVAR_BOOL and
751 DEFVAR_BUFFER_DEFAULTS. */
752 if (generate_globals && type == BOOLEAN && c != 'O')
753 type = INVALID;
604 } 754 }
605 else if (c == 'D') 755 else if (c == 'D')
606 { 756 {
@@ -612,11 +762,13 @@ scan_c_file (char *filename, const char *mode)
612 continue; 762 continue;
613 c = getc (infile); 763 c = getc (infile);
614 defunflag = c == 'U'; 764 defunflag = c == 'U';
615 defvarflag = 0;
616 defvarperbufferflag = 0;
617 } 765 }
618 else continue; 766 else continue;
619 767
768 if (generate_globals && (!defvarflag || defvarperbufferflag
769 || type == INVALID))
770 continue;
771
620 while (c != '(') 772 while (c != '(')
621 { 773 {
622 if (c < 0) 774 if (c < 0)
@@ -630,6 +782,34 @@ scan_c_file (char *filename, const char *mode)
630 continue; 782 continue;
631 c = read_c_string_or_comment (infile, -1, 0, 0); 783 c = read_c_string_or_comment (infile, -1, 0, 0);
632 784
785 if (generate_globals)
786 {
787 int i = 0;
788 char *name;
789
790 /* Skip "," and whitespace. */
791 do
792 {
793 c = getc (infile);
794 }
795 while (c == ',' || c == ' ' || c == '\t' || c == '\n' || c == '\r');
796
797 /* Read in the identifier. */
798 do
799 {
800 input_buffer[i++] = c;
801 c = getc (infile);
802 }
803 while (! (c == ',' || c == ' ' || c == '\t' ||
804 c == '\n' || c == '\r'));
805 input_buffer[i] = '\0';
806
807 name = xmalloc (i + 1);
808 memcpy (name, input_buffer, i + 1);
809 add_global (type, name);
810 continue;
811 }
812
633 /* DEFVAR_LISP ("name", addr, "doc") 813 /* DEFVAR_LISP ("name", addr, "doc")
634 DEFVAR_LISP ("name", addr /\* doc *\/) 814 DEFVAR_LISP ("name", addr /\* doc *\/)
635 DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */ 815 DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */
@@ -637,7 +817,7 @@ scan_c_file (char *filename, const char *mode)
637 if (defunflag) 817 if (defunflag)
638 commas = 5; 818 commas = 5;
639 else if (defvarperbufferflag) 819 else if (defvarperbufferflag)
640 commas = 2; 820 commas = 3;
641 else if (defvarflag) 821 else if (defvarflag)
642 commas = 1; 822 commas = 1;
643 else /* For DEFSIMPLE and DEFPRED */ 823 else /* For DEFSIMPLE and DEFPRED */
@@ -710,7 +890,7 @@ scan_c_file (char *filename, const char *mode)
710 890
711 putc (037, outfile); 891 putc (037, outfile);
712 putc (defvarflag ? 'V' : 'F', outfile); 892 putc (defvarflag ? 'V' : 'F', outfile);
713 fprintf (outfile, "%s\n", buf); 893 fprintf (outfile, "%s\n", input_buffer);
714 894
715 if (comment) 895 if (comment)
716 getc (infile); /* Skip past `*' */ 896 getc (infile); /* Skip past `*' */
@@ -753,11 +933,12 @@ scan_c_file (char *filename, const char *mode)
753 *p = '\0'; 933 *p = '\0';
754 /* Output them. */ 934 /* Output them. */
755 fprintf (outfile, "\n\n"); 935 fprintf (outfile, "\n\n");
756 write_c_args (outfile, buf, argbuf, minargs, maxargs); 936 write_c_args (outfile, input_buffer, argbuf, minargs, maxargs);
757 } 937 }
758 else if (defunflag && maxargs == -1 && !saw_usage) 938 else if (defunflag && maxargs == -1 && !saw_usage)
759 /* The DOC should provide the usage form. */ 939 /* The DOC should provide the usage form. */
760 fprintf (stderr, "Missing `usage' for function `%s'.\n", buf); 940 fprintf (stderr, "Missing `usage' for function `%s'.\n",
941 input_buffer);
761 } 942 }
762 } 943 }
763 eof: 944 eof:
@@ -801,7 +982,7 @@ scan_c_file (char *filename, const char *mode)
801 An entry is output only if DOCSTRING has \ newline just after the opening " 982 An entry is output only if DOCSTRING has \ newline just after the opening "
802 */ 983 */
803 984
804void 985static void
805skip_white (FILE *infile) 986skip_white (FILE *infile)
806{ 987{
807 char c = ' '; 988 char c = ' ';
@@ -810,7 +991,7 @@ skip_white (FILE *infile)
810 ungetc (c, infile); 991 ungetc (c, infile);
811} 992}
812 993
813void 994static void
814read_lisp_symbol (FILE *infile, char *buffer) 995read_lisp_symbol (FILE *infile, char *buffer)
815{ 996{
816 char c; 997 char c;
@@ -838,13 +1019,16 @@ read_lisp_symbol (FILE *infile, char *buffer)
838 skip_white (infile); 1019 skip_white (infile);
839} 1020}
840 1021
841int 1022static int
842scan_lisp_file (const char *filename, const char *mode) 1023scan_lisp_file (const char *filename, const char *mode)
843{ 1024{
844 FILE *infile; 1025 FILE *infile;
845 register int c; 1026 register int c;
846 char *saved_string = 0; 1027 char *saved_string = 0;
847 1028
1029 if (generate_globals)
1030 fatal ("scanning lisp file when -g specified", 0);
1031
848 infile = fopen (filename, mode); 1032 infile = fopen (filename, mode);
849 if (infile == NULL) 1033 if (infile == NULL)
850 { 1034 {