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