]> code.delx.au - gnu-emacs/blob - lib-src/make-docfile.c
Don't say Fnext_read_file_uses_dialog_p is const
[gnu-emacs] / lib-src / make-docfile.c
1 /* Generate doc-string file for GNU Emacs from source files.
2
3 Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2015 Free Software
4 Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20
21
22 /* The arguments given to this program are all the C and Lisp source files
23 of GNU Emacs. .elc and .el and .c files are allowed.
24 A .o file can also be specified; the .c file it was made from is used.
25 This helps the makefile pass the correct list of files.
26 Option -d DIR means change to DIR before looking for files.
27
28 The results, which go to standard output or to a file
29 specified with -a or -o (-a to append, -o to start from nothing),
30 are entries containing function or variable names and their documentation.
31 Each entry starts with a ^_ character.
32 Then comes F for a function or V for a variable.
33 Then comes the function or variable name, terminated with a newline.
34 Then comes the documentation for that function or variable.
35 */
36
37 #include <config.h>
38
39 #include <stdbool.h>
40 #include <stdio.h>
41 #include <stdlib.h> /* config.h unconditionally includes this anyway */
42
43 #ifdef WINDOWSNT
44 /* Defined to be sys_fopen in ms-w32.h, but only #ifdef emacs, so this
45 is really just insurance. */
46 #undef fopen
47 #include <direct.h>
48 #endif /* WINDOWSNT */
49
50 #include <binary-io.h>
51
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
59 #define IS_SLASH(c) ((c) == '/' || (c) == '\\' || (c) == ':')
60 #else /* not DOS_NT */
61 #define IS_SLASH(c) ((c) == '/')
62 #endif /* not DOS_NT */
63
64 static int scan_file (char *filename);
65 static int scan_lisp_file (const char *filename, const char *mode);
66 static int scan_c_file (char *filename, const char *mode);
67 static int scan_c_stream (FILE *infile);
68 static void start_globals (void);
69 static void write_globals (void);
70
71 #include <unistd.h>
72
73 /* Name this program was invoked with. */
74 char *progname;
75
76 /* Nonzero if this invocation is generating globals.h. */
77 int generate_globals;
78
79 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
80
81 /* VARARGS1 */
82 static void
83 error (const char *s1, const char *s2)
84 {
85 fprintf (stderr, "%s: ", progname);
86 fprintf (stderr, s1, s2);
87 fprintf (stderr, "\n");
88 }
89
90 /* Print error message and exit. */
91
92 /* VARARGS1 */
93 static _Noreturn void
94 fatal (const char *s1, const char *s2)
95 {
96 error (s1, s2);
97 exit (EXIT_FAILURE);
98 }
99
100 /* Like malloc but get fatal error if memory is exhausted. */
101
102 static void *
103 xmalloc (unsigned int size)
104 {
105 void *result = (void *) malloc (size);
106 if (result == NULL)
107 fatal ("virtual memory exhausted", 0);
108 return result;
109 }
110
111 /* Like strdup, but get fatal error if memory is exhausted. */
112
113 static char *
114 xstrdup (char *s)
115 {
116 char *result = strdup (s);
117 if (! result)
118 fatal ("virtual memory exhausted", 0);
119 return result;
120 }
121
122 /* Like realloc but get fatal error if memory is exhausted. */
123
124 static void *
125 xrealloc (void *arg, unsigned int size)
126 {
127 void *result = (void *) realloc (arg, size);
128 if (result == NULL)
129 fatal ("virtual memory exhausted", 0);
130 return result;
131 }
132
133 \f
134 int
135 main (int argc, char **argv)
136 {
137 int i;
138 int err_count = 0;
139
140 progname = argv[0];
141
142 /* If first two args are -o FILE, output to FILE. */
143 i = 1;
144 if (argc > i + 1 && !strcmp (argv[i], "-o"))
145 {
146 if (! freopen (argv[i + 1], "w", stdout))
147 {
148 perror (argv[i + 1]);
149 return EXIT_FAILURE;
150 }
151 i += 2;
152 }
153 if (argc > i + 1 && !strcmp (argv[i], "-a"))
154 {
155 if (! freopen (argv[i + 1], "a", stdout))
156 {
157 perror (argv[i + 1]);
158 return EXIT_FAILURE;
159 }
160 i += 2;
161 }
162 if (argc > i + 1 && !strcmp (argv[i], "-d"))
163 {
164 if (chdir (argv[i + 1]) != 0)
165 {
166 perror (argv[i + 1]);
167 return EXIT_FAILURE;
168 }
169 i += 2;
170 }
171 if (argc > i && !strcmp (argv[i], "-g"))
172 {
173 generate_globals = 1;
174 ++i;
175 }
176
177 set_binary_mode (fileno (stdout), O_BINARY);
178
179 if (generate_globals)
180 start_globals ();
181
182 if (argc <= i)
183 scan_c_stream (stdin);
184 else
185 {
186 int first_infile = i;
187 for (; i < argc; i++)
188 {
189 int j;
190 /* Don't process one file twice. */
191 for (j = first_infile; j < i; j++)
192 if (strcmp (argv[i], argv[j]) == 0)
193 break;
194 if (j == i)
195 err_count += scan_file (argv[i]);
196 }
197 }
198
199 if (err_count == 0 && generate_globals)
200 write_globals ();
201
202 return (err_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
203 }
204
205 /* Add a source file name boundary marker in the output file. */
206 static void
207 put_filename (char *filename)
208 {
209 char *tmp;
210
211 for (tmp = filename; *tmp; tmp++)
212 {
213 if (IS_DIRECTORY_SEP (*tmp))
214 filename = tmp + 1;
215 }
216
217 printf ("\037S%s\n", filename);
218 }
219
220 /* Read file FILENAME and output its doc strings to stdout.
221 Return 1 if file is not found, 0 if it is found. */
222
223 static int
224 scan_file (char *filename)
225 {
226
227 size_t len = strlen (filename);
228
229 if (!generate_globals)
230 put_filename (filename);
231 if (len > 4 && !strcmp (filename + len - 4, ".elc"))
232 return scan_lisp_file (filename, "rb");
233 else if (len > 3 && !strcmp (filename + len - 3, ".el"))
234 return scan_lisp_file (filename, "r");
235 else
236 return scan_c_file (filename, "r");
237 }
238
239 static void
240 start_globals (void)
241 {
242 puts ("/* This file was auto-generated by make-docfile. */");
243 puts ("/* DO NOT EDIT. */");
244 puts ("struct emacs_globals {");
245 }
246 \f
247 static char input_buffer[128];
248
249 /* Some state during the execution of `read_c_string_or_comment'. */
250 struct rcsoc_state
251 {
252 /* A count of spaces and newlines that have been read, but not output. */
253 unsigned pending_spaces, pending_newlines;
254
255 /* Where we're reading from. */
256 FILE *in_file;
257
258 /* If non-zero, a buffer into which to copy characters. */
259 char *buf_ptr;
260 /* If non-zero, a file into which to copy characters. */
261 FILE *out_file;
262
263 /* A keyword we look for at the beginning of lines. If found, it is
264 not copied, and SAW_KEYWORD is set to true. */
265 const char *keyword;
266 /* The current point we've reached in an occurrence of KEYWORD in
267 the input stream. */
268 const char *cur_keyword_ptr;
269 /* Set to true if we saw an occurrence of KEYWORD. */
270 int saw_keyword;
271 };
272
273 /* Output CH to the file or buffer in STATE. Any pending newlines or
274 spaces are output first. */
275
276 static void
277 put_char (int ch, struct rcsoc_state *state)
278 {
279 int out_ch;
280 do
281 {
282 if (state->pending_newlines > 0)
283 {
284 state->pending_newlines--;
285 out_ch = '\n';
286 }
287 else if (state->pending_spaces > 0)
288 {
289 state->pending_spaces--;
290 out_ch = ' ';
291 }
292 else
293 out_ch = ch;
294
295 if (state->out_file)
296 putc (out_ch, state->out_file);
297 if (state->buf_ptr)
298 *state->buf_ptr++ = out_ch;
299 }
300 while (out_ch != ch);
301 }
302
303 /* If in the middle of scanning a keyword, continue scanning with
304 character CH, otherwise output CH to the file or buffer in STATE.
305 Any pending newlines or spaces are output first, as well as any
306 previously scanned characters that were thought to be part of a
307 keyword, but were in fact not. */
308
309 static void
310 scan_keyword_or_put_char (int ch, struct rcsoc_state *state)
311 {
312 if (state->keyword
313 && *state->cur_keyword_ptr == ch
314 && (state->cur_keyword_ptr > state->keyword
315 || state->pending_newlines > 0))
316 /* We might be looking at STATE->keyword at some point.
317 Keep looking until we know for sure. */
318 {
319 if (*++state->cur_keyword_ptr == '\0')
320 /* Saw the whole keyword. Set SAW_KEYWORD flag to true. */
321 {
322 state->saw_keyword = 1;
323
324 /* Reset the scanning pointer. */
325 state->cur_keyword_ptr = state->keyword;
326
327 /* Canonicalize whitespace preceding a usage string. */
328 state->pending_newlines = 2;
329 state->pending_spaces = 0;
330
331 /* Skip any whitespace between the keyword and the
332 usage string. */
333 do
334 ch = getc (state->in_file);
335 while (ch == ' ' || ch == '\n');
336
337 /* Output the open-paren we just read. */
338 put_char (ch, state);
339
340 /* Skip the function name and replace it with `fn'. */
341 do
342 ch = getc (state->in_file);
343 while (ch != ' ' && ch != ')');
344 put_char ('f', state);
345 put_char ('n', state);
346
347 /* Put back the last character. */
348 ungetc (ch, state->in_file);
349 }
350 }
351 else
352 {
353 if (state->keyword && state->cur_keyword_ptr > state->keyword)
354 /* We scanned the beginning of a potential usage
355 keyword, but it was a false alarm. Output the
356 part we scanned. */
357 {
358 const char *p;
359
360 for (p = state->keyword; p < state->cur_keyword_ptr; p++)
361 put_char (*p, state);
362
363 state->cur_keyword_ptr = state->keyword;
364 }
365
366 put_char (ch, state);
367 }
368 }
369
370
371 /* Skip a C string or C-style comment from INFILE, and return the
372 character that follows. COMMENT non-zero means skip a comment. If
373 PRINTFLAG is positive, output string contents to stdout. If it is
374 negative, store contents in buf. Convert escape sequences \n and
375 \t to newline and tab; discard \ followed by newline.
376 If SAW_USAGE is non-zero, then any occurrences of the string `usage:'
377 at the beginning of a line will be removed, and *SAW_USAGE set to
378 true if any were encountered. */
379
380 static int
381 read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usage)
382 {
383 register int c;
384 struct rcsoc_state state;
385
386 state.in_file = infile;
387 state.buf_ptr = (printflag < 0 ? input_buffer : 0);
388 state.out_file = (printflag > 0 ? stdout : 0);
389 state.pending_spaces = 0;
390 state.pending_newlines = 0;
391 state.keyword = (saw_usage ? "usage:" : 0);
392 state.cur_keyword_ptr = state.keyword;
393 state.saw_keyword = 0;
394
395 c = getc (infile);
396 if (comment)
397 while (c == '\n' || c == '\r' || c == '\t' || c == ' ')
398 c = getc (infile);
399
400 while (c != EOF)
401 {
402 while (c != EOF && (comment ? c != '*' : c != '"'))
403 {
404 if (c == '\\')
405 {
406 c = getc (infile);
407 if (c == '\n' || c == '\r')
408 {
409 c = getc (infile);
410 continue;
411 }
412 if (c == 'n')
413 c = '\n';
414 if (c == 't')
415 c = '\t';
416 }
417
418 if (c == ' ')
419 state.pending_spaces++;
420 else if (c == '\n')
421 {
422 state.pending_newlines++;
423 state.pending_spaces = 0;
424 }
425 else
426 scan_keyword_or_put_char (c, &state);
427
428 c = getc (infile);
429 }
430
431 if (c != EOF)
432 c = getc (infile);
433
434 if (comment)
435 {
436 if (c == '/')
437 {
438 c = getc (infile);
439 break;
440 }
441
442 scan_keyword_or_put_char ('*', &state);
443 }
444 else
445 {
446 if (c != '"')
447 break;
448
449 /* If we had a "", concatenate the two strings. */
450 c = getc (infile);
451 }
452 }
453
454 if (printflag < 0)
455 *state.buf_ptr = 0;
456
457 if (saw_usage)
458 *saw_usage = state.saw_keyword;
459
460 return c;
461 }
462
463
464 \f
465 /* Write to stdout the argument names of function FUNC, whose text is in BUF.
466 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
467
468 static void
469 write_c_args (char *func, char *buf, int minargs, int maxargs)
470 {
471 register char *p;
472 int in_ident = 0;
473 char *ident_start IF_LINT (= NULL);
474 size_t ident_length = 0;
475
476 fputs ("(fn", stdout);
477
478 if (*buf == '(')
479 ++buf;
480
481 for (p = buf; *p; p++)
482 {
483 char c = *p;
484
485 /* Notice when a new identifier starts. */
486 if ((('A' <= c && c <= 'Z')
487 || ('a' <= c && c <= 'z')
488 || ('0' <= c && c <= '9')
489 || c == '_')
490 != in_ident)
491 {
492 if (!in_ident)
493 {
494 in_ident = 1;
495 ident_start = p;
496 }
497 else
498 {
499 in_ident = 0;
500 ident_length = p - ident_start;
501 }
502 }
503
504 /* Found the end of an argument, write out the last seen
505 identifier. */
506 if (c == ',' || c == ')')
507 {
508 if (ident_length == 0)
509 {
510 error ("empty arg list for `%s' should be (void), not ()", func);
511 continue;
512 }
513
514 if (strncmp (ident_start, "void", ident_length) == 0)
515 continue;
516
517 putchar (' ');
518
519 if (minargs == 0 && maxargs > 0)
520 fputs ("&optional ", stdout);
521
522 minargs--;
523 maxargs--;
524
525 /* In C code, `default' is a reserved word, so we spell it
526 `defalt'; demangle that here. */
527 if (ident_length == 6 && memcmp (ident_start, "defalt", 6) == 0)
528 fputs ("DEFAULT", stdout);
529 else
530 while (ident_length-- > 0)
531 {
532 c = *ident_start++;
533 if (c >= 'a' && c <= 'z')
534 /* Upcase the letter. */
535 c += 'A' - 'a';
536 else if (c == '_')
537 /* Print underscore as hyphen. */
538 c = '-';
539 putchar (c);
540 }
541 }
542 }
543
544 putchar (')');
545 }
546 \f
547 /* The types of globals. These are sorted roughly in decreasing alignment
548 order to avoid allocation gaps, except that symbols and functions
549 are last. */
550 enum global_type
551 {
552 INVALID,
553 LISP_OBJECT,
554 EMACS_INTEGER,
555 BOOLEAN,
556 SYMBOL,
557 FUNCTION
558 };
559
560 /* A single global. */
561 struct global
562 {
563 enum global_type type;
564 char *name;
565 int flags;
566 union
567 {
568 int value;
569 char const *svalue;
570 } v;
571 };
572
573 /* Bit values for FLAGS field from the above. Applied for DEFUNs only. */
574 enum { DEFUN_noreturn = 1, DEFUN_const = 2 };
575
576 /* All the variable names we saw while scanning C sources in `-g'
577 mode. */
578 int num_globals;
579 int num_globals_allocated;
580 struct global *globals;
581
582 static struct global *
583 add_global (enum global_type type, char *name, int value, char const *svalue)
584 {
585 /* Ignore the one non-symbol that can occur. */
586 if (strcmp (name, "..."))
587 {
588 ++num_globals;
589
590 if (num_globals_allocated == 0)
591 {
592 num_globals_allocated = 100;
593 globals = xmalloc (num_globals_allocated * sizeof (struct global));
594 }
595 else if (num_globals == num_globals_allocated)
596 {
597 num_globals_allocated *= 2;
598 globals = xrealloc (globals,
599 num_globals_allocated * sizeof (struct global));
600 }
601
602 globals[num_globals - 1].type = type;
603 globals[num_globals - 1].name = name;
604 if (svalue)
605 globals[num_globals - 1].v.svalue = svalue;
606 else
607 globals[num_globals - 1].v.value = value;
608 globals[num_globals - 1].flags = 0;
609 return globals + num_globals - 1;
610 }
611 return NULL;
612 }
613
614 static int
615 compare_globals (const void *a, const void *b)
616 {
617 const struct global *ga = a;
618 const struct global *gb = b;
619
620 if (ga->type != gb->type)
621 return ga->type - gb->type;
622
623 /* Consider "nil" to be the least, so that iQnil is zero. That
624 way, Qnil's internal representation is zero, which is a bit faster. */
625 if (ga->type == SYMBOL)
626 {
627 bool a_nil = strcmp (ga->name, "Qnil") == 0;
628 bool b_nil = strcmp (gb->name, "Qnil") == 0;
629 if (a_nil | b_nil)
630 return b_nil - a_nil;
631 }
632
633 return strcmp (ga->name, gb->name);
634 }
635
636 static void
637 close_emacs_globals (int num_symbols)
638 {
639 printf (("};\n"
640 "extern struct emacs_globals globals;\n"
641 "\n"
642 "#ifndef DEFINE_SYMBOLS\n"
643 "extern\n"
644 "#endif\n"
645 "struct Lisp_Symbol alignas (GCALIGNMENT) lispsym[%d];\n"),
646 num_symbols);
647 }
648
649 static void
650 write_globals (void)
651 {
652 int i, j;
653 bool seen_defun = false;
654 int symnum = 0;
655 int num_symbols = 0;
656 qsort (globals, num_globals, sizeof (struct global), compare_globals);
657
658 j = 0;
659 for (i = 0; i < num_globals; i++)
660 {
661 while (i + 1 < num_globals
662 && strcmp (globals[i].name, globals[i + 1].name) == 0)
663 {
664 if (globals[i].type == FUNCTION
665 && globals[i].v.value != globals[i + 1].v.value)
666 error ("function '%s' defined twice with differing signatures",
667 globals[i].name);
668 i++;
669 }
670 num_symbols += globals[i].type == SYMBOL;
671 globals[j++] = globals[i];
672 }
673 num_globals = j;
674
675 for (i = 0; i < num_globals; ++i)
676 {
677 char const *type = 0;
678
679 switch (globals[i].type)
680 {
681 case EMACS_INTEGER:
682 type = "EMACS_INT";
683 break;
684 case BOOLEAN:
685 type = "bool";
686 break;
687 case LISP_OBJECT:
688 type = "Lisp_Object";
689 break;
690 case SYMBOL:
691 case FUNCTION:
692 if (!seen_defun)
693 {
694 close_emacs_globals (num_symbols);
695 putchar ('\n');
696 seen_defun = true;
697 }
698 break;
699 default:
700 fatal ("not a recognized DEFVAR_", 0);
701 }
702
703 if (type)
704 {
705 printf (" %s f_%s;\n", type, globals[i].name);
706 printf ("#define %s globals.f_%s\n",
707 globals[i].name, globals[i].name);
708 }
709 else if (globals[i].type == SYMBOL)
710 printf (("DEFINE_LISP_SYMBOL_BEGIN (%s)\n"
711 "#define i%s %d\n"
712 "#define %s builtin_lisp_symbol (i%s)\n"
713 "DEFINE_LISP_SYMBOL_END (%s)\n\n"),
714 globals[i].name, globals[i].name, symnum++,
715 globals[i].name, globals[i].name, globals[i].name);
716 else
717 {
718 if (globals[i].flags & DEFUN_noreturn)
719 fputs ("_Noreturn ", stdout);
720
721 printf ("EXFUN (%s, ", globals[i].name);
722 if (globals[i].v.value == -1)
723 fputs ("MANY", stdout);
724 else if (globals[i].v.value == -2)
725 fputs ("UNEVALLED", stdout);
726 else
727 printf ("%d", globals[i].v.value);
728 putchar (')');
729
730 if (globals[i].flags & DEFUN_const)
731 fputs (" ATTRIBUTE_CONST", stdout);
732 else if (strcmp (globals[i].name, "Fnext_read_file_uses_dialog_p")
733 == 0)
734 {
735 /* It would be nice to have a cleaner way to deal with this
736 special hack. */
737 fputs (("\n"
738 "#if ! (defined USE_GTK || defined USE_MOTIF \\\n"
739 " || defined HAVE_NS || defined HAVE_NTGUI)\n"
740 "\tATTRIBUTE_CONST\n"
741 "#endif\n"),
742 stdout);
743 }
744
745 puts (";");
746 }
747 }
748
749 if (!seen_defun)
750 close_emacs_globals (num_symbols);
751
752 puts ("#ifdef DEFINE_SYMBOLS");
753 puts ("static char const *const defsym_name[] = {");
754 for (int i = 0; i < num_globals; i++)
755 {
756 if (globals[i].type == SYMBOL)
757 printf ("\t\"%s\",\n", globals[i].v.svalue);
758 while (i + 1 < num_globals
759 && strcmp (globals[i].name, globals[i + 1].name) == 0)
760 i++;
761 }
762 puts ("};");
763 puts ("#endif");
764 }
765
766 \f
767 /* Read through a c file. If a .o file is named,
768 the corresponding .c or .m file is read instead.
769 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
770 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
771
772 static int
773 scan_c_file (char *filename, const char *mode)
774 {
775 FILE *infile;
776 int extension = filename[strlen (filename) - 1];
777
778 if (extension == 'o')
779 filename[strlen (filename) - 1] = 'c';
780
781 infile = fopen (filename, mode);
782
783 if (infile == NULL && extension == 'o')
784 {
785 /* Try .m. */
786 filename[strlen (filename) - 1] = 'm';
787 infile = fopen (filename, mode);
788 if (infile == NULL)
789 filename[strlen (filename) - 1] = 'c'; /* Don't confuse people. */
790 }
791
792 /* No error if non-ex input file. */
793 if (infile == NULL)
794 {
795 perror (filename);
796 return 0;
797 }
798
799 /* Reset extension to be able to detect duplicate files. */
800 filename[strlen (filename) - 1] = extension;
801 return scan_c_stream (infile);
802 }
803
804 /* Return 1 if next input from INFILE is equal to P, -1 if EOF,
805 0 if input doesn't match. */
806
807 static int
808 stream_match (FILE *infile, const char *p)
809 {
810 for (; *p; p++)
811 {
812 int c = getc (infile);
813 if (c == EOF)
814 return -1;
815 if (c != *p)
816 return 0;
817 }
818 return 1;
819 }
820
821 static int
822 scan_c_stream (FILE *infile)
823 {
824 int commas, minargs, maxargs;
825 int c = '\n';
826
827 while (!feof (infile))
828 {
829 int doc_keyword = 0;
830 int defunflag = 0;
831 int defvarperbufferflag = 0;
832 int defvarflag = 0;
833 enum global_type type = INVALID;
834 char *name IF_LINT (= 0);
835
836 if (c != '\n' && c != '\r')
837 {
838 c = getc (infile);
839 continue;
840 }
841 c = getc (infile);
842 if (c == ' ')
843 {
844 while (c == ' ')
845 c = getc (infile);
846 if (c != 'D')
847 continue;
848 c = getc (infile);
849 if (c != 'E')
850 continue;
851 c = getc (infile);
852 if (c != 'F')
853 continue;
854 c = getc (infile);
855 if (c == 'S')
856 {
857 c = getc (infile);
858 if (c != 'Y')
859 continue;
860 c = getc (infile);
861 if (c != 'M')
862 continue;
863 c = getc (infile);
864 if (c != ' ' && c != '\t' && c != '(')
865 continue;
866 type = SYMBOL;
867 }
868 else if (c == 'V')
869 {
870 c = getc (infile);
871 if (c != 'A')
872 continue;
873 c = getc (infile);
874 if (c != 'R')
875 continue;
876 c = getc (infile);
877 if (c != '_')
878 continue;
879
880 defvarflag = 1;
881
882 c = getc (infile);
883 defvarperbufferflag = (c == 'P');
884 if (generate_globals)
885 {
886 if (c == 'I')
887 type = EMACS_INTEGER;
888 else if (c == 'L')
889 type = LISP_OBJECT;
890 else if (c == 'B')
891 type = BOOLEAN;
892 }
893
894 c = getc (infile);
895 /* We need to distinguish between DEFVAR_BOOL and
896 DEFVAR_BUFFER_DEFAULTS. */
897 if (generate_globals && type == BOOLEAN && c != 'O')
898 type = INVALID;
899 }
900 else
901 continue;
902 }
903 else if (c == 'D')
904 {
905 c = getc (infile);
906 if (c != 'E')
907 continue;
908 c = getc (infile);
909 if (c != 'F')
910 continue;
911 c = getc (infile);
912 defunflag = c == 'U';
913 }
914 else continue;
915
916 if (generate_globals
917 && (!defvarflag || defvarperbufferflag || type == INVALID)
918 && !defunflag && type != SYMBOL)
919 continue;
920
921 while (c != '(')
922 {
923 if (c < 0)
924 goto eof;
925 c = getc (infile);
926 }
927
928 if (type != SYMBOL)
929 {
930 /* Lisp variable or function name. */
931 c = getc (infile);
932 if (c != '"')
933 continue;
934 c = read_c_string_or_comment (infile, -1, 0, 0);
935 }
936
937 if (generate_globals)
938 {
939 int i = 0;
940 char const *svalue = 0;
941
942 /* Skip "," and whitespace. */
943 do
944 {
945 c = getc (infile);
946 }
947 while (c == ',' || c == ' ' || c == '\t' || c == '\n' || c == '\r');
948
949 /* Read in the identifier. */
950 do
951 {
952 if (c < 0)
953 goto eof;
954 input_buffer[i++] = c;
955 c = getc (infile);
956 }
957 while (! (c == ',' || c == ' ' || c == '\t'
958 || c == '\n' || c == '\r'));
959 input_buffer[i] = '\0';
960
961 name = xmalloc (i + 1);
962 memcpy (name, input_buffer, i + 1);
963
964 if (type == SYMBOL)
965 {
966 do
967 c = getc (infile);
968 while (c == ' ' || c == '\t' || c == '\n' || c == '\r');
969 if (c != '"')
970 continue;
971 c = read_c_string_or_comment (infile, -1, 0, 0);
972 svalue = xstrdup (input_buffer);
973 }
974
975 if (!defunflag)
976 {
977 add_global (type, name, 0, svalue);
978 continue;
979 }
980 }
981
982 if (type == SYMBOL)
983 continue;
984
985 /* DEFVAR_LISP ("name", addr, "doc")
986 DEFVAR_LISP ("name", addr /\* doc *\/)
987 DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */
988
989 if (defunflag)
990 commas = generate_globals ? 4 : 5;
991 else if (defvarperbufferflag)
992 commas = 3;
993 else if (defvarflag)
994 commas = 1;
995 else /* For DEFSIMPLE and DEFPRED. */
996 commas = 2;
997
998 while (commas)
999 {
1000 if (c == ',')
1001 {
1002 commas--;
1003
1004 if (defunflag && (commas == 1 || commas == 2))
1005 {
1006 int scanned = 0;
1007 do
1008 c = getc (infile);
1009 while (c == ' ' || c == '\n' || c == '\r' || c == '\t');
1010 if (c < 0)
1011 goto eof;
1012 ungetc (c, infile);
1013 if (commas == 2) /* Pick up minargs. */
1014 scanned = fscanf (infile, "%d", &minargs);
1015 else /* Pick up maxargs. */
1016 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
1017 {
1018 if (generate_globals)
1019 maxargs = (c == 'M') ? -1 : -2;
1020 else
1021 maxargs = -1;
1022 }
1023 else
1024 scanned = fscanf (infile, "%d", &maxargs);
1025 if (scanned < 0)
1026 goto eof;
1027 }
1028 }
1029
1030 if (c == EOF)
1031 goto eof;
1032 c = getc (infile);
1033 }
1034
1035 if (generate_globals)
1036 {
1037 struct global *g = add_global (FUNCTION, name, maxargs, 0);
1038
1039 /* The following code tries to recognize function attributes
1040 specified after the docstring, e.g.:
1041
1042 DEFUN ("foo", Ffoo, Sfoo, X, Y, Z,
1043 doc: /\* doc *\/
1044 attributes: attribute1 attribute2 ...)
1045 (Lisp_Object arg...)
1046
1047 Now only 'noreturn' and 'const' attributes are used. */
1048
1049 /* Advance to the end of docstring. */
1050 c = getc (infile);
1051 if (c == EOF)
1052 goto eof;
1053 int d = getc (infile);
1054 if (d == EOF)
1055 goto eof;
1056 while (1)
1057 {
1058 if (c == '*' && d == '/')
1059 break;
1060 c = d, d = getc (infile);
1061 if (d == EOF)
1062 goto eof;
1063 }
1064 /* Skip spaces, if any. */
1065 do
1066 {
1067 c = getc (infile);
1068 if (c == EOF)
1069 goto eof;
1070 }
1071 while (c == ' ' || c == '\n' || c == '\r' || c == '\t');
1072 /* Check for 'attributes:' token. */
1073 if (c == 'a' && stream_match (infile, "ttributes:"))
1074 {
1075 char *p = input_buffer;
1076 /* Collect attributes up to ')'. */
1077 while (1)
1078 {
1079 c = getc (infile);
1080 if (c == EOF)
1081 goto eof;
1082 if (c == ')')
1083 break;
1084 if (p - input_buffer > sizeof (input_buffer))
1085 abort ();
1086 *p++ = c;
1087 }
1088 *p = 0;
1089 if (strstr (input_buffer, "noreturn"))
1090 g->flags |= DEFUN_noreturn;
1091 if (strstr (input_buffer, "const"))
1092 g->flags |= DEFUN_const;
1093 }
1094 continue;
1095 }
1096
1097 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
1098 c = getc (infile);
1099
1100 if (c == '"')
1101 c = read_c_string_or_comment (infile, 0, 0, 0);
1102
1103 while (c != EOF && c != ',' && c != '/')
1104 c = getc (infile);
1105 if (c == ',')
1106 {
1107 c = getc (infile);
1108 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
1109 c = getc (infile);
1110 while ((c >= 'a' && c <= 'z') || (c >= 'Z' && c <= 'Z'))
1111 c = getc (infile);
1112 if (c == ':')
1113 {
1114 doc_keyword = 1;
1115 c = getc (infile);
1116 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
1117 c = getc (infile);
1118 }
1119 }
1120
1121 if (c == '"'
1122 || (c == '/'
1123 && (c = getc (infile),
1124 ungetc (c, infile),
1125 c == '*')))
1126 {
1127 int comment = c != '"';
1128 int saw_usage;
1129
1130 printf ("\037%c%s\n", defvarflag ? 'V' : 'F', input_buffer);
1131
1132 if (comment)
1133 getc (infile); /* Skip past `*'. */
1134 c = read_c_string_or_comment (infile, 1, comment, &saw_usage);
1135
1136 /* If this is a defun, find the arguments and print them. If
1137 this function takes MANY or UNEVALLED args, then the C source
1138 won't give the names of the arguments, so we shouldn't bother
1139 trying to find them.
1140
1141 Various doc-string styles:
1142 0: DEFUN (..., "DOC") (args) [!comment]
1143 1: DEFUN (..., /\* DOC *\/ (args)) [comment && !doc_keyword]
1144 2: DEFUN (..., doc: /\* DOC *\/) (args) [comment && doc_keyword]
1145 */
1146 if (defunflag && maxargs != -1 && !saw_usage)
1147 {
1148 char argbuf[1024], *p = argbuf;
1149
1150 if (!comment || doc_keyword)
1151 while (c != ')')
1152 {
1153 if (c < 0)
1154 goto eof;
1155 c = getc (infile);
1156 }
1157
1158 /* Skip into arguments. */
1159 while (c != '(')
1160 {
1161 if (c < 0)
1162 goto eof;
1163 c = getc (infile);
1164 }
1165 /* Copy arguments into ARGBUF. */
1166 *p++ = c;
1167 do
1168 *p++ = c = getc (infile);
1169 while (c != ')');
1170 *p = '\0';
1171 /* Output them. */
1172 fputs ("\n\n", stdout);
1173 write_c_args (input_buffer, argbuf, minargs, maxargs);
1174 }
1175 else if (defunflag && maxargs == -1 && !saw_usage)
1176 /* The DOC should provide the usage form. */
1177 fprintf (stderr, "Missing `usage' for function `%s'.\n",
1178 input_buffer);
1179 }
1180 }
1181 eof:
1182 fclose (infile);
1183 return 0;
1184 }
1185 \f
1186 /* Read a file of Lisp code, compiled or interpreted.
1187 Looks for
1188 (defun NAME ARGS DOCSTRING ...)
1189 (defmacro NAME ARGS DOCSTRING ...)
1190 (defsubst NAME ARGS DOCSTRING ...)
1191 (autoload (quote NAME) FILE DOCSTRING ...)
1192 (defvar NAME VALUE DOCSTRING)
1193 (defconst NAME VALUE DOCSTRING)
1194 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
1195 (fset (quote NAME) #[... DOCSTRING ...])
1196 (defalias (quote NAME) #[... DOCSTRING ...])
1197 (custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
1198 starting in column zero.
1199 (quote NAME) may appear as 'NAME as well.
1200
1201 We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
1202 When we find that, we save it for the following defining-form,
1203 and we use that instead of reading a doc string within that defining-form.
1204
1205 For defvar, defconst, and fset we skip to the docstring with a kludgy
1206 formatting convention: all docstrings must appear on the same line as the
1207 initial open-paren (the one in column zero) and must contain a backslash
1208 and a newline immediately after the initial double-quote. No newlines
1209 must appear between the beginning of the form and the first double-quote.
1210 For defun, defmacro, and autoload, we know how to skip over the
1211 arglist, but the doc string must still have a backslash and newline
1212 immediately after the double quote.
1213 The only source files that must follow this convention are preloaded
1214 uncompiled ones like loaddefs.el; aside from that, it is always the .elc
1215 file that we should look at, and they are no problem because byte-compiler
1216 output follows this convention.
1217 The NAME and DOCSTRING are output.
1218 NAME is preceded by `F' for a function or `V' for a variable.
1219 An entry is output only if DOCSTRING has \ newline just after the opening ".
1220 */
1221
1222 static void
1223 skip_white (FILE *infile)
1224 {
1225 char c = ' ';
1226 while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
1227 c = getc (infile);
1228 ungetc (c, infile);
1229 }
1230
1231 static void
1232 read_lisp_symbol (FILE *infile, char *buffer)
1233 {
1234 char c;
1235 char *fillp = buffer;
1236
1237 skip_white (infile);
1238 while (1)
1239 {
1240 c = getc (infile);
1241 if (c == '\\')
1242 *(++fillp) = getc (infile);
1243 else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '(' || c == ')')
1244 {
1245 ungetc (c, infile);
1246 *fillp = 0;
1247 break;
1248 }
1249 else
1250 *fillp++ = c;
1251 }
1252
1253 if (! buffer[0])
1254 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
1255
1256 skip_white (infile);
1257 }
1258
1259 static int
1260 search_lisp_doc_at_eol (FILE *infile)
1261 {
1262 int c = 0, c1 = 0, c2 = 0;
1263
1264 /* Skip until the end of line; remember two previous chars. */
1265 while (c != '\n' && c != '\r' && c != EOF)
1266 {
1267 c2 = c1;
1268 c1 = c;
1269 c = getc (infile);
1270 }
1271
1272 /* If two previous characters were " and \,
1273 this is a doc string. Otherwise, there is none. */
1274 if (c2 != '"' || c1 != '\\')
1275 {
1276 #ifdef DEBUG
1277 fprintf (stderr, "## non-docstring found\n");
1278 #endif
1279 if (c != EOF)
1280 ungetc (c, infile);
1281 return 0;
1282 }
1283 return 1;
1284 }
1285
1286 #define DEF_ELISP_FILE(fn) { #fn, sizeof(#fn) - 1 }
1287
1288 static int
1289 scan_lisp_file (const char *filename, const char *mode)
1290 {
1291 FILE *infile;
1292 register int c;
1293 char *saved_string = 0;
1294 /* These are the only files that are loaded uncompiled, and must
1295 follow the conventions of the doc strings expected by this
1296 function. These conventions are automatically followed by the
1297 byte compiler when it produces the .elc files. */
1298 static struct {
1299 const char *fn;
1300 size_t fl;
1301 } const uncompiled[] = {
1302 DEF_ELISP_FILE (loaddefs.el),
1303 DEF_ELISP_FILE (loadup.el),
1304 DEF_ELISP_FILE (charprop.el),
1305 DEF_ELISP_FILE (cp51932.el),
1306 DEF_ELISP_FILE (eucjp-ms.el)
1307 };
1308 int i, match;
1309 size_t flen = strlen (filename);
1310
1311 if (generate_globals)
1312 fatal ("scanning lisp file when -g specified", 0);
1313 if (flen > 3 && !strcmp (filename + flen - 3, ".el"))
1314 {
1315 for (i = 0, match = 0; i < sizeof (uncompiled) / sizeof (uncompiled[0]);
1316 i++)
1317 {
1318 if (uncompiled[i].fl <= flen
1319 && !strcmp (filename + flen - uncompiled[i].fl, uncompiled[i].fn)
1320 && (flen == uncompiled[i].fl
1321 || IS_SLASH (filename[flen - uncompiled[i].fl - 1])))
1322 {
1323 match = 1;
1324 break;
1325 }
1326 }
1327 if (!match)
1328 fatal ("uncompiled lisp file %s is not supported", filename);
1329 }
1330
1331 infile = fopen (filename, mode);
1332 if (infile == NULL)
1333 {
1334 perror (filename);
1335 return 0; /* No error. */
1336 }
1337
1338 c = '\n';
1339 while (!feof (infile))
1340 {
1341 char buffer[BUFSIZ];
1342 char type;
1343
1344 /* If not at end of line, skip till we get to one. */
1345 if (c != '\n' && c != '\r')
1346 {
1347 c = getc (infile);
1348 continue;
1349 }
1350 /* Skip the line break. */
1351 while (c == '\n' || c == '\r')
1352 c = getc (infile);
1353 /* Detect a dynamic doc string and save it for the next expression. */
1354 if (c == '#')
1355 {
1356 c = getc (infile);
1357 if (c == '@')
1358 {
1359 size_t length = 0;
1360 size_t i;
1361
1362 /* Read the length. */
1363 while ((c = getc (infile),
1364 c >= '0' && c <= '9'))
1365 {
1366 length *= 10;
1367 length += c - '0';
1368 }
1369
1370 if (length <= 1)
1371 fatal ("invalid dynamic doc string length", "");
1372
1373 if (c != ' ')
1374 fatal ("space not found after dynamic doc string length", "");
1375
1376 /* The next character is a space that is counted in the length
1377 but not part of the doc string.
1378 We already read it, so just ignore it. */
1379 length--;
1380
1381 /* Read in the contents. */
1382 free (saved_string);
1383 saved_string = (char *) xmalloc (length);
1384 for (i = 0; i < length; i++)
1385 saved_string[i] = getc (infile);
1386 /* The last character is a ^_.
1387 That is needed in the .elc file
1388 but it is redundant in DOC. So get rid of it here. */
1389 saved_string[length - 1] = 0;
1390 /* Skip the line break. */
1391 while (c == '\n' || c == '\r')
1392 c = getc (infile);
1393 /* Skip the following line. */
1394 while (c != '\n' && c != '\r')
1395 c = getc (infile);
1396 }
1397 continue;
1398 }
1399
1400 if (c != '(')
1401 continue;
1402
1403 read_lisp_symbol (infile, buffer);
1404
1405 if (! strcmp (buffer, "defun")
1406 || ! strcmp (buffer, "defmacro")
1407 || ! strcmp (buffer, "defsubst"))
1408 {
1409 type = 'F';
1410 read_lisp_symbol (infile, buffer);
1411
1412 /* Skip the arguments: either "nil" or a list in parens. */
1413
1414 c = getc (infile);
1415 if (c == 'n') /* nil */
1416 {
1417 if ((c = getc (infile)) != 'i'
1418 || (c = getc (infile)) != 'l')
1419 {
1420 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
1421 buffer, filename);
1422 continue;
1423 }
1424 }
1425 else if (c != '(')
1426 {
1427 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
1428 buffer, filename);
1429 continue;
1430 }
1431 else
1432 while (c != ')')
1433 c = getc (infile);
1434 skip_white (infile);
1435
1436 /* If the next three characters aren't `dquote bslash newline'
1437 then we're not reading a docstring.
1438 */
1439 if ((c = getc (infile)) != '"'
1440 || (c = getc (infile)) != '\\'
1441 || ((c = getc (infile)) != '\n' && c != '\r'))
1442 {
1443 #ifdef DEBUG
1444 fprintf (stderr, "## non-docstring in %s (%s)\n",
1445 buffer, filename);
1446 #endif
1447 continue;
1448 }
1449 }
1450
1451 /* defcustom can only occur in uncompiled Lisp files. */
1452 else if (! strcmp (buffer, "defvar")
1453 || ! strcmp (buffer, "defconst")
1454 || ! strcmp (buffer, "defcustom"))
1455 {
1456 type = 'V';
1457 read_lisp_symbol (infile, buffer);
1458
1459 if (saved_string == 0)
1460 if (!search_lisp_doc_at_eol (infile))
1461 continue;
1462 }
1463
1464 else if (! strcmp (buffer, "custom-declare-variable")
1465 || ! strcmp (buffer, "defvaralias")
1466 )
1467 {
1468 type = 'V';
1469
1470 c = getc (infile);
1471 if (c == '\'')
1472 read_lisp_symbol (infile, buffer);
1473 else
1474 {
1475 if (c != '(')
1476 {
1477 fprintf (stderr,
1478 "## unparsable name in custom-declare-variable in %s\n",
1479 filename);
1480 continue;
1481 }
1482 read_lisp_symbol (infile, buffer);
1483 if (strcmp (buffer, "quote"))
1484 {
1485 fprintf (stderr,
1486 "## unparsable name in custom-declare-variable in %s\n",
1487 filename);
1488 continue;
1489 }
1490 read_lisp_symbol (infile, buffer);
1491 c = getc (infile);
1492 if (c != ')')
1493 {
1494 fprintf (stderr,
1495 "## unparsable quoted name in custom-declare-variable in %s\n",
1496 filename);
1497 continue;
1498 }
1499 }
1500
1501 if (saved_string == 0)
1502 if (!search_lisp_doc_at_eol (infile))
1503 continue;
1504 }
1505
1506 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
1507 {
1508 type = 'F';
1509
1510 c = getc (infile);
1511 if (c == '\'')
1512 read_lisp_symbol (infile, buffer);
1513 else
1514 {
1515 if (c != '(')
1516 {
1517 fprintf (stderr, "## unparsable name in fset in %s\n",
1518 filename);
1519 continue;
1520 }
1521 read_lisp_symbol (infile, buffer);
1522 if (strcmp (buffer, "quote"))
1523 {
1524 fprintf (stderr, "## unparsable name in fset in %s\n",
1525 filename);
1526 continue;
1527 }
1528 read_lisp_symbol (infile, buffer);
1529 c = getc (infile);
1530 if (c != ')')
1531 {
1532 fprintf (stderr,
1533 "## unparsable quoted name in fset in %s\n",
1534 filename);
1535 continue;
1536 }
1537 }
1538
1539 if (saved_string == 0)
1540 if (!search_lisp_doc_at_eol (infile))
1541 continue;
1542 }
1543
1544 else if (! strcmp (buffer, "autoload"))
1545 {
1546 type = 'F';
1547 c = getc (infile);
1548 if (c == '\'')
1549 read_lisp_symbol (infile, buffer);
1550 else
1551 {
1552 if (c != '(')
1553 {
1554 fprintf (stderr, "## unparsable name in autoload in %s\n",
1555 filename);
1556 continue;
1557 }
1558 read_lisp_symbol (infile, buffer);
1559 if (strcmp (buffer, "quote"))
1560 {
1561 fprintf (stderr, "## unparsable name in autoload in %s\n",
1562 filename);
1563 continue;
1564 }
1565 read_lisp_symbol (infile, buffer);
1566 c = getc (infile);
1567 if (c != ')')
1568 {
1569 fprintf (stderr,
1570 "## unparsable quoted name in autoload in %s\n",
1571 filename);
1572 continue;
1573 }
1574 }
1575 skip_white (infile);
1576 if ((c = getc (infile)) != '\"')
1577 {
1578 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
1579 buffer, filename);
1580 continue;
1581 }
1582 read_c_string_or_comment (infile, 0, 0, 0);
1583
1584 if (saved_string == 0)
1585 if (!search_lisp_doc_at_eol (infile))
1586 continue;
1587 }
1588
1589 #ifdef DEBUG
1590 else if (! strcmp (buffer, "if")
1591 || ! strcmp (buffer, "byte-code"))
1592 continue;
1593 #endif
1594
1595 else
1596 {
1597 #ifdef DEBUG
1598 fprintf (stderr, "## unrecognized top-level form, %s (%s)\n",
1599 buffer, filename);
1600 #endif
1601 continue;
1602 }
1603
1604 /* At this point, we should either use the previous dynamic doc string in
1605 saved_string or gobble a doc string from the input file.
1606 In the latter case, the opening quote (and leading backslash-newline)
1607 have already been read. */
1608
1609 printf ("\037%c%s\n", type, buffer);
1610 if (saved_string)
1611 {
1612 fputs (saved_string, stdout);
1613 /* Don't use one dynamic doc string twice. */
1614 free (saved_string);
1615 saved_string = 0;
1616 }
1617 else
1618 read_c_string_or_comment (infile, 1, 0, 0);
1619 }
1620 fclose (infile);
1621 return 0;
1622 }
1623
1624
1625 /* make-docfile.c ends here */