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