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