comparison lib-src/make-docfile.c @ 0:376386a54a3c r19-14

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