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