Auto-commit of generated files.
[emacs.git] / lib-src / make-docfile.c
blob627f4639aaad58530d8b935cc5b124462b4e85d0
1 /* Generate doc-string file for GNU Emacs from source files.
3 Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2012
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22 /* The arguments given to this program are all the C and Lisp source files
23 of GNU Emacs. .elc and .el and .c files are allowed.
24 A .o file can also be specified; the .c file it was made from is used.
25 This helps the makefile pass the correct list of files.
26 Option -d DIR means change to DIR before looking for files.
28 The results, which go to standard output or to a file
29 specified with -a or -o (-a to append, -o to start from nothing),
30 are entries containing function or variable names and their documentation.
31 Each entry starts with a ^_ character.
32 Then comes F for a function or V for a variable.
33 Then comes the function or variable name, terminated with a newline.
34 Then comes the documentation for that function or variable.
37 #include <config.h>
39 #include <stdio.h>
40 #include <stdlib.h> /* config.h unconditionally includes this anyway */
41 #ifdef MSDOS
42 #include <fcntl.h>
43 #endif /* MSDOS */
44 #ifdef WINDOWSNT
45 /* Defined to be sys_fopen in ms-w32.h, but only #ifdef emacs, so this
46 is really just insurance. */
47 #undef fopen
48 #include <fcntl.h>
49 #include <direct.h>
50 #endif /* WINDOWSNT */
52 #ifdef DOS_NT
53 /* Defined to be sys_chdir in ms-w32.h, but only #ifdef emacs, so this
54 is really just insurance.
56 Similarly, msdos defines this as sys_chdir, but we're not linking with the
57 file where that function is defined. */
58 #undef chdir
59 #define READ_TEXT "rt"
60 #define READ_BINARY "rb"
61 #else /* not DOS_NT */
62 #define READ_TEXT "r"
63 #define READ_BINARY "r"
64 #endif /* not DOS_NT */
66 /* Use this to suppress gcc's `...may be used before initialized' warnings. */
67 #ifdef lint
68 # define IF_LINT(Code) Code
69 #else
70 # define IF_LINT(Code) /* empty */
71 #endif
73 static int scan_file (char *filename);
74 static int scan_lisp_file (const char *filename, const char *mode);
75 static int scan_c_file (char *filename, const char *mode);
76 static void start_globals (void);
77 static void write_globals (void);
79 #include <unistd.h>
81 /* Stdio stream for output to the DOC file. */
82 FILE *outfile;
84 /* Name this program was invoked with. */
85 char *progname;
87 /* Nonzero if this invocation is generating globals.h. */
88 int generate_globals;
90 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
92 /* VARARGS1 */
93 static void
94 error (const char *s1, const char *s2)
96 fprintf (stderr, "%s: ", progname);
97 fprintf (stderr, s1, s2);
98 fprintf (stderr, "\n");
101 /* Print error message and exit. */
103 /* VARARGS1 */
104 static _Noreturn void
105 fatal (const char *s1, const char *s2)
107 error (s1, s2);
108 exit (EXIT_FAILURE);
111 /* Like malloc but get fatal error if memory is exhausted. */
113 static void *
114 xmalloc (unsigned int size)
116 void *result = (void *) malloc (size);
117 if (result == NULL)
118 fatal ("virtual memory exhausted", 0);
119 return result;
122 /* Like realloc but get fatal error if memory is exhausted. */
124 static void *
125 xrealloc (void *arg, unsigned int size)
127 void *result = (void *) realloc (arg, size);
128 if (result == NULL)
129 fatal ("virtual memory exhausted", 0);
130 return result;
135 main (int argc, char **argv)
137 int i;
138 int err_count = 0;
139 int first_infile;
141 progname = argv[0];
143 outfile = stdout;
145 /* Don't put CRs in the DOC file. */
146 #ifdef MSDOS
147 _fmode = O_BINARY;
148 #if 0 /* Suspicion is that this causes hanging.
149 So instead we require people to use -o on MSDOS. */
150 (stdout)->_flag &= ~_IOTEXT;
151 _setmode (fileno (stdout), O_BINARY);
152 #endif
153 outfile = 0;
154 #endif /* MSDOS */
155 #ifdef WINDOWSNT
156 _fmode = O_BINARY;
157 _setmode (fileno (stdout), O_BINARY);
158 #endif /* WINDOWSNT */
160 /* If first two args are -o FILE, output to FILE. */
161 i = 1;
162 if (argc > i + 1 && !strcmp (argv[i], "-o"))
164 outfile = fopen (argv[i + 1], "w");
165 i += 2;
167 if (argc > i + 1 && !strcmp (argv[i], "-a"))
169 outfile = fopen (argv[i + 1], "a");
170 i += 2;
172 if (argc > i + 1 && !strcmp (argv[i], "-d"))
174 if (chdir (argv[i + 1]) != 0)
176 perror (argv[i + 1]);
177 return EXIT_FAILURE;
179 i += 2;
181 if (argc > i && !strcmp (argv[i], "-g"))
183 generate_globals = 1;
184 ++i;
187 if (outfile == 0)
188 fatal ("No output file specified", "");
190 if (generate_globals)
191 start_globals ();
193 first_infile = i;
194 for (; i < argc; i++)
196 int j;
197 /* Don't process one file twice. */
198 for (j = first_infile; j < i; j++)
199 if (! strcmp (argv[i], argv[j]))
200 break;
201 if (j == i)
202 err_count += scan_file (argv[i]);
205 if (err_count == 0 && generate_globals)
206 write_globals ();
208 return (err_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
211 /* Add a source file name boundary marker in the output file. */
212 static void
213 put_filename (char *filename)
215 char *tmp;
217 for (tmp = filename; *tmp; tmp++)
219 if (IS_DIRECTORY_SEP (*tmp))
220 filename = tmp + 1;
223 putc (037, outfile);
224 putc ('S', outfile);
225 fprintf (outfile, "%s\n", filename);
228 /* Read file FILENAME and output its doc strings to outfile. */
229 /* Return 1 if file is not found, 0 if it is found. */
231 static int
232 scan_file (char *filename)
235 size_t len = strlen (filename);
237 if (!generate_globals)
238 put_filename (filename);
239 if (len > 4 && !strcmp (filename + len - 4, ".elc"))
240 return scan_lisp_file (filename, READ_BINARY);
241 else if (len > 3 && !strcmp (filename + len - 3, ".el"))
242 return scan_lisp_file (filename, READ_TEXT);
243 else
244 return scan_c_file (filename, READ_TEXT);
247 static void
248 start_globals (void)
250 fprintf (outfile, "/* This file was auto-generated by make-docfile. */\n");
251 fprintf (outfile, "/* DO NOT EDIT. */\n");
252 fprintf (outfile, "struct emacs_globals {\n");
255 static char input_buffer[128];
257 /* Some state during the execution of `read_c_string_or_comment'. */
258 struct rcsoc_state
260 /* A count of spaces and newlines that have been read, but not output. */
261 unsigned pending_spaces, pending_newlines;
263 /* Where we're reading from. */
264 FILE *in_file;
266 /* If non-zero, a buffer into which to copy characters. */
267 char *buf_ptr;
268 /* If non-zero, a file into which to copy characters. */
269 FILE *out_file;
271 /* A keyword we look for at the beginning of lines. If found, it is
272 not copied, and SAW_KEYWORD is set to true. */
273 const char *keyword;
274 /* The current point we've reached in an occurrence of KEYWORD in
275 the input stream. */
276 const char *cur_keyword_ptr;
277 /* Set to true if we saw an occurrence of KEYWORD. */
278 int saw_keyword;
281 /* Output CH to the file or buffer in STATE. Any pending newlines or
282 spaces are output first. */
284 static inline void
285 put_char (int ch, struct rcsoc_state *state)
287 int out_ch;
290 if (state->pending_newlines > 0)
292 state->pending_newlines--;
293 out_ch = '\n';
295 else if (state->pending_spaces > 0)
297 state->pending_spaces--;
298 out_ch = ' ';
300 else
301 out_ch = ch;
303 if (state->out_file)
304 putc (out_ch, state->out_file);
305 if (state->buf_ptr)
306 *state->buf_ptr++ = out_ch;
308 while (out_ch != ch);
311 /* If in the middle of scanning a keyword, continue scanning with
312 character CH, otherwise output CH to the file or buffer in STATE.
313 Any pending newlines or spaces are output first, as well as any
314 previously scanned characters that were thought to be part of a
315 keyword, but were in fact not. */
317 static void
318 scan_keyword_or_put_char (int ch, struct rcsoc_state *state)
320 if (state->keyword
321 && *state->cur_keyword_ptr == ch
322 && (state->cur_keyword_ptr > state->keyword
323 || state->pending_newlines > 0))
324 /* We might be looking at STATE->keyword at some point.
325 Keep looking until we know for sure. */
327 if (*++state->cur_keyword_ptr == '\0')
328 /* Saw the whole keyword. Set SAW_KEYWORD flag to true. */
330 state->saw_keyword = 1;
332 /* Reset the scanning pointer. */
333 state->cur_keyword_ptr = state->keyword;
335 /* Canonicalize whitespace preceding a usage string. */
336 state->pending_newlines = 2;
337 state->pending_spaces = 0;
339 /* Skip any whitespace between the keyword and the
340 usage string. */
342 ch = getc (state->in_file);
343 while (ch == ' ' || ch == '\n');
345 /* Output the open-paren we just read. */
346 put_char (ch, state);
348 /* Skip the function name and replace it with `fn'. */
350 ch = getc (state->in_file);
351 while (ch != ' ' && ch != ')');
352 put_char ('f', state);
353 put_char ('n', state);
355 /* Put back the last character. */
356 ungetc (ch, state->in_file);
359 else
361 if (state->keyword && state->cur_keyword_ptr > state->keyword)
362 /* We scanned the beginning of a potential usage
363 keyword, but it was a false alarm. Output the
364 part we scanned. */
366 const char *p;
368 for (p = state->keyword; p < state->cur_keyword_ptr; p++)
369 put_char (*p, state);
371 state->cur_keyword_ptr = state->keyword;
374 put_char (ch, state);
379 /* Skip a C string or C-style comment from INFILE, and return the
380 character that follows. COMMENT non-zero means skip a comment. If
381 PRINTFLAG is positive, output string contents to outfile. If it is
382 negative, store contents in buf. Convert escape sequences \n and
383 \t to newline and tab; discard \ followed by newline.
384 If SAW_USAGE is non-zero, then any occurrences of the string `usage:'
385 at the beginning of a line will be removed, and *SAW_USAGE set to
386 true if any were encountered. */
388 static int
389 read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usage)
391 register int c;
392 struct rcsoc_state state;
394 state.in_file = infile;
395 state.buf_ptr = (printflag < 0 ? input_buffer : 0);
396 state.out_file = (printflag > 0 ? outfile : 0);
397 state.pending_spaces = 0;
398 state.pending_newlines = 0;
399 state.keyword = (saw_usage ? "usage:" : 0);
400 state.cur_keyword_ptr = state.keyword;
401 state.saw_keyword = 0;
403 c = getc (infile);
404 if (comment)
405 while (c == '\n' || c == '\r' || c == '\t' || c == ' ')
406 c = getc (infile);
408 while (c != EOF)
410 while (c != EOF && (comment ? c != '*' : c != '"'))
412 if (c == '\\')
414 c = getc (infile);
415 if (c == '\n' || c == '\r')
417 c = getc (infile);
418 continue;
420 if (c == 'n')
421 c = '\n';
422 if (c == 't')
423 c = '\t';
426 if (c == ' ')
427 state.pending_spaces++;
428 else if (c == '\n')
430 state.pending_newlines++;
431 state.pending_spaces = 0;
433 else
434 scan_keyword_or_put_char (c, &state);
436 c = getc (infile);
439 if (c != EOF)
440 c = getc (infile);
442 if (comment)
444 if (c == '/')
446 c = getc (infile);
447 break;
450 scan_keyword_or_put_char ('*', &state);
452 else
454 if (c != '"')
455 break;
457 /* If we had a "", concatenate the two strings. */
458 c = getc (infile);
462 if (printflag < 0)
463 *state.buf_ptr = 0;
465 if (saw_usage)
466 *saw_usage = state.saw_keyword;
468 return c;
473 /* Write to file OUT the argument names of function FUNC, whose text is in BUF.
474 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
476 static void
477 write_c_args (FILE *out, char *func, char *buf, int minargs, int maxargs)
479 register char *p;
480 int in_ident = 0;
481 char *ident_start IF_LINT (= NULL);
482 size_t ident_length = 0;
484 fprintf (out, "(fn");
486 if (*buf == '(')
487 ++buf;
489 for (p = buf; *p; p++)
491 char c = *p;
493 /* Notice when a new identifier starts. */
494 if ((('A' <= c && c <= 'Z')
495 || ('a' <= c && c <= 'z')
496 || ('0' <= c && c <= '9')
497 || c == '_')
498 != in_ident)
500 if (!in_ident)
502 in_ident = 1;
503 ident_start = p;
505 else
507 in_ident = 0;
508 ident_length = p - ident_start;
512 /* Found the end of an argument, write out the last seen
513 identifier. */
514 if (c == ',' || c == ')')
516 if (ident_length == 0)
518 error ("empty arg list for `%s' should be (void), not ()", func);
519 continue;
522 if (strncmp (ident_start, "void", ident_length) == 0)
523 continue;
525 putc (' ', out);
527 if (minargs == 0 && maxargs > 0)
528 fprintf (out, "&optional ");
530 minargs--;
531 maxargs--;
533 /* In C code, `default' is a reserved word, so we spell it
534 `defalt'; demangle that here. */
535 if (ident_length == 6 && memcmp (ident_start, "defalt", 6) == 0)
536 fprintf (out, "DEFAULT");
537 else
538 while (ident_length-- > 0)
540 c = *ident_start++;
541 if (c >= 'a' && c <= 'z')
542 /* Upcase the letter. */
543 c += 'A' - 'a';
544 else if (c == '_')
545 /* Print underscore as hyphen. */
546 c = '-';
547 putc (c, out);
552 putc (')', out);
555 /* The types of globals. */
556 enum global_type
558 FUNCTION,
559 EMACS_INTEGER,
560 BOOLEAN,
561 LISP_OBJECT,
562 INVALID
565 /* A single global. */
566 struct global
568 enum global_type type;
569 char *name;
570 int value;
573 /* All the variable names we saw while scanning C sources in `-g'
574 mode. */
575 int num_globals;
576 int num_globals_allocated;
577 struct global *globals;
579 static void
580 add_global (enum global_type type, char *name, int value)
582 /* Ignore the one non-symbol that can occur. */
583 if (strcmp (name, "..."))
585 ++num_globals;
587 if (num_globals_allocated == 0)
589 num_globals_allocated = 100;
590 globals = xmalloc (num_globals_allocated * sizeof (struct global));
592 else if (num_globals == num_globals_allocated)
594 num_globals_allocated *= 2;
595 globals = xrealloc (globals,
596 num_globals_allocated * sizeof (struct global));
599 globals[num_globals - 1].type = type;
600 globals[num_globals - 1].name = name;
601 globals[num_globals - 1].value = value;
605 static int
606 compare_globals (const void *a, const void *b)
608 const struct global *ga = a;
609 const struct global *gb = b;
611 if (ga->type == FUNCTION)
613 if (gb->type != FUNCTION)
614 return 1;
616 else if (gb->type == FUNCTION)
617 return -1;
619 return strcmp (ga->name, gb->name);
622 static void
623 close_emacs_globals (void)
625 fprintf (outfile, "};\n");
626 fprintf (outfile, "extern struct emacs_globals globals;\n");
629 static void
630 write_globals (void)
632 int i, seen_defun = 0;
633 qsort (globals, num_globals, sizeof (struct global), compare_globals);
634 for (i = 0; i < num_globals; ++i)
636 char const *type;
638 switch (globals[i].type)
640 case EMACS_INTEGER:
641 type = "EMACS_INT";
642 break;
643 case BOOLEAN:
644 type = "int";
645 break;
646 case LISP_OBJECT:
647 type = "Lisp_Object";
648 break;
649 case FUNCTION:
650 if (!seen_defun)
652 close_emacs_globals ();
653 fprintf (outfile, "\n");
654 seen_defun = 1;
656 break;
657 default:
658 fatal ("not a recognized DEFVAR_", 0);
661 if (globals[i].type != FUNCTION)
663 fprintf (outfile, " %s f_%s;\n", type, globals[i].name);
664 fprintf (outfile, "#define %s globals.f_%s\n",
665 globals[i].name, globals[i].name);
667 else
669 /* It would be nice to have a cleaner way to deal with these
670 special hacks. */
671 if (strcmp (globals[i].name, "Fthrow") == 0
672 || strcmp (globals[i].name, "Ftop_level") == 0
673 || strcmp (globals[i].name, "Fkill_emacs") == 0)
674 fprintf (outfile, "_Noreturn ");
675 fprintf (outfile, "EXFUN (%s, ", globals[i].name);
676 if (globals[i].value == -1)
677 fprintf (outfile, "MANY");
678 else if (globals[i].value == -2)
679 fprintf (outfile, "UNEVALLED");
680 else
681 fprintf (outfile, "%d", globals[i].value);
682 fprintf (outfile, ");\n");
685 while (i + 1 < num_globals
686 && !strcmp (globals[i].name, globals[i + 1].name))
688 if (globals[i].type == FUNCTION
689 && globals[i].value != globals[i + 1].value)
690 error ("function '%s' defined twice with differing signatures",
691 globals[i].name);
692 ++i;
696 if (!seen_defun)
697 close_emacs_globals ();
701 /* Read through a c file. If a .o file is named,
702 the corresponding .c or .m file is read instead.
703 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
704 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
706 static int
707 scan_c_file (char *filename, const char *mode)
709 FILE *infile;
710 register int c;
711 register int commas;
712 int minargs, maxargs;
713 int extension = filename[strlen (filename) - 1];
715 if (extension == 'o')
716 filename[strlen (filename) - 1] = 'c';
718 infile = fopen (filename, mode);
720 if (infile == NULL && extension == 'o')
722 /* Try .m. */
723 filename[strlen (filename) - 1] = 'm';
724 infile = fopen (filename, mode);
725 if (infile == NULL)
726 filename[strlen (filename) - 1] = 'c'; /* Don't confuse people. */
729 /* No error if non-ex input file. */
730 if (infile == NULL)
732 perror (filename);
733 return 0;
736 /* Reset extension to be able to detect duplicate files. */
737 filename[strlen (filename) - 1] = extension;
739 c = '\n';
740 while (!feof (infile))
742 int doc_keyword = 0;
743 int defunflag = 0;
744 int defvarperbufferflag = 0;
745 int defvarflag = 0;
746 enum global_type type = INVALID;
747 char *name IF_LINT (= 0);
749 if (c != '\n' && c != '\r')
751 c = getc (infile);
752 continue;
754 c = getc (infile);
755 if (c == ' ')
757 while (c == ' ')
758 c = getc (infile);
759 if (c != 'D')
760 continue;
761 c = getc (infile);
762 if (c != 'E')
763 continue;
764 c = getc (infile);
765 if (c != 'F')
766 continue;
767 c = getc (infile);
768 if (c != 'V')
769 continue;
770 c = getc (infile);
771 if (c != 'A')
772 continue;
773 c = getc (infile);
774 if (c != 'R')
775 continue;
776 c = getc (infile);
777 if (c != '_')
778 continue;
780 defvarflag = 1;
782 c = getc (infile);
783 defvarperbufferflag = (c == 'P');
784 if (generate_globals)
786 if (c == 'I')
787 type = EMACS_INTEGER;
788 else if (c == 'L')
789 type = LISP_OBJECT;
790 else if (c == 'B')
791 type = BOOLEAN;
794 c = getc (infile);
795 /* We need to distinguish between DEFVAR_BOOL and
796 DEFVAR_BUFFER_DEFAULTS. */
797 if (generate_globals && type == BOOLEAN && c != 'O')
798 type = INVALID;
800 else if (c == 'D')
802 c = getc (infile);
803 if (c != 'E')
804 continue;
805 c = getc (infile);
806 if (c != 'F')
807 continue;
808 c = getc (infile);
809 defunflag = c == 'U';
811 else continue;
813 if (generate_globals
814 && (!defvarflag || defvarperbufferflag || type == INVALID)
815 && !defunflag)
816 continue;
818 while (c != '(')
820 if (c < 0)
821 goto eof;
822 c = getc (infile);
825 /* Lisp variable or function name. */
826 c = getc (infile);
827 if (c != '"')
828 continue;
829 c = read_c_string_or_comment (infile, -1, 0, 0);
831 if (generate_globals)
833 int i = 0;
835 /* Skip "," and whitespace. */
838 c = getc (infile);
840 while (c == ',' || c == ' ' || c == '\t' || c == '\n' || c == '\r');
842 /* Read in the identifier. */
845 input_buffer[i++] = c;
846 c = getc (infile);
848 while (! (c == ',' || c == ' ' || c == '\t'
849 || c == '\n' || c == '\r'));
850 input_buffer[i] = '\0';
852 name = xmalloc (i + 1);
853 memcpy (name, input_buffer, i + 1);
855 if (!defunflag)
857 add_global (type, name, 0);
858 continue;
862 /* DEFVAR_LISP ("name", addr, "doc")
863 DEFVAR_LISP ("name", addr /\* doc *\/)
864 DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */
866 if (defunflag)
867 commas = generate_globals ? 4 : 5;
868 else if (defvarperbufferflag)
869 commas = 3;
870 else if (defvarflag)
871 commas = 1;
872 else /* For DEFSIMPLE and DEFPRED. */
873 commas = 2;
875 while (commas)
877 if (c == ',')
879 commas--;
881 if (defunflag && (commas == 1 || commas == 2))
883 int scanned = 0;
885 c = getc (infile);
886 while (c == ' ' || c == '\n' || c == '\r' || c == '\t');
887 if (c < 0)
888 goto eof;
889 ungetc (c, infile);
890 if (commas == 2) /* Pick up minargs. */
891 scanned = fscanf (infile, "%d", &minargs);
892 else /* Pick up maxargs. */
893 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
895 if (generate_globals)
896 maxargs = (c == 'M') ? -1 : -2;
897 else
898 maxargs = -1;
900 else
901 scanned = fscanf (infile, "%d", &maxargs);
902 if (scanned < 0)
903 goto eof;
907 if (c == EOF)
908 goto eof;
909 c = getc (infile);
912 if (generate_globals)
914 add_global (FUNCTION, name, maxargs);
915 continue;
918 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
919 c = getc (infile);
921 if (c == '"')
922 c = read_c_string_or_comment (infile, 0, 0, 0);
924 while (c != EOF && c != ',' && c != '/')
925 c = getc (infile);
926 if (c == ',')
928 c = getc (infile);
929 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
930 c = getc (infile);
931 while ((c >= 'a' && c <= 'z') || (c >= 'Z' && c <= 'Z'))
932 c = getc (infile);
933 if (c == ':')
935 doc_keyword = 1;
936 c = getc (infile);
937 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
938 c = getc (infile);
942 if (c == '"'
943 || (c == '/'
944 && (c = getc (infile),
945 ungetc (c, infile),
946 c == '*')))
948 int comment = c != '"';
949 int saw_usage;
951 putc (037, outfile);
952 putc (defvarflag ? 'V' : 'F', outfile);
953 fprintf (outfile, "%s\n", input_buffer);
955 if (comment)
956 getc (infile); /* Skip past `*'. */
957 c = read_c_string_or_comment (infile, 1, comment, &saw_usage);
959 /* If this is a defun, find the arguments and print them. If
960 this function takes MANY or UNEVALLED args, then the C source
961 won't give the names of the arguments, so we shouldn't bother
962 trying to find them.
964 Various doc-string styles:
965 0: DEFUN (..., "DOC") (args) [!comment]
966 1: DEFUN (..., /\* DOC *\/ (args)) [comment && !doc_keyword]
967 2: DEFUN (..., doc: /\* DOC *\/) (args) [comment && doc_keyword]
969 if (defunflag && maxargs != -1 && !saw_usage)
971 char argbuf[1024], *p = argbuf;
973 if (!comment || doc_keyword)
974 while (c != ')')
976 if (c < 0)
977 goto eof;
978 c = getc (infile);
981 /* Skip into arguments. */
982 while (c != '(')
984 if (c < 0)
985 goto eof;
986 c = getc (infile);
988 /* Copy arguments into ARGBUF. */
989 *p++ = c;
991 *p++ = c = getc (infile);
992 while (c != ')');
993 *p = '\0';
994 /* Output them. */
995 fprintf (outfile, "\n\n");
996 write_c_args (outfile, input_buffer, argbuf, minargs, maxargs);
998 else if (defunflag && maxargs == -1 && !saw_usage)
999 /* The DOC should provide the usage form. */
1000 fprintf (stderr, "Missing `usage' for function `%s'.\n",
1001 input_buffer);
1004 eof:
1005 fclose (infile);
1006 return 0;
1009 /* Read a file of Lisp code, compiled or interpreted.
1010 Looks for
1011 (defun NAME ARGS DOCSTRING ...)
1012 (defmacro NAME ARGS DOCSTRING ...)
1013 (defsubst NAME ARGS DOCSTRING ...)
1014 (autoload (quote NAME) FILE DOCSTRING ...)
1015 (defvar NAME VALUE DOCSTRING)
1016 (defconst NAME VALUE DOCSTRING)
1017 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
1018 (fset (quote NAME) #[... DOCSTRING ...])
1019 (defalias (quote NAME) #[... DOCSTRING ...])
1020 (custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
1021 starting in column zero.
1022 (quote NAME) may appear as 'NAME as well.
1024 We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
1025 When we find that, we save it for the following defining-form,
1026 and we use that instead of reading a doc string within that defining-form.
1028 For defvar, defconst, and fset we skip to the docstring with a kludgy
1029 formatting convention: all docstrings must appear on the same line as the
1030 initial open-paren (the one in column zero) and must contain a backslash
1031 and a newline immediately after the initial double-quote. No newlines
1032 must appear between the beginning of the form and the first double-quote.
1033 For defun, defmacro, and autoload, we know how to skip over the
1034 arglist, but the doc string must still have a backslash and newline
1035 immediately after the double quote.
1036 The only source files that must follow this convention are preloaded
1037 uncompiled ones like loaddefs.el and bindings.el; aside
1038 from that, it is always the .elc file that we look at, and they are no
1039 problem because byte-compiler output follows this convention.
1040 The NAME and DOCSTRING are output.
1041 NAME is preceded by `F' for a function or `V' for a variable.
1042 An entry is output only if DOCSTRING has \ newline just after the opening ".
1045 static void
1046 skip_white (FILE *infile)
1048 char c = ' ';
1049 while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
1050 c = getc (infile);
1051 ungetc (c, infile);
1054 static void
1055 read_lisp_symbol (FILE *infile, char *buffer)
1057 char c;
1058 char *fillp = buffer;
1060 skip_white (infile);
1061 while (1)
1063 c = getc (infile);
1064 if (c == '\\')
1065 *(++fillp) = getc (infile);
1066 else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '(' || c == ')')
1068 ungetc (c, infile);
1069 *fillp = 0;
1070 break;
1072 else
1073 *fillp++ = c;
1076 if (! buffer[0])
1077 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
1079 skip_white (infile);
1082 static int
1083 search_lisp_doc_at_eol (FILE *infile)
1085 char c = 0, c1 = 0, c2 = 0;
1087 /* Skip until the end of line; remember two previous chars. */
1088 while (c != '\n' && c != '\r' && c != EOF)
1090 c2 = c1;
1091 c1 = c;
1092 c = getc (infile);
1095 /* If two previous characters were " and \,
1096 this is a doc string. Otherwise, there is none. */
1097 if (c2 != '"' || c1 != '\\')
1099 #ifdef DEBUG
1100 fprintf (stderr, "## non-docstring in %s (%s)\n",
1101 buffer, filename);
1102 #endif
1103 if (c != EOF)
1104 ungetc (c, infile);
1105 return 0;
1107 return 1;
1110 static int
1111 scan_lisp_file (const char *filename, const char *mode)
1113 FILE *infile;
1114 register int c;
1115 char *saved_string = 0;
1117 if (generate_globals)
1118 fatal ("scanning lisp file when -g specified", 0);
1120 infile = fopen (filename, mode);
1121 if (infile == NULL)
1123 perror (filename);
1124 return 0; /* No error. */
1127 c = '\n';
1128 while (!feof (infile))
1130 char buffer[BUFSIZ];
1131 char type;
1133 /* If not at end of line, skip till we get to one. */
1134 if (c != '\n' && c != '\r')
1136 c = getc (infile);
1137 continue;
1139 /* Skip the line break. */
1140 while (c == '\n' || c == '\r')
1141 c = getc (infile);
1142 /* Detect a dynamic doc string and save it for the next expression. */
1143 if (c == '#')
1145 c = getc (infile);
1146 if (c == '@')
1148 size_t length = 0;
1149 size_t i;
1151 /* Read the length. */
1152 while ((c = getc (infile),
1153 c >= '0' && c <= '9'))
1155 length *= 10;
1156 length += c - '0';
1159 if (length <= 1)
1160 fatal ("invalid dynamic doc string length", "");
1162 if (c != ' ')
1163 fatal ("space not found after dynamic doc string length", "");
1165 /* The next character is a space that is counted in the length
1166 but not part of the doc string.
1167 We already read it, so just ignore it. */
1168 length--;
1170 /* Read in the contents. */
1171 free (saved_string);
1172 saved_string = (char *) xmalloc (length);
1173 for (i = 0; i < length; i++)
1174 saved_string[i] = getc (infile);
1175 /* The last character is a ^_.
1176 That is needed in the .elc file
1177 but it is redundant in DOC. So get rid of it here. */
1178 saved_string[length - 1] = 0;
1179 /* Skip the line break. */
1180 while (c == '\n' || c == '\r')
1181 c = getc (infile);
1182 /* Skip the following line. */
1183 while (c != '\n' && c != '\r')
1184 c = getc (infile);
1186 continue;
1189 if (c != '(')
1190 continue;
1192 read_lisp_symbol (infile, buffer);
1194 if (! strcmp (buffer, "defun")
1195 || ! strcmp (buffer, "defmacro")
1196 || ! strcmp (buffer, "defsubst"))
1198 type = 'F';
1199 read_lisp_symbol (infile, buffer);
1201 /* Skip the arguments: either "nil" or a list in parens. */
1203 c = getc (infile);
1204 if (c == 'n') /* nil */
1206 if ((c = getc (infile)) != 'i'
1207 || (c = getc (infile)) != 'l')
1209 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
1210 buffer, filename);
1211 continue;
1214 else if (c != '(')
1216 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
1217 buffer, filename);
1218 continue;
1220 else
1221 while (c != ')')
1222 c = getc (infile);
1223 skip_white (infile);
1225 /* If the next three characters aren't `dquote bslash newline'
1226 then we're not reading a docstring.
1228 if ((c = getc (infile)) != '"'
1229 || (c = getc (infile)) != '\\'
1230 || ((c = getc (infile)) != '\n' && c != '\r'))
1232 #ifdef DEBUG
1233 fprintf (stderr, "## non-docstring in %s (%s)\n",
1234 buffer, filename);
1235 #endif
1236 continue;
1240 /* defcustom can only occur in uncompiled Lisp files. */
1241 else if (! strcmp (buffer, "defvar")
1242 || ! strcmp (buffer, "defconst")
1243 || ! strcmp (buffer, "defcustom"))
1245 type = 'V';
1246 read_lisp_symbol (infile, buffer);
1248 if (saved_string == 0)
1249 if (!search_lisp_doc_at_eol (infile))
1250 continue;
1253 else if (! strcmp (buffer, "custom-declare-variable")
1254 || ! strcmp (buffer, "defvaralias")
1257 type = 'V';
1259 c = getc (infile);
1260 if (c == '\'')
1261 read_lisp_symbol (infile, buffer);
1262 else
1264 if (c != '(')
1266 fprintf (stderr,
1267 "## unparsable name in custom-declare-variable in %s\n",
1268 filename);
1269 continue;
1271 read_lisp_symbol (infile, buffer);
1272 if (strcmp (buffer, "quote"))
1274 fprintf (stderr,
1275 "## unparsable name in custom-declare-variable in %s\n",
1276 filename);
1277 continue;
1279 read_lisp_symbol (infile, buffer);
1280 c = getc (infile);
1281 if (c != ')')
1283 fprintf (stderr,
1284 "## unparsable quoted name in custom-declare-variable in %s\n",
1285 filename);
1286 continue;
1290 if (saved_string == 0)
1291 if (!search_lisp_doc_at_eol (infile))
1292 continue;
1295 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
1297 type = 'F';
1299 c = getc (infile);
1300 if (c == '\'')
1301 read_lisp_symbol (infile, buffer);
1302 else
1304 if (c != '(')
1306 fprintf (stderr, "## unparsable name in fset in %s\n",
1307 filename);
1308 continue;
1310 read_lisp_symbol (infile, buffer);
1311 if (strcmp (buffer, "quote"))
1313 fprintf (stderr, "## unparsable name in fset in %s\n",
1314 filename);
1315 continue;
1317 read_lisp_symbol (infile, buffer);
1318 c = getc (infile);
1319 if (c != ')')
1321 fprintf (stderr,
1322 "## unparsable quoted name in fset in %s\n",
1323 filename);
1324 continue;
1328 if (saved_string == 0)
1329 if (!search_lisp_doc_at_eol (infile))
1330 continue;
1333 else if (! strcmp (buffer, "autoload"))
1335 type = 'F';
1336 c = getc (infile);
1337 if (c == '\'')
1338 read_lisp_symbol (infile, buffer);
1339 else
1341 if (c != '(')
1343 fprintf (stderr, "## unparsable name in autoload in %s\n",
1344 filename);
1345 continue;
1347 read_lisp_symbol (infile, buffer);
1348 if (strcmp (buffer, "quote"))
1350 fprintf (stderr, "## unparsable name in autoload in %s\n",
1351 filename);
1352 continue;
1354 read_lisp_symbol (infile, buffer);
1355 c = getc (infile);
1356 if (c != ')')
1358 fprintf (stderr,
1359 "## unparsable quoted name in autoload in %s\n",
1360 filename);
1361 continue;
1364 skip_white (infile);
1365 if ((c = getc (infile)) != '\"')
1367 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
1368 buffer, filename);
1369 continue;
1371 read_c_string_or_comment (infile, 0, 0, 0);
1373 if (saved_string == 0)
1374 if (!search_lisp_doc_at_eol (infile))
1375 continue;
1378 #ifdef DEBUG
1379 else if (! strcmp (buffer, "if")
1380 || ! strcmp (buffer, "byte-code"))
1381 continue;
1382 #endif
1384 else
1386 #ifdef DEBUG
1387 fprintf (stderr, "## unrecognized top-level form, %s (%s)\n",
1388 buffer, filename);
1389 #endif
1390 continue;
1393 /* At this point, we should either use the previous dynamic doc string in
1394 saved_string or gobble a doc string from the input file.
1395 In the latter case, the opening quote (and leading backslash-newline)
1396 have already been read. */
1398 putc (037, outfile);
1399 putc (type, outfile);
1400 fprintf (outfile, "%s\n", buffer);
1401 if (saved_string)
1403 fputs (saved_string, outfile);
1404 /* Don't use one dynamic doc string twice. */
1405 free (saved_string);
1406 saved_string = 0;
1408 else
1409 read_c_string_or_comment (infile, 1, 0, 0);
1411 fclose (infile);
1412 return 0;
1416 /* make-docfile.c ends here */