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