Add support for large files. Merge glibc 2.1.2.
[bpt/emacs.git] / lib-src / make-docfile.c
1 /* Generate doc-string file for GNU Emacs from source files.
2 Copyright (C) 1985, 86, 92, 93, 94, 97, 1999 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* The arguments given to this program are all the C and Lisp source files
22 of GNU Emacs. .elc and .el and .c files are allowed.
23 A .o file can also be specified; the .c file it was made from is used.
24 This helps the makefile pass the correct list of files.
25
26 The results, which go to standard output or to a file
27 specified with -a or -o (-a to append, -o to start from nothing),
28 are entries containing function or variable names and their documentation.
29 Each entry starts with a ^_ character.
30 Then comes F for a function or V for a variable.
31 Then comes the function or variable name, terminated with a newline.
32 Then comes the documentation for that function or variable.
33 */
34
35 #define NO_SHORTNAMES /* Tell config not to load remap.h */
36 #include <config.h>
37
38 /* defined to be emacs_main, sys_fopen, etc. in config.h */
39 #undef main
40 #undef fopen
41 #undef chdir
42
43 #include <stdio.h>
44 #ifdef MSDOS
45 #include <fcntl.h>
46 #endif /* MSDOS */
47 #ifdef WINDOWSNT
48 #include <stdlib.h>
49 #include <fcntl.h>
50 #include <direct.h>
51 #endif /* WINDOWSNT */
52
53 #ifdef DOS_NT
54 #define READ_TEXT "rt"
55 #define READ_BINARY "rb"
56 #else /* not DOS_NT */
57 #define READ_TEXT "r"
58 #define READ_BINARY "r"
59 #endif /* not DOS_NT */
60
61 int scan_file ();
62 int scan_lisp_file ();
63 int scan_c_file ();
64
65 #ifdef MSDOS
66 /* s/msdos.h defines this as sys_chdir, but we're not linking with the
67 file where that function is defined. */
68 #undef chdir
69 #endif
70
71 #ifdef HAVE_UNISTD_H
72 #include <unistd.h>
73 #endif
74
75 /* Stdio stream for output to the DOC file. */
76 FILE *outfile;
77
78 /* Name this program was invoked with. */
79 char *progname;
80
81 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
82
83 /* VARARGS1 */
84 void
85 error (s1, s2)
86 char *s1, *s2;
87 {
88 fprintf (stderr, "%s: ", progname);
89 fprintf (stderr, s1, s2);
90 fprintf (stderr, "\n");
91 }
92
93 /* Print error message and exit. */
94
95 /* VARARGS1 */
96 void
97 fatal (s1, s2)
98 char *s1, *s2;
99 {
100 error (s1, s2);
101 exit (1);
102 }
103
104 /* Like malloc but get fatal error if memory is exhausted. */
105
106 long *
107 xmalloc (size)
108 unsigned int size;
109 {
110 long *result = (long *) malloc (size);
111 if (result == NULL)
112 fatal ("virtual memory exhausted", 0);
113 return result;
114 }
115 \f
116 int
117 main (argc, argv)
118 int argc;
119 char **argv;
120 {
121 int i;
122 int err_count = 0;
123 int first_infile;
124
125 progname = argv[0];
126
127 outfile = stdout;
128
129 /* Don't put CRs in the DOC file. */
130 #ifdef MSDOS
131 _fmode = O_BINARY;
132 #if 0 /* Suspicion is that this causes hanging.
133 So instead we require people to use -o on MSDOS. */
134 (stdout)->_flag &= ~_IOTEXT;
135 _setmode (fileno (stdout), O_BINARY);
136 #endif
137 outfile = 0;
138 #endif /* MSDOS */
139 #ifdef WINDOWSNT
140 _fmode = O_BINARY;
141 _setmode (fileno (stdout), O_BINARY);
142 #endif /* WINDOWSNT */
143
144 /* If first two args are -o FILE, output to FILE. */
145 i = 1;
146 if (argc > i + 1 && !strcmp (argv[i], "-o"))
147 {
148 outfile = fopen (argv[i + 1], "w");
149 i += 2;
150 }
151 if (argc > i + 1 && !strcmp (argv[i], "-a"))
152 {
153 outfile = fopen (argv[i + 1], "a");
154 i += 2;
155 }
156 if (argc > i + 1 && !strcmp (argv[i], "-d"))
157 {
158 chdir (argv[i + 1]);
159 i += 2;
160 }
161
162 if (outfile == 0)
163 fatal ("No output file specified", "");
164
165 first_infile = i;
166 for (; i < argc; i++)
167 {
168 int j;
169 /* Don't process one file twice. */
170 for (j = first_infile; j < i; j++)
171 if (! strcmp (argv[i], argv[j]))
172 break;
173 if (j == i)
174 err_count += scan_file (argv[i]);
175 }
176 #ifndef VMS
177 exit (err_count > 0);
178 #endif /* VMS */
179 return err_count > 0;
180 }
181
182 /* Read file FILENAME and output its doc strings to outfile. */
183 /* Return 1 if file is not found, 0 if it is found. */
184
185 int
186 scan_file (filename)
187 char *filename;
188 {
189 int len = strlen (filename);
190 if (len > 4 && !strcmp (filename + len - 4, ".elc"))
191 return scan_lisp_file (filename, READ_BINARY);
192 else if (len > 3 && !strcmp (filename + len - 3, ".el"))
193 return scan_lisp_file (filename, READ_TEXT);
194 else
195 return scan_c_file (filename, READ_TEXT);
196 }
197 \f
198 char buf[128];
199
200 /* Skip a C string from INFILE,
201 and return the character that follows the closing ".
202 If printflag is positive, output string contents to outfile.
203 If it is negative, store contents in buf.
204 Convert escape sequences \n and \t to newline and tab;
205 discard \ followed by newline. */
206
207 int
208 read_c_string (infile, printflag)
209 FILE *infile;
210 int printflag;
211 {
212 register int c;
213 char *p = buf;
214
215 c = getc (infile);
216 while (c != EOF)
217 {
218 while (c != '"' && c != EOF)
219 {
220 if (c == '\\')
221 {
222 c = getc (infile);
223 if (c == '\n' || c == '\r')
224 {
225 c = getc (infile);
226 continue;
227 }
228 if (c == 'n')
229 c = '\n';
230 if (c == 't')
231 c = '\t';
232 }
233 if (printflag > 0)
234 putc (c, outfile);
235 else if (printflag < 0)
236 *p++ = c;
237 c = getc (infile);
238 }
239 c = getc (infile);
240 if (c != '"')
241 break;
242 /* If we had a "", concatenate the two strings. */
243 c = getc (infile);
244 }
245
246 if (printflag < 0)
247 *p = 0;
248
249 return c;
250 }
251 \f
252 /* Write to file OUT the argument names of function FUNC, whose text is in BUF.
253 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
254
255 void
256 write_c_args (out, func, buf, minargs, maxargs)
257 FILE *out;
258 char *func, *buf;
259 int minargs, maxargs;
260 {
261 register char *p;
262 int in_ident = 0;
263 int just_spaced = 0;
264 int need_space = 1;
265
266 fprintf (out, "(%s", func);
267
268 if (*buf == '(')
269 ++buf;
270
271 for (p = buf; *p; p++)
272 {
273 char c = *p;
274 int ident_start = 0;
275
276 /* Notice when we start printing a new identifier. */
277 if ((('A' <= c && c <= 'Z')
278 || ('a' <= c && c <= 'z')
279 || ('0' <= c && c <= '9')
280 || c == '_')
281 != in_ident)
282 {
283 if (!in_ident)
284 {
285 in_ident = 1;
286 ident_start = 1;
287
288 if (need_space)
289 putc (' ', out);
290
291 if (minargs == 0 && maxargs > 0)
292 fprintf (out, "&optional ");
293 just_spaced = 1;
294
295 minargs--;
296 maxargs--;
297 }
298 else
299 in_ident = 0;
300 }
301
302 /* Print the C argument list as it would appear in lisp:
303 print underscores as hyphens, and print commas as spaces.
304 Collapse adjacent spaces into one. */
305 if (c == '_') c = '-';
306 if (c == ',') c = ' ';
307
308 /* In C code, `default' is a reserved word, so we spell it
309 `defalt'; unmangle that here. */
310 if (ident_start
311 && strncmp (p, "defalt", 6) == 0
312 && ! (('A' <= p[6] && p[6] <= 'Z')
313 || ('a' <= p[6] && p[6] <= 'z')
314 || ('0' <= p[6] && p[6] <= '9')
315 || p[6] == '_'))
316 {
317 fprintf (out, "DEFAULT");
318 p += 5;
319 in_ident = 0;
320 just_spaced = 0;
321 }
322 else if (c != ' ' || ! just_spaced)
323 {
324 if (c >= 'a' && c <= 'z')
325 /* Upcase the letter. */
326 c += 'A' - 'a';
327 putc (c, out);
328 }
329
330 just_spaced = (c == ' ');
331 need_space = 0;
332 }
333 }
334 \f
335 /* Read through a c file. If a .o file is named,
336 the corresponding .c file is read instead.
337 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
338 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
339
340 int
341 scan_c_file (filename, mode)
342 char *filename, *mode;
343 {
344 FILE *infile;
345 register int c;
346 register int commas;
347 register int defunflag;
348 register int defvarperbufferflag;
349 register int defvarflag;
350 int minargs, maxargs;
351 int extension = filename[strlen (filename) - 1];
352
353 if (extension == 'o')
354 filename[strlen (filename) - 1] = 'c';
355
356 infile = fopen (filename, mode);
357
358 /* No error if non-ex input file */
359 if (infile == NULL)
360 {
361 perror (filename);
362 return 0;
363 }
364
365 /* Reset extension to be able to detect duplicate files. */
366 filename[strlen (filename) - 1] = extension;
367
368 c = '\n';
369 while (!feof (infile))
370 {
371 if (c != '\n' && c != '\r')
372 {
373 c = getc (infile);
374 continue;
375 }
376 c = getc (infile);
377 if (c == ' ')
378 {
379 while (c == ' ')
380 c = getc (infile);
381 if (c != 'D')
382 continue;
383 c = getc (infile);
384 if (c != 'E')
385 continue;
386 c = getc (infile);
387 if (c != 'F')
388 continue;
389 c = getc (infile);
390 if (c != 'V')
391 continue;
392 c = getc (infile);
393 if (c != 'A')
394 continue;
395 c = getc (infile);
396 if (c != 'R')
397 continue;
398 c = getc (infile);
399 if (c != '_')
400 continue;
401
402 defvarflag = 1;
403 defunflag = 0;
404
405 c = getc (infile);
406 defvarperbufferflag = (c == 'P');
407
408 c = getc (infile);
409 }
410 else if (c == 'D')
411 {
412 c = getc (infile);
413 if (c != 'E')
414 continue;
415 c = getc (infile);
416 if (c != 'F')
417 continue;
418 c = getc (infile);
419 defunflag = c == 'U';
420 defvarflag = 0;
421 }
422 else continue;
423
424 while (c != '(')
425 {
426 if (c < 0)
427 goto eof;
428 c = getc (infile);
429 }
430
431 c = getc (infile);
432 if (c != '"')
433 continue;
434 c = read_c_string (infile, -1);
435
436 if (defunflag)
437 commas = 5;
438 else if (defvarperbufferflag)
439 commas = 2;
440 else if (defvarflag)
441 commas = 1;
442 else /* For DEFSIMPLE and DEFPRED */
443 commas = 2;
444
445 while (commas)
446 {
447 if (c == ',')
448 {
449 commas--;
450 if (defunflag && (commas == 1 || commas == 2))
451 {
452 do
453 c = getc (infile);
454 while (c == ' ' || c == '\n' || c == '\r' || c == '\t');
455 if (c < 0)
456 goto eof;
457 ungetc (c, infile);
458 if (commas == 2) /* pick up minargs */
459 fscanf (infile, "%d", &minargs);
460 else /* pick up maxargs */
461 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
462 maxargs = -1;
463 else
464 fscanf (infile, "%d", &maxargs);
465 }
466 }
467 if (c < 0)
468 goto eof;
469 c = getc (infile);
470 }
471 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
472 c = getc (infile);
473 if (c == '"')
474 c = read_c_string (infile, 0);
475 while (c != ',')
476 c = getc (infile);
477 c = getc (infile);
478 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
479 c = getc (infile);
480
481 if (c == '"')
482 {
483 putc (037, outfile);
484 putc (defvarflag ? 'V' : 'F', outfile);
485 fprintf (outfile, "%s\n", buf);
486 c = read_c_string (infile, 1);
487
488 /* If this is a defun, find the arguments and print them. If
489 this function takes MANY or UNEVALLED args, then the C source
490 won't give the names of the arguments, so we shouldn't bother
491 trying to find them. */
492 if (defunflag && maxargs != -1)
493 {
494 char argbuf[1024], *p = argbuf;
495 while (c != ')')
496 {
497 if (c < 0)
498 goto eof;
499 c = getc (infile);
500 }
501 /* Skip into arguments. */
502 while (c != '(')
503 {
504 if (c < 0)
505 goto eof;
506 c = getc (infile);
507 }
508 /* Copy arguments into ARGBUF. */
509 *p++ = c;
510 do
511 *p++ = c = getc (infile);
512 while (c != ')');
513 *p = '\0';
514 /* Output them. */
515 fprintf (outfile, "\n\n");
516 write_c_args (outfile, buf, argbuf, minargs, maxargs);
517 }
518 }
519 }
520 eof:
521 fclose (infile);
522 return 0;
523 }
524 \f
525 /* Read a file of Lisp code, compiled or interpreted.
526 Looks for
527 (defun NAME ARGS DOCSTRING ...)
528 (defmacro NAME ARGS DOCSTRING ...)
529 (autoload (quote NAME) FILE DOCSTRING ...)
530 (defvar NAME VALUE DOCSTRING)
531 (defconst NAME VALUE DOCSTRING)
532 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
533 (fset (quote NAME) #[... DOCSTRING ...])
534 (defalias (quote NAME) #[... DOCSTRING ...])
535 (custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
536 starting in column zero.
537 (quote NAME) may appear as 'NAME as well.
538
539 We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
540 When we find that, we save it for the following defining-form,
541 and we use that instead of reading a doc string within that defining-form.
542
543 For defvar, defconst, and fset we skip to the docstring with a kludgy
544 formatting convention: all docstrings must appear on the same line as the
545 initial open-paren (the one in column zero) and must contain a backslash
546 and a newline immediately after the initial double-quote. No newlines
547 must appear between the beginning of the form and the first double-quote.
548 For defun, defmacro, and autoload, we know how to skip over the
549 arglist, but the doc string must still have a backslash and newline
550 immediately after the double quote.
551 The only source files that must follow this convention are preloaded
552 uncompiled ones like loaddefs.el and bindings.el; aside
553 from that, it is always the .elc file that we look at, and they are no
554 problem because byte-compiler output follows this convention.
555 The NAME and DOCSTRING are output.
556 NAME is preceded by `F' for a function or `V' for a variable.
557 An entry is output only if DOCSTRING has \ newline just after the opening "
558 */
559
560 void
561 skip_white (infile)
562 FILE *infile;
563 {
564 char c = ' ';
565 while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
566 c = getc (infile);
567 ungetc (c, infile);
568 }
569
570 void
571 read_lisp_symbol (infile, buffer)
572 FILE *infile;
573 char *buffer;
574 {
575 char c;
576 char *fillp = buffer;
577
578 skip_white (infile);
579 while (1)
580 {
581 c = getc (infile);
582 if (c == '\\')
583 *(++fillp) = getc (infile);
584 else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '(' || c == ')')
585 {
586 ungetc (c, infile);
587 *fillp = 0;
588 break;
589 }
590 else
591 *fillp++ = c;
592 }
593
594 if (! buffer[0])
595 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
596
597 skip_white (infile);
598 }
599
600 int
601 scan_lisp_file (filename, mode)
602 char *filename, *mode;
603 {
604 FILE *infile;
605 register int c;
606 char *saved_string = 0;
607
608 infile = fopen (filename, mode);
609 if (infile == NULL)
610 {
611 perror (filename);
612 return 0; /* No error */
613 }
614
615 c = '\n';
616 while (!feof (infile))
617 {
618 char buffer[BUFSIZ];
619 char type;
620
621 /* If not at end of line, skip till we get to one. */
622 if (c != '\n' && c != '\r')
623 {
624 c = getc (infile);
625 continue;
626 }
627 /* Skip the line break. */
628 while (c == '\n' || c == '\r')
629 c = getc (infile);
630 /* Detect a dynamic doc string and save it for the next expression. */
631 if (c == '#')
632 {
633 c = getc (infile);
634 if (c == '@')
635 {
636 int length = 0;
637 int i;
638
639 /* Read the length. */
640 while ((c = getc (infile),
641 c >= '0' && c <= '9'))
642 {
643 length *= 10;
644 length += c - '0';
645 }
646
647 /* The next character is a space that is counted in the length
648 but not part of the doc string.
649 We already read it, so just ignore it. */
650 length--;
651
652 /* Read in the contents. */
653 if (saved_string != 0)
654 free (saved_string);
655 saved_string = (char *) malloc (length);
656 for (i = 0; i < length; i++)
657 saved_string[i] = getc (infile);
658 /* The last character is a ^_.
659 That is needed in the .elc file
660 but it is redundant in DOC. So get rid of it here. */
661 saved_string[length - 1] = 0;
662 /* Skip the line break. */
663 while (c == '\n' && c == '\r')
664 c = getc (infile);
665 /* Skip the following line. */
666 while (c != '\n' && c != '\r')
667 c = getc (infile);
668 }
669 continue;
670 }
671
672 if (c != '(')
673 continue;
674
675 read_lisp_symbol (infile, buffer);
676
677 if (! strcmp (buffer, "defun")
678 || ! strcmp (buffer, "defmacro"))
679 {
680 type = 'F';
681 read_lisp_symbol (infile, buffer);
682
683 /* Skip the arguments: either "nil" or a list in parens */
684
685 c = getc (infile);
686 if (c == 'n') /* nil */
687 {
688 if ((c = getc (infile)) != 'i'
689 || (c = getc (infile)) != 'l')
690 {
691 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
692 buffer, filename);
693 continue;
694 }
695 }
696 else if (c != '(')
697 {
698 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
699 buffer, filename);
700 continue;
701 }
702 else
703 while (c != ')')
704 c = getc (infile);
705 skip_white (infile);
706
707 /* If the next three characters aren't `dquote bslash newline'
708 then we're not reading a docstring.
709 */
710 if ((c = getc (infile)) != '"'
711 || (c = getc (infile)) != '\\'
712 || ((c = getc (infile)) != '\n' && c != '\r'))
713 {
714 #ifdef DEBUG
715 fprintf (stderr, "## non-docstring in %s (%s)\n",
716 buffer, filename);
717 #endif
718 continue;
719 }
720 }
721
722 else if (! strcmp (buffer, "defvar")
723 || ! strcmp (buffer, "defconst"))
724 {
725 char c1 = 0, c2 = 0;
726 type = 'V';
727 read_lisp_symbol (infile, buffer);
728
729 if (saved_string == 0)
730 {
731
732 /* Skip until the end of line; remember two previous chars. */
733 while (c != '\n' && c != '\r' && c >= 0)
734 {
735 c2 = c1;
736 c1 = c;
737 c = getc (infile);
738 }
739
740 /* If two previous characters were " and \,
741 this is a doc string. Otherwise, there is none. */
742 if (c2 != '"' || c1 != '\\')
743 {
744 #ifdef DEBUG
745 fprintf (stderr, "## non-docstring in %s (%s)\n",
746 buffer, filename);
747 #endif
748 continue;
749 }
750 }
751 }
752
753 else if (! strcmp (buffer, "custom-declare-variable"))
754 {
755 char c1 = 0, c2 = 0;
756 type = 'V';
757
758 c = getc (infile);
759 if (c == '\'')
760 read_lisp_symbol (infile, buffer);
761 else
762 {
763 if (c != '(')
764 {
765 fprintf (stderr,
766 "## unparsable name in custom-declare-variable in %s\n",
767 filename);
768 continue;
769 }
770 read_lisp_symbol (infile, buffer);
771 if (strcmp (buffer, "quote"))
772 {
773 fprintf (stderr,
774 "## unparsable name in custom-declare-variable in %s\n",
775 filename);
776 continue;
777 }
778 read_lisp_symbol (infile, buffer);
779 c = getc (infile);
780 if (c != ')')
781 {
782 fprintf (stderr,
783 "## unparsable quoted name in custom-declare-variable in %s\n",
784 filename);
785 continue;
786 }
787 }
788
789 if (saved_string == 0)
790 {
791 /* Skip to end of line; remember the two previous chars. */
792 while (c != '\n' && c != '\r' && c >= 0)
793 {
794 c2 = c1;
795 c1 = c;
796 c = getc (infile);
797 }
798
799 /* If two previous characters were " and \,
800 this is a doc string. Otherwise, there is none. */
801 if (c2 != '"' || c1 != '\\')
802 {
803 #ifdef DEBUG
804 fprintf (stderr, "## non-docstring in %s (%s)\n",
805 buffer, filename);
806 #endif
807 continue;
808 }
809 }
810 }
811
812 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
813 {
814 char c1 = 0, c2 = 0;
815 type = 'F';
816
817 c = getc (infile);
818 if (c == '\'')
819 read_lisp_symbol (infile, buffer);
820 else
821 {
822 if (c != '(')
823 {
824 fprintf (stderr, "## unparsable name in fset in %s\n",
825 filename);
826 continue;
827 }
828 read_lisp_symbol (infile, buffer);
829 if (strcmp (buffer, "quote"))
830 {
831 fprintf (stderr, "## unparsable name in fset in %s\n",
832 filename);
833 continue;
834 }
835 read_lisp_symbol (infile, buffer);
836 c = getc (infile);
837 if (c != ')')
838 {
839 fprintf (stderr,
840 "## unparsable quoted name in fset in %s\n",
841 filename);
842 continue;
843 }
844 }
845
846 if (saved_string == 0)
847 {
848 /* Skip to end of line; remember the two previous chars. */
849 while (c != '\n' && c != '\r' && c >= 0)
850 {
851 c2 = c1;
852 c1 = c;
853 c = getc (infile);
854 }
855
856 /* If two previous characters were " and \,
857 this is a doc string. Otherwise, there is none. */
858 if (c2 != '"' || c1 != '\\')
859 {
860 #ifdef DEBUG
861 fprintf (stderr, "## non-docstring in %s (%s)\n",
862 buffer, filename);
863 #endif
864 continue;
865 }
866 }
867 }
868
869 else if (! strcmp (buffer, "autoload"))
870 {
871 type = 'F';
872 c = getc (infile);
873 if (c == '\'')
874 read_lisp_symbol (infile, buffer);
875 else
876 {
877 if (c != '(')
878 {
879 fprintf (stderr, "## unparsable name in autoload in %s\n",
880 filename);
881 continue;
882 }
883 read_lisp_symbol (infile, buffer);
884 if (strcmp (buffer, "quote"))
885 {
886 fprintf (stderr, "## unparsable name in autoload in %s\n",
887 filename);
888 continue;
889 }
890 read_lisp_symbol (infile, buffer);
891 c = getc (infile);
892 if (c != ')')
893 {
894 fprintf (stderr,
895 "## unparsable quoted name in autoload in %s\n",
896 filename);
897 continue;
898 }
899 }
900 skip_white (infile);
901 if ((c = getc (infile)) != '\"')
902 {
903 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
904 buffer, filename);
905 continue;
906 }
907 read_c_string (infile, 0);
908 skip_white (infile);
909
910 if (saved_string == 0)
911 {
912 /* If the next three characters aren't `dquote bslash newline'
913 then we're not reading a docstring. */
914 if ((c = getc (infile)) != '"'
915 || (c = getc (infile)) != '\\'
916 || ((c = getc (infile)) != '\n' && c != '\r'))
917 {
918 #ifdef DEBUG
919 fprintf (stderr, "## non-docstring in %s (%s)\n",
920 buffer, filename);
921 #endif
922 continue;
923 }
924 }
925 }
926
927 #ifdef DEBUG
928 else if (! strcmp (buffer, "if")
929 || ! strcmp (buffer, "byte-code"))
930 ;
931 #endif
932
933 else
934 {
935 #ifdef DEBUG
936 fprintf (stderr, "## unrecognised top-level form, %s (%s)\n",
937 buffer, filename);
938 #endif
939 continue;
940 }
941
942 /* At this point, we should either use the previous
943 dynamic doc string in saved_string
944 or gobble a doc string from the input file.
945
946 In the latter case, the opening quote (and leading
947 backslash-newline) have already been read. */
948
949 putc (037, outfile);
950 putc (type, outfile);
951 fprintf (outfile, "%s\n", buffer);
952 if (saved_string)
953 {
954 fputs (saved_string, outfile);
955 /* Don't use one dynamic doc string twice. */
956 free (saved_string);
957 saved_string = 0;
958 }
959 else
960 read_c_string (infile, 1);
961 }
962 fclose (infile);
963 return 0;
964 }