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