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