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