]> code.delx.au - gnu-emacs/blob - lib-src/make-docfile.c
*** empty log message ***
[gnu-emacs] / lib-src / make-docfile.c
1 /* Generate doc-string file for GNU Emacs from source files.
2 Copyright (C) 1985, 86, 92, 93, 94, 97, 1999, 2000, 01, 2004
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
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 Option -d DIR means change to DIR before looking for files.
27
28 The results, which go to standard output or to a file
29 specified with -a or -o (-a to append, -o to start from nothing),
30 are entries containing function or variable names and their documentation.
31 Each entry starts with a ^_ character.
32 Then comes F for a function or V for a variable.
33 Then comes the function or variable name, terminated with a newline.
34 Then comes the documentation for that function or variable.
35 */
36
37 #define NO_SHORTNAMES /* Tell config not to load remap.h */
38 #include <config.h>
39
40 /* defined to be emacs_main, sys_fopen, etc. in config.h */
41 #undef main
42 #undef fopen
43 #undef chdir
44
45 #include <stdio.h>
46 #ifdef MSDOS
47 #include <fcntl.h>
48 #endif /* MSDOS */
49 #ifdef WINDOWSNT
50 #include <stdlib.h>
51 #include <fcntl.h>
52 #include <direct.h>
53 #endif /* WINDOWSNT */
54
55 #ifdef DOS_NT
56 #define READ_TEXT "rt"
57 #define READ_BINARY "rb"
58 #else /* not DOS_NT */
59 #define READ_TEXT "r"
60 #define READ_BINARY "r"
61 #endif /* not DOS_NT */
62
63 int scan_file ();
64 int scan_lisp_file ();
65 int scan_c_file ();
66
67 #ifdef MSDOS
68 /* s/msdos.h defines this as sys_chdir, but we're not linking with the
69 file where that function is defined. */
70 #undef chdir
71 #endif
72
73 #ifdef HAVE_UNISTD_H
74 #include <unistd.h>
75 #endif
76
77 /* Stdio stream for output to the DOC file. */
78 FILE *outfile;
79
80 /* Name this program was invoked with. */
81 char *progname;
82
83 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
84
85 /* VARARGS1 */
86 void
87 error (s1, s2)
88 char *s1, *s2;
89 {
90 fprintf (stderr, "%s: ", progname);
91 fprintf (stderr, s1, s2);
92 fprintf (stderr, "\n");
93 }
94
95 /* Print error message and exit. */
96
97 /* VARARGS1 */
98 void
99 fatal (s1, s2)
100 char *s1, *s2;
101 {
102 error (s1, s2);
103 exit (1);
104 }
105
106 /* Like malloc but get fatal error if memory is exhausted. */
107
108 void *
109 xmalloc (size)
110 unsigned int size;
111 {
112 void *result = (void *) malloc (size);
113 if (result == NULL)
114 fatal ("virtual memory exhausted", 0);
115 return result;
116 }
117 \f
118 int
119 main (argc, argv)
120 int argc;
121 char **argv;
122 {
123 int i;
124 int err_count = 0;
125 int first_infile;
126
127 progname = argv[0];
128
129 outfile = stdout;
130
131 /* Don't put CRs in the DOC file. */
132 #ifdef MSDOS
133 _fmode = O_BINARY;
134 #if 0 /* Suspicion is that this causes hanging.
135 So instead we require people to use -o on MSDOS. */
136 (stdout)->_flag &= ~_IOTEXT;
137 _setmode (fileno (stdout), O_BINARY);
138 #endif
139 outfile = 0;
140 #endif /* MSDOS */
141 #ifdef WINDOWSNT
142 _fmode = O_BINARY;
143 _setmode (fileno (stdout), O_BINARY);
144 #endif /* WINDOWSNT */
145
146 /* If first two args are -o FILE, output to FILE. */
147 i = 1;
148 if (argc > i + 1 && !strcmp (argv[i], "-o"))
149 {
150 outfile = fopen (argv[i + 1], "w");
151 i += 2;
152 }
153 if (argc > i + 1 && !strcmp (argv[i], "-a"))
154 {
155 outfile = fopen (argv[i + 1], "a");
156 i += 2;
157 }
158 if (argc > i + 1 && !strcmp (argv[i], "-d"))
159 {
160 chdir (argv[i + 1]);
161 i += 2;
162 }
163
164 if (outfile == 0)
165 fatal ("No output file specified", "");
166
167 first_infile = i;
168 for (; i < argc; i++)
169 {
170 int j;
171 /* Don't process one file twice. */
172 for (j = first_infile; j < i; j++)
173 if (! strcmp (argv[i], argv[j]))
174 break;
175 if (j == i)
176 err_count += scan_file (argv[i]);
177 }
178 return (err_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
179 }
180
181 /* Add a source file name boundary marker in the output file. */
182 void
183 put_filename (filename)
184 char *filename;
185 {
186 char *tmp = filename;
187 int len;
188
189 while ((tmp = index (filename, '/')))
190 filename = tmp + 1;
191
192 putc (037, outfile);
193 putc ('S', outfile);
194 fprintf (outfile, "%s\n", filename);
195 }
196
197 /* Read file FILENAME and output its doc strings to outfile. */
198 /* Return 1 if file is not found, 0 if it is found. */
199
200 int
201 scan_file (filename)
202 char *filename;
203 {
204 int len = strlen (filename);
205
206 put_filename (filename);
207 if (len > 4 && !strcmp (filename + len - 4, ".elc"))
208 return scan_lisp_file (filename, READ_BINARY);
209 else if (len > 3 && !strcmp (filename + len - 3, ".el"))
210 return scan_lisp_file (filename, READ_TEXT);
211 else
212 return scan_c_file (filename, READ_TEXT);
213 }
214 \f
215 char buf[128];
216
217 /* Some state during the execution of `read_c_string_or_comment'. */
218 struct rcsoc_state
219 {
220 /* A count of spaces and newlines that have been read, but not output. */
221 unsigned pending_spaces, pending_newlines;
222
223 /* Where we're reading from. */
224 FILE *in_file;
225
226 /* If non-zero, a buffer into which to copy characters. */
227 char *buf_ptr;
228 /* If non-zero, a file into which to copy characters. */
229 FILE *out_file;
230
231 /* A keyword we look for at the beginning of lines. If found, it is
232 not copied, and SAW_KEYWORD is set to true. */
233 char *keyword;
234 /* The current point we've reached in an occurance of KEYWORD in
235 the input stream. */
236 char *cur_keyword_ptr;
237 /* Set to true if we saw an occurance of KEYWORD. */
238 int saw_keyword;
239 };
240
241 /* Output CH to the file or buffer in STATE. Any pending newlines or
242 spaces are output first. */
243
244 static INLINE void
245 put_char (ch, state)
246 int ch;
247 struct rcsoc_state *state;
248 {
249 int out_ch;
250 do
251 {
252 if (state->pending_newlines > 0)
253 {
254 state->pending_newlines--;
255 out_ch = '\n';
256 }
257 else if (state->pending_spaces > 0)
258 {
259 state->pending_spaces--;
260 out_ch = ' ';
261 }
262 else
263 out_ch = ch;
264
265 if (state->out_file)
266 putc (out_ch, state->out_file);
267 if (state->buf_ptr)
268 *state->buf_ptr++ = out_ch;
269 }
270 while (out_ch != ch);
271 }
272
273 /* If in the middle of scanning a keyword, continue scanning with
274 character CH, otherwise output CH to the file or buffer in STATE.
275 Any pending newlines or spaces are output first, as well as any
276 previously scanned characters that were thought to be part of a
277 keyword, but were in fact not. */
278
279 static void
280 scan_keyword_or_put_char (ch, state)
281 int ch;
282 struct rcsoc_state *state;
283 {
284 if (state->keyword
285 && *state->cur_keyword_ptr == ch
286 && (state->cur_keyword_ptr > state->keyword
287 || state->pending_newlines > 0))
288 /* We might be looking at STATE->keyword at some point.
289 Keep looking until we know for sure. */
290 {
291 if (*++state->cur_keyword_ptr == '\0')
292 /* Saw the whole keyword. Set SAW_KEYWORD flag to true. */
293 {
294 state->saw_keyword = 1;
295
296 /* Reset the scanning pointer. */
297 state->cur_keyword_ptr = state->keyword;
298
299 /* Canonicalize whitespace preceding a usage string. */
300 state->pending_newlines = 2;
301 state->pending_spaces = 0;
302
303 /* Skip any whitespace between the keyword and the
304 usage string. */
305 do
306 ch = getc (state->in_file);
307 while (ch == ' ' || ch == '\n');
308
309 /* Output the open-paren we just read. */
310 put_char (ch, state);
311
312 /* Skip the function name and replace it with `fn'. */
313 do
314 ch = getc (state->in_file);
315 while (ch != ' ' && ch != ')');
316 put_char ('f', state);
317 put_char ('n', state);
318
319 /* Put back the last character. */
320 ungetc (ch, state->in_file);
321 }
322 }
323 else
324 {
325 if (state->keyword && state->cur_keyword_ptr > state->keyword)
326 /* We scanned the beginning of a potential usage
327 keyword, but it was a false alarm. Output the
328 part we scanned. */
329 {
330 char *p;
331
332 for (p = state->keyword; p < state->cur_keyword_ptr; p++)
333 put_char (*p, state);
334
335 state->cur_keyword_ptr = state->keyword;
336 }
337
338 put_char (ch, state);
339 }
340 }
341
342
343 /* Skip a C string or C-style comment from INFILE, and return the
344 character that follows. COMMENT non-zero means skip a comment. If
345 PRINTFLAG is positive, output string contents to outfile. If it is
346 negative, store contents in buf. Convert escape sequences \n and
347 \t to newline and tab; discard \ followed by newline.
348 If SAW_USAGE is non-zero, then any occurances of the string `usage:'
349 at the beginning of a line will be removed, and *SAW_USAGE set to
350 true if any were encountered. */
351
352 int
353 read_c_string_or_comment (infile, printflag, comment, saw_usage)
354 FILE *infile;
355 int printflag;
356 int *saw_usage;
357 int comment;
358 {
359 register int c;
360 struct rcsoc_state state;
361
362 state.in_file = infile;
363 state.buf_ptr = (printflag < 0 ? buf : 0);
364 state.out_file = (printflag > 0 ? outfile : 0);
365 state.pending_spaces = 0;
366 state.pending_newlines = 0;
367 state.keyword = (saw_usage ? "usage:" : 0);
368 state.cur_keyword_ptr = state.keyword;
369 state.saw_keyword = 0;
370
371 c = getc (infile);
372 if (comment)
373 while (c == '\n' || c == '\r' || c == '\t' || c == ' ')
374 c = getc (infile);
375
376 while (c != EOF)
377 {
378 while (c != EOF && (comment ? c != '*' : c != '"'))
379 {
380 if (c == '\\')
381 {
382 c = getc (infile);
383 if (c == '\n' || c == '\r')
384 {
385 c = getc (infile);
386 continue;
387 }
388 if (c == 'n')
389 c = '\n';
390 if (c == 't')
391 c = '\t';
392 }
393
394 if (c == ' ')
395 state.pending_spaces++;
396 else if (c == '\n')
397 {
398 state.pending_newlines++;
399 state.pending_spaces = 0;
400 }
401 else
402 scan_keyword_or_put_char (c, &state);
403
404 c = getc (infile);
405 }
406
407 if (c != EOF)
408 c = getc (infile);
409
410 if (comment)
411 {
412 if (c == '/')
413 {
414 c = getc (infile);
415 break;
416 }
417
418 scan_keyword_or_put_char ('*', &state);
419 }
420 else
421 {
422 if (c != '"')
423 break;
424
425 /* If we had a "", concatenate the two strings. */
426 c = getc (infile);
427 }
428 }
429
430 if (printflag < 0)
431 *state.buf_ptr = 0;
432
433 if (saw_usage)
434 *saw_usage = state.saw_keyword;
435
436 return c;
437 }
438
439
440 \f
441 /* Write to file OUT the argument names of function FUNC, whose text is in BUF.
442 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
443
444 void
445 write_c_args (out, func, buf, minargs, maxargs)
446 FILE *out;
447 char *func, *buf;
448 int minargs, maxargs;
449 {
450 register char *p;
451 int in_ident = 0;
452 int just_spaced = 0;
453 int need_space = 1;
454
455 fprintf (out, "(fn");
456
457 if (*buf == '(')
458 ++buf;
459
460 for (p = buf; *p; p++)
461 {
462 char c = *p;
463 int ident_start = 0;
464
465 /* Notice when we start printing a new identifier. */
466 if ((('A' <= c && c <= 'Z')
467 || ('a' <= c && c <= 'z')
468 || ('0' <= c && c <= '9')
469 || c == '_')
470 != in_ident)
471 {
472 if (!in_ident)
473 {
474 in_ident = 1;
475 ident_start = 1;
476
477 if (need_space)
478 putc (' ', out);
479
480 if (minargs == 0 && maxargs > 0)
481 fprintf (out, "&optional ");
482 just_spaced = 1;
483
484 minargs--;
485 maxargs--;
486 }
487 else
488 in_ident = 0;
489 }
490
491 /* Print the C argument list as it would appear in lisp:
492 print underscores as hyphens, and print commas and newlines
493 as spaces. Collapse adjacent spaces into one. */
494 if (c == '_')
495 c = '-';
496 else if (c == ',' || c == '\n')
497 c = ' ';
498
499 /* In C code, `default' is a reserved word, so we spell it
500 `defalt'; unmangle that here. */
501 if (ident_start
502 && strncmp (p, "defalt", 6) == 0
503 && ! (('A' <= p[6] && p[6] <= 'Z')
504 || ('a' <= p[6] && p[6] <= 'z')
505 || ('0' <= p[6] && p[6] <= '9')
506 || p[6] == '_'))
507 {
508 fprintf (out, "DEFAULT");
509 p += 5;
510 in_ident = 0;
511 just_spaced = 0;
512 }
513 else if (c != ' ' || !just_spaced)
514 {
515 if (c >= 'a' && c <= 'z')
516 /* Upcase the letter. */
517 c += 'A' - 'a';
518 putc (c, out);
519 }
520
521 just_spaced = c == ' ';
522 need_space = 0;
523 }
524 }
525 \f
526 /* Read through a c file. If a .o file is named,
527 the corresponding .c file is read instead.
528 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
529 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
530
531 int
532 scan_c_file (filename, mode)
533 char *filename, *mode;
534 {
535 FILE *infile;
536 register int c;
537 register int commas;
538 register int defunflag;
539 register int defvarperbufferflag;
540 register int defvarflag;
541 int minargs, maxargs;
542 int extension = filename[strlen (filename) - 1];
543
544 if (extension == 'o')
545 filename[strlen (filename) - 1] = 'c';
546
547 infile = fopen (filename, mode);
548
549 /* No error if non-ex input file */
550 if (infile == NULL)
551 {
552 perror (filename);
553 return 0;
554 }
555
556 /* Reset extension to be able to detect duplicate files. */
557 filename[strlen (filename) - 1] = extension;
558
559 c = '\n';
560 while (!feof (infile))
561 {
562 int doc_keyword = 0;
563
564 if (c != '\n' && c != '\r')
565 {
566 c = getc (infile);
567 continue;
568 }
569 c = getc (infile);
570 if (c == ' ')
571 {
572 while (c == ' ')
573 c = getc (infile);
574 if (c != 'D')
575 continue;
576 c = getc (infile);
577 if (c != 'E')
578 continue;
579 c = getc (infile);
580 if (c != 'F')
581 continue;
582 c = getc (infile);
583 if (c != 'V')
584 continue;
585 c = getc (infile);
586 if (c != 'A')
587 continue;
588 c = getc (infile);
589 if (c != 'R')
590 continue;
591 c = getc (infile);
592 if (c != '_')
593 continue;
594
595 defvarflag = 1;
596 defunflag = 0;
597
598 c = getc (infile);
599 defvarperbufferflag = (c == 'P');
600
601 c = getc (infile);
602 }
603 else if (c == 'D')
604 {
605 c = getc (infile);
606 if (c != 'E')
607 continue;
608 c = getc (infile);
609 if (c != 'F')
610 continue;
611 c = getc (infile);
612 defunflag = c == 'U';
613 defvarflag = 0;
614 }
615 else continue;
616
617 while (c != '(')
618 {
619 if (c < 0)
620 goto eof;
621 c = getc (infile);
622 }
623
624 /* Lisp variable or function name. */
625 c = getc (infile);
626 if (c != '"')
627 continue;
628 c = read_c_string_or_comment (infile, -1, 0, 0);
629
630 /* DEFVAR_LISP ("name", addr, "doc")
631 DEFVAR_LISP ("name", addr /\* doc *\/)
632 DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */
633
634 if (defunflag)
635 commas = 5;
636 else if (defvarperbufferflag)
637 commas = 2;
638 else if (defvarflag)
639 commas = 1;
640 else /* For DEFSIMPLE and DEFPRED */
641 commas = 2;
642
643 while (commas)
644 {
645 if (c == ',')
646 {
647 commas--;
648
649 if (defunflag && (commas == 1 || commas == 2))
650 {
651 do
652 c = getc (infile);
653 while (c == ' ' || c == '\n' || c == '\r' || c == '\t');
654 if (c < 0)
655 goto eof;
656 ungetc (c, infile);
657 if (commas == 2) /* pick up minargs */
658 fscanf (infile, "%d", &minargs);
659 else /* pick up maxargs */
660 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
661 maxargs = -1;
662 else
663 fscanf (infile, "%d", &maxargs);
664 }
665 }
666
667 if (c == EOF)
668 goto eof;
669 c = getc (infile);
670 }
671
672 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
673 c = getc (infile);
674
675 if (c == '"')
676 c = read_c_string_or_comment (infile, 0, 0, 0);
677
678 while (c != EOF && c != ',' && c != '/')
679 c = getc (infile);
680 if (c == ',')
681 {
682 c = getc (infile);
683 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
684 c = getc (infile);
685 while ((c >= 'a' && c <= 'z') || (c >= 'Z' && c <= 'Z'))
686 c = getc (infile);
687 if (c == ':')
688 {
689 doc_keyword = 1;
690 c = getc (infile);
691 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
692 c = getc (infile);
693 }
694 }
695
696 if (c == '"'
697 || (c == '/'
698 && (c = getc (infile),
699 ungetc (c, infile),
700 c == '*')))
701 {
702 int comment = c != '"';
703 int saw_usage;
704
705 putc (037, outfile);
706 putc (defvarflag ? 'V' : 'F', outfile);
707 fprintf (outfile, "%s\n", buf);
708
709 if (comment)
710 getc (infile); /* Skip past `*' */
711 c = read_c_string_or_comment (infile, 1, comment, &saw_usage);
712
713 /* If this is a defun, find the arguments and print them. If
714 this function takes MANY or UNEVALLED args, then the C source
715 won't give the names of the arguments, so we shouldn't bother
716 trying to find them.
717
718 Various doc-string styles:
719 0: DEFUN (..., "DOC") (args) [!comment]
720 1: DEFUN (..., /\* DOC *\/ (args)) [comment && !doc_keyword]
721 2: DEFUN (..., doc: /\* DOC *\/) (args) [comment && doc_keyword]
722 */
723 if (defunflag && maxargs != -1 && !saw_usage)
724 {
725 char argbuf[1024], *p = argbuf;
726
727 if (!comment || doc_keyword)
728 while (c != ')')
729 {
730 if (c < 0)
731 goto eof;
732 c = getc (infile);
733 }
734
735 /* Skip into arguments. */
736 while (c != '(')
737 {
738 if (c < 0)
739 goto eof;
740 c = getc (infile);
741 }
742 /* Copy arguments into ARGBUF. */
743 *p++ = c;
744 do
745 *p++ = c = getc (infile);
746 while (c != ')');
747 *p = '\0';
748 /* Output them. */
749 fprintf (outfile, "\n\n");
750 write_c_args (outfile, buf, argbuf, minargs, maxargs);
751 }
752 else if (defunflag && maxargs == -1 && !saw_usage)
753 /* The DOC should provide the usage form. */
754 fprintf (stderr, "Missing `usage' for function `%s'.\n", buf);
755 }
756 }
757 eof:
758 fclose (infile);
759 return 0;
760 }
761 \f
762 /* Read a file of Lisp code, compiled or interpreted.
763 Looks for
764 (defun NAME ARGS DOCSTRING ...)
765 (defmacro NAME ARGS DOCSTRING ...)
766 (defsubst NAME ARGS DOCSTRING ...)
767 (autoload (quote NAME) FILE DOCSTRING ...)
768 (defvar NAME VALUE DOCSTRING)
769 (defconst NAME VALUE DOCSTRING)
770 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
771 (fset (quote NAME) #[... DOCSTRING ...])
772 (defalias (quote NAME) #[... DOCSTRING ...])
773 (custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
774 starting in column zero.
775 (quote NAME) may appear as 'NAME as well.
776
777 We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
778 When we find that, we save it for the following defining-form,
779 and we use that instead of reading a doc string within that defining-form.
780
781 For defvar, defconst, and fset we skip to the docstring with a kludgy
782 formatting convention: all docstrings must appear on the same line as the
783 initial open-paren (the one in column zero) and must contain a backslash
784 and a newline immediately after the initial double-quote. No newlines
785 must appear between the beginning of the form and the first double-quote.
786 For defun, defmacro, and autoload, we know how to skip over the
787 arglist, but the doc string must still have a backslash and newline
788 immediately after the double quote.
789 The only source files that must follow this convention are preloaded
790 uncompiled ones like loaddefs.el and bindings.el; aside
791 from that, it is always the .elc file that we look at, and they are no
792 problem because byte-compiler output follows this convention.
793 The NAME and DOCSTRING are output.
794 NAME is preceded by `F' for a function or `V' for a variable.
795 An entry is output only if DOCSTRING has \ newline just after the opening "
796 */
797
798 void
799 skip_white (infile)
800 FILE *infile;
801 {
802 char c = ' ';
803 while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
804 c = getc (infile);
805 ungetc (c, infile);
806 }
807
808 void
809 read_lisp_symbol (infile, buffer)
810 FILE *infile;
811 char *buffer;
812 {
813 char c;
814 char *fillp = buffer;
815
816 skip_white (infile);
817 while (1)
818 {
819 c = getc (infile);
820 if (c == '\\')
821 *(++fillp) = getc (infile);
822 else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '(' || c == ')')
823 {
824 ungetc (c, infile);
825 *fillp = 0;
826 break;
827 }
828 else
829 *fillp++ = c;
830 }
831
832 if (! buffer[0])
833 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
834
835 skip_white (infile);
836 }
837
838 int
839 scan_lisp_file (filename, mode)
840 char *filename, *mode;
841 {
842 FILE *infile;
843 register int c;
844 char *saved_string = 0;
845
846 infile = fopen (filename, mode);
847 if (infile == NULL)
848 {
849 perror (filename);
850 return 0; /* No error */
851 }
852
853 c = '\n';
854 while (!feof (infile))
855 {
856 char buffer[BUFSIZ];
857 char type;
858
859 /* If not at end of line, skip till we get to one. */
860 if (c != '\n' && c != '\r')
861 {
862 c = getc (infile);
863 continue;
864 }
865 /* Skip the line break. */
866 while (c == '\n' || c == '\r')
867 c = getc (infile);
868 /* Detect a dynamic doc string and save it for the next expression. */
869 if (c == '#')
870 {
871 c = getc (infile);
872 if (c == '@')
873 {
874 int length = 0;
875 int i;
876
877 /* Read the length. */
878 while ((c = getc (infile),
879 c >= '0' && c <= '9'))
880 {
881 length *= 10;
882 length += c - '0';
883 }
884
885 /* The next character is a space that is counted in the length
886 but not part of the doc string.
887 We already read it, so just ignore it. */
888 length--;
889
890 /* Read in the contents. */
891 if (saved_string != 0)
892 free (saved_string);
893 saved_string = (char *) malloc (length);
894 for (i = 0; i < length; i++)
895 saved_string[i] = getc (infile);
896 /* The last character is a ^_.
897 That is needed in the .elc file
898 but it is redundant in DOC. So get rid of it here. */
899 saved_string[length - 1] = 0;
900 /* Skip the line break. */
901 while (c == '\n' && c == '\r')
902 c = getc (infile);
903 /* Skip the following line. */
904 while (c != '\n' && c != '\r')
905 c = getc (infile);
906 }
907 continue;
908 }
909
910 if (c != '(')
911 continue;
912
913 read_lisp_symbol (infile, buffer);
914
915 if (! strcmp (buffer, "defun")
916 || ! strcmp (buffer, "defmacro")
917 || ! strcmp (buffer, "defsubst"))
918 {
919 type = 'F';
920 read_lisp_symbol (infile, buffer);
921
922 /* Skip the arguments: either "nil" or a list in parens */
923
924 c = getc (infile);
925 if (c == 'n') /* nil */
926 {
927 if ((c = getc (infile)) != 'i'
928 || (c = getc (infile)) != 'l')
929 {
930 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
931 buffer, filename);
932 continue;
933 }
934 }
935 else if (c != '(')
936 {
937 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
938 buffer, filename);
939 continue;
940 }
941 else
942 while (c != ')')
943 c = getc (infile);
944 skip_white (infile);
945
946 /* If the next three characters aren't `dquote bslash newline'
947 then we're not reading a docstring.
948 */
949 if ((c = getc (infile)) != '"'
950 || (c = getc (infile)) != '\\'
951 || ((c = getc (infile)) != '\n' && c != '\r'))
952 {
953 #ifdef DEBUG
954 fprintf (stderr, "## non-docstring in %s (%s)\n",
955 buffer, filename);
956 #endif
957 continue;
958 }
959 }
960
961 else if (! strcmp (buffer, "defvar")
962 || ! strcmp (buffer, "defconst"))
963 {
964 char c1 = 0, c2 = 0;
965 type = 'V';
966 read_lisp_symbol (infile, buffer);
967
968 if (saved_string == 0)
969 {
970
971 /* Skip until the end of line; remember two previous chars. */
972 while (c != '\n' && c != '\r' && c >= 0)
973 {
974 c2 = c1;
975 c1 = c;
976 c = getc (infile);
977 }
978
979 /* If two previous characters were " and \,
980 this is a doc string. Otherwise, there is none. */
981 if (c2 != '"' || c1 != '\\')
982 {
983 #ifdef DEBUG
984 fprintf (stderr, "## non-docstring in %s (%s)\n",
985 buffer, filename);
986 #endif
987 continue;
988 }
989 }
990 }
991
992 else if (! strcmp (buffer, "custom-declare-variable"))
993 {
994 char c1 = 0, c2 = 0;
995 type = 'V';
996
997 c = getc (infile);
998 if (c == '\'')
999 read_lisp_symbol (infile, buffer);
1000 else
1001 {
1002 if (c != '(')
1003 {
1004 fprintf (stderr,
1005 "## unparsable name in custom-declare-variable in %s\n",
1006 filename);
1007 continue;
1008 }
1009 read_lisp_symbol (infile, buffer);
1010 if (strcmp (buffer, "quote"))
1011 {
1012 fprintf (stderr,
1013 "## unparsable name in custom-declare-variable in %s\n",
1014 filename);
1015 continue;
1016 }
1017 read_lisp_symbol (infile, buffer);
1018 c = getc (infile);
1019 if (c != ')')
1020 {
1021 fprintf (stderr,
1022 "## unparsable quoted name in custom-declare-variable in %s\n",
1023 filename);
1024 continue;
1025 }
1026 }
1027
1028 if (saved_string == 0)
1029 {
1030 /* Skip to end of line; remember the two previous chars. */
1031 while (c != '\n' && c != '\r' && c >= 0)
1032 {
1033 c2 = c1;
1034 c1 = c;
1035 c = getc (infile);
1036 }
1037
1038 /* If two previous characters were " and \,
1039 this is a doc string. Otherwise, there is none. */
1040 if (c2 != '"' || c1 != '\\')
1041 {
1042 #ifdef DEBUG
1043 fprintf (stderr, "## non-docstring in %s (%s)\n",
1044 buffer, filename);
1045 #endif
1046 continue;
1047 }
1048 }
1049 }
1050
1051 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
1052 {
1053 char c1 = 0, c2 = 0;
1054 type = 'F';
1055
1056 c = getc (infile);
1057 if (c == '\'')
1058 read_lisp_symbol (infile, buffer);
1059 else
1060 {
1061 if (c != '(')
1062 {
1063 fprintf (stderr, "## unparsable name in fset in %s\n",
1064 filename);
1065 continue;
1066 }
1067 read_lisp_symbol (infile, buffer);
1068 if (strcmp (buffer, "quote"))
1069 {
1070 fprintf (stderr, "## unparsable name in fset in %s\n",
1071 filename);
1072 continue;
1073 }
1074 read_lisp_symbol (infile, buffer);
1075 c = getc (infile);
1076 if (c != ')')
1077 {
1078 fprintf (stderr,
1079 "## unparsable quoted name in fset in %s\n",
1080 filename);
1081 continue;
1082 }
1083 }
1084
1085 if (saved_string == 0)
1086 {
1087 /* Skip to end of line; remember the two previous chars. */
1088 while (c != '\n' && c != '\r' && c >= 0)
1089 {
1090 c2 = c1;
1091 c1 = c;
1092 c = getc (infile);
1093 }
1094
1095 /* If two previous characters were " and \,
1096 this is a doc string. Otherwise, there is none. */
1097 if (c2 != '"' || c1 != '\\')
1098 {
1099 #ifdef DEBUG
1100 fprintf (stderr, "## non-docstring in %s (%s)\n",
1101 buffer, filename);
1102 #endif
1103 continue;
1104 }
1105 }
1106 }
1107
1108 else if (! strcmp (buffer, "autoload"))
1109 {
1110 type = 'F';
1111 c = getc (infile);
1112 if (c == '\'')
1113 read_lisp_symbol (infile, buffer);
1114 else
1115 {
1116 if (c != '(')
1117 {
1118 fprintf (stderr, "## unparsable name in autoload in %s\n",
1119 filename);
1120 continue;
1121 }
1122 read_lisp_symbol (infile, buffer);
1123 if (strcmp (buffer, "quote"))
1124 {
1125 fprintf (stderr, "## unparsable name in autoload in %s\n",
1126 filename);
1127 continue;
1128 }
1129 read_lisp_symbol (infile, buffer);
1130 c = getc (infile);
1131 if (c != ')')
1132 {
1133 fprintf (stderr,
1134 "## unparsable quoted name in autoload in %s\n",
1135 filename);
1136 continue;
1137 }
1138 }
1139 skip_white (infile);
1140 if ((c = getc (infile)) != '\"')
1141 {
1142 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
1143 buffer, filename);
1144 continue;
1145 }
1146 read_c_string_or_comment (infile, 0, 0, 0);
1147 skip_white (infile);
1148
1149 if (saved_string == 0)
1150 {
1151 /* If the next three characters aren't `dquote bslash newline'
1152 then we're not reading a docstring. */
1153 if ((c = getc (infile)) != '"'
1154 || (c = getc (infile)) != '\\'
1155 || ((c = getc (infile)) != '\n' && c != '\r'))
1156 {
1157 #ifdef DEBUG
1158 fprintf (stderr, "## non-docstring in %s (%s)\n",
1159 buffer, filename);
1160 #endif
1161 continue;
1162 }
1163 }
1164 }
1165
1166 #ifdef DEBUG
1167 else if (! strcmp (buffer, "if")
1168 || ! strcmp (buffer, "byte-code"))
1169 ;
1170 #endif
1171
1172 else
1173 {
1174 #ifdef DEBUG
1175 fprintf (stderr, "## unrecognised top-level form, %s (%s)\n",
1176 buffer, filename);
1177 #endif
1178 continue;
1179 }
1180
1181 /* At this point, we should either use the previous
1182 dynamic doc string in saved_string
1183 or gobble a doc string from the input file.
1184
1185 In the latter case, the opening quote (and leading
1186 backslash-newline) have already been read. */
1187
1188 putc (037, outfile);
1189 putc (type, outfile);
1190 fprintf (outfile, "%s\n", buffer);
1191 if (saved_string)
1192 {
1193 fputs (saved_string, outfile);
1194 /* Don't use one dynamic doc string twice. */
1195 free (saved_string);
1196 saved_string = 0;
1197 }
1198 else
1199 read_c_string_or_comment (infile, 1, 0, 0);
1200 }
1201 fclose (infile);
1202 return 0;
1203 }
1204
1205 /* arch-tag: f7203aaf-991a-4238-acb5-601db56f2894
1206 (do not change this comment) */