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