(ph-server): Fix customize type.
[bpt/emacs.git] / 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 /* Stdio stream for output to the DOC file. */
67 FILE *outfile;
68
69 /* Name this program was invoked with. */
70 char *progname;
71
72 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
73
74 /* VARARGS1 */
75 void
76 error (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 */
87 void
88 fatal (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
97 long *
98 xmalloc (size)
99 unsigned int size;
100 {
101 long *result = (long *) malloc (size);
102 if (result == NULL)
103 fatal ("virtual memory exhausted", 0);
104 return result;
105 }
106 \f
107 int
108 main (argc, argv)
109 int argc;
110 char **argv;
111 {
112 int i;
113 int err_count = 0;
114 int first_infile;
115
116 progname = argv[0];
117
118 outfile = stdout;
119
120 /* Don't put CRs in the DOC file. */
121 #ifdef MSDOS
122 _fmode = O_BINARY;
123 #if 0 /* Suspicion is that this causes hanging.
124 So instead we require people to use -o on MSDOS. */
125 (stdout)->_flag &= ~_IOTEXT;
126 _setmode (fileno (stdout), O_BINARY);
127 #endif
128 outfile = 0;
129 #endif /* MSDOS */
130 #ifdef WINDOWSNT
131 _fmode = O_BINARY;
132 _setmode (fileno (stdout), O_BINARY);
133 #endif /* WINDOWSNT */
134
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 }
147 if (argc > i + 1 && !strcmp (argv[i], "-d"))
148 {
149 chdir (argv[i + 1]);
150 i += 2;
151 }
152
153 if (outfile == 0)
154 fatal ("No output file specified", "");
155
156 first_infile = i;
157 for (; i < argc; i++)
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 }
167 #ifndef VMS
168 exit (err_count > 0);
169 #endif /* VMS */
170 return err_count > 0;
171 }
172
173 /* Read file FILENAME and output its doc strings to outfile. */
174 /* Return 1 if file is not found, 0 if it is found. */
175
176 int
177 scan_file (filename)
178 char *filename;
179 {
180 int len = strlen (filename);
181 if (len > 4 && !strcmp (filename + len - 4, ".elc"))
182 return scan_lisp_file (filename, READ_BINARY);
183 else if (len > 3 && !strcmp (filename + len - 3, ".el"))
184 return scan_lisp_file (filename, READ_TEXT);
185 else
186 return scan_c_file (filename, READ_TEXT);
187 }
188 \f
189 char buf[128];
190
191 /* Skip a C string from INFILE,
192 and return the character that follows the closing ".
193 If printflag is positive, output string contents to outfile.
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
198 int
199 read_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;
233 /* If we had a "", concatenate the two strings. */
234 c = getc (infile);
235 }
236
237 if (printflag < 0)
238 *p = 0;
239
240 return c;
241 }
242 \f
243 /* Write to file OUT the argument names of function FUNC, whose text is in BUF.
244 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
245
246 void
247 write_c_args (out, func, buf, minargs, maxargs)
248 FILE *out;
249 char *func, *buf;
250 int minargs, maxargs;
251 {
252 register char *p;
253 int in_ident = 0;
254 int just_spaced = 0;
255 int need_space = 1;
256
257 fprintf (out, "(%s", func);
258
259 if (*buf == '(')
260 ++buf;
261
262 for (p = buf; *p; p++)
263 {
264 char c = *p;
265 int ident_start = 0;
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)
273 {
274 if (!in_ident)
275 {
276 in_ident = 1;
277 ident_start = 1;
278
279 if (need_space)
280 putc (' ', out);
281
282 if (minargs == 0 && maxargs > 0)
283 fprintf (out, "&optional ");
284 just_spaced = 1;
285
286 minargs--;
287 maxargs--;
288 }
289 else
290 in_ident = 0;
291 }
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
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 {
308 fprintf (out, "DEFAULT");
309 p += 5;
310 in_ident = 0;
311 just_spaced = 0;
312 }
313 else if (c != ' ' || ! just_spaced)
314 {
315 if (c >= 'a' && c <= 'z')
316 /* Upcase the letter. */
317 c += 'A' - 'a';
318 putc (c, out);
319 }
320
321 just_spaced = (c == ' ');
322 need_space = 0;
323 }
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
331 int
332 scan_c_file (filename, mode)
333 char *filename, *mode;
334 {
335 FILE *infile;
336 register int c;
337 register int commas;
338 register int defunflag;
339 register int defvarperbufferflag;
340 register int defvarflag;
341 int minargs, maxargs;
342 int extension = filename[strlen (filename) - 1];
343
344 if (extension == 'o')
345 filename[strlen (filename) - 1] = 'c';
346
347 infile = fopen (filename, mode);
348
349 /* No error if non-ex input file */
350 if (infile == NULL)
351 {
352 perror (filename);
353 return 0;
354 }
355
356 /* Reset extension to be able to detect duplicate files. */
357 filename[strlen (filename) - 1] = extension;
358
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;
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
393 defvarflag = 1;
394 defunflag = 0;
395
396 c = getc (infile);
397 defvarperbufferflag = (c == 'P');
398
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;
429 else if (defvarperbufferflag)
430 commas = 2;
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);
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)
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");
507 write_c_args (outfile, buf, argbuf, minargs, maxargs);
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 ...)
519 (defmacro NAME ARGS DOCSTRING ...)
520 (autoload (quote NAME) FILE DOCSTRING ...)
521 (defvar NAME VALUE DOCSTRING)
522 (defconst NAME VALUE DOCSTRING)
523 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
524 (fset (quote NAME) #[... DOCSTRING ...])
525 (defalias (quote NAME) #[... DOCSTRING ...])
526 (custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
527 starting in column zero.
528 (quote NAME) may appear as 'NAME as well.
529
530 We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
531 When we find that, we save it for the following defining-form,
532 and we use that instead of reading a doc string within that defining-form.
533
534 For defun, defmacro, and autoload, we know how to skip over the arglist.
535 For defvar, defconst, and fset we skip to the docstring with a kludgy
536 formatting convention: all docstrings must appear on the same line as the
537 initial open-paren (the one in column zero) and must contain a backslash
538 and a double-quote immediately after the initial double-quote. No newlines
539 must appear between the beginning of the form and the first double-quote.
540 The only source file that must follow this convention is loaddefs.el; aside
541 from that, it is always the .elc file that we look at, and they are no
542 problem because byte-compiler output follows this convention.
543 The NAME and DOCSTRING are output.
544 NAME is preceded by `F' for a function or `V' for a variable.
545 An entry is output only if DOCSTRING has \ newline just after the opening "
546 */
547
548 void
549 skip_white (infile)
550 FILE *infile;
551 {
552 char c = ' ';
553 while (c == ' ' || c == '\t' || c == '\n')
554 c = getc (infile);
555 ungetc (c, infile);
556 }
557
558 void
559 read_lisp_symbol (infile, buffer)
560 FILE *infile;
561 char *buffer;
562 {
563 char c;
564 char *fillp = buffer;
565
566 skip_white (infile);
567 while (1)
568 {
569 c = getc (infile);
570 if (c == '\\')
571 *(++fillp) = getc (infile);
572 else if (c == ' ' || c == '\t' || c == '\n' || c == '(' || c == ')')
573 {
574 ungetc (c, infile);
575 *fillp = 0;
576 break;
577 }
578 else
579 *fillp++ = c;
580 }
581
582 if (! buffer[0])
583 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
584
585 skip_white (infile);
586 }
587
588 int
589 scan_lisp_file (filename, mode)
590 char *filename, *mode;
591 {
592 FILE *infile;
593 register int c;
594 char *saved_string = 0;
595
596 infile = fopen (filename, mode);
597 if (infile == NULL)
598 {
599 perror (filename);
600 return 0; /* No error */
601 }
602
603 c = '\n';
604 while (!feof (infile))
605 {
606 char buffer[BUFSIZ];
607 char type;
608
609 if (c != '\n')
610 {
611 c = getc (infile);
612 continue;
613 }
614 c = getc (infile);
615 /* Detect a dynamic doc string and save it for the next expression. */
616 if (c == '#')
617 {
618 c = getc (infile);
619 if (c == '@')
620 {
621 int length = 0;
622 int i;
623
624 /* Read the length. */
625 while ((c = getc (infile),
626 c >= '0' && c <= '9'))
627 {
628 length *= 10;
629 length += c - '0';
630 }
631
632 /* The next character is a space that is counted in the length
633 but not part of the doc string.
634 We already read it, so just ignore it. */
635 length--;
636
637 /* Read in the contents. */
638 if (saved_string != 0)
639 free (saved_string);
640 saved_string = (char *) malloc (length);
641 for (i = 0; i < length; i++)
642 saved_string[i] = getc (infile);
643 /* The last character is a ^_.
644 That is needed in the .elc file
645 but it is redundant in DOC. So get rid of it here. */
646 saved_string[length - 1] = 0;
647 /* Skip the newline. */
648 c = getc (infile);
649 while (c != '\n')
650 c = getc (infile);
651 }
652 continue;
653 }
654
655 if (c != '(')
656 continue;
657
658 read_lisp_symbol (infile, buffer);
659
660 if (! strcmp (buffer, "defun") ||
661 ! strcmp (buffer, "defmacro"))
662 {
663 type = 'F';
664 read_lisp_symbol (infile, buffer);
665
666 /* Skip the arguments: either "nil" or a list in parens */
667
668 c = getc (infile);
669 if (c == 'n') /* nil */
670 {
671 if ((c = getc (infile)) != 'i' ||
672 (c = getc (infile)) != 'l')
673 {
674 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
675 buffer, filename);
676 continue;
677 }
678 }
679 else if (c != '(')
680 {
681 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
682 buffer, filename);
683 continue;
684 }
685 else
686 while (c != ')')
687 c = getc (infile);
688 skip_white (infile);
689
690 /* If the next three characters aren't `dquote bslash newline'
691 then we're not reading a docstring.
692 */
693 if ((c = getc (infile)) != '"' ||
694 (c = getc (infile)) != '\\' ||
695 (c = getc (infile)) != '\n')
696 {
697 #ifdef DEBUG
698 fprintf (stderr, "## non-docstring in %s (%s)\n",
699 buffer, filename);
700 #endif
701 continue;
702 }
703 }
704
705 else if (! strcmp (buffer, "defvar") ||
706 ! strcmp (buffer, "defconst"))
707 {
708 char c1 = 0, c2 = 0;
709 type = 'V';
710 read_lisp_symbol (infile, buffer);
711
712 if (saved_string == 0)
713 {
714
715 /* Skip until the first newline; remember the two previous chars. */
716 while (c != '\n' && c >= 0)
717 {
718 c2 = c1;
719 c1 = c;
720 c = getc (infile);
721 }
722
723 /* If two previous characters were " and \,
724 this is a doc string. Otherwise, there is none. */
725 if (c2 != '"' || c1 != '\\')
726 {
727 #ifdef DEBUG
728 fprintf (stderr, "## non-docstring in %s (%s)\n",
729 buffer, filename);
730 #endif
731 continue;
732 }
733 }
734 }
735
736 else if (! strcmp (buffer, "custom-declare-variable"))
737 {
738 char c1 = 0, c2 = 0;
739 type = 'V';
740
741 c = getc (infile);
742 if (c == '\'')
743 read_lisp_symbol (infile, buffer);
744 else
745 {
746 if (c != '(')
747 {
748 fprintf (stderr,
749 "## unparsable name in custom-declare-variable in %s\n",
750 filename);
751 continue;
752 }
753 read_lisp_symbol (infile, buffer);
754 if (strcmp (buffer, "quote"))
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 c = getc (infile);
763 if (c != ')')
764 {
765 fprintf (stderr,
766 "## unparsable quoted name in custom-declare-variable in %s\n",
767 filename);
768 continue;
769 }
770 }
771
772 if (saved_string == 0)
773 {
774 /* Skip until the first newline; remember the two previous
775 chars. */
776 while (c != '\n' && c >= 0)
777 {
778 c2 = c1;
779 c1 = c;
780 c = getc (infile);
781 }
782
783 /* If two previous characters were " and \,
784 this is a doc string. Otherwise, there is none. */
785 if (c2 != '"' || c1 != '\\')
786 {
787 #ifdef DEBUG
788 fprintf (stderr, "## non-docstring in %s (%s)\n",
789 buffer, filename);
790 #endif
791 continue;
792 }
793 }
794 }
795
796 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
797 {
798 char c1 = 0, c2 = 0;
799 type = 'F';
800
801 c = getc (infile);
802 if (c == '\'')
803 read_lisp_symbol (infile, buffer);
804 else
805 {
806 if (c != '(')
807 {
808 fprintf (stderr, "## unparsable name in fset in %s\n",
809 filename);
810 continue;
811 }
812 read_lisp_symbol (infile, buffer);
813 if (strcmp (buffer, "quote"))
814 {
815 fprintf (stderr, "## unparsable name in fset in %s\n",
816 filename);
817 continue;
818 }
819 read_lisp_symbol (infile, buffer);
820 c = getc (infile);
821 if (c != ')')
822 {
823 fprintf (stderr,
824 "## unparsable quoted name in fset in %s\n",
825 filename);
826 continue;
827 }
828 }
829
830 if (saved_string == 0)
831 {
832 /* Skip until the first newline; remember the two previous chars. */
833 while (c != '\n' && c >= 0)
834 {
835 c2 = c1;
836 c1 = c;
837 c = getc (infile);
838 }
839
840 /* If two previous characters were " and \,
841 this is a doc string. Otherwise, there is none. */
842 if (c2 != '"' || c1 != '\\')
843 {
844 #ifdef DEBUG
845 fprintf (stderr, "## non-docstring in %s (%s)\n",
846 buffer, filename);
847 #endif
848 continue;
849 }
850 }
851 }
852
853 else if (! strcmp (buffer, "autoload"))
854 {
855 type = 'F';
856 c = getc (infile);
857 if (c == '\'')
858 read_lisp_symbol (infile, buffer);
859 else
860 {
861 if (c != '(')
862 {
863 fprintf (stderr, "## unparsable name in autoload in %s\n",
864 filename);
865 continue;
866 }
867 read_lisp_symbol (infile, buffer);
868 if (strcmp (buffer, "quote"))
869 {
870 fprintf (stderr, "## unparsable name in autoload in %s\n",
871 filename);
872 continue;
873 }
874 read_lisp_symbol (infile, buffer);
875 c = getc (infile);
876 if (c != ')')
877 {
878 fprintf (stderr,
879 "## unparsable quoted name in autoload in %s\n",
880 filename);
881 continue;
882 }
883 }
884 skip_white (infile);
885 if ((c = getc (infile)) != '\"')
886 {
887 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
888 buffer, filename);
889 continue;
890 }
891 read_c_string (infile, 0);
892 skip_white (infile);
893
894 if (saved_string == 0)
895 {
896 /* If the next three characters aren't `dquote bslash newline'
897 then we're not reading a docstring. */
898 if ((c = getc (infile)) != '"' ||
899 (c = getc (infile)) != '\\' ||
900 (c = getc (infile)) != '\n')
901 {
902 #ifdef DEBUG
903 fprintf (stderr, "## non-docstring in %s (%s)\n",
904 buffer, filename);
905 #endif
906 continue;
907 }
908 }
909 }
910
911 #ifdef DEBUG
912 else if (! strcmp (buffer, "if") ||
913 ! strcmp (buffer, "byte-code"))
914 ;
915 #endif
916
917 else
918 {
919 #ifdef DEBUG
920 fprintf (stderr, "## unrecognised top-level form, %s (%s)\n",
921 buffer, filename);
922 #endif
923 continue;
924 }
925
926 /* At this point, we should either use the previous
927 dynamic doc string in saved_string
928 or gobble a doc string from the input file.
929
930 In the latter case, the opening quote (and leading
931 backslash-newline) have already been read. */
932
933 putc (037, outfile);
934 putc (type, outfile);
935 fprintf (outfile, "%s\n", buffer);
936 if (saved_string)
937 {
938 fputs (saved_string, outfile);
939 /* Don't use one dynamic doc string twice. */
940 free (saved_string);
941 saved_string = 0;
942 }
943 else
944 read_c_string (infile, 1);
945 }
946 fclose (infile);
947 return 0;
948 }