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