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