(b2m): Add dependency on GETOPTDEPS.
[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
JB
528 (defmacro NAME ARGS DOCSTRING ...)
529 (autoload (quote NAME) FILE DOCSTRING ...)
f2cc4248
RS
530 (defvar NAME VALUE DOCSTRING)
531 (defconst NAME VALUE DOCSTRING)
23d6b5a6
JB
532 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
533 (fset (quote NAME) #[... DOCSTRING ...])
2d6e2619 534 (defalias (quote NAME) #[... DOCSTRING ...])
3fe77f98 535 (custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
f2cc4248 536 starting in column zero.
23d6b5a6 537 (quote NAME) may appear as 'NAME as well.
b5ff43cc
RS
538
539 We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
540 When we find that, we save it for the following defining-form,
541 and we use that instead of reading a doc string within that defining-form.
542
eb8c3be9 543 For defvar, defconst, and fset we skip to the docstring with a kludgy
23d6b5a6
JB
544 formatting convention: all docstrings must appear on the same line as the
545 initial open-paren (the one in column zero) and must contain a backslash
b0f08a24 546 and a newline immediately after the initial double-quote. No newlines
23d6b5a6 547 must appear between the beginning of the form and the first double-quote.
b0f08a24
DL
548 For defun, defmacro, and autoload, we know how to skip over the
549 arglist, but the doc string must still have a backslash and newline
550 immediately after the double quote.
551 The only source files that must follow this convention are preloaded
552 uncompiled ones like loaddefs.el and bindings.el; aside
23d6b5a6
JB
553 from that, it is always the .elc file that we look at, and they are no
554 problem because byte-compiler output follows this convention.
f2cc4248
RS
555 The NAME and DOCSTRING are output.
556 NAME is preceded by `F' for a function or `V' for a variable.
557 An entry is output only if DOCSTRING has \ newline just after the opening "
558 */
559
23d6b5a6
JB
560void
561skip_white (infile)
562 FILE *infile;
563{
564 char c = ' ';
433d333d 565 while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
23d6b5a6
JB
566 c = getc (infile);
567 ungetc (c, infile);
568}
569
570void
571read_lisp_symbol (infile, buffer)
572 FILE *infile;
573 char *buffer;
574{
575 char c;
576 char *fillp = buffer;
577
578 skip_white (infile);
579 while (1)
580 {
581 c = getc (infile);
582 if (c == '\\')
583 *(++fillp) = getc (infile);
433d333d 584 else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '(' || c == ')')
23d6b5a6
JB
585 {
586 ungetc (c, infile);
587 *fillp = 0;
588 break;
589 }
590 else
591 *fillp++ = c;
592 }
593
594 if (! buffer[0])
595 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
596
597 skip_white (infile);
598}
599
340ff9de 600int
e3938952
RS
601scan_lisp_file (filename, mode)
602 char *filename, *mode;
f2cc4248
RS
603{
604 FILE *infile;
605 register int c;
b5ff43cc 606 char *saved_string = 0;
f2cc4248 607
e3938952 608 infile = fopen (filename, mode);
f2cc4248
RS
609 if (infile == NULL)
610 {
611 perror (filename);
612 return 0; /* No error */
613 }
614
615 c = '\n';
616 while (!feof (infile))
617 {
b5ff43cc 618 char buffer[BUFSIZ];
23d6b5a6
JB
619 char type;
620
66f54605 621 /* If not at end of line, skip till we get to one. */
433d333d 622 if (c != '\n' && c != '\r')
f2cc4248
RS
623 {
624 c = getc (infile);
625 continue;
626 }
66f54605 627 /* Skip the line break. */
7e6972e9 628 while (c == '\n' || c == '\r')
66f54605 629 c = getc (infile);
b5ff43cc
RS
630 /* Detect a dynamic doc string and save it for the next expression. */
631 if (c == '#')
632 {
633 c = getc (infile);
634 if (c == '@')
635 {
636 int length = 0;
637 int i;
638
639 /* Read the length. */
640 while ((c = getc (infile),
641 c >= '0' && c <= '9'))
642 {
643 length *= 10;
644 length += c - '0';
645 }
646
647 /* The next character is a space that is counted in the length
648 but not part of the doc string.
649 We already read it, so just ignore it. */
650 length--;
651
652 /* Read in the contents. */
653 if (saved_string != 0)
654 free (saved_string);
655 saved_string = (char *) malloc (length);
656 for (i = 0; i < length; i++)
657 saved_string[i] = getc (infile);
658 /* The last character is a ^_.
659 That is needed in the .elc file
660 but it is redundant in DOC. So get rid of it here. */
661 saved_string[length - 1] = 0;
66f54605
PR
662 /* Skip the line break. */
663 while (c == '\n' && c == '\r')
664 c = getc (infile);
665 /* Skip the following line. */
433d333d 666 while (c != '\n' && c != '\r')
b5ff43cc
RS
667 c = getc (infile);
668 }
669 continue;
670 }
671
f2cc4248
RS
672 if (c != '(')
673 continue;
a8a7afbe 674
23d6b5a6
JB
675 read_lisp_symbol (infile, buffer);
676
66f54605
PR
677 if (! strcmp (buffer, "defun")
678 || ! strcmp (buffer, "defmacro"))
f2cc4248 679 {
23d6b5a6
JB
680 type = 'F';
681 read_lisp_symbol (infile, buffer);
f2cc4248 682
23d6b5a6 683 /* Skip the arguments: either "nil" or a list in parens */
f2cc4248 684
23d6b5a6
JB
685 c = getc (infile);
686 if (c == 'n') /* nil */
f2cc4248 687 {
66f54605
PR
688 if ((c = getc (infile)) != 'i'
689 || (c = getc (infile)) != 'l')
23d6b5a6
JB
690 {
691 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
692 buffer, filename);
693 continue;
694 }
f2cc4248 695 }
23d6b5a6 696 else if (c != '(')
f2cc4248 697 {
23d6b5a6
JB
698 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
699 buffer, filename);
700 continue;
f2cc4248 701 }
23d6b5a6
JB
702 else
703 while (c != ')')
f2cc4248 704 c = getc (infile);
23d6b5a6
JB
705 skip_white (infile);
706
707 /* If the next three characters aren't `dquote bslash newline'
708 then we're not reading a docstring.
709 */
66f54605
PR
710 if ((c = getc (infile)) != '"'
711 || (c = getc (infile)) != '\\'
712 || ((c = getc (infile)) != '\n' && c != '\r'))
f2cc4248 713 {
23d6b5a6
JB
714#ifdef DEBUG
715 fprintf (stderr, "## non-docstring in %s (%s)\n",
716 buffer, filename);
717#endif
718 continue;
f2cc4248 719 }
f2cc4248 720 }
a8a7afbe 721
66f54605
PR
722 else if (! strcmp (buffer, "defvar")
723 || ! strcmp (buffer, "defconst"))
f2cc4248 724 {
23d6b5a6
JB
725 char c1 = 0, c2 = 0;
726 type = 'V';
727 read_lisp_symbol (infile, buffer);
a8a7afbe 728
b5ff43cc 729 if (saved_string == 0)
f2cc4248 730 {
b5ff43cc 731
66f54605 732 /* Skip until the end of line; remember two previous chars. */
433d333d 733 while (c != '\n' && c != '\r' && c >= 0)
b5ff43cc
RS
734 {
735 c2 = c1;
736 c1 = c;
737 c = getc (infile);
738 }
23d6b5a6 739
b5ff43cc
RS
740 /* If two previous characters were " and \,
741 this is a doc string. Otherwise, there is none. */
742 if (c2 != '"' || c1 != '\\')
743 {
23d6b5a6 744#ifdef DEBUG
b5ff43cc
RS
745 fprintf (stderr, "## non-docstring in %s (%s)\n",
746 buffer, filename);
23d6b5a6 747#endif
b5ff43cc
RS
748 continue;
749 }
f2cc4248 750 }
23d6b5a6
JB
751 }
752
3fe77f98
RS
753 else if (! strcmp (buffer, "custom-declare-variable"))
754 {
755 char c1 = 0, c2 = 0;
756 type = 'V';
757
758 c = getc (infile);
759 if (c == '\'')
760 read_lisp_symbol (infile, buffer);
761 else
762 {
763 if (c != '(')
764 {
765 fprintf (stderr,
766 "## unparsable name in custom-declare-variable in %s\n",
767 filename);
768 continue;
769 }
770 read_lisp_symbol (infile, buffer);
771 if (strcmp (buffer, "quote"))
772 {
773 fprintf (stderr,
774 "## unparsable name in custom-declare-variable in %s\n",
775 filename);
776 continue;
777 }
778 read_lisp_symbol (infile, buffer);
779 c = getc (infile);
780 if (c != ')')
781 {
782 fprintf (stderr,
783 "## unparsable quoted name in custom-declare-variable in %s\n",
784 filename);
785 continue;
786 }
787 }
788
789 if (saved_string == 0)
790 {
66f54605 791 /* Skip to end of line; remember the two previous chars. */
433d333d 792 while (c != '\n' && c != '\r' && c >= 0)
3fe77f98
RS
793 {
794 c2 = c1;
795 c1 = c;
796 c = getc (infile);
797 }
798
799 /* If two previous characters were " and \,
800 this is a doc string. Otherwise, there is none. */
801 if (c2 != '"' || c1 != '\\')
802 {
803#ifdef DEBUG
804 fprintf (stderr, "## non-docstring in %s (%s)\n",
805 buffer, filename);
806#endif
807 continue;
808 }
809 }
810 }
811
2d6e2619 812 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
23d6b5a6
JB
813 {
814 char c1 = 0, c2 = 0;
815 type = 'F';
a8a7afbe 816
23d6b5a6
JB
817 c = getc (infile);
818 if (c == '\'')
819 read_lisp_symbol (infile, buffer);
820 else
f2cc4248 821 {
23d6b5a6
JB
822 if (c != '(')
823 {
824 fprintf (stderr, "## unparsable name in fset in %s\n",
825 filename);
826 continue;
827 }
828 read_lisp_symbol (infile, buffer);
829 if (strcmp (buffer, "quote"))
830 {
831 fprintf (stderr, "## unparsable name in fset in %s\n",
832 filename);
833 continue;
834 }
835 read_lisp_symbol (infile, buffer);
f2cc4248 836 c = getc (infile);
23d6b5a6
JB
837 if (c != ')')
838 {
839 fprintf (stderr,
840 "## unparsable quoted name in fset in %s\n",
841 filename);
842 continue;
843 }
f2cc4248 844 }
f2cc4248 845
b5ff43cc 846 if (saved_string == 0)
f2cc4248 847 {
66f54605 848 /* Skip to end of line; remember the two previous chars. */
433d333d 849 while (c != '\n' && c != '\r' && c >= 0)
b5ff43cc
RS
850 {
851 c2 = c1;
852 c1 = c;
853 c = getc (infile);
854 }
23d6b5a6 855
b5ff43cc
RS
856 /* If two previous characters were " and \,
857 this is a doc string. Otherwise, there is none. */
858 if (c2 != '"' || c1 != '\\')
859 {
23d6b5a6 860#ifdef DEBUG
b5ff43cc
RS
861 fprintf (stderr, "## non-docstring in %s (%s)\n",
862 buffer, filename);
23d6b5a6 863#endif
b5ff43cc
RS
864 continue;
865 }
23d6b5a6
JB
866 }
867 }
f2cc4248 868
23d6b5a6
JB
869 else if (! strcmp (buffer, "autoload"))
870 {
871 type = 'F';
872 c = getc (infile);
873 if (c == '\'')
874 read_lisp_symbol (infile, buffer);
875 else
f2cc4248 876 {
23d6b5a6 877 if (c != '(')
f2cc4248 878 {
23d6b5a6
JB
879 fprintf (stderr, "## unparsable name in autoload in %s\n",
880 filename);
881 continue;
f2cc4248 882 }
23d6b5a6
JB
883 read_lisp_symbol (infile, buffer);
884 if (strcmp (buffer, "quote"))
f2cc4248 885 {
23d6b5a6
JB
886 fprintf (stderr, "## unparsable name in autoload in %s\n",
887 filename);
888 continue;
f2cc4248 889 }
23d6b5a6 890 read_lisp_symbol (infile, buffer);
f2cc4248 891 c = getc (infile);
23d6b5a6 892 if (c != ')')
f2cc4248 893 {
23d6b5a6
JB
894 fprintf (stderr,
895 "## unparsable quoted name in autoload in %s\n",
896 filename);
897 continue;
f2cc4248 898 }
23d6b5a6
JB
899 }
900 skip_white (infile);
901 if ((c = getc (infile)) != '\"')
902 {
903 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
904 buffer, filename);
f2cc4248
RS
905 continue;
906 }
23d6b5a6
JB
907 read_c_string (infile, 0);
908 skip_white (infile);
909
b5ff43cc 910 if (saved_string == 0)
a8a7afbe 911 {
b5ff43cc
RS
912 /* If the next three characters aren't `dquote bslash newline'
913 then we're not reading a docstring. */
66f54605
PR
914 if ((c = getc (infile)) != '"'
915 || (c = getc (infile)) != '\\'
916 || ((c = getc (infile)) != '\n' && c != '\r'))
b5ff43cc 917 {
23d6b5a6 918#ifdef DEBUG
b5ff43cc
RS
919 fprintf (stderr, "## non-docstring in %s (%s)\n",
920 buffer, filename);
23d6b5a6 921#endif
b5ff43cc
RS
922 continue;
923 }
a8a7afbe 924 }
a8a7afbe 925 }
f2cc4248 926
23d6b5a6 927#ifdef DEBUG
66f54605
PR
928 else if (! strcmp (buffer, "if")
929 || ! strcmp (buffer, "byte-code"))
23d6b5a6
JB
930 ;
931#endif
f2cc4248 932
23d6b5a6
JB
933 else
934 {
935#ifdef DEBUG
936 fprintf (stderr, "## unrecognised top-level form, %s (%s)\n",
937 buffer, filename);
938#endif
939 continue;
940 }
f2cc4248 941
b5ff43cc
RS
942 /* At this point, we should either use the previous
943 dynamic doc string in saved_string
944 or gobble a doc string from the input file.
945
946 In the latter case, the opening quote (and leading
947 backslash-newline) have already been read. */
948
f2cc4248 949 putc (037, outfile);
23d6b5a6
JB
950 putc (type, outfile);
951 fprintf (outfile, "%s\n", buffer);
b5ff43cc
RS
952 if (saved_string)
953 {
954 fputs (saved_string, outfile);
955 /* Don't use one dynamic doc string twice. */
956 free (saved_string);
957 saved_string = 0;
958 }
959 else
960 read_c_string (infile, 1);
f2cc4248
RS
961 }
962 fclose (infile);
963 return 0;
964}