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