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