Convert function definitions to standard C.
[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
74 #ifdef MSDOS
75 /* s/msdos.h defines this as sys_chdir, but we're not linking with the
76 file where that function is defined. */
77 #undef chdir
78 #endif
79
80 #ifdef HAVE_UNISTD_H
81 #include <unistd.h>
82 #endif
83
84 /* Stdio stream for output to the DOC file. */
85 FILE *outfile;
86
87 /* Name this program was invoked with. */
88 char *progname;
89
90 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
91
92 /* VARARGS1 */
93 void
94 error (char *s1, char *s2)
95 {
96 fprintf (stderr, "%s: ", progname);
97 fprintf (stderr, s1, s2);
98 fprintf (stderr, "\n");
99 }
100
101 /* Print error message and exit. */
102
103 /* VARARGS1 */
104 void
105 fatal (char *s1, char *s2)
106 {
107 error (s1, s2);
108 exit (EXIT_FAILURE);
109 }
110
111 /* Like malloc but get fatal error if memory is exhausted. */
112
113 void *
114 xmalloc (unsigned int size)
115 {
116 void *result = (void *) malloc (size);
117 if (result == NULL)
118 fatal ("virtual memory exhausted", 0);
119 return result;
120 }
121 \f
122 int
123 main (int argc, char **argv)
124 {
125 int i;
126 int err_count = 0;
127 int first_infile;
128
129 progname = argv[0];
130
131 outfile = stdout;
132
133 /* Don't put CRs in the DOC file. */
134 #ifdef MSDOS
135 _fmode = O_BINARY;
136 #if 0 /* Suspicion is that this causes hanging.
137 So instead we require people to use -o on MSDOS. */
138 (stdout)->_flag &= ~_IOTEXT;
139 _setmode (fileno (stdout), O_BINARY);
140 #endif
141 outfile = 0;
142 #endif /* MSDOS */
143 #ifdef WINDOWSNT
144 _fmode = O_BINARY;
145 _setmode (fileno (stdout), O_BINARY);
146 #endif /* WINDOWSNT */
147
148 /* If first two args are -o FILE, output to FILE. */
149 i = 1;
150 if (argc > i + 1 && !strcmp (argv[i], "-o"))
151 {
152 outfile = fopen (argv[i + 1], "w");
153 i += 2;
154 }
155 if (argc > i + 1 && !strcmp (argv[i], "-a"))
156 {
157 outfile = fopen (argv[i + 1], "a");
158 i += 2;
159 }
160 if (argc > i + 1 && !strcmp (argv[i], "-d"))
161 {
162 chdir (argv[i + 1]);
163 i += 2;
164 }
165
166 if (outfile == 0)
167 fatal ("No output file specified", "");
168
169 first_infile = i;
170 for (; i < argc; i++)
171 {
172 int j;
173 /* Don't process one file twice. */
174 for (j = first_infile; j < i; j++)
175 if (! strcmp (argv[i], argv[j]))
176 break;
177 if (j == i)
178 err_count += scan_file (argv[i]);
179 }
180 return (err_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
181 }
182
183 /* Add a source file name boundary marker in the output file. */
184 void
185 put_filename (char *filename)
186 {
187 char *tmp;
188
189 for (tmp = filename; *tmp; tmp++)
190 {
191 if (IS_DIRECTORY_SEP(*tmp))
192 filename = tmp + 1;
193 }
194
195 putc (037, outfile);
196 putc ('S', outfile);
197 fprintf (outfile, "%s\n", filename);
198 }
199
200 /* Read file FILENAME and output its doc strings to outfile. */
201 /* Return 1 if file is not found, 0 if it is found. */
202
203 int
204 scan_file (char *filename)
205 {
206 int 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 char *keyword;
236 /* The current point we've reached in an occurrence of KEYWORD in
237 the input stream. */
238 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 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 int ident_length;
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 (strncmp (ident_start, "void", ident_length) == 0)
479 continue;
480
481 putc (' ', out);
482
483 if (minargs == 0 && maxargs > 0)
484 fprintf (out, "&optional ");
485
486 minargs--;
487 maxargs--;
488
489 /* In C code, `default' is a reserved word, so we spell it
490 `defalt'; unmangle that here. */
491 if (strncmp (ident_start, "defalt", ident_length) == 0)
492 fprintf (out, "DEFAULT");
493 else
494 while (ident_length-- > 0)
495 {
496 c = *ident_start++;
497 if (c >= 'a' && c <= 'z')
498 /* Upcase the letter. */
499 c += 'A' - 'a';
500 else if (c == '_')
501 /* Print underscore as hyphen. */
502 c = '-';
503 putc (c, out);
504 }
505 }
506 }
507
508 putc (')', out);
509 }
510 \f
511 /* Read through a c file. If a .o file is named,
512 the corresponding .c or .m file is read instead.
513 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
514 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
515
516 int
517 scan_c_file (char *filename, char *mode)
518 {
519 FILE *infile;
520 register int c;
521 register int commas;
522 register int defunflag;
523 register int defvarperbufferflag;
524 register int defvarflag;
525 int minargs, maxargs;
526 int extension = filename[strlen (filename) - 1];
527
528 if (extension == 'o')
529 filename[strlen (filename) - 1] = 'c';
530
531 infile = fopen (filename, mode);
532
533 if (infile == NULL && extension == 'o')
534 {
535 /* try .m */
536 filename[strlen (filename) - 1] = 'm';
537 infile = fopen (filename, mode);
538 if (infile == NULL)
539 filename[strlen (filename) - 1] = 'c'; /* don't confuse people */
540 }
541
542 /* No error if non-ex input file */
543 if (infile == NULL)
544 {
545 perror (filename);
546 return 0;
547 }
548
549 /* Reset extension to be able to detect duplicate files. */
550 filename[strlen (filename) - 1] = extension;
551
552 c = '\n';
553 while (!feof (infile))
554 {
555 int doc_keyword = 0;
556
557 if (c != '\n' && c != '\r')
558 {
559 c = getc (infile);
560 continue;
561 }
562 c = getc (infile);
563 if (c == ' ')
564 {
565 while (c == ' ')
566 c = getc (infile);
567 if (c != 'D')
568 continue;
569 c = getc (infile);
570 if (c != 'E')
571 continue;
572 c = getc (infile);
573 if (c != 'F')
574 continue;
575 c = getc (infile);
576 if (c != 'V')
577 continue;
578 c = getc (infile);
579 if (c != 'A')
580 continue;
581 c = getc (infile);
582 if (c != 'R')
583 continue;
584 c = getc (infile);
585 if (c != '_')
586 continue;
587
588 defvarflag = 1;
589 defunflag = 0;
590
591 c = getc (infile);
592 defvarperbufferflag = (c == 'P');
593
594 c = getc (infile);
595 }
596 else if (c == 'D')
597 {
598 c = getc (infile);
599 if (c != 'E')
600 continue;
601 c = getc (infile);
602 if (c != 'F')
603 continue;
604 c = getc (infile);
605 defunflag = c == 'U';
606 defvarflag = 0;
607 defvarperbufferflag = 0;
608 }
609 else continue;
610
611 while (c != '(')
612 {
613 if (c < 0)
614 goto eof;
615 c = getc (infile);
616 }
617
618 /* Lisp variable or function name. */
619 c = getc (infile);
620 if (c != '"')
621 continue;
622 c = read_c_string_or_comment (infile, -1, 0, 0);
623
624 /* DEFVAR_LISP ("name", addr, "doc")
625 DEFVAR_LISP ("name", addr /\* doc *\/)
626 DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */
627
628 if (defunflag)
629 commas = 5;
630 else if (defvarperbufferflag)
631 commas = 2;
632 else if (defvarflag)
633 commas = 1;
634 else /* For DEFSIMPLE and DEFPRED */
635 commas = 2;
636
637 while (commas)
638 {
639 if (c == ',')
640 {
641 commas--;
642
643 if (defunflag && (commas == 1 || commas == 2))
644 {
645 do
646 c = getc (infile);
647 while (c == ' ' || c == '\n' || c == '\r' || c == '\t');
648 if (c < 0)
649 goto eof;
650 ungetc (c, infile);
651 if (commas == 2) /* pick up minargs */
652 fscanf (infile, "%d", &minargs);
653 else /* pick up maxargs */
654 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
655 maxargs = -1;
656 else
657 fscanf (infile, "%d", &maxargs);
658 }
659 }
660
661 if (c == EOF)
662 goto eof;
663 c = getc (infile);
664 }
665
666 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
667 c = getc (infile);
668
669 if (c == '"')
670 c = read_c_string_or_comment (infile, 0, 0, 0);
671
672 while (c != EOF && c != ',' && c != '/')
673 c = getc (infile);
674 if (c == ',')
675 {
676 c = getc (infile);
677 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
678 c = getc (infile);
679 while ((c >= 'a' && c <= 'z') || (c >= 'Z' && c <= 'Z'))
680 c = getc (infile);
681 if (c == ':')
682 {
683 doc_keyword = 1;
684 c = getc (infile);
685 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
686 c = getc (infile);
687 }
688 }
689
690 if (c == '"'
691 || (c == '/'
692 && (c = getc (infile),
693 ungetc (c, infile),
694 c == '*')))
695 {
696 int comment = c != '"';
697 int saw_usage;
698
699 putc (037, outfile);
700 putc (defvarflag ? 'V' : 'F', outfile);
701 fprintf (outfile, "%s\n", buf);
702
703 if (comment)
704 getc (infile); /* Skip past `*' */
705 c = read_c_string_or_comment (infile, 1, comment, &saw_usage);
706
707 /* If this is a defun, find the arguments and print them. If
708 this function takes MANY or UNEVALLED args, then the C source
709 won't give the names of the arguments, so we shouldn't bother
710 trying to find them.
711
712 Various doc-string styles:
713 0: DEFUN (..., "DOC") (args) [!comment]
714 1: DEFUN (..., /\* DOC *\/ (args)) [comment && !doc_keyword]
715 2: DEFUN (..., doc: /\* DOC *\/) (args) [comment && doc_keyword]
716 */
717 if (defunflag && maxargs != -1 && !saw_usage)
718 {
719 char argbuf[1024], *p = argbuf;
720
721 if (!comment || doc_keyword)
722 while (c != ')')
723 {
724 if (c < 0)
725 goto eof;
726 c = getc (infile);
727 }
728
729 /* Skip into arguments. */
730 while (c != '(')
731 {
732 if (c < 0)
733 goto eof;
734 c = getc (infile);
735 }
736 /* Copy arguments into ARGBUF. */
737 *p++ = c;
738 do
739 *p++ = c = getc (infile);
740 while (c != ')');
741 *p = '\0';
742 /* Output them. */
743 fprintf (outfile, "\n\n");
744 write_c_args (outfile, buf, argbuf, minargs, maxargs);
745 }
746 else if (defunflag && maxargs == -1 && !saw_usage)
747 /* The DOC should provide the usage form. */
748 fprintf (stderr, "Missing `usage' for function `%s'.\n", buf);
749 }
750 }
751 eof:
752 fclose (infile);
753 return 0;
754 }
755 \f
756 /* Read a file of Lisp code, compiled or interpreted.
757 Looks for
758 (defun NAME ARGS DOCSTRING ...)
759 (defmacro NAME ARGS DOCSTRING ...)
760 (defsubst NAME ARGS DOCSTRING ...)
761 (autoload (quote NAME) FILE DOCSTRING ...)
762 (defvar NAME VALUE DOCSTRING)
763 (defconst NAME VALUE DOCSTRING)
764 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
765 (fset (quote NAME) #[... DOCSTRING ...])
766 (defalias (quote NAME) #[... DOCSTRING ...])
767 (custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
768 starting in column zero.
769 (quote NAME) may appear as 'NAME as well.
770
771 We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
772 When we find that, we save it for the following defining-form,
773 and we use that instead of reading a doc string within that defining-form.
774
775 For defvar, defconst, and fset we skip to the docstring with a kludgy
776 formatting convention: all docstrings must appear on the same line as the
777 initial open-paren (the one in column zero) and must contain a backslash
778 and a newline immediately after the initial double-quote. No newlines
779 must appear between the beginning of the form and the first double-quote.
780 For defun, defmacro, and autoload, we know how to skip over the
781 arglist, but the doc string must still have a backslash and newline
782 immediately after the double quote.
783 The only source files that must follow this convention are preloaded
784 uncompiled ones like loaddefs.el and bindings.el; aside
785 from that, it is always the .elc file that we look at, and they are no
786 problem because byte-compiler output follows this convention.
787 The NAME and DOCSTRING are output.
788 NAME is preceded by `F' for a function or `V' for a variable.
789 An entry is output only if DOCSTRING has \ newline just after the opening "
790 */
791
792 void
793 skip_white (FILE *infile)
794 {
795 char c = ' ';
796 while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
797 c = getc (infile);
798 ungetc (c, infile);
799 }
800
801 void
802 read_lisp_symbol (FILE *infile, char *buffer)
803 {
804 char c;
805 char *fillp = buffer;
806
807 skip_white (infile);
808 while (1)
809 {
810 c = getc (infile);
811 if (c == '\\')
812 *(++fillp) = getc (infile);
813 else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '(' || c == ')')
814 {
815 ungetc (c, infile);
816 *fillp = 0;
817 break;
818 }
819 else
820 *fillp++ = c;
821 }
822
823 if (! buffer[0])
824 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
825
826 skip_white (infile);
827 }
828
829 int
830 scan_lisp_file (char *filename, char *mode)
831 {
832 FILE *infile;
833 register int c;
834 char *saved_string = 0;
835
836 infile = fopen (filename, mode);
837 if (infile == NULL)
838 {
839 perror (filename);
840 return 0; /* No error */
841 }
842
843 c = '\n';
844 while (!feof (infile))
845 {
846 char buffer[BUFSIZ];
847 char type;
848
849 /* If not at end of line, skip till we get to one. */
850 if (c != '\n' && c != '\r')
851 {
852 c = getc (infile);
853 continue;
854 }
855 /* Skip the line break. */
856 while (c == '\n' || c == '\r')
857 c = getc (infile);
858 /* Detect a dynamic doc string and save it for the next expression. */
859 if (c == '#')
860 {
861 c = getc (infile);
862 if (c == '@')
863 {
864 int length = 0;
865 int i;
866
867 /* Read the length. */
868 while ((c = getc (infile),
869 c >= '0' && c <= '9'))
870 {
871 length *= 10;
872 length += c - '0';
873 }
874
875 /* The next character is a space that is counted in the length
876 but not part of the doc string.
877 We already read it, so just ignore it. */
878 length--;
879
880 /* Read in the contents. */
881 free (saved_string);
882 saved_string = (char *) xmalloc (length);
883 for (i = 0; i < length; i++)
884 saved_string[i] = getc (infile);
885 /* The last character is a ^_.
886 That is needed in the .elc file
887 but it is redundant in DOC. So get rid of it here. */
888 saved_string[length - 1] = 0;
889 /* Skip the line break. */
890 while (c == '\n' && c == '\r')
891 c = getc (infile);
892 /* Skip the following line. */
893 while (c != '\n' && c != '\r')
894 c = getc (infile);
895 }
896 continue;
897 }
898
899 if (c != '(')
900 continue;
901
902 read_lisp_symbol (infile, buffer);
903
904 if (! strcmp (buffer, "defun")
905 || ! strcmp (buffer, "defmacro")
906 || ! strcmp (buffer, "defsubst"))
907 {
908 type = 'F';
909 read_lisp_symbol (infile, buffer);
910
911 /* Skip the arguments: either "nil" or a list in parens */
912
913 c = getc (infile);
914 if (c == 'n') /* nil */
915 {
916 if ((c = getc (infile)) != 'i'
917 || (c = getc (infile)) != 'l')
918 {
919 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
920 buffer, filename);
921 continue;
922 }
923 }
924 else if (c != '(')
925 {
926 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
927 buffer, filename);
928 continue;
929 }
930 else
931 while (c != ')')
932 c = getc (infile);
933 skip_white (infile);
934
935 /* If the next three characters aren't `dquote bslash newline'
936 then we're not reading a docstring.
937 */
938 if ((c = getc (infile)) != '"'
939 || (c = getc (infile)) != '\\'
940 || ((c = getc (infile)) != '\n' && c != '\r'))
941 {
942 #ifdef DEBUG
943 fprintf (stderr, "## non-docstring in %s (%s)\n",
944 buffer, filename);
945 #endif
946 continue;
947 }
948 }
949
950 else if (! strcmp (buffer, "defvar")
951 || ! strcmp (buffer, "defconst"))
952 {
953 char c1 = 0, c2 = 0;
954 type = 'V';
955 read_lisp_symbol (infile, buffer);
956
957 if (saved_string == 0)
958 {
959
960 /* Skip until the end of line; remember two previous chars. */
961 while (c != '\n' && c != '\r' && c >= 0)
962 {
963 c2 = c1;
964 c1 = c;
965 c = getc (infile);
966 }
967
968 /* If two previous characters were " and \,
969 this is a doc string. Otherwise, there is none. */
970 if (c2 != '"' || c1 != '\\')
971 {
972 #ifdef DEBUG
973 fprintf (stderr, "## non-docstring in %s (%s)\n",
974 buffer, filename);
975 #endif
976 continue;
977 }
978 }
979 }
980
981 else if (! strcmp (buffer, "custom-declare-variable")
982 || ! strcmp (buffer, "defvaralias")
983 )
984 {
985 char c1 = 0, c2 = 0;
986 type = 'V';
987
988 c = getc (infile);
989 if (c == '\'')
990 read_lisp_symbol (infile, buffer);
991 else
992 {
993 if (c != '(')
994 {
995 fprintf (stderr,
996 "## unparsable name in custom-declare-variable in %s\n",
997 filename);
998 continue;
999 }
1000 read_lisp_symbol (infile, buffer);
1001 if (strcmp (buffer, "quote"))
1002 {
1003 fprintf (stderr,
1004 "## unparsable name in custom-declare-variable in %s\n",
1005 filename);
1006 continue;
1007 }
1008 read_lisp_symbol (infile, buffer);
1009 c = getc (infile);
1010 if (c != ')')
1011 {
1012 fprintf (stderr,
1013 "## unparsable quoted name in custom-declare-variable in %s\n",
1014 filename);
1015 continue;
1016 }
1017 }
1018
1019 if (saved_string == 0)
1020 {
1021 /* Skip to end of line; remember the two previous chars. */
1022 while (c != '\n' && c != '\r' && c >= 0)
1023 {
1024 c2 = c1;
1025 c1 = c;
1026 c = getc (infile);
1027 }
1028
1029 /* If two previous characters were " and \,
1030 this is a doc string. Otherwise, there is none. */
1031 if (c2 != '"' || c1 != '\\')
1032 {
1033 #ifdef DEBUG
1034 fprintf (stderr, "## non-docstring in %s (%s)\n",
1035 buffer, filename);
1036 #endif
1037 continue;
1038 }
1039 }
1040 }
1041
1042 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
1043 {
1044 char c1 = 0, c2 = 0;
1045 type = 'F';
1046
1047 c = getc (infile);
1048 if (c == '\'')
1049 read_lisp_symbol (infile, buffer);
1050 else
1051 {
1052 if (c != '(')
1053 {
1054 fprintf (stderr, "## unparsable name in fset in %s\n",
1055 filename);
1056 continue;
1057 }
1058 read_lisp_symbol (infile, buffer);
1059 if (strcmp (buffer, "quote"))
1060 {
1061 fprintf (stderr, "## unparsable name in fset in %s\n",
1062 filename);
1063 continue;
1064 }
1065 read_lisp_symbol (infile, buffer);
1066 c = getc (infile);
1067 if (c != ')')
1068 {
1069 fprintf (stderr,
1070 "## unparsable quoted name in fset in %s\n",
1071 filename);
1072 continue;
1073 }
1074 }
1075
1076 if (saved_string == 0)
1077 {
1078 /* Skip to end of line; remember the two previous chars. */
1079 while (c != '\n' && c != '\r' && c >= 0)
1080 {
1081 c2 = c1;
1082 c1 = c;
1083 c = getc (infile);
1084 }
1085
1086 /* If two previous characters were " and \,
1087 this is a doc string. Otherwise, there is none. */
1088 if (c2 != '"' || c1 != '\\')
1089 {
1090 #ifdef DEBUG
1091 fprintf (stderr, "## non-docstring in %s (%s)\n",
1092 buffer, filename);
1093 #endif
1094 continue;
1095 }
1096 }
1097 }
1098
1099 else if (! strcmp (buffer, "autoload"))
1100 {
1101 type = 'F';
1102 c = getc (infile);
1103 if (c == '\'')
1104 read_lisp_symbol (infile, buffer);
1105 else
1106 {
1107 if (c != '(')
1108 {
1109 fprintf (stderr, "## unparsable name in autoload in %s\n",
1110 filename);
1111 continue;
1112 }
1113 read_lisp_symbol (infile, buffer);
1114 if (strcmp (buffer, "quote"))
1115 {
1116 fprintf (stderr, "## unparsable name in autoload in %s\n",
1117 filename);
1118 continue;
1119 }
1120 read_lisp_symbol (infile, buffer);
1121 c = getc (infile);
1122 if (c != ')')
1123 {
1124 fprintf (stderr,
1125 "## unparsable quoted name in autoload in %s\n",
1126 filename);
1127 continue;
1128 }
1129 }
1130 skip_white (infile);
1131 if ((c = getc (infile)) != '\"')
1132 {
1133 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
1134 buffer, filename);
1135 continue;
1136 }
1137 read_c_string_or_comment (infile, 0, 0, 0);
1138 skip_white (infile);
1139
1140 if (saved_string == 0)
1141 {
1142 /* If the next three characters aren't `dquote bslash newline'
1143 then we're not reading a docstring. */
1144 if ((c = getc (infile)) != '"'
1145 || (c = getc (infile)) != '\\'
1146 || ((c = getc (infile)) != '\n' && c != '\r'))
1147 {
1148 #ifdef DEBUG
1149 fprintf (stderr, "## non-docstring in %s (%s)\n",
1150 buffer, filename);
1151 #endif
1152 continue;
1153 }
1154 }
1155 }
1156
1157 #ifdef DEBUG
1158 else if (! strcmp (buffer, "if")
1159 || ! strcmp (buffer, "byte-code"))
1160 ;
1161 #endif
1162
1163 else
1164 {
1165 #ifdef DEBUG
1166 fprintf (stderr, "## unrecognized top-level form, %s (%s)\n",
1167 buffer, filename);
1168 #endif
1169 continue;
1170 }
1171
1172 /* At this point, we should either use the previous
1173 dynamic doc string in saved_string
1174 or gobble a doc string from the input file.
1175
1176 In the latter case, the opening quote (and leading
1177 backslash-newline) have already been read. */
1178
1179 putc (037, outfile);
1180 putc (type, outfile);
1181 fprintf (outfile, "%s\n", buffer);
1182 if (saved_string)
1183 {
1184 fputs (saved_string, outfile);
1185 /* Don't use one dynamic doc string twice. */
1186 free (saved_string);
1187 saved_string = 0;
1188 }
1189 else
1190 read_c_string_or_comment (infile, 1, 0, 0);
1191 }
1192 fclose (infile);
1193 return 0;
1194 }
1195
1196 /* arch-tag: f7203aaf-991a-4238-acb5-601db56f2894
1197 (do not change this comment) */
1198
1199 /* make-docfile.c ends here */