Merge from mainline.
[bpt/emacs.git] / lib-src / make-docfile.c
1 /* Generate doc-string file for GNU Emacs from source files.
2 Copyright (C) 1985, 1986, 1992, 1993, 1994, 1997, 1999, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 Free Software Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20
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 #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
43
44 #include <stdio.h>
45 #ifdef MSDOS
46 #include <fcntl.h>
47 #endif /* MSDOS */
48 #ifdef WINDOWSNT
49 #include <stdlib.h>
50 #include <fcntl.h>
51 #include <direct.h>
52 #endif /* WINDOWSNT */
53
54 #ifdef DOS_NT
55 #define READ_TEXT "rt"
56 #define READ_BINARY "rb"
57 #else /* not DOS_NT */
58 #define READ_TEXT "r"
59 #define READ_BINARY "r"
60 #endif /* not DOS_NT */
61
62 #ifndef DIRECTORY_SEP
63 #define DIRECTORY_SEP '/'
64 #endif
65
66 #ifndef IS_DIRECTORY_SEP
67 #define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
68 #endif
69
70 int scan_file (char *filename);
71 int scan_lisp_file (const char *filename, const char *mode);
72 int scan_c_file (char *filename, const char *mode);
73 void fatal (const char *s1, const char *s2) NO_RETURN;
74
75 #ifdef MSDOS
76 /* s/msdos.h defines this as sys_chdir, but we're not linking with the
77 file where that function is defined. */
78 #undef chdir
79 #endif
80
81 #include <unistd.h>
82
83 /* Stdio stream for output to the DOC file. */
84 FILE *outfile;
85
86 /* Name this program was invoked with. */
87 char *progname;
88
89 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
90
91 /* VARARGS1 */
92 void
93 error (const char *s1, const char *s2)
94 {
95 fprintf (stderr, "%s: ", progname);
96 fprintf (stderr, s1, s2);
97 fprintf (stderr, "\n");
98 }
99
100 /* Print error message and exit. */
101
102 /* VARARGS1 */
103 void
104 fatal (const char *s1, const char *s2)
105 {
106 error (s1, s2);
107 exit (EXIT_FAILURE);
108 }
109
110 /* Like malloc but get fatal error if memory is exhausted. */
111
112 void *
113 xmalloc (unsigned int size)
114 {
115 void *result = (void *) malloc (size);
116 if (result == NULL)
117 fatal ("virtual memory exhausted", 0);
118 return result;
119 }
120 \f
121 int
122 main (int argc, char **argv)
123 {
124 int i;
125 int err_count = 0;
126 int first_infile;
127
128 progname = argv[0];
129
130 outfile = stdout;
131
132 /* Don't put CRs in the DOC file. */
133 #ifdef MSDOS
134 _fmode = O_BINARY;
135 #if 0 /* Suspicion is that this causes hanging.
136 So instead we require people to use -o on MSDOS. */
137 (stdout)->_flag &= ~_IOTEXT;
138 _setmode (fileno (stdout), O_BINARY);
139 #endif
140 outfile = 0;
141 #endif /* MSDOS */
142 #ifdef WINDOWSNT
143 _fmode = O_BINARY;
144 _setmode (fileno (stdout), O_BINARY);
145 #endif /* WINDOWSNT */
146
147 /* If first two args are -o FILE, output to FILE. */
148 i = 1;
149 if (argc > i + 1 && !strcmp (argv[i], "-o"))
150 {
151 outfile = fopen (argv[i + 1], "w");
152 i += 2;
153 }
154 if (argc > i + 1 && !strcmp (argv[i], "-a"))
155 {
156 outfile = fopen (argv[i + 1], "a");
157 i += 2;
158 }
159 if (argc > i + 1 && !strcmp (argv[i], "-d"))
160 {
161 chdir (argv[i + 1]);
162 i += 2;
163 }
164
165 if (outfile == 0)
166 fatal ("No output file specified", "");
167
168 first_infile = i;
169 for (; i < argc; i++)
170 {
171 int j;
172 /* Don't process one file twice. */
173 for (j = first_infile; j < i; j++)
174 if (! strcmp (argv[i], argv[j]))
175 break;
176 if (j == i)
177 err_count += scan_file (argv[i]);
178 }
179 return (err_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
180 }
181
182 /* Add a source file name boundary marker in the output file. */
183 void
184 put_filename (char *filename)
185 {
186 char *tmp;
187
188 for (tmp = filename; *tmp; tmp++)
189 {
190 if (IS_DIRECTORY_SEP(*tmp))
191 filename = tmp + 1;
192 }
193
194 putc (037, outfile);
195 putc ('S', outfile);
196 fprintf (outfile, "%s\n", filename);
197 }
198
199 /* Read file FILENAME and output its doc strings to outfile. */
200 /* Return 1 if file is not found, 0 if it is found. */
201
202 int
203 scan_file (char *filename)
204 {
205
206 size_t len = strlen (filename);
207
208 put_filename (filename);
209 if (len > 4 && !strcmp (filename + len - 4, ".elc"))
210 return scan_lisp_file (filename, READ_BINARY);
211 else if (len > 3 && !strcmp (filename + len - 3, ".el"))
212 return scan_lisp_file (filename, READ_TEXT);
213 else
214 return scan_c_file (filename, READ_TEXT);
215 }
216 \f
217 char buf[128];
218
219 /* Some state during the execution of `read_c_string_or_comment'. */
220 struct rcsoc_state
221 {
222 /* A count of spaces and newlines that have been read, but not output. */
223 unsigned pending_spaces, pending_newlines;
224
225 /* Where we're reading from. */
226 FILE *in_file;
227
228 /* If non-zero, a buffer into which to copy characters. */
229 char *buf_ptr;
230 /* If non-zero, a file into which to copy characters. */
231 FILE *out_file;
232
233 /* A keyword we look for at the beginning of lines. If found, it is
234 not copied, and SAW_KEYWORD is set to true. */
235 const char *keyword;
236 /* The current point we've reached in an occurrence of KEYWORD in
237 the input stream. */
238 const char *cur_keyword_ptr;
239 /* Set to true if we saw an occurrence of KEYWORD. */
240 int saw_keyword;
241 };
242
243 /* Output CH to the file or buffer in STATE. Any pending newlines or
244 spaces are output first. */
245
246 static INLINE void
247 put_char (int ch, 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 (int ch, struct rcsoc_state *state)
281 {
282 if (state->keyword
283 && *state->cur_keyword_ptr == ch
284 && (state->cur_keyword_ptr > state->keyword
285 || state->pending_newlines > 0))
286 /* We might be looking at STATE->keyword at some point.
287 Keep looking until we know for sure. */
288 {
289 if (*++state->cur_keyword_ptr == '\0')
290 /* Saw the whole keyword. Set SAW_KEYWORD flag to true. */
291 {
292 state->saw_keyword = 1;
293
294 /* Reset the scanning pointer. */
295 state->cur_keyword_ptr = state->keyword;
296
297 /* Canonicalize whitespace preceding a usage string. */
298 state->pending_newlines = 2;
299 state->pending_spaces = 0;
300
301 /* Skip any whitespace between the keyword and the
302 usage string. */
303 do
304 ch = getc (state->in_file);
305 while (ch == ' ' || ch == '\n');
306
307 /* Output the open-paren we just read. */
308 put_char (ch, state);
309
310 /* Skip the function name and replace it with `fn'. */
311 do
312 ch = getc (state->in_file);
313 while (ch != ' ' && ch != ')');
314 put_char ('f', state);
315 put_char ('n', state);
316
317 /* Put back the last character. */
318 ungetc (ch, state->in_file);
319 }
320 }
321 else
322 {
323 if (state->keyword && state->cur_keyword_ptr > state->keyword)
324 /* We scanned the beginning of a potential usage
325 keyword, but it was a false alarm. Output the
326 part we scanned. */
327 {
328 const char *p;
329
330 for (p = state->keyword; p < state->cur_keyword_ptr; p++)
331 put_char (*p, state);
332
333 state->cur_keyword_ptr = state->keyword;
334 }
335
336 put_char (ch, state);
337 }
338 }
339
340
341 /* Skip a C string or C-style comment from INFILE, and return the
342 character that follows. COMMENT non-zero means skip a comment. If
343 PRINTFLAG is positive, output string contents to outfile. If it is
344 negative, store contents in buf. Convert escape sequences \n and
345 \t to newline and tab; discard \ followed by newline.
346 If SAW_USAGE is non-zero, then any occurrences of the string `usage:'
347 at the beginning of a line will be removed, and *SAW_USAGE set to
348 true if any were encountered. */
349
350 int
351 read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usage)
352 {
353 register int c;
354 struct rcsoc_state state;
355
356 state.in_file = infile;
357 state.buf_ptr = (printflag < 0 ? buf : 0);
358 state.out_file = (printflag > 0 ? outfile : 0);
359 state.pending_spaces = 0;
360 state.pending_newlines = 0;
361 state.keyword = (saw_usage ? "usage:" : 0);
362 state.cur_keyword_ptr = state.keyword;
363 state.saw_keyword = 0;
364
365 c = getc (infile);
366 if (comment)
367 while (c == '\n' || c == '\r' || c == '\t' || c == ' ')
368 c = getc (infile);
369
370 while (c != EOF)
371 {
372 while (c != EOF && (comment ? c != '*' : c != '"'))
373 {
374 if (c == '\\')
375 {
376 c = getc (infile);
377 if (c == '\n' || c == '\r')
378 {
379 c = getc (infile);
380 continue;
381 }
382 if (c == 'n')
383 c = '\n';
384 if (c == 't')
385 c = '\t';
386 }
387
388 if (c == ' ')
389 state.pending_spaces++;
390 else if (c == '\n')
391 {
392 state.pending_newlines++;
393 state.pending_spaces = 0;
394 }
395 else
396 scan_keyword_or_put_char (c, &state);
397
398 c = getc (infile);
399 }
400
401 if (c != EOF)
402 c = getc (infile);
403
404 if (comment)
405 {
406 if (c == '/')
407 {
408 c = getc (infile);
409 break;
410 }
411
412 scan_keyword_or_put_char ('*', &state);
413 }
414 else
415 {
416 if (c != '"')
417 break;
418
419 /* If we had a "", concatenate the two strings. */
420 c = getc (infile);
421 }
422 }
423
424 if (printflag < 0)
425 *state.buf_ptr = 0;
426
427 if (saw_usage)
428 *saw_usage = state.saw_keyword;
429
430 return c;
431 }
432
433
434 \f
435 /* Write to file OUT the argument names of function FUNC, whose text is in BUF.
436 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
437
438 void
439 write_c_args (FILE *out, char *func, char *buf, int minargs, int maxargs)
440 {
441 register char *p;
442 int in_ident = 0;
443 char *ident_start;
444 size_t ident_length = 0;
445
446 fprintf (out, "(fn");
447
448 if (*buf == '(')
449 ++buf;
450
451 for (p = buf; *p; p++)
452 {
453 char c = *p;
454
455 /* Notice when a new identifier starts. */
456 if ((('A' <= c && c <= 'Z')
457 || ('a' <= c && c <= 'z')
458 || ('0' <= c && c <= '9')
459 || c == '_')
460 != in_ident)
461 {
462 if (!in_ident)
463 {
464 in_ident = 1;
465 ident_start = p;
466 }
467 else
468 {
469 in_ident = 0;
470 ident_length = p - ident_start;
471 }
472 }
473
474 /* Found the end of an argument, write out the last seen
475 identifier. */
476 if (c == ',' || c == ')')
477 {
478 if (ident_length == 0)
479 {
480 error ("empty arg list for `%s' should be (void), not ()", func);
481 continue;
482 }
483
484 if (strncmp (ident_start, "void", ident_length) == 0)
485 continue;
486
487 putc (' ', out);
488
489 if (minargs == 0 && maxargs > 0)
490 fprintf (out, "&optional ");
491
492 minargs--;
493 maxargs--;
494
495 /* In C code, `default' is a reserved word, so we spell it
496 `defalt'; unmangle that here. */
497 if (ident_length == 6 && strncmp (ident_start, "defalt", 6) == 0)
498 fprintf (out, "DEFAULT");
499 else
500 while (ident_length-- > 0)
501 {
502 c = *ident_start++;
503 if (c >= 'a' && c <= 'z')
504 /* Upcase the letter. */
505 c += 'A' - 'a';
506 else if (c == '_')
507 /* Print underscore as hyphen. */
508 c = '-';
509 putc (c, out);
510 }
511 }
512 }
513
514 putc (')', out);
515 }
516 \f
517 /* Read through a c file. If a .o file is named,
518 the corresponding .c or .m file is read instead.
519 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
520 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
521
522 int
523 scan_c_file (char *filename, const char *mode)
524 {
525 FILE *infile;
526 register int c;
527 register int commas;
528 register int defunflag;
529 register int defvarperbufferflag;
530 register int defvarflag;
531 int minargs, maxargs;
532 int extension = filename[strlen (filename) - 1];
533
534 if (extension == 'o')
535 filename[strlen (filename) - 1] = 'c';
536
537 infile = fopen (filename, mode);
538
539 if (infile == NULL && extension == 'o')
540 {
541 /* try .m */
542 filename[strlen (filename) - 1] = 'm';
543 infile = fopen (filename, mode);
544 if (infile == NULL)
545 filename[strlen (filename) - 1] = 'c'; /* don't confuse people */
546 }
547
548 /* No error if non-ex input file */
549 if (infile == NULL)
550 {
551 perror (filename);
552 return 0;
553 }
554
555 /* Reset extension to be able to detect duplicate files. */
556 filename[strlen (filename) - 1] = extension;
557
558 c = '\n';
559 while (!feof (infile))
560 {
561 int doc_keyword = 0;
562
563 if (c != '\n' && c != '\r')
564 {
565 c = getc (infile);
566 continue;
567 }
568 c = getc (infile);
569 if (c == ' ')
570 {
571 while (c == ' ')
572 c = getc (infile);
573 if (c != 'D')
574 continue;
575 c = getc (infile);
576 if (c != 'E')
577 continue;
578 c = getc (infile);
579 if (c != 'F')
580 continue;
581 c = getc (infile);
582 if (c != 'V')
583 continue;
584 c = getc (infile);
585 if (c != 'A')
586 continue;
587 c = getc (infile);
588 if (c != 'R')
589 continue;
590 c = getc (infile);
591 if (c != '_')
592 continue;
593
594 defvarflag = 1;
595 defunflag = 0;
596
597 c = getc (infile);
598 defvarperbufferflag = (c == 'P');
599
600 c = getc (infile);
601 }
602 else if (c == 'D')
603 {
604 c = getc (infile);
605 if (c != 'E')
606 continue;
607 c = getc (infile);
608 if (c != 'F')
609 continue;
610 c = getc (infile);
611 defunflag = c == 'U';
612 defvarflag = 0;
613 defvarperbufferflag = 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 (FILE *infile)
800 {
801 char c = ' ';
802 while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
803 c = getc (infile);
804 ungetc (c, infile);
805 }
806
807 void
808 read_lisp_symbol (FILE *infile, char *buffer)
809 {
810 char c;
811 char *fillp = buffer;
812
813 skip_white (infile);
814 while (1)
815 {
816 c = getc (infile);
817 if (c == '\\')
818 *(++fillp) = getc (infile);
819 else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '(' || c == ')')
820 {
821 ungetc (c, infile);
822 *fillp = 0;
823 break;
824 }
825 else
826 *fillp++ = c;
827 }
828
829 if (! buffer[0])
830 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
831
832 skip_white (infile);
833 }
834
835 int
836 scan_lisp_file (const char *filename, const char *mode)
837 {
838 FILE *infile;
839 register int c;
840 char *saved_string = 0;
841
842 infile = fopen (filename, mode);
843 if (infile == NULL)
844 {
845 perror (filename);
846 return 0; /* No error */
847 }
848
849 c = '\n';
850 while (!feof (infile))
851 {
852 char buffer[BUFSIZ];
853 char type;
854
855 /* If not at end of line, skip till we get to one. */
856 if (c != '\n' && c != '\r')
857 {
858 c = getc (infile);
859 continue;
860 }
861 /* Skip the line break. */
862 while (c == '\n' || c == '\r')
863 c = getc (infile);
864 /* Detect a dynamic doc string and save it for the next expression. */
865 if (c == '#')
866 {
867 c = getc (infile);
868 if (c == '@')
869 {
870 int length = 0;
871 int i;
872
873 /* Read the length. */
874 while ((c = getc (infile),
875 c >= '0' && c <= '9'))
876 {
877 length *= 10;
878 length += c - '0';
879 }
880
881 /* The next character is a space that is counted in the length
882 but not part of the doc string.
883 We already read it, so just ignore it. */
884 length--;
885
886 /* Read in the contents. */
887 free (saved_string);
888 saved_string = (char *) xmalloc (length);
889 for (i = 0; i < length; i++)
890 saved_string[i] = getc (infile);
891 /* The last character is a ^_.
892 That is needed in the .elc file
893 but it is redundant in DOC. So get rid of it here. */
894 saved_string[length - 1] = 0;
895 /* Skip the line break. */
896 while (c == '\n' && c == '\r')
897 c = getc (infile);
898 /* Skip the following line. */
899 while (c != '\n' && c != '\r')
900 c = getc (infile);
901 }
902 continue;
903 }
904
905 if (c != '(')
906 continue;
907
908 read_lisp_symbol (infile, buffer);
909
910 if (! strcmp (buffer, "defun")
911 || ! strcmp (buffer, "defmacro")
912 || ! strcmp (buffer, "defsubst"))
913 {
914 type = 'F';
915 read_lisp_symbol (infile, buffer);
916
917 /* Skip the arguments: either "nil" or a list in parens */
918
919 c = getc (infile);
920 if (c == 'n') /* nil */
921 {
922 if ((c = getc (infile)) != 'i'
923 || (c = getc (infile)) != 'l')
924 {
925 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
926 buffer, filename);
927 continue;
928 }
929 }
930 else if (c != '(')
931 {
932 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
933 buffer, filename);
934 continue;
935 }
936 else
937 while (c != ')')
938 c = getc (infile);
939 skip_white (infile);
940
941 /* If the next three characters aren't `dquote bslash newline'
942 then we're not reading a docstring.
943 */
944 if ((c = getc (infile)) != '"'
945 || (c = getc (infile)) != '\\'
946 || ((c = getc (infile)) != '\n' && c != '\r'))
947 {
948 #ifdef DEBUG
949 fprintf (stderr, "## non-docstring in %s (%s)\n",
950 buffer, filename);
951 #endif
952 continue;
953 }
954 }
955
956 else if (! strcmp (buffer, "defvar")
957 || ! strcmp (buffer, "defconst"))
958 {
959 char c1 = 0, c2 = 0;
960 type = 'V';
961 read_lisp_symbol (infile, buffer);
962
963 if (saved_string == 0)
964 {
965
966 /* Skip until the end of line; remember two previous chars. */
967 while (c != '\n' && c != '\r' && c >= 0)
968 {
969 c2 = c1;
970 c1 = c;
971 c = getc (infile);
972 }
973
974 /* If two previous characters were " and \,
975 this is a doc string. Otherwise, there is none. */
976 if (c2 != '"' || c1 != '\\')
977 {
978 #ifdef DEBUG
979 fprintf (stderr, "## non-docstring in %s (%s)\n",
980 buffer, filename);
981 #endif
982 continue;
983 }
984 }
985 }
986
987 else if (! strcmp (buffer, "custom-declare-variable")
988 || ! strcmp (buffer, "defvaralias")
989 )
990 {
991 char c1 = 0, c2 = 0;
992 type = 'V';
993
994 c = getc (infile);
995 if (c == '\'')
996 read_lisp_symbol (infile, buffer);
997 else
998 {
999 if (c != '(')
1000 {
1001 fprintf (stderr,
1002 "## unparsable name in custom-declare-variable in %s\n",
1003 filename);
1004 continue;
1005 }
1006 read_lisp_symbol (infile, buffer);
1007 if (strcmp (buffer, "quote"))
1008 {
1009 fprintf (stderr,
1010 "## unparsable name in custom-declare-variable in %s\n",
1011 filename);
1012 continue;
1013 }
1014 read_lisp_symbol (infile, buffer);
1015 c = getc (infile);
1016 if (c != ')')
1017 {
1018 fprintf (stderr,
1019 "## unparsable quoted name in custom-declare-variable in %s\n",
1020 filename);
1021 continue;
1022 }
1023 }
1024
1025 if (saved_string == 0)
1026 {
1027 /* Skip to end of line; remember the two previous chars. */
1028 while (c != '\n' && c != '\r' && c >= 0)
1029 {
1030 c2 = c1;
1031 c1 = c;
1032 c = getc (infile);
1033 }
1034
1035 /* If two previous characters were " and \,
1036 this is a doc string. Otherwise, there is none. */
1037 if (c2 != '"' || c1 != '\\')
1038 {
1039 #ifdef DEBUG
1040 fprintf (stderr, "## non-docstring in %s (%s)\n",
1041 buffer, filename);
1042 #endif
1043 continue;
1044 }
1045 }
1046 }
1047
1048 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
1049 {
1050 char c1 = 0, c2 = 0;
1051 type = 'F';
1052
1053 c = getc (infile);
1054 if (c == '\'')
1055 read_lisp_symbol (infile, buffer);
1056 else
1057 {
1058 if (c != '(')
1059 {
1060 fprintf (stderr, "## unparsable name in fset in %s\n",
1061 filename);
1062 continue;
1063 }
1064 read_lisp_symbol (infile, buffer);
1065 if (strcmp (buffer, "quote"))
1066 {
1067 fprintf (stderr, "## unparsable name in fset in %s\n",
1068 filename);
1069 continue;
1070 }
1071 read_lisp_symbol (infile, buffer);
1072 c = getc (infile);
1073 if (c != ')')
1074 {
1075 fprintf (stderr,
1076 "## unparsable quoted name in fset in %s\n",
1077 filename);
1078 continue;
1079 }
1080 }
1081
1082 if (saved_string == 0)
1083 {
1084 /* Skip to end of line; remember the two previous chars. */
1085 while (c != '\n' && c != '\r' && c >= 0)
1086 {
1087 c2 = c1;
1088 c1 = c;
1089 c = getc (infile);
1090 }
1091
1092 /* If two previous characters were " and \,
1093 this is a doc string. Otherwise, there is none. */
1094 if (c2 != '"' || c1 != '\\')
1095 {
1096 #ifdef DEBUG
1097 fprintf (stderr, "## non-docstring in %s (%s)\n",
1098 buffer, filename);
1099 #endif
1100 continue;
1101 }
1102 }
1103 }
1104
1105 else if (! strcmp (buffer, "autoload"))
1106 {
1107 type = 'F';
1108 c = getc (infile);
1109 if (c == '\'')
1110 read_lisp_symbol (infile, buffer);
1111 else
1112 {
1113 if (c != '(')
1114 {
1115 fprintf (stderr, "## unparsable name in autoload in %s\n",
1116 filename);
1117 continue;
1118 }
1119 read_lisp_symbol (infile, buffer);
1120 if (strcmp (buffer, "quote"))
1121 {
1122 fprintf (stderr, "## unparsable name in autoload in %s\n",
1123 filename);
1124 continue;
1125 }
1126 read_lisp_symbol (infile, buffer);
1127 c = getc (infile);
1128 if (c != ')')
1129 {
1130 fprintf (stderr,
1131 "## unparsable quoted name in autoload in %s\n",
1132 filename);
1133 continue;
1134 }
1135 }
1136 skip_white (infile);
1137 if ((c = getc (infile)) != '\"')
1138 {
1139 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
1140 buffer, filename);
1141 continue;
1142 }
1143 read_c_string_or_comment (infile, 0, 0, 0);
1144 skip_white (infile);
1145
1146 if (saved_string == 0)
1147 {
1148 /* If the next three characters aren't `dquote bslash newline'
1149 then we're not reading a docstring. */
1150 if ((c = getc (infile)) != '"'
1151 || (c = getc (infile)) != '\\'
1152 || ((c = getc (infile)) != '\n' && c != '\r'))
1153 {
1154 #ifdef DEBUG
1155 fprintf (stderr, "## non-docstring in %s (%s)\n",
1156 buffer, filename);
1157 #endif
1158 continue;
1159 }
1160 }
1161 }
1162
1163 #ifdef DEBUG
1164 else if (! strcmp (buffer, "if")
1165 || ! strcmp (buffer, "byte-code"))
1166 ;
1167 #endif
1168
1169 else
1170 {
1171 #ifdef DEBUG
1172 fprintf (stderr, "## unrecognized top-level form, %s (%s)\n",
1173 buffer, filename);
1174 #endif
1175 continue;
1176 }
1177
1178 /* At this point, we should either use the previous
1179 dynamic doc string in saved_string
1180 or gobble a doc string from the input file.
1181
1182 In the latter case, the opening quote (and leading
1183 backslash-newline) have already been read. */
1184
1185 putc (037, outfile);
1186 putc (type, outfile);
1187 fprintf (outfile, "%s\n", buffer);
1188 if (saved_string)
1189 {
1190 fputs (saved_string, outfile);
1191 /* Don't use one dynamic doc string twice. */
1192 free (saved_string);
1193 saved_string = 0;
1194 }
1195 else
1196 read_c_string_or_comment (infile, 1, 0, 0);
1197 }
1198 fclose (infile);
1199 return 0;
1200 }
1201
1202 /* arch-tag: f7203aaf-991a-4238-acb5-601db56f2894
1203 (do not change this comment) */
1204
1205 /* make-docfile.c ends here */