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