* admin/notes/versioning: Relocate and rewrite.
[emacs/old-mirror.git] / lib-src / make-docfile.c
blob884b6c1001e42a0e2cdd7d2d97291d5521a54595
1 /* Generate doc-string file for GNU Emacs from source files.
3 Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2014 Free Software
4 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 */
42 #ifdef WINDOWSNT
43 /* Defined to be sys_fopen in ms-w32.h, but only #ifdef emacs, so this
44 is really just insurance. */
45 #undef fopen
46 #include <direct.h>
47 #endif /* WINDOWSNT */
49 #include <binary-io.h>
51 #ifdef DOS_NT
52 /* Defined to be sys_chdir in ms-w32.h, but only #ifdef emacs, so this
53 is really just insurance.
55 Similarly, msdos defines this as sys_chdir, but we're not linking with the
56 file where that function is defined. */
57 #undef chdir
58 #define IS_SLASH(c) ((c) == '/' || (c) == '\\' || (c) == ':')
59 #else /* not DOS_NT */
60 #define IS_SLASH(c) ((c) == '/')
61 #endif /* not DOS_NT */
63 static int scan_file (char *filename);
64 static int scan_lisp_file (const char *filename, const char *mode);
65 static int scan_c_file (char *filename, const char *mode);
66 static void start_globals (void);
67 static void write_globals (void);
69 #include <unistd.h>
71 /* Name this program was invoked with. */
72 char *progname;
74 /* Nonzero if this invocation is generating globals.h. */
75 int generate_globals;
77 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
79 /* VARARGS1 */
80 static void
81 error (const char *s1, const char *s2)
83 fprintf (stderr, "%s: ", progname);
84 fprintf (stderr, s1, s2);
85 fprintf (stderr, "\n");
88 /* Print error message and exit. */
90 /* VARARGS1 */
91 static _Noreturn void
92 fatal (const char *s1, const char *s2)
94 error (s1, s2);
95 exit (EXIT_FAILURE);
98 /* Like malloc but get fatal error if memory is exhausted. */
100 static void *
101 xmalloc (unsigned int size)
103 void *result = (void *) malloc (size);
104 if (result == NULL)
105 fatal ("virtual memory exhausted", 0);
106 return result;
109 /* Like realloc but get fatal error if memory is exhausted. */
111 static void *
112 xrealloc (void *arg, unsigned int size)
114 void *result = (void *) realloc (arg, size);
115 if (result == NULL)
116 fatal ("virtual memory exhausted", 0);
117 return result;
122 main (int argc, char **argv)
124 int i;
125 int err_count = 0;
126 int first_infile;
128 progname = argv[0];
130 /* If first two args are -o FILE, output to FILE. */
131 i = 1;
132 if (argc > i + 1 && !strcmp (argv[i], "-o"))
134 if (! freopen (argv[i + 1], "w", stdout))
136 perror (argv[i + 1]);
137 return EXIT_FAILURE;
139 i += 2;
141 if (argc > i + 1 && !strcmp (argv[i], "-a"))
143 if (! freopen (argv[i + 1], "a", stdout))
145 perror (argv[i + 1]);
146 return EXIT_FAILURE;
148 i += 2;
150 if (argc > i + 1 && !strcmp (argv[i], "-d"))
152 if (chdir (argv[i + 1]) != 0)
154 perror (argv[i + 1]);
155 return EXIT_FAILURE;
157 i += 2;
159 if (argc > i && !strcmp (argv[i], "-g"))
161 generate_globals = 1;
162 ++i;
165 set_binary_mode (fileno (stdout), O_BINARY);
167 if (generate_globals)
168 start_globals ();
170 first_infile = i;
171 for (; i < argc; i++)
173 int j;
174 /* Don't process one file twice. */
175 for (j = first_infile; j < i; j++)
176 if (! strcmp (argv[i], argv[j]))
177 break;
178 if (j == i)
179 err_count += scan_file (argv[i]);
182 if (err_count == 0 && generate_globals)
183 write_globals ();
185 return (err_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
188 /* Add a source file name boundary marker in the output file. */
189 static void
190 put_filename (char *filename)
192 char *tmp;
194 for (tmp = filename; *tmp; tmp++)
196 if (IS_DIRECTORY_SEP (*tmp))
197 filename = tmp + 1;
200 printf ("\037S%s\n", filename);
203 /* Read file FILENAME and output its doc strings to stdout.
204 Return 1 if file is not found, 0 if it is found. */
206 static int
207 scan_file (char *filename)
210 size_t len = strlen (filename);
212 if (!generate_globals)
213 put_filename (filename);
214 if (len > 4 && !strcmp (filename + len - 4, ".elc"))
215 return scan_lisp_file (filename, "rb");
216 else if (len > 3 && !strcmp (filename + len - 3, ".el"))
217 return scan_lisp_file (filename, "r");
218 else
219 return scan_c_file (filename, "r");
222 static void
223 start_globals (void)
225 puts ("/* This file was auto-generated by make-docfile. */");
226 puts ("/* DO NOT EDIT. */");
227 puts ("struct emacs_globals {");
230 static char input_buffer[128];
232 /* Some state during the execution of `read_c_string_or_comment'. */
233 struct rcsoc_state
235 /* A count of spaces and newlines that have been read, but not output. */
236 unsigned pending_spaces, pending_newlines;
238 /* Where we're reading from. */
239 FILE *in_file;
241 /* If non-zero, a buffer into which to copy characters. */
242 char *buf_ptr;
243 /* If non-zero, a file into which to copy characters. */
244 FILE *out_file;
246 /* A keyword we look for at the beginning of lines. If found, it is
247 not copied, and SAW_KEYWORD is set to true. */
248 const char *keyword;
249 /* The current point we've reached in an occurrence of KEYWORD in
250 the input stream. */
251 const char *cur_keyword_ptr;
252 /* Set to true if we saw an occurrence of KEYWORD. */
253 int saw_keyword;
256 /* Output CH to the file or buffer in STATE. Any pending newlines or
257 spaces are output first. */
259 static void
260 put_char (int ch, struct rcsoc_state *state)
262 int out_ch;
265 if (state->pending_newlines > 0)
267 state->pending_newlines--;
268 out_ch = '\n';
270 else if (state->pending_spaces > 0)
272 state->pending_spaces--;
273 out_ch = ' ';
275 else
276 out_ch = ch;
278 if (state->out_file)
279 putc (out_ch, state->out_file);
280 if (state->buf_ptr)
281 *state->buf_ptr++ = out_ch;
283 while (out_ch != ch);
286 /* If in the middle of scanning a keyword, continue scanning with
287 character CH, otherwise output CH to the file or buffer in STATE.
288 Any pending newlines or spaces are output first, as well as any
289 previously scanned characters that were thought to be part of a
290 keyword, but were in fact not. */
292 static void
293 scan_keyword_or_put_char (int ch, struct rcsoc_state *state)
295 if (state->keyword
296 && *state->cur_keyword_ptr == ch
297 && (state->cur_keyword_ptr > state->keyword
298 || state->pending_newlines > 0))
299 /* We might be looking at STATE->keyword at some point.
300 Keep looking until we know for sure. */
302 if (*++state->cur_keyword_ptr == '\0')
303 /* Saw the whole keyword. Set SAW_KEYWORD flag to true. */
305 state->saw_keyword = 1;
307 /* Reset the scanning pointer. */
308 state->cur_keyword_ptr = state->keyword;
310 /* Canonicalize whitespace preceding a usage string. */
311 state->pending_newlines = 2;
312 state->pending_spaces = 0;
314 /* Skip any whitespace between the keyword and the
315 usage string. */
317 ch = getc (state->in_file);
318 while (ch == ' ' || ch == '\n');
320 /* Output the open-paren we just read. */
321 put_char (ch, state);
323 /* Skip the function name and replace it with `fn'. */
325 ch = getc (state->in_file);
326 while (ch != ' ' && ch != ')');
327 put_char ('f', state);
328 put_char ('n', state);
330 /* Put back the last character. */
331 ungetc (ch, state->in_file);
334 else
336 if (state->keyword && state->cur_keyword_ptr > state->keyword)
337 /* We scanned the beginning of a potential usage
338 keyword, but it was a false alarm. Output the
339 part we scanned. */
341 const char *p;
343 for (p = state->keyword; p < state->cur_keyword_ptr; p++)
344 put_char (*p, state);
346 state->cur_keyword_ptr = state->keyword;
349 put_char (ch, state);
354 /* Skip a C string or C-style comment from INFILE, and return the
355 character that follows. COMMENT non-zero means skip a comment. If
356 PRINTFLAG is positive, output string contents to stdout. If it is
357 negative, store contents in buf. Convert escape sequences \n and
358 \t to newline and tab; discard \ followed by newline.
359 If SAW_USAGE is non-zero, then any occurrences of the string `usage:'
360 at the beginning of a line will be removed, and *SAW_USAGE set to
361 true if any were encountered. */
363 static int
364 read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usage)
366 register int c;
367 struct rcsoc_state state;
369 state.in_file = infile;
370 state.buf_ptr = (printflag < 0 ? input_buffer : 0);
371 state.out_file = (printflag > 0 ? stdout : 0);
372 state.pending_spaces = 0;
373 state.pending_newlines = 0;
374 state.keyword = (saw_usage ? "usage:" : 0);
375 state.cur_keyword_ptr = state.keyword;
376 state.saw_keyword = 0;
378 c = getc (infile);
379 if (comment)
380 while (c == '\n' || c == '\r' || c == '\t' || c == ' ')
381 c = getc (infile);
383 while (c != EOF)
385 while (c != EOF && (comment ? c != '*' : c != '"'))
387 if (c == '\\')
389 c = getc (infile);
390 if (c == '\n' || c == '\r')
392 c = getc (infile);
393 continue;
395 if (c == 'n')
396 c = '\n';
397 if (c == 't')
398 c = '\t';
401 if (c == ' ')
402 state.pending_spaces++;
403 else if (c == '\n')
405 state.pending_newlines++;
406 state.pending_spaces = 0;
408 else
409 scan_keyword_or_put_char (c, &state);
411 c = getc (infile);
414 if (c != EOF)
415 c = getc (infile);
417 if (comment)
419 if (c == '/')
421 c = getc (infile);
422 break;
425 scan_keyword_or_put_char ('*', &state);
427 else
429 if (c != '"')
430 break;
432 /* If we had a "", concatenate the two strings. */
433 c = getc (infile);
437 if (printflag < 0)
438 *state.buf_ptr = 0;
440 if (saw_usage)
441 *saw_usage = state.saw_keyword;
443 return c;
448 /* Write to stdout the argument names of function FUNC, whose text is in BUF.
449 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
451 static void
452 write_c_args (char *func, char *buf, int minargs, int maxargs)
454 register char *p;
455 int in_ident = 0;
456 char *ident_start IF_LINT (= NULL);
457 size_t ident_length = 0;
459 fputs ("(fn", stdout);
461 if (*buf == '(')
462 ++buf;
464 for (p = buf; *p; p++)
466 char c = *p;
468 /* Notice when a new identifier starts. */
469 if ((('A' <= c && c <= 'Z')
470 || ('a' <= c && c <= 'z')
471 || ('0' <= c && c <= '9')
472 || c == '_')
473 != in_ident)
475 if (!in_ident)
477 in_ident = 1;
478 ident_start = p;
480 else
482 in_ident = 0;
483 ident_length = p - ident_start;
487 /* Found the end of an argument, write out the last seen
488 identifier. */
489 if (c == ',' || c == ')')
491 if (ident_length == 0)
493 error ("empty arg list for `%s' should be (void), not ()", func);
494 continue;
497 if (strncmp (ident_start, "void", ident_length) == 0)
498 continue;
500 putchar (' ');
502 if (minargs == 0 && maxargs > 0)
503 fputs ("&optional ", stdout);
505 minargs--;
506 maxargs--;
508 /* In C code, `default' is a reserved word, so we spell it
509 `defalt'; demangle that here. */
510 if (ident_length == 6 && memcmp (ident_start, "defalt", 6) == 0)
511 fputs ("DEFAULT", stdout);
512 else
513 while (ident_length-- > 0)
515 c = *ident_start++;
516 if (c >= 'a' && c <= 'z')
517 /* Upcase the letter. */
518 c += 'A' - 'a';
519 else if (c == '_')
520 /* Print underscore as hyphen. */
521 c = '-';
522 putchar (c);
527 putchar (')');
530 /* The types of globals. These are sorted roughly in decreasing alignment
531 order to avoid allocation gaps, except that functions are last. */
532 enum global_type
534 INVALID,
535 LISP_OBJECT,
536 EMACS_INTEGER,
537 BOOLEAN,
538 FUNCTION
541 /* A single global. */
542 struct global
544 enum global_type type;
545 char *name;
546 int value;
549 /* All the variable names we saw while scanning C sources in `-g'
550 mode. */
551 int num_globals;
552 int num_globals_allocated;
553 struct global *globals;
555 static void
556 add_global (enum global_type type, char *name, int value)
558 /* Ignore the one non-symbol that can occur. */
559 if (strcmp (name, "..."))
561 ++num_globals;
563 if (num_globals_allocated == 0)
565 num_globals_allocated = 100;
566 globals = xmalloc (num_globals_allocated * sizeof (struct global));
568 else if (num_globals == num_globals_allocated)
570 num_globals_allocated *= 2;
571 globals = xrealloc (globals,
572 num_globals_allocated * sizeof (struct global));
575 globals[num_globals - 1].type = type;
576 globals[num_globals - 1].name = name;
577 globals[num_globals - 1].value = value;
581 static int
582 compare_globals (const void *a, const void *b)
584 const struct global *ga = a;
585 const struct global *gb = b;
587 if (ga->type != gb->type)
588 return ga->type - gb->type;
590 return strcmp (ga->name, gb->name);
593 static void
594 close_emacs_globals (void)
596 puts ("};");
597 puts ("extern struct emacs_globals globals;");
600 static void
601 write_globals (void)
603 int i, seen_defun = 0;
604 qsort (globals, num_globals, sizeof (struct global), compare_globals);
605 for (i = 0; i < num_globals; ++i)
607 char const *type = 0;
609 switch (globals[i].type)
611 case EMACS_INTEGER:
612 type = "EMACS_INT";
613 break;
614 case BOOLEAN:
615 type = "bool";
616 break;
617 case LISP_OBJECT:
618 type = "Lisp_Object";
619 break;
620 case FUNCTION:
621 if (!seen_defun)
623 close_emacs_globals ();
624 putchar ('\n');
625 seen_defun = 1;
627 break;
628 default:
629 fatal ("not a recognized DEFVAR_", 0);
632 if (type)
634 printf (" %s f_%s;\n", type, globals[i].name);
635 printf ("#define %s globals.f_%s\n",
636 globals[i].name, globals[i].name);
638 else
640 /* It would be nice to have a cleaner way to deal with these
641 special hacks. */
642 if (strcmp (globals[i].name, "Fthrow") == 0
643 || strcmp (globals[i].name, "Ftop_level") == 0
644 || strcmp (globals[i].name, "Fkill_emacs") == 0
645 || strcmp (globals[i].name, "Fexit_recursive_edit") == 0
646 || strcmp (globals[i].name, "Fabort_recursive_edit") == 0)
647 fputs ("_Noreturn ", stdout);
649 printf ("EXFUN (%s, ", globals[i].name);
650 if (globals[i].value == -1)
651 fputs ("MANY", stdout);
652 else if (globals[i].value == -2)
653 fputs ("UNEVALLED", stdout);
654 else
655 printf ("%d", globals[i].value);
656 putchar (')');
658 /* It would be nice to have a cleaner way to deal with these
659 special hacks, too. */
660 if (strcmp (globals[i].name, "Fbyteorder") == 0
661 || strcmp (globals[i].name, "Ftool_bar_height") == 0
662 || strcmp (globals[i].name, "Fmax_char") == 0
663 || strcmp (globals[i].name, "Fidentity") == 0)
664 fputs (" ATTRIBUTE_CONST", stdout);
666 puts (";");
669 while (i + 1 < num_globals
670 && !strcmp (globals[i].name, globals[i + 1].name))
672 if (globals[i].type == FUNCTION
673 && globals[i].value != globals[i + 1].value)
674 error ("function '%s' defined twice with differing signatures",
675 globals[i].name);
676 ++i;
680 if (!seen_defun)
681 close_emacs_globals ();
685 /* Read through a c file. If a .o file is named,
686 the corresponding .c or .m file is read instead.
687 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
688 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
690 static int
691 scan_c_file (char *filename, const char *mode)
693 FILE *infile;
694 register int c;
695 register int commas;
696 int minargs, maxargs;
697 int extension = filename[strlen (filename) - 1];
699 if (extension == 'o')
700 filename[strlen (filename) - 1] = 'c';
702 infile = fopen (filename, mode);
704 if (infile == NULL && extension == 'o')
706 /* Try .m. */
707 filename[strlen (filename) - 1] = 'm';
708 infile = fopen (filename, mode);
709 if (infile == NULL)
710 filename[strlen (filename) - 1] = 'c'; /* Don't confuse people. */
713 /* No error if non-ex input file. */
714 if (infile == NULL)
716 perror (filename);
717 return 0;
720 /* Reset extension to be able to detect duplicate files. */
721 filename[strlen (filename) - 1] = extension;
723 c = '\n';
724 while (!feof (infile))
726 int doc_keyword = 0;
727 int defunflag = 0;
728 int defvarperbufferflag = 0;
729 int defvarflag = 0;
730 enum global_type type = INVALID;
731 char *name IF_LINT (= 0);
733 if (c != '\n' && c != '\r')
735 c = getc (infile);
736 continue;
738 c = getc (infile);
739 if (c == ' ')
741 while (c == ' ')
742 c = getc (infile);
743 if (c != 'D')
744 continue;
745 c = getc (infile);
746 if (c != 'E')
747 continue;
748 c = getc (infile);
749 if (c != 'F')
750 continue;
751 c = getc (infile);
752 if (c != 'V')
753 continue;
754 c = getc (infile);
755 if (c != 'A')
756 continue;
757 c = getc (infile);
758 if (c != 'R')
759 continue;
760 c = getc (infile);
761 if (c != '_')
762 continue;
764 defvarflag = 1;
766 c = getc (infile);
767 defvarperbufferflag = (c == 'P');
768 if (generate_globals)
770 if (c == 'I')
771 type = EMACS_INTEGER;
772 else if (c == 'L')
773 type = LISP_OBJECT;
774 else if (c == 'B')
775 type = BOOLEAN;
778 c = getc (infile);
779 /* We need to distinguish between DEFVAR_BOOL and
780 DEFVAR_BUFFER_DEFAULTS. */
781 if (generate_globals && type == BOOLEAN && c != 'O')
782 type = INVALID;
784 else if (c == 'D')
786 c = getc (infile);
787 if (c != 'E')
788 continue;
789 c = getc (infile);
790 if (c != 'F')
791 continue;
792 c = getc (infile);
793 defunflag = c == 'U';
795 else continue;
797 if (generate_globals
798 && (!defvarflag || defvarperbufferflag || type == INVALID)
799 && !defunflag)
800 continue;
802 while (c != '(')
804 if (c < 0)
805 goto eof;
806 c = getc (infile);
809 /* Lisp variable or function name. */
810 c = getc (infile);
811 if (c != '"')
812 continue;
813 c = read_c_string_or_comment (infile, -1, 0, 0);
815 if (generate_globals)
817 int i = 0;
819 /* Skip "," and whitespace. */
822 c = getc (infile);
824 while (c == ',' || c == ' ' || c == '\t' || c == '\n' || c == '\r');
826 /* Read in the identifier. */
829 input_buffer[i++] = c;
830 c = getc (infile);
832 while (! (c == ',' || c == ' ' || c == '\t'
833 || c == '\n' || c == '\r'));
834 input_buffer[i] = '\0';
836 name = xmalloc (i + 1);
837 memcpy (name, input_buffer, i + 1);
839 if (!defunflag)
841 add_global (type, name, 0);
842 continue;
846 /* DEFVAR_LISP ("name", addr, "doc")
847 DEFVAR_LISP ("name", addr /\* doc *\/)
848 DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */
850 if (defunflag)
851 commas = generate_globals ? 4 : 5;
852 else if (defvarperbufferflag)
853 commas = 3;
854 else if (defvarflag)
855 commas = 1;
856 else /* For DEFSIMPLE and DEFPRED. */
857 commas = 2;
859 while (commas)
861 if (c == ',')
863 commas--;
865 if (defunflag && (commas == 1 || commas == 2))
867 int scanned = 0;
869 c = getc (infile);
870 while (c == ' ' || c == '\n' || c == '\r' || c == '\t');
871 if (c < 0)
872 goto eof;
873 ungetc (c, infile);
874 if (commas == 2) /* Pick up minargs. */
875 scanned = fscanf (infile, "%d", &minargs);
876 else /* Pick up maxargs. */
877 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
879 if (generate_globals)
880 maxargs = (c == 'M') ? -1 : -2;
881 else
882 maxargs = -1;
884 else
885 scanned = fscanf (infile, "%d", &maxargs);
886 if (scanned < 0)
887 goto eof;
891 if (c == EOF)
892 goto eof;
893 c = getc (infile);
896 if (generate_globals)
898 add_global (FUNCTION, name, maxargs);
899 continue;
902 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
903 c = getc (infile);
905 if (c == '"')
906 c = read_c_string_or_comment (infile, 0, 0, 0);
908 while (c != EOF && c != ',' && c != '/')
909 c = getc (infile);
910 if (c == ',')
912 c = getc (infile);
913 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
914 c = getc (infile);
915 while ((c >= 'a' && c <= 'z') || (c >= 'Z' && c <= 'Z'))
916 c = getc (infile);
917 if (c == ':')
919 doc_keyword = 1;
920 c = getc (infile);
921 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
922 c = getc (infile);
926 if (c == '"'
927 || (c == '/'
928 && (c = getc (infile),
929 ungetc (c, infile),
930 c == '*')))
932 int comment = c != '"';
933 int saw_usage;
935 printf ("\037%c%s\n", defvarflag ? 'V' : 'F', input_buffer);
937 if (comment)
938 getc (infile); /* Skip past `*'. */
939 c = read_c_string_or_comment (infile, 1, comment, &saw_usage);
941 /* If this is a defun, find the arguments and print them. If
942 this function takes MANY or UNEVALLED args, then the C source
943 won't give the names of the arguments, so we shouldn't bother
944 trying to find them.
946 Various doc-string styles:
947 0: DEFUN (..., "DOC") (args) [!comment]
948 1: DEFUN (..., /\* DOC *\/ (args)) [comment && !doc_keyword]
949 2: DEFUN (..., doc: /\* DOC *\/) (args) [comment && doc_keyword]
951 if (defunflag && maxargs != -1 && !saw_usage)
953 char argbuf[1024], *p = argbuf;
955 if (!comment || doc_keyword)
956 while (c != ')')
958 if (c < 0)
959 goto eof;
960 c = getc (infile);
963 /* Skip into arguments. */
964 while (c != '(')
966 if (c < 0)
967 goto eof;
968 c = getc (infile);
970 /* Copy arguments into ARGBUF. */
971 *p++ = c;
973 *p++ = c = getc (infile);
974 while (c != ')');
975 *p = '\0';
976 /* Output them. */
977 fputs ("\n\n", stdout);
978 write_c_args (input_buffer, argbuf, minargs, maxargs);
980 else if (defunflag && maxargs == -1 && !saw_usage)
981 /* The DOC should provide the usage form. */
982 fprintf (stderr, "Missing `usage' for function `%s'.\n",
983 input_buffer);
986 eof:
987 fclose (infile);
988 return 0;
991 /* Read a file of Lisp code, compiled or interpreted.
992 Looks for
993 (defun NAME ARGS DOCSTRING ...)
994 (defmacro NAME ARGS DOCSTRING ...)
995 (defsubst NAME ARGS DOCSTRING ...)
996 (autoload (quote NAME) FILE DOCSTRING ...)
997 (defvar NAME VALUE DOCSTRING)
998 (defconst NAME VALUE DOCSTRING)
999 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
1000 (fset (quote NAME) #[... DOCSTRING ...])
1001 (defalias (quote NAME) #[... DOCSTRING ...])
1002 (custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
1003 starting in column zero.
1004 (quote NAME) may appear as 'NAME as well.
1006 We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
1007 When we find that, we save it for the following defining-form,
1008 and we use that instead of reading a doc string within that defining-form.
1010 For defvar, defconst, and fset we skip to the docstring with a kludgy
1011 formatting convention: all docstrings must appear on the same line as the
1012 initial open-paren (the one in column zero) and must contain a backslash
1013 and a newline immediately after the initial double-quote. No newlines
1014 must appear between the beginning of the form and the first double-quote.
1015 For defun, defmacro, and autoload, we know how to skip over the
1016 arglist, but the doc string must still have a backslash and newline
1017 immediately after the double quote.
1018 The only source files that must follow this convention are preloaded
1019 uncompiled ones like loaddefs.el; aside from that, it is always the .elc
1020 file that we should look at, and they are no problem because byte-compiler
1021 output follows this convention.
1022 The NAME and DOCSTRING are output.
1023 NAME is preceded by `F' for a function or `V' for a variable.
1024 An entry is output only if DOCSTRING has \ newline just after the opening ".
1027 static void
1028 skip_white (FILE *infile)
1030 char c = ' ';
1031 while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
1032 c = getc (infile);
1033 ungetc (c, infile);
1036 static void
1037 read_lisp_symbol (FILE *infile, char *buffer)
1039 char c;
1040 char *fillp = buffer;
1042 skip_white (infile);
1043 while (1)
1045 c = getc (infile);
1046 if (c == '\\')
1047 *(++fillp) = getc (infile);
1048 else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '(' || c == ')')
1050 ungetc (c, infile);
1051 *fillp = 0;
1052 break;
1054 else
1055 *fillp++ = c;
1058 if (! buffer[0])
1059 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
1061 skip_white (infile);
1064 static int
1065 search_lisp_doc_at_eol (FILE *infile)
1067 int c = 0, c1 = 0, c2 = 0;
1069 /* Skip until the end of line; remember two previous chars. */
1070 while (c != '\n' && c != '\r' && c != EOF)
1072 c2 = c1;
1073 c1 = c;
1074 c = getc (infile);
1077 /* If two previous characters were " and \,
1078 this is a doc string. Otherwise, there is none. */
1079 if (c2 != '"' || c1 != '\\')
1081 #ifdef DEBUG
1082 fprintf (stderr, "## non-docstring found\n");
1083 #endif
1084 if (c != EOF)
1085 ungetc (c, infile);
1086 return 0;
1088 return 1;
1091 #define DEF_ELISP_FILE(fn) { #fn, sizeof(#fn) - 1 }
1093 static int
1094 scan_lisp_file (const char *filename, const char *mode)
1096 FILE *infile;
1097 register int c;
1098 char *saved_string = 0;
1099 /* These are the only files that are loaded uncompiled, and must
1100 follow the conventions of the doc strings expected by this
1101 function. These conventions are automatically followed by the
1102 byte compiler when it produces the .elc files. */
1103 static struct {
1104 const char *fn;
1105 size_t fl;
1106 } const uncompiled[] = {
1107 DEF_ELISP_FILE (loaddefs.el),
1108 DEF_ELISP_FILE (loadup.el),
1109 DEF_ELISP_FILE (charprop.el),
1110 DEF_ELISP_FILE (cp51932.el),
1111 DEF_ELISP_FILE (eucjp-ms.el)
1113 int i, match;
1114 size_t flen = strlen (filename);
1116 if (generate_globals)
1117 fatal ("scanning lisp file when -g specified", 0);
1118 if (flen > 3 && !strcmp (filename + flen - 3, ".el"))
1120 for (i = 0, match = 0; i < sizeof (uncompiled) / sizeof (uncompiled[0]);
1121 i++)
1123 if (uncompiled[i].fl <= flen
1124 && !strcmp (filename + flen - uncompiled[i].fl, uncompiled[i].fn)
1125 && (flen == uncompiled[i].fl
1126 || IS_SLASH (filename[flen - uncompiled[i].fl - 1])))
1128 match = 1;
1129 break;
1132 if (!match)
1133 fatal ("uncompiled lisp file %s is not supported", filename);
1136 infile = fopen (filename, mode);
1137 if (infile == NULL)
1139 perror (filename);
1140 return 0; /* No error. */
1143 c = '\n';
1144 while (!feof (infile))
1146 char buffer[BUFSIZ];
1147 char type;
1149 /* If not at end of line, skip till we get to one. */
1150 if (c != '\n' && c != '\r')
1152 c = getc (infile);
1153 continue;
1155 /* Skip the line break. */
1156 while (c == '\n' || c == '\r')
1157 c = getc (infile);
1158 /* Detect a dynamic doc string and save it for the next expression. */
1159 if (c == '#')
1161 c = getc (infile);
1162 if (c == '@')
1164 size_t length = 0;
1165 size_t i;
1167 /* Read the length. */
1168 while ((c = getc (infile),
1169 c >= '0' && c <= '9'))
1171 length *= 10;
1172 length += c - '0';
1175 if (length <= 1)
1176 fatal ("invalid dynamic doc string length", "");
1178 if (c != ' ')
1179 fatal ("space not found after dynamic doc string length", "");
1181 /* The next character is a space that is counted in the length
1182 but not part of the doc string.
1183 We already read it, so just ignore it. */
1184 length--;
1186 /* Read in the contents. */
1187 free (saved_string);
1188 saved_string = (char *) xmalloc (length);
1189 for (i = 0; i < length; i++)
1190 saved_string[i] = getc (infile);
1191 /* The last character is a ^_.
1192 That is needed in the .elc file
1193 but it is redundant in DOC. So get rid of it here. */
1194 saved_string[length - 1] = 0;
1195 /* Skip the line break. */
1196 while (c == '\n' || c == '\r')
1197 c = getc (infile);
1198 /* Skip the following line. */
1199 while (c != '\n' && c != '\r')
1200 c = getc (infile);
1202 continue;
1205 if (c != '(')
1206 continue;
1208 read_lisp_symbol (infile, buffer);
1210 if (! strcmp (buffer, "defun")
1211 || ! strcmp (buffer, "defmacro")
1212 || ! strcmp (buffer, "defsubst"))
1214 type = 'F';
1215 read_lisp_symbol (infile, buffer);
1217 /* Skip the arguments: either "nil" or a list in parens. */
1219 c = getc (infile);
1220 if (c == 'n') /* nil */
1222 if ((c = getc (infile)) != 'i'
1223 || (c = getc (infile)) != 'l')
1225 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
1226 buffer, filename);
1227 continue;
1230 else if (c != '(')
1232 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
1233 buffer, filename);
1234 continue;
1236 else
1237 while (c != ')')
1238 c = getc (infile);
1239 skip_white (infile);
1241 /* If the next three characters aren't `dquote bslash newline'
1242 then we're not reading a docstring.
1244 if ((c = getc (infile)) != '"'
1245 || (c = getc (infile)) != '\\'
1246 || ((c = getc (infile)) != '\n' && c != '\r'))
1248 #ifdef DEBUG
1249 fprintf (stderr, "## non-docstring in %s (%s)\n",
1250 buffer, filename);
1251 #endif
1252 continue;
1256 /* defcustom can only occur in uncompiled Lisp files. */
1257 else if (! strcmp (buffer, "defvar")
1258 || ! strcmp (buffer, "defconst")
1259 || ! strcmp (buffer, "defcustom"))
1261 type = 'V';
1262 read_lisp_symbol (infile, buffer);
1264 if (saved_string == 0)
1265 if (!search_lisp_doc_at_eol (infile))
1266 continue;
1269 else if (! strcmp (buffer, "custom-declare-variable")
1270 || ! strcmp (buffer, "defvaralias")
1273 type = 'V';
1275 c = getc (infile);
1276 if (c == '\'')
1277 read_lisp_symbol (infile, buffer);
1278 else
1280 if (c != '(')
1282 fprintf (stderr,
1283 "## unparsable name in custom-declare-variable in %s\n",
1284 filename);
1285 continue;
1287 read_lisp_symbol (infile, buffer);
1288 if (strcmp (buffer, "quote"))
1290 fprintf (stderr,
1291 "## unparsable name in custom-declare-variable in %s\n",
1292 filename);
1293 continue;
1295 read_lisp_symbol (infile, buffer);
1296 c = getc (infile);
1297 if (c != ')')
1299 fprintf (stderr,
1300 "## unparsable quoted name in custom-declare-variable in %s\n",
1301 filename);
1302 continue;
1306 if (saved_string == 0)
1307 if (!search_lisp_doc_at_eol (infile))
1308 continue;
1311 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
1313 type = 'F';
1315 c = getc (infile);
1316 if (c == '\'')
1317 read_lisp_symbol (infile, buffer);
1318 else
1320 if (c != '(')
1322 fprintf (stderr, "## unparsable name in fset in %s\n",
1323 filename);
1324 continue;
1326 read_lisp_symbol (infile, buffer);
1327 if (strcmp (buffer, "quote"))
1329 fprintf (stderr, "## unparsable name in fset in %s\n",
1330 filename);
1331 continue;
1333 read_lisp_symbol (infile, buffer);
1334 c = getc (infile);
1335 if (c != ')')
1337 fprintf (stderr,
1338 "## unparsable quoted name in fset in %s\n",
1339 filename);
1340 continue;
1344 if (saved_string == 0)
1345 if (!search_lisp_doc_at_eol (infile))
1346 continue;
1349 else if (! strcmp (buffer, "autoload"))
1351 type = 'F';
1352 c = getc (infile);
1353 if (c == '\'')
1354 read_lisp_symbol (infile, buffer);
1355 else
1357 if (c != '(')
1359 fprintf (stderr, "## unparsable name in autoload in %s\n",
1360 filename);
1361 continue;
1363 read_lisp_symbol (infile, buffer);
1364 if (strcmp (buffer, "quote"))
1366 fprintf (stderr, "## unparsable name in autoload in %s\n",
1367 filename);
1368 continue;
1370 read_lisp_symbol (infile, buffer);
1371 c = getc (infile);
1372 if (c != ')')
1374 fprintf (stderr,
1375 "## unparsable quoted name in autoload in %s\n",
1376 filename);
1377 continue;
1380 skip_white (infile);
1381 if ((c = getc (infile)) != '\"')
1383 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
1384 buffer, filename);
1385 continue;
1387 read_c_string_or_comment (infile, 0, 0, 0);
1389 if (saved_string == 0)
1390 if (!search_lisp_doc_at_eol (infile))
1391 continue;
1394 #ifdef DEBUG
1395 else if (! strcmp (buffer, "if")
1396 || ! strcmp (buffer, "byte-code"))
1397 continue;
1398 #endif
1400 else
1402 #ifdef DEBUG
1403 fprintf (stderr, "## unrecognized top-level form, %s (%s)\n",
1404 buffer, filename);
1405 #endif
1406 continue;
1409 /* At this point, we should either use the previous dynamic doc string in
1410 saved_string or gobble a doc string from the input file.
1411 In the latter case, the opening quote (and leading backslash-newline)
1412 have already been read. */
1414 printf ("\037%c%s\n", type, buffer);
1415 if (saved_string)
1417 fputs (saved_string, stdout);
1418 /* Don't use one dynamic doc string twice. */
1419 free (saved_string);
1420 saved_string = 0;
1422 else
1423 read_c_string_or_comment (infile, 1, 0, 0);
1425 fclose (infile);
1426 return 0;
1430 /* make-docfile.c ends here */