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