]> code.delx.au - gnu-emacs/blob - lib-src/make-docfile.c
Merge from emacs-24; up to 2012-05-02T11:38:01Z!lekktu@gmail.com
[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-2012
4 Free Software 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 <stdio.h>
40 #include <stdlib.h> /* config.h unconditionally includes this anyway */
41 #ifdef MSDOS
42 #include <fcntl.h>
43 #endif /* MSDOS */
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
48 #include <fcntl.h>
49 #include <direct.h>
50 #endif /* WINDOWSNT */
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 READ_TEXT "rt"
60 #define READ_BINARY "rb"
61 #else /* not DOS_NT */
62 #define READ_TEXT "r"
63 #define READ_BINARY "r"
64 #endif /* not DOS_NT */
65
66 static int scan_file (char *filename);
67 static int scan_lisp_file (const char *filename, const char *mode);
68 static int scan_c_file (char *filename, const char *mode);
69 static void start_globals (void);
70 static void write_globals (void);
71
72 #include <unistd.h>
73
74 /* Stdio stream for output to the DOC file. */
75 FILE *outfile;
76
77 /* Name this program was invoked with. */
78 char *progname;
79
80 /* Nonzero if this invocation is generating globals.h. */
81 int generate_globals;
82
83 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
84
85 /* VARARGS1 */
86 static void
87 error (const char *s1, const char *s2)
88 {
89 fprintf (stderr, "%s: ", progname);
90 fprintf (stderr, s1, s2);
91 fprintf (stderr, "\n");
92 }
93
94 /* Print error message and exit. */
95
96 /* VARARGS1 */
97 static _Noreturn void
98 fatal (const char *s1, const char *s2)
99 {
100 error (s1, s2);
101 exit (EXIT_FAILURE);
102 }
103
104 /* Like malloc but get fatal error if memory is exhausted. */
105
106 static void *
107 xmalloc (unsigned int size)
108 {
109 void *result = (void *) malloc (size);
110 if (result == NULL)
111 fatal ("virtual memory exhausted", 0);
112 return result;
113 }
114
115 /* Like realloc but get fatal error if memory is exhausted. */
116
117 static void *
118 xrealloc (void *arg, unsigned int size)
119 {
120 void *result = (void *) realloc (arg, size);
121 if (result == NULL)
122 fatal ("virtual memory exhausted", 0);
123 return result;
124 }
125
126 \f
127 int
128 main (int argc, char **argv)
129 {
130 int i;
131 int err_count = 0;
132 int first_infile;
133
134 progname = argv[0];
135
136 outfile = stdout;
137
138 /* Don't put CRs in the DOC file. */
139 #ifdef MSDOS
140 _fmode = O_BINARY;
141 #if 0 /* Suspicion is that this causes hanging.
142 So instead we require people to use -o on MSDOS. */
143 (stdout)->_flag &= ~_IOTEXT;
144 _setmode (fileno (stdout), O_BINARY);
145 #endif
146 outfile = 0;
147 #endif /* MSDOS */
148 #ifdef WINDOWSNT
149 _fmode = O_BINARY;
150 _setmode (fileno (stdout), O_BINARY);
151 #endif /* WINDOWSNT */
152
153 /* If first two args are -o FILE, output to FILE. */
154 i = 1;
155 if (argc > i + 1 && !strcmp (argv[i], "-o"))
156 {
157 outfile = fopen (argv[i + 1], "w");
158 i += 2;
159 }
160 if (argc > i + 1 && !strcmp (argv[i], "-a"))
161 {
162 outfile = fopen (argv[i + 1], "a");
163 i += 2;
164 }
165 if (argc > i + 1 && !strcmp (argv[i], "-d"))
166 {
167 if (chdir (argv[i + 1]) != 0)
168 {
169 perror (argv[i + 1]);
170 return EXIT_FAILURE;
171 }
172 i += 2;
173 }
174 if (argc > i && !strcmp (argv[i], "-g"))
175 {
176 generate_globals = 1;
177 ++i;
178 }
179
180 if (outfile == 0)
181 fatal ("No output file specified", "");
182
183 if (generate_globals)
184 start_globals ();
185
186 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]))
193 break;
194 if (j == i)
195 err_count += scan_file (argv[i]);
196 }
197
198 if (err_count == 0 && generate_globals)
199 write_globals ();
200
201 return (err_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
202 }
203
204 /* Add a source file name boundary marker in the output file. */
205 static void
206 put_filename (char *filename)
207 {
208 char *tmp;
209
210 for (tmp = filename; *tmp; tmp++)
211 {
212 if (IS_DIRECTORY_SEP (*tmp))
213 filename = tmp + 1;
214 }
215
216 putc (037, outfile);
217 putc ('S', outfile);
218 fprintf (outfile, "%s\n", filename);
219 }
220
221 /* Read file FILENAME and output its doc strings to outfile. */
222 /* Return 1 if file is not found, 0 if it is found. */
223
224 static int
225 scan_file (char *filename)
226 {
227
228 size_t len = strlen (filename);
229
230 if (!generate_globals)
231 put_filename (filename);
232 if (len > 4 && !strcmp (filename + len - 4, ".elc"))
233 return scan_lisp_file (filename, READ_BINARY);
234 else if (len > 3 && !strcmp (filename + len - 3, ".el"))
235 return scan_lisp_file (filename, READ_TEXT);
236 else
237 return scan_c_file (filename, READ_TEXT);
238 }
239
240 static void
241 start_globals (void)
242 {
243 fprintf (outfile, "/* This file was auto-generated by make-docfile. */\n");
244 fprintf (outfile, "/* DO NOT EDIT. */\n");
245 fprintf (outfile, "struct emacs_globals {\n");
246 }
247 \f
248 static char input_buffer[128];
249
250 /* Some state during the execution of `read_c_string_or_comment'. */
251 struct rcsoc_state
252 {
253 /* A count of spaces and newlines that have been read, but not output. */
254 unsigned pending_spaces, pending_newlines;
255
256 /* Where we're reading from. */
257 FILE *in_file;
258
259 /* If non-zero, a buffer into which to copy characters. */
260 char *buf_ptr;
261 /* If non-zero, a file into which to copy characters. */
262 FILE *out_file;
263
264 /* A keyword we look for at the beginning of lines. If found, it is
265 not copied, and SAW_KEYWORD is set to true. */
266 const char *keyword;
267 /* The current point we've reached in an occurrence of KEYWORD in
268 the input stream. */
269 const char *cur_keyword_ptr;
270 /* Set to true if we saw an occurrence of KEYWORD. */
271 int saw_keyword;
272 };
273
274 /* Output CH to the file or buffer in STATE. Any pending newlines or
275 spaces are output first. */
276
277 static inline void
278 put_char (int ch, struct rcsoc_state *state)
279 {
280 int out_ch;
281 do
282 {
283 if (state->pending_newlines > 0)
284 {
285 state->pending_newlines--;
286 out_ch = '\n';
287 }
288 else if (state->pending_spaces > 0)
289 {
290 state->pending_spaces--;
291 out_ch = ' ';
292 }
293 else
294 out_ch = ch;
295
296 if (state->out_file)
297 putc (out_ch, state->out_file);
298 if (state->buf_ptr)
299 *state->buf_ptr++ = out_ch;
300 }
301 while (out_ch != ch);
302 }
303
304 /* If in the middle of scanning a keyword, continue scanning with
305 character CH, otherwise output CH to the file or buffer in STATE.
306 Any pending newlines or spaces are output first, as well as any
307 previously scanned characters that were thought to be part of a
308 keyword, but were in fact not. */
309
310 static void
311 scan_keyword_or_put_char (int ch, struct rcsoc_state *state)
312 {
313 if (state->keyword
314 && *state->cur_keyword_ptr == ch
315 && (state->cur_keyword_ptr > state->keyword
316 || state->pending_newlines > 0))
317 /* We might be looking at STATE->keyword at some point.
318 Keep looking until we know for sure. */
319 {
320 if (*++state->cur_keyword_ptr == '\0')
321 /* Saw the whole keyword. Set SAW_KEYWORD flag to true. */
322 {
323 state->saw_keyword = 1;
324
325 /* Reset the scanning pointer. */
326 state->cur_keyword_ptr = state->keyword;
327
328 /* Canonicalize whitespace preceding a usage string. */
329 state->pending_newlines = 2;
330 state->pending_spaces = 0;
331
332 /* Skip any whitespace between the keyword and the
333 usage string. */
334 do
335 ch = getc (state->in_file);
336 while (ch == ' ' || ch == '\n');
337
338 /* Output the open-paren we just read. */
339 put_char (ch, state);
340
341 /* Skip the function name and replace it with `fn'. */
342 do
343 ch = getc (state->in_file);
344 while (ch != ' ' && ch != ')');
345 put_char ('f', state);
346 put_char ('n', state);
347
348 /* Put back the last character. */
349 ungetc (ch, state->in_file);
350 }
351 }
352 else
353 {
354 if (state->keyword && state->cur_keyword_ptr > state->keyword)
355 /* We scanned the beginning of a potential usage
356 keyword, but it was a false alarm. Output the
357 part we scanned. */
358 {
359 const char *p;
360
361 for (p = state->keyword; p < state->cur_keyword_ptr; p++)
362 put_char (*p, state);
363
364 state->cur_keyword_ptr = state->keyword;
365 }
366
367 put_char (ch, state);
368 }
369 }
370
371
372 /* Skip a C string or C-style comment from INFILE, and return the
373 character that follows. COMMENT non-zero means skip a comment. If
374 PRINTFLAG is positive, output string contents to outfile. If it is
375 negative, store contents in buf. Convert escape sequences \n and
376 \t to newline and tab; discard \ followed by newline.
377 If SAW_USAGE is non-zero, then any occurrences of the string `usage:'
378 at the beginning of a line will be removed, and *SAW_USAGE set to
379 true if any were encountered. */
380
381 static int
382 read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usage)
383 {
384 register int c;
385 struct rcsoc_state state;
386
387 state.in_file = infile;
388 state.buf_ptr = (printflag < 0 ? input_buffer : 0);
389 state.out_file = (printflag > 0 ? outfile : 0);
390 state.pending_spaces = 0;
391 state.pending_newlines = 0;
392 state.keyword = (saw_usage ? "usage:" : 0);
393 state.cur_keyword_ptr = state.keyword;
394 state.saw_keyword = 0;
395
396 c = getc (infile);
397 if (comment)
398 while (c == '\n' || c == '\r' || c == '\t' || c == ' ')
399 c = getc (infile);
400
401 while (c != EOF)
402 {
403 while (c != EOF && (comment ? c != '*' : c != '"'))
404 {
405 if (c == '\\')
406 {
407 c = getc (infile);
408 if (c == '\n' || c == '\r')
409 {
410 c = getc (infile);
411 continue;
412 }
413 if (c == 'n')
414 c = '\n';
415 if (c == 't')
416 c = '\t';
417 }
418
419 if (c == ' ')
420 state.pending_spaces++;
421 else if (c == '\n')
422 {
423 state.pending_newlines++;
424 state.pending_spaces = 0;
425 }
426 else
427 scan_keyword_or_put_char (c, &state);
428
429 c = getc (infile);
430 }
431
432 if (c != EOF)
433 c = getc (infile);
434
435 if (comment)
436 {
437 if (c == '/')
438 {
439 c = getc (infile);
440 break;
441 }
442
443 scan_keyword_or_put_char ('*', &state);
444 }
445 else
446 {
447 if (c != '"')
448 break;
449
450 /* If we had a "", concatenate the two strings. */
451 c = getc (infile);
452 }
453 }
454
455 if (printflag < 0)
456 *state.buf_ptr = 0;
457
458 if (saw_usage)
459 *saw_usage = state.saw_keyword;
460
461 return c;
462 }
463
464
465 \f
466 /* Write to file OUT the argument names of function FUNC, whose text is in BUF.
467 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
468
469 static void
470 write_c_args (FILE *out, char *func, char *buf, int minargs, int maxargs)
471 {
472 register char *p;
473 int in_ident = 0;
474 char *ident_start IF_LINT (= NULL);
475 size_t ident_length = 0;
476
477 fprintf (out, "(fn");
478
479 if (*buf == '(')
480 ++buf;
481
482 for (p = buf; *p; p++)
483 {
484 char c = *p;
485
486 /* Notice when a new identifier starts. */
487 if ((('A' <= c && c <= 'Z')
488 || ('a' <= c && c <= 'z')
489 || ('0' <= c && c <= '9')
490 || c == '_')
491 != in_ident)
492 {
493 if (!in_ident)
494 {
495 in_ident = 1;
496 ident_start = p;
497 }
498 else
499 {
500 in_ident = 0;
501 ident_length = p - ident_start;
502 }
503 }
504
505 /* Found the end of an argument, write out the last seen
506 identifier. */
507 if (c == ',' || c == ')')
508 {
509 if (ident_length == 0)
510 {
511 error ("empty arg list for `%s' should be (void), not ()", func);
512 continue;
513 }
514
515 if (strncmp (ident_start, "void", ident_length) == 0)
516 continue;
517
518 putc (' ', out);
519
520 if (minargs == 0 && maxargs > 0)
521 fprintf (out, "&optional ");
522
523 minargs--;
524 maxargs--;
525
526 /* In C code, `default' is a reserved word, so we spell it
527 `defalt'; demangle that here. */
528 if (ident_length == 6 && memcmp (ident_start, "defalt", 6) == 0)
529 fprintf (out, "DEFAULT");
530 else
531 while (ident_length-- > 0)
532 {
533 c = *ident_start++;
534 if (c >= 'a' && c <= 'z')
535 /* Upcase the letter. */
536 c += 'A' - 'a';
537 else if (c == '_')
538 /* Print underscore as hyphen. */
539 c = '-';
540 putc (c, out);
541 }
542 }
543 }
544
545 putc (')', out);
546 }
547 \f
548 /* The types of globals. */
549 enum global_type
550 {
551 FUNCTION,
552 EMACS_INTEGER,
553 BOOLEAN,
554 LISP_OBJECT,
555 INVALID
556 };
557
558 /* A single global. */
559 struct global
560 {
561 enum global_type type;
562 char *name;
563 int value;
564 };
565
566 /* All the variable names we saw while scanning C sources in `-g'
567 mode. */
568 int num_globals;
569 int num_globals_allocated;
570 struct global *globals;
571
572 static void
573 add_global (enum global_type type, char *name, int value)
574 {
575 /* Ignore the one non-symbol that can occur. */
576 if (strcmp (name, "..."))
577 {
578 ++num_globals;
579
580 if (num_globals_allocated == 0)
581 {
582 num_globals_allocated = 100;
583 globals = xmalloc (num_globals_allocated * sizeof (struct global));
584 }
585 else if (num_globals == num_globals_allocated)
586 {
587 num_globals_allocated *= 2;
588 globals = xrealloc (globals,
589 num_globals_allocated * sizeof (struct global));
590 }
591
592 globals[num_globals - 1].type = type;
593 globals[num_globals - 1].name = name;
594 globals[num_globals - 1].value = value;
595 }
596 }
597
598 static int
599 compare_globals (const void *a, const void *b)
600 {
601 const struct global *ga = a;
602 const struct global *gb = b;
603
604 if (ga->type == FUNCTION)
605 {
606 if (gb->type != FUNCTION)
607 return 1;
608 }
609 else if (gb->type == FUNCTION)
610 return -1;
611
612 return strcmp (ga->name, gb->name);
613 }
614
615 static void
616 close_emacs_globals (void)
617 {
618 fprintf (outfile, "};\n");
619 fprintf (outfile, "extern struct emacs_globals globals;\n");
620 }
621
622 static void
623 write_globals (void)
624 {
625 int i, seen_defun = 0;
626 qsort (globals, num_globals, sizeof (struct global), compare_globals);
627 for (i = 0; i < num_globals; ++i)
628 {
629 char const *type;
630
631 switch (globals[i].type)
632 {
633 case EMACS_INTEGER:
634 type = "EMACS_INT";
635 break;
636 case BOOLEAN:
637 type = "int";
638 break;
639 case LISP_OBJECT:
640 type = "Lisp_Object";
641 break;
642 case FUNCTION:
643 if (!seen_defun)
644 {
645 close_emacs_globals ();
646 fprintf (outfile, "\n");
647 seen_defun = 1;
648 }
649 break;
650 default:
651 fatal ("not a recognized DEFVAR_", 0);
652 }
653
654 if (globals[i].type != FUNCTION)
655 {
656 fprintf (outfile, " %s f_%s;\n", type, globals[i].name);
657 fprintf (outfile, "#define %s globals.f_%s\n",
658 globals[i].name, globals[i].name);
659 }
660 else
661 {
662 /* It would be nice to have a cleaner way to deal with these
663 special hacks. */
664 if (strcmp (globals[i].name, "Fthrow") == 0
665 || strcmp (globals[i].name, "Ftop_level") == 0
666 || strcmp (globals[i].name, "Fkill_emacs") == 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
678 while (i + 1 < num_globals
679 && !strcmp (globals[i].name, globals[i + 1].name))
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 }
687 }
688
689 if (!seen_defun)
690 close_emacs_globals ();
691 }
692
693 \f
694 /* Read through a c file. If a .o file is named,
695 the corresponding .c or .m file is read instead.
696 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
697 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
698
699 static int
700 scan_c_file (char *filename, const char *mode)
701 {
702 FILE *infile;
703 register int c;
704 register int commas;
705 int minargs, maxargs;
706 int extension = filename[strlen (filename) - 1];
707
708 if (extension == 'o')
709 filename[strlen (filename) - 1] = 'c';
710
711 infile = fopen (filename, mode);
712
713 if (infile == NULL && extension == 'o')
714 {
715 /* Try .m. */
716 filename[strlen (filename) - 1] = 'm';
717 infile = fopen (filename, mode);
718 if (infile == NULL)
719 filename[strlen (filename) - 1] = 'c'; /* Don't confuse people. */
720 }
721
722 /* No error if non-ex input file. */
723 if (infile == NULL)
724 {
725 perror (filename);
726 return 0;
727 }
728
729 /* Reset extension to be able to detect duplicate files. */
730 filename[strlen (filename) - 1] = extension;
731
732 c = '\n';
733 while (!feof (infile))
734 {
735 int doc_keyword = 0;
736 int defunflag = 0;
737 int defvarperbufferflag = 0;
738 int defvarflag = 0;
739 enum global_type type = INVALID;
740 char *name IF_LINT (= 0);
741
742 if (c != '\n' && c != '\r')
743 {
744 c = getc (infile);
745 continue;
746 }
747 c = getc (infile);
748 if (c == ' ')
749 {
750 while (c == ' ')
751 c = getc (infile);
752 if (c != 'D')
753 continue;
754 c = getc (infile);
755 if (c != 'E')
756 continue;
757 c = getc (infile);
758 if (c != 'F')
759 continue;
760 c = getc (infile);
761 if (c != 'V')
762 continue;
763 c = getc (infile);
764 if (c != 'A')
765 continue;
766 c = getc (infile);
767 if (c != 'R')
768 continue;
769 c = getc (infile);
770 if (c != '_')
771 continue;
772
773 defvarflag = 1;
774
775 c = getc (infile);
776 defvarperbufferflag = (c == 'P');
777 if (generate_globals)
778 {
779 if (c == 'I')
780 type = EMACS_INTEGER;
781 else if (c == 'L')
782 type = LISP_OBJECT;
783 else if (c == 'B')
784 type = BOOLEAN;
785 }
786
787 c = getc (infile);
788 /* We need to distinguish between DEFVAR_BOOL and
789 DEFVAR_BUFFER_DEFAULTS. */
790 if (generate_globals && type == BOOLEAN && c != 'O')
791 type = INVALID;
792 }
793 else if (c == 'D')
794 {
795 c = getc (infile);
796 if (c != 'E')
797 continue;
798 c = getc (infile);
799 if (c != 'F')
800 continue;
801 c = getc (infile);
802 defunflag = c == 'U';
803 }
804 else continue;
805
806 if (generate_globals
807 && (!defvarflag || defvarperbufferflag || type == INVALID)
808 && !defunflag)
809 continue;
810
811 while (c != '(')
812 {
813 if (c < 0)
814 goto eof;
815 c = getc (infile);
816 }
817
818 /* Lisp variable or function name. */
819 c = getc (infile);
820 if (c != '"')
821 continue;
822 c = read_c_string_or_comment (infile, -1, 0, 0);
823
824 if (generate_globals)
825 {
826 int i = 0;
827
828 /* Skip "," and whitespace. */
829 do
830 {
831 c = getc (infile);
832 }
833 while (c == ',' || c == ' ' || c == '\t' || c == '\n' || c == '\r');
834
835 /* Read in the identifier. */
836 do
837 {
838 input_buffer[i++] = c;
839 c = getc (infile);
840 }
841 while (! (c == ',' || c == ' ' || c == '\t'
842 || c == '\n' || c == '\r'));
843 input_buffer[i] = '\0';
844
845 name = xmalloc (i + 1);
846 memcpy (name, input_buffer, i + 1);
847
848 if (!defunflag)
849 {
850 add_global (type, name, 0);
851 continue;
852 }
853 }
854
855 /* DEFVAR_LISP ("name", addr, "doc")
856 DEFVAR_LISP ("name", addr /\* doc *\/)
857 DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */
858
859 if (defunflag)
860 commas = generate_globals ? 4 : 5;
861 else if (defvarperbufferflag)
862 commas = 3;
863 else if (defvarflag)
864 commas = 1;
865 else /* For DEFSIMPLE and DEFPRED. */
866 commas = 2;
867
868 while (commas)
869 {
870 if (c == ',')
871 {
872 commas--;
873
874 if (defunflag && (commas == 1 || commas == 2))
875 {
876 int scanned = 0;
877 do
878 c = getc (infile);
879 while (c == ' ' || c == '\n' || c == '\r' || c == '\t');
880 if (c < 0)
881 goto eof;
882 ungetc (c, infile);
883 if (commas == 2) /* Pick up minargs. */
884 scanned = fscanf (infile, "%d", &minargs);
885 else /* Pick up maxargs. */
886 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
887 {
888 if (generate_globals)
889 maxargs = (c == 'M') ? -1 : -2;
890 else
891 maxargs = -1;
892 }
893 else
894 scanned = fscanf (infile, "%d", &maxargs);
895 if (scanned < 0)
896 goto eof;
897 }
898 }
899
900 if (c == EOF)
901 goto eof;
902 c = getc (infile);
903 }
904
905 if (generate_globals)
906 {
907 add_global (FUNCTION, name, maxargs);
908 continue;
909 }
910
911 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
912 c = getc (infile);
913
914 if (c == '"')
915 c = read_c_string_or_comment (infile, 0, 0, 0);
916
917 while (c != EOF && c != ',' && c != '/')
918 c = getc (infile);
919 if (c == ',')
920 {
921 c = getc (infile);
922 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
923 c = getc (infile);
924 while ((c >= 'a' && c <= 'z') || (c >= 'Z' && c <= 'Z'))
925 c = getc (infile);
926 if (c == ':')
927 {
928 doc_keyword = 1;
929 c = getc (infile);
930 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
931 c = getc (infile);
932 }
933 }
934
935 if (c == '"'
936 || (c == '/'
937 && (c = getc (infile),
938 ungetc (c, infile),
939 c == '*')))
940 {
941 int comment = c != '"';
942 int saw_usage;
943
944 putc (037, outfile);
945 putc (defvarflag ? 'V' : 'F', outfile);
946 fprintf (outfile, "%s\n", input_buffer);
947
948 if (comment)
949 getc (infile); /* Skip past `*'. */
950 c = read_c_string_or_comment (infile, 1, comment, &saw_usage);
951
952 /* If this is a defun, find the arguments and print them. If
953 this function takes MANY or UNEVALLED args, then the C source
954 won't give the names of the arguments, so we shouldn't bother
955 trying to find them.
956
957 Various doc-string styles:
958 0: DEFUN (..., "DOC") (args) [!comment]
959 1: DEFUN (..., /\* DOC *\/ (args)) [comment && !doc_keyword]
960 2: DEFUN (..., doc: /\* DOC *\/) (args) [comment && doc_keyword]
961 */
962 if (defunflag && maxargs != -1 && !saw_usage)
963 {
964 char argbuf[1024], *p = argbuf;
965
966 if (!comment || doc_keyword)
967 while (c != ')')
968 {
969 if (c < 0)
970 goto eof;
971 c = getc (infile);
972 }
973
974 /* Skip into arguments. */
975 while (c != '(')
976 {
977 if (c < 0)
978 goto eof;
979 c = getc (infile);
980 }
981 /* Copy arguments into ARGBUF. */
982 *p++ = c;
983 do
984 *p++ = c = getc (infile);
985 while (c != ')');
986 *p = '\0';
987 /* Output them. */
988 fprintf (outfile, "\n\n");
989 write_c_args (outfile, input_buffer, argbuf, minargs, maxargs);
990 }
991 else if (defunflag && maxargs == -1 && !saw_usage)
992 /* The DOC should provide the usage form. */
993 fprintf (stderr, "Missing `usage' for function `%s'.\n",
994 input_buffer);
995 }
996 }
997 eof:
998 fclose (infile);
999 return 0;
1000 }
1001 \f
1002 /* Read a file of Lisp code, compiled or interpreted.
1003 Looks for
1004 (defun NAME ARGS DOCSTRING ...)
1005 (defmacro NAME ARGS DOCSTRING ...)
1006 (defsubst NAME ARGS DOCSTRING ...)
1007 (autoload (quote NAME) FILE DOCSTRING ...)
1008 (defvar NAME VALUE DOCSTRING)
1009 (defconst NAME VALUE DOCSTRING)
1010 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
1011 (fset (quote NAME) #[... DOCSTRING ...])
1012 (defalias (quote NAME) #[... DOCSTRING ...])
1013 (custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
1014 starting in column zero.
1015 (quote NAME) may appear as 'NAME as well.
1016
1017 We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
1018 When we find that, we save it for the following defining-form,
1019 and we use that instead of reading a doc string within that defining-form.
1020
1021 For defvar, defconst, and fset we skip to the docstring with a kludgy
1022 formatting convention: all docstrings must appear on the same line as the
1023 initial open-paren (the one in column zero) and must contain a backslash
1024 and a newline immediately after the initial double-quote. No newlines
1025 must appear between the beginning of the form and the first double-quote.
1026 For defun, defmacro, and autoload, we know how to skip over the
1027 arglist, but the doc string must still have a backslash and newline
1028 immediately after the double quote.
1029 The only source files that must follow this convention are preloaded
1030 uncompiled ones like loaddefs.el and bindings.el; aside
1031 from that, it is always the .elc file that we look at, and they are no
1032 problem because byte-compiler output follows this convention.
1033 The NAME and DOCSTRING are output.
1034 NAME is preceded by `F' for a function or `V' for a variable.
1035 An entry is output only if DOCSTRING has \ newline just after the opening ".
1036 */
1037
1038 static void
1039 skip_white (FILE *infile)
1040 {
1041 char c = ' ';
1042 while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
1043 c = getc (infile);
1044 ungetc (c, infile);
1045 }
1046
1047 static void
1048 read_lisp_symbol (FILE *infile, char *buffer)
1049 {
1050 char c;
1051 char *fillp = buffer;
1052
1053 skip_white (infile);
1054 while (1)
1055 {
1056 c = getc (infile);
1057 if (c == '\\')
1058 *(++fillp) = getc (infile);
1059 else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '(' || c == ')')
1060 {
1061 ungetc (c, infile);
1062 *fillp = 0;
1063 break;
1064 }
1065 else
1066 *fillp++ = c;
1067 }
1068
1069 if (! buffer[0])
1070 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
1071
1072 skip_white (infile);
1073 }
1074
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 static int
1104 scan_lisp_file (const char *filename, const char *mode)
1105 {
1106 FILE *infile;
1107 register int c;
1108 char *saved_string = 0;
1109
1110 if (generate_globals)
1111 fatal ("scanning lisp file when -g specified", 0);
1112
1113 infile = fopen (filename, mode);
1114 if (infile == NULL)
1115 {
1116 perror (filename);
1117 return 0; /* No error. */
1118 }
1119
1120 c = '\n';
1121 while (!feof (infile))
1122 {
1123 char buffer[BUFSIZ];
1124 char type;
1125
1126 /* If not at end of line, skip till we get to one. */
1127 if (c != '\n' && c != '\r')
1128 {
1129 c = getc (infile);
1130 continue;
1131 }
1132 /* Skip the line break. */
1133 while (c == '\n' || c == '\r')
1134 c = getc (infile);
1135 /* Detect a dynamic doc string and save it for the next expression. */
1136 if (c == '#')
1137 {
1138 c = getc (infile);
1139 if (c == '@')
1140 {
1141 size_t length = 0;
1142 size_t i;
1143
1144 /* Read the length. */
1145 while ((c = getc (infile),
1146 c >= '0' && c <= '9'))
1147 {
1148 length *= 10;
1149 length += c - '0';
1150 }
1151
1152 if (length <= 1)
1153 fatal ("invalid dynamic doc string length", "");
1154
1155 if (c != ' ')
1156 fatal ("space not found after dynamic doc string length", "");
1157
1158 /* The next character is a space that is counted in the length
1159 but not part of the doc string.
1160 We already read it, so just ignore it. */
1161 length--;
1162
1163 /* Read in the contents. */
1164 free (saved_string);
1165 saved_string = (char *) xmalloc (length);
1166 for (i = 0; i < length; i++)
1167 saved_string[i] = getc (infile);
1168 /* The last character is a ^_.
1169 That is needed in the .elc file
1170 but it is redundant in DOC. So get rid of it here. */
1171 saved_string[length - 1] = 0;
1172 /* Skip the line break. */
1173 while (c == '\n' || c == '\r')
1174 c = getc (infile);
1175 /* Skip the following line. */
1176 while (c != '\n' && c != '\r')
1177 c = getc (infile);
1178 }
1179 continue;
1180 }
1181
1182 if (c != '(')
1183 continue;
1184
1185 read_lisp_symbol (infile, buffer);
1186
1187 if (! strcmp (buffer, "defun")
1188 || ! strcmp (buffer, "defmacro")
1189 || ! strcmp (buffer, "defsubst"))
1190 {
1191 type = 'F';
1192 read_lisp_symbol (infile, buffer);
1193
1194 /* Skip the arguments: either "nil" or a list in parens. */
1195
1196 c = getc (infile);
1197 if (c == 'n') /* nil */
1198 {
1199 if ((c = getc (infile)) != 'i'
1200 || (c = getc (infile)) != 'l')
1201 {
1202 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
1203 buffer, filename);
1204 continue;
1205 }
1206 }
1207 else if (c != '(')
1208 {
1209 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
1210 buffer, filename);
1211 continue;
1212 }
1213 else
1214 while (c != ')')
1215 c = getc (infile);
1216 skip_white (infile);
1217
1218 /* If the next three characters aren't `dquote bslash newline'
1219 then we're not reading a docstring.
1220 */
1221 if ((c = getc (infile)) != '"'
1222 || (c = getc (infile)) != '\\'
1223 || ((c = getc (infile)) != '\n' && c != '\r'))
1224 {
1225 #ifdef DEBUG
1226 fprintf (stderr, "## non-docstring in %s (%s)\n",
1227 buffer, filename);
1228 #endif
1229 continue;
1230 }
1231 }
1232
1233 /* defcustom can only occur in uncompiled Lisp files. */
1234 else if (! strcmp (buffer, "defvar")
1235 || ! strcmp (buffer, "defconst")
1236 || ! strcmp (buffer, "defcustom"))
1237 {
1238 type = 'V';
1239 read_lisp_symbol (infile, buffer);
1240
1241 if (saved_string == 0)
1242 if (!search_lisp_doc_at_eol (infile))
1243 continue;
1244 }
1245
1246 else if (! strcmp (buffer, "custom-declare-variable")
1247 || ! strcmp (buffer, "defvaralias")
1248 )
1249 {
1250 type = 'V';
1251
1252 c = getc (infile);
1253 if (c == '\'')
1254 read_lisp_symbol (infile, buffer);
1255 else
1256 {
1257 if (c != '(')
1258 {
1259 fprintf (stderr,
1260 "## unparsable name in custom-declare-variable in %s\n",
1261 filename);
1262 continue;
1263 }
1264 read_lisp_symbol (infile, buffer);
1265 if (strcmp (buffer, "quote"))
1266 {
1267 fprintf (stderr,
1268 "## unparsable name in custom-declare-variable in %s\n",
1269 filename);
1270 continue;
1271 }
1272 read_lisp_symbol (infile, buffer);
1273 c = getc (infile);
1274 if (c != ')')
1275 {
1276 fprintf (stderr,
1277 "## unparsable quoted name in custom-declare-variable in %s\n",
1278 filename);
1279 continue;
1280 }
1281 }
1282
1283 if (saved_string == 0)
1284 if (!search_lisp_doc_at_eol (infile))
1285 continue;
1286 }
1287
1288 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
1289 {
1290 type = 'F';
1291
1292 c = getc (infile);
1293 if (c == '\'')
1294 read_lisp_symbol (infile, buffer);
1295 else
1296 {
1297 if (c != '(')
1298 {
1299 fprintf (stderr, "## unparsable name in fset in %s\n",
1300 filename);
1301 continue;
1302 }
1303 read_lisp_symbol (infile, buffer);
1304 if (strcmp (buffer, "quote"))
1305 {
1306 fprintf (stderr, "## unparsable name in fset in %s\n",
1307 filename);
1308 continue;
1309 }
1310 read_lisp_symbol (infile, buffer);
1311 c = getc (infile);
1312 if (c != ')')
1313 {
1314 fprintf (stderr,
1315 "## unparsable quoted name in fset in %s\n",
1316 filename);
1317 continue;
1318 }
1319 }
1320
1321 if (saved_string == 0)
1322 if (!search_lisp_doc_at_eol (infile))
1323 continue;
1324 }
1325
1326 else if (! strcmp (buffer, "autoload"))
1327 {
1328 type = 'F';
1329 c = getc (infile);
1330 if (c == '\'')
1331 read_lisp_symbol (infile, buffer);
1332 else
1333 {
1334 if (c != '(')
1335 {
1336 fprintf (stderr, "## unparsable name in autoload in %s\n",
1337 filename);
1338 continue;
1339 }
1340 read_lisp_symbol (infile, buffer);
1341 if (strcmp (buffer, "quote"))
1342 {
1343 fprintf (stderr, "## unparsable name in autoload in %s\n",
1344 filename);
1345 continue;
1346 }
1347 read_lisp_symbol (infile, buffer);
1348 c = getc (infile);
1349 if (c != ')')
1350 {
1351 fprintf (stderr,
1352 "## unparsable quoted name in autoload in %s\n",
1353 filename);
1354 continue;
1355 }
1356 }
1357 skip_white (infile);
1358 if ((c = getc (infile)) != '\"')
1359 {
1360 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
1361 buffer, filename);
1362 continue;
1363 }
1364 read_c_string_or_comment (infile, 0, 0, 0);
1365
1366 if (saved_string == 0)
1367 if (!search_lisp_doc_at_eol (infile))
1368 continue;
1369 }
1370
1371 #ifdef DEBUG
1372 else if (! strcmp (buffer, "if")
1373 || ! strcmp (buffer, "byte-code"))
1374 continue;
1375 #endif
1376
1377 else
1378 {
1379 #ifdef DEBUG
1380 fprintf (stderr, "## unrecognized top-level form, %s (%s)\n",
1381 buffer, filename);
1382 #endif
1383 continue;
1384 }
1385
1386 /* At this point, we should either use the previous dynamic doc string in
1387 saved_string or gobble a doc string from the input file.
1388 In the latter case, the opening quote (and leading backslash-newline)
1389 have already been read. */
1390
1391 putc (037, outfile);
1392 putc (type, outfile);
1393 fprintf (outfile, "%s\n", buffer);
1394 if (saved_string)
1395 {
1396 fputs (saved_string, outfile);
1397 /* Don't use one dynamic doc string twice. */
1398 free (saved_string);
1399 saved_string = 0;
1400 }
1401 else
1402 read_c_string_or_comment (infile, 1, 0, 0);
1403 }
1404 fclose (infile);
1405 return 0;
1406 }
1407
1408
1409 /* make-docfile.c ends here */