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