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