Define STDC_HEADERS.
[bpt/emacs.git] / lib-src / make-docfile.c
... / ...
CommitLineData
1/* Generate doc-string file for GNU Emacs from source files.
2 Copyright (C) 1985, 1986, 1992, 1993, 1994 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20/* The arguments given to this program are all the C and Lisp source files
21 of GNU Emacs. .elc and .el and .c files are allowed.
22 A .o file can also be specified; the .c file it was made from is used.
23 This helps the makefile pass the correct list of files.
24
25 The results, which go to standard output or to a file
26 specified with -a or -o (-a to append, -o to start from nothing),
27 are entries containing function or variable names and their documentation.
28 Each entry starts with a ^_ character.
29 Then comes F for a function or V for a variable.
30 Then comes the function or variable name, terminated with a newline.
31 Then comes the documentation for that function or variable.
32 */
33
34#define NO_SHORTNAMES /* Tell config not to load remap.h */
35#include <../src/config.h>
36
37#include <stdio.h>
38#ifdef MSDOS
39#include <fcntl.h>
40#endif /* MSDOS */
41#ifdef WINDOWSNT
42#include <stdlib.h>
43#include <fcntl.h>
44#include <direct.h>
45#endif /* WINDOWSNT */
46
47#ifdef DOS_NT
48#define READ_TEXT "rt"
49#define READ_BINARY "rb"
50#else /* not DOS_NT */
51#define READ_TEXT "r"
52#define READ_BINARY "r"
53#endif /* not DOS_NT */
54
55int scan_file ();
56int scan_lisp_file ();
57int scan_c_file ();
58
59/* Stdio stream for output to the DOC file. */
60FILE *outfile;
61
62/* Name this program was invoked with. */
63char *progname;
64
65/* Print error message. `s1' is printf control string, `s2' is arg for it. */
66
67/* VARARGS1 */
68void
69error (s1, s2)
70 char *s1, *s2;
71{
72 fprintf (stderr, "%s: ", progname);
73 fprintf (stderr, s1, s2);
74 fprintf (stderr, "\n");
75}
76
77/* Print error message and exit. */
78
79/* VARARGS1 */
80void
81fatal (s1, s2)
82 char *s1, *s2;
83{
84 error (s1, s2);
85 exit (1);
86}
87
88/* Like malloc but get fatal error if memory is exhausted. */
89
90long *
91xmalloc (size)
92 unsigned int size;
93{
94 long *result = (long *) malloc (size);
95 if (result == NULL)
96 fatal ("virtual memory exhausted", 0);
97 return result;
98}
99\f
100int
101main (argc, argv)
102 int argc;
103 char **argv;
104{
105 int i;
106 int err_count = 0;
107 int first_infile;
108
109 progname = argv[0];
110
111 /* Don't put CRs in the DOC file. */
112#ifdef MSDOS
113 _fmode = O_BINARY;
114 (stdout)->_flag &= ~_IOTEXT;
115 _setmode (fileno (stdout), O_BINARY);
116#endif /* MSDOS */
117#ifdef WINDOWSNT
118 _fmode = O_BINARY;
119 _setmode (fileno (stdout), O_BINARY);
120#endif /* WINDOWSNT */
121
122 outfile = stdout;
123
124 /* If first two args are -o FILE, output to FILE. */
125 i = 1;
126 if (argc > i + 1 && !strcmp (argv[i], "-o"))
127 {
128 outfile = fopen (argv[i + 1], "w");
129 i += 2;
130 }
131 if (argc > i + 1 && !strcmp (argv[i], "-a"))
132 {
133 outfile = fopen (argv[i + 1], "a");
134 i += 2;
135 }
136 if (argc > i + 1 && !strcmp (argv[i], "-d"))
137 {
138 chdir (argv[i + 1]);
139 i += 2;
140 }
141
142 first_infile = i;
143 for (; i < argc; i++)
144 {
145 int j;
146 /* Don't process one file twice. */
147 for (j = first_infile; j < i; j++)
148 if (! strcmp (argv[i], argv[j]))
149 break;
150 if (j == i)
151 err_count += scan_file (argv[i]);
152 }
153#ifndef VMS
154 exit (err_count > 0);
155#endif /* VMS */
156 return err_count > 0;
157}
158
159/* Read file FILENAME and output its doc strings to outfile. */
160/* Return 1 if file is not found, 0 if it is found. */
161
162int
163scan_file (filename)
164 char *filename;
165{
166 int len = strlen (filename);
167 if (!strcmp (filename + len - 4, ".elc"))
168 return scan_lisp_file (filename, READ_BINARY);
169 else if (!strcmp (filename + len - 3, ".el"))
170 return scan_lisp_file (filename, READ_TEXT);
171 else
172 return scan_c_file (filename, READ_TEXT);
173}
174\f
175char buf[128];
176
177/* Skip a C string from INFILE,
178 and return the character that follows the closing ".
179 If printflag is positive, output string contents to outfile.
180 If it is negative, store contents in buf.
181 Convert escape sequences \n and \t to newline and tab;
182 discard \ followed by newline. */
183
184int
185read_c_string (infile, printflag)
186 FILE *infile;
187 int printflag;
188{
189 register int c;
190 char *p = buf;
191
192 c = getc (infile);
193 while (c != EOF)
194 {
195 while (c != '"' && c != EOF)
196 {
197 if (c == '\\')
198 {
199 c = getc (infile);
200 if (c == '\n')
201 {
202 c = getc (infile);
203 continue;
204 }
205 if (c == 'n')
206 c = '\n';
207 if (c == 't')
208 c = '\t';
209 }
210 if (printflag > 0)
211 putc (c, outfile);
212 else if (printflag < 0)
213 *p++ = c;
214 c = getc (infile);
215 }
216 c = getc (infile);
217 if (c != '"')
218 break;
219 /* If we had a "", concatenate the two strings. */
220 c = getc (infile);
221 }
222
223 if (printflag < 0)
224 *p = 0;
225
226 return c;
227}
228\f
229/* Write to file OUT the argument names of function FUNC, whose text is in BUF.
230 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
231
232void
233write_c_args (out, func, buf, minargs, maxargs)
234 FILE *out;
235 char *func, *buf;
236 int minargs, maxargs;
237{
238 register char *p;
239 int in_ident = 0;
240 int just_spaced = 0;
241 int need_space = 1;
242
243 fprintf (out, "(%s", func);
244
245 if (*buf == '(')
246 ++buf;
247
248 for (p = buf; *p; p++)
249 {
250 char c = *p;
251 int ident_start = 0;
252
253 /* Notice when we start printing a new identifier. */
254 if ((('A' <= c && c <= 'Z')
255 || ('a' <= c && c <= 'z')
256 || ('0' <= c && c <= '9')
257 || c == '_')
258 != in_ident)
259 {
260 if (!in_ident)
261 {
262 in_ident = 1;
263 ident_start = 1;
264
265 if (need_space)
266 putc (' ', out);
267
268 if (minargs == 0 && maxargs > 0)
269 fprintf (out, "&optional ");
270 just_spaced = 1;
271
272 minargs--;
273 maxargs--;
274 }
275 else
276 in_ident = 0;
277 }
278
279 /* Print the C argument list as it would appear in lisp:
280 print underscores as hyphens, and print commas as spaces.
281 Collapse adjacent spaces into one. */
282 if (c == '_') c = '-';
283 if (c == ',') c = ' ';
284
285 /* In C code, `default' is a reserved word, so we spell it
286 `defalt'; unmangle that here. */
287 if (ident_start
288 && strncmp (p, "defalt", 6) == 0
289 && ! (('A' <= p[6] && p[6] <= 'Z')
290 || ('a' <= p[6] && p[6] <= 'z')
291 || ('0' <= p[6] && p[6] <= '9')
292 || p[6] == '_'))
293 {
294 fprintf (out, "DEFAULT");
295 p += 5;
296 in_ident = 0;
297 just_spaced = 0;
298 }
299 else if (c != ' ' || ! just_spaced)
300 {
301 if (c >= 'a' && c <= 'z')
302 /* Upcase the letter. */
303 c += 'A' - 'a';
304 putc (c, out);
305 }
306
307 just_spaced = (c == ' ');
308 need_space = 0;
309 }
310}
311\f
312/* Read through a c file. If a .o file is named,
313 the corresponding .c file is read instead.
314 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
315 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
316
317int
318scan_c_file (filename, mode)
319 char *filename, *mode;
320{
321 FILE *infile;
322 register int c;
323 register int commas;
324 register int defunflag;
325 register int defvarperbufferflag;
326 register int defvarflag;
327 int minargs, maxargs;
328 int extension = filename[strlen (filename) - 1];
329
330 if (extension == 'o')
331 filename[strlen (filename) - 1] = 'c';
332
333 infile = fopen (filename, mode);
334
335 /* No error if non-ex input file */
336 if (infile == NULL)
337 {
338 perror (filename);
339 return 0;
340 }
341
342 /* Reset extension to be able to detect duplicate files. */
343 filename[strlen (filename) - 1] = extension;
344
345 c = '\n';
346 while (!feof (infile))
347 {
348 if (c != '\n')
349 {
350 c = getc (infile);
351 continue;
352 }
353 c = getc (infile);
354 if (c == ' ')
355 {
356 while (c == ' ')
357 c = getc (infile);
358 if (c != 'D')
359 continue;
360 c = getc (infile);
361 if (c != 'E')
362 continue;
363 c = getc (infile);
364 if (c != 'F')
365 continue;
366 c = getc (infile);
367 if (c != 'V')
368 continue;
369 c = getc (infile);
370 if (c != 'A')
371 continue;
372 c = getc (infile);
373 if (c != 'R')
374 continue;
375 c = getc (infile);
376 if (c != '_')
377 continue;
378
379 defvarflag = 1;
380 defunflag = 0;
381
382 c = getc (infile);
383 defvarperbufferflag = (c == 'P');
384
385 c = getc (infile);
386 }
387 else if (c == 'D')
388 {
389 c = getc (infile);
390 if (c != 'E')
391 continue;
392 c = getc (infile);
393 if (c != 'F')
394 continue;
395 c = getc (infile);
396 defunflag = c == 'U';
397 defvarflag = 0;
398 }
399 else continue;
400
401 while (c != '(')
402 {
403 if (c < 0)
404 goto eof;
405 c = getc (infile);
406 }
407
408 c = getc (infile);
409 if (c != '"')
410 continue;
411 c = read_c_string (infile, -1);
412
413 if (defunflag)
414 commas = 5;
415 else if (defvarperbufferflag)
416 commas = 2;
417 else if (defvarflag)
418 commas = 1;
419 else /* For DEFSIMPLE and DEFPRED */
420 commas = 2;
421
422 while (commas)
423 {
424 if (c == ',')
425 {
426 commas--;
427 if (defunflag && (commas == 1 || commas == 2))
428 {
429 do
430 c = getc (infile);
431 while (c == ' ' || c == '\n' || c == '\t');
432 if (c < 0)
433 goto eof;
434 ungetc (c, infile);
435 if (commas == 2) /* pick up minargs */
436 fscanf (infile, "%d", &minargs);
437 else /* pick up maxargs */
438 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
439 maxargs = -1;
440 else
441 fscanf (infile, "%d", &maxargs);
442 }
443 }
444 if (c < 0)
445 goto eof;
446 c = getc (infile);
447 }
448 while (c == ' ' || c == '\n' || c == '\t')
449 c = getc (infile);
450 if (c == '"')
451 c = read_c_string (infile, 0);
452 while (c != ',')
453 c = getc (infile);
454 c = getc (infile);
455 while (c == ' ' || c == '\n' || c == '\t')
456 c = getc (infile);
457
458 if (c == '"')
459 {
460 putc (037, outfile);
461 putc (defvarflag ? 'V' : 'F', outfile);
462 fprintf (outfile, "%s\n", buf);
463 c = read_c_string (infile, 1);
464
465 /* If this is a defun, find the arguments and print them. If
466 this function takes MANY or UNEVALLED args, then the C source
467 won't give the names of the arguments, so we shouldn't bother
468 trying to find them. */
469 if (defunflag && maxargs != -1)
470 {
471 char argbuf[1024], *p = argbuf;
472 while (c != ')')
473 {
474 if (c < 0)
475 goto eof;
476 c = getc (infile);
477 }
478 /* Skip into arguments. */
479 while (c != '(')
480 {
481 if (c < 0)
482 goto eof;
483 c = getc (infile);
484 }
485 /* Copy arguments into ARGBUF. */
486 *p++ = c;
487 do
488 *p++ = c = getc (infile);
489 while (c != ')');
490 *p = '\0';
491 /* Output them. */
492 fprintf (outfile, "\n\n");
493 write_c_args (outfile, buf, argbuf, minargs, maxargs);
494 }
495 }
496 }
497 eof:
498 fclose (infile);
499 return 0;
500}
501\f
502/* Read a file of Lisp code, compiled or interpreted.
503 Looks for
504 (defun NAME ARGS DOCSTRING ...)
505 (defmacro NAME ARGS DOCSTRING ...)
506 (autoload (quote NAME) FILE DOCSTRING ...)
507 (defvar NAME VALUE DOCSTRING)
508 (defconst NAME VALUE DOCSTRING)
509 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
510 (fset (quote NAME) #[... DOCSTRING ...])
511 (defalias (quote NAME) #[... DOCSTRING ...])
512 starting in column zero.
513 (quote NAME) may appear as 'NAME as well.
514
515 We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
516 When we find that, we save it for the following defining-form,
517 and we use that instead of reading a doc string within that defining-form.
518
519 For defun, defmacro, and autoload, we know how to skip over the arglist.
520 For defvar, defconst, and fset we skip to the docstring with a kludgy
521 formatting convention: all docstrings must appear on the same line as the
522 initial open-paren (the one in column zero) and must contain a backslash
523 and a double-quote immediately after the initial double-quote. No newlines
524 must appear between the beginning of the form and the first double-quote.
525 The only source file that must follow this convention is loaddefs.el; aside
526 from that, it is always the .elc file that we look at, and they are no
527 problem because byte-compiler output follows this convention.
528 The NAME and DOCSTRING are output.
529 NAME is preceded by `F' for a function or `V' for a variable.
530 An entry is output only if DOCSTRING has \ newline just after the opening "
531 */
532
533void
534skip_white (infile)
535 FILE *infile;
536{
537 char c = ' ';
538 while (c == ' ' || c == '\t' || c == '\n')
539 c = getc (infile);
540 ungetc (c, infile);
541}
542
543void
544read_lisp_symbol (infile, buffer)
545 FILE *infile;
546 char *buffer;
547{
548 char c;
549 char *fillp = buffer;
550
551 skip_white (infile);
552 while (1)
553 {
554 c = getc (infile);
555 if (c == '\\')
556 *(++fillp) = getc (infile);
557 else if (c == ' ' || c == '\t' || c == '\n' || c == '(' || c == ')')
558 {
559 ungetc (c, infile);
560 *fillp = 0;
561 break;
562 }
563 else
564 *fillp++ = c;
565 }
566
567 if (! buffer[0])
568 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
569
570 skip_white (infile);
571}
572
573int
574scan_lisp_file (filename, mode)
575 char *filename, *mode;
576{
577 FILE *infile;
578 register int c;
579 char *saved_string = 0;
580
581 infile = fopen (filename, mode);
582 if (infile == NULL)
583 {
584 perror (filename);
585 return 0; /* No error */
586 }
587
588 c = '\n';
589 while (!feof (infile))
590 {
591 char buffer[BUFSIZ];
592 char type;
593
594 if (c != '\n')
595 {
596 c = getc (infile);
597 continue;
598 }
599 c = getc (infile);
600 /* Detect a dynamic doc string and save it for the next expression. */
601 if (c == '#')
602 {
603 c = getc (infile);
604 if (c == '@')
605 {
606 int length = 0;
607 int i;
608
609 /* Read the length. */
610 while ((c = getc (infile),
611 c >= '0' && c <= '9'))
612 {
613 length *= 10;
614 length += c - '0';
615 }
616
617 /* The next character is a space that is counted in the length
618 but not part of the doc string.
619 We already read it, so just ignore it. */
620 length--;
621
622 /* Read in the contents. */
623 if (saved_string != 0)
624 free (saved_string);
625 saved_string = (char *) malloc (length);
626 for (i = 0; i < length; i++)
627 saved_string[i] = getc (infile);
628 /* The last character is a ^_.
629 That is needed in the .elc file
630 but it is redundant in DOC. So get rid of it here. */
631 saved_string[length - 1] = 0;
632 /* Skip the newline. */
633 c = getc (infile);
634 while (c != '\n')
635 c = getc (infile);
636 }
637 continue;
638 }
639
640 if (c != '(')
641 continue;
642
643 read_lisp_symbol (infile, buffer);
644
645 if (! strcmp (buffer, "defun") ||
646 ! strcmp (buffer, "defmacro"))
647 {
648 type = 'F';
649 read_lisp_symbol (infile, buffer);
650
651 /* Skip the arguments: either "nil" or a list in parens */
652
653 c = getc (infile);
654 if (c == 'n') /* nil */
655 {
656 if ((c = getc (infile)) != 'i' ||
657 (c = getc (infile)) != 'l')
658 {
659 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
660 buffer, filename);
661 continue;
662 }
663 }
664 else if (c != '(')
665 {
666 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
667 buffer, filename);
668 continue;
669 }
670 else
671 while (c != ')')
672 c = getc (infile);
673 skip_white (infile);
674
675 /* If the next three characters aren't `dquote bslash newline'
676 then we're not reading a docstring.
677 */
678 if ((c = getc (infile)) != '"' ||
679 (c = getc (infile)) != '\\' ||
680 (c = getc (infile)) != '\n')
681 {
682#ifdef DEBUG
683 fprintf (stderr, "## non-docstring in %s (%s)\n",
684 buffer, filename);
685#endif
686 continue;
687 }
688 }
689
690 else if (! strcmp (buffer, "defvar") ||
691 ! strcmp (buffer, "defconst"))
692 {
693 char c1 = 0, c2 = 0;
694 type = 'V';
695 read_lisp_symbol (infile, buffer);
696
697 if (saved_string == 0)
698 {
699
700 /* Skip until the first newline; remember the two previous chars. */
701 while (c != '\n' && c >= 0)
702 {
703 c2 = c1;
704 c1 = c;
705 c = getc (infile);
706 }
707
708 /* If two previous characters were " and \,
709 this is a doc string. Otherwise, there is none. */
710 if (c2 != '"' || c1 != '\\')
711 {
712#ifdef DEBUG
713 fprintf (stderr, "## non-docstring in %s (%s)\n",
714 buffer, filename);
715#endif
716 continue;
717 }
718 }
719 }
720
721 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
722 {
723 char c1 = 0, c2 = 0;
724 type = 'F';
725
726 c = getc (infile);
727 if (c == '\'')
728 read_lisp_symbol (infile, buffer);
729 else
730 {
731 if (c != '(')
732 {
733 fprintf (stderr, "## unparsable name in fset in %s\n",
734 filename);
735 continue;
736 }
737 read_lisp_symbol (infile, buffer);
738 if (strcmp (buffer, "quote"))
739 {
740 fprintf (stderr, "## unparsable name in fset in %s\n",
741 filename);
742 continue;
743 }
744 read_lisp_symbol (infile, buffer);
745 c = getc (infile);
746 if (c != ')')
747 {
748 fprintf (stderr,
749 "## unparsable quoted name in fset in %s\n",
750 filename);
751 continue;
752 }
753 }
754
755 if (saved_string == 0)
756 {
757 /* Skip until the first newline; remember the two previous chars. */
758 while (c != '\n' && c >= 0)
759 {
760 c2 = c1;
761 c1 = c;
762 c = getc (infile);
763 }
764
765 /* If two previous characters were " and \,
766 this is a doc string. Otherwise, there is none. */
767 if (c2 != '"' || c1 != '\\')
768 {
769#ifdef DEBUG
770 fprintf (stderr, "## non-docstring in %s (%s)\n",
771 buffer, filename);
772#endif
773 continue;
774 }
775 }
776 }
777
778 else if (! strcmp (buffer, "autoload"))
779 {
780 type = 'F';
781 c = getc (infile);
782 if (c == '\'')
783 read_lisp_symbol (infile, buffer);
784 else
785 {
786 if (c != '(')
787 {
788 fprintf (stderr, "## unparsable name in autoload in %s\n",
789 filename);
790 continue;
791 }
792 read_lisp_symbol (infile, buffer);
793 if (strcmp (buffer, "quote"))
794 {
795 fprintf (stderr, "## unparsable name in autoload in %s\n",
796 filename);
797 continue;
798 }
799 read_lisp_symbol (infile, buffer);
800 c = getc (infile);
801 if (c != ')')
802 {
803 fprintf (stderr,
804 "## unparsable quoted name in autoload in %s\n",
805 filename);
806 continue;
807 }
808 }
809 skip_white (infile);
810 if ((c = getc (infile)) != '\"')
811 {
812 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
813 buffer, filename);
814 continue;
815 }
816 read_c_string (infile, 0);
817 skip_white (infile);
818
819 if (saved_string == 0)
820 {
821 /* If the next three characters aren't `dquote bslash newline'
822 then we're not reading a docstring. */
823 if ((c = getc (infile)) != '"' ||
824 (c = getc (infile)) != '\\' ||
825 (c = getc (infile)) != '\n')
826 {
827#ifdef DEBUG
828 fprintf (stderr, "## non-docstring in %s (%s)\n",
829 buffer, filename);
830#endif
831 continue;
832 }
833 }
834 }
835
836#ifdef DEBUG
837 else if (! strcmp (buffer, "if") ||
838 ! strcmp (buffer, "byte-code"))
839 ;
840#endif
841
842 else
843 {
844#ifdef DEBUG
845 fprintf (stderr, "## unrecognised top-level form, %s (%s)\n",
846 buffer, filename);
847#endif
848 continue;
849 }
850
851 /* At this point, we should either use the previous
852 dynamic doc string in saved_string
853 or gobble a doc string from the input file.
854
855 In the latter case, the opening quote (and leading
856 backslash-newline) have already been read. */
857
858 putc (037, outfile);
859 putc (type, outfile);
860 fprintf (outfile, "%s\n", buffer);
861 if (saved_string)
862 {
863 fputs (saved_string, outfile);
864 /* Don't use one dynamic doc string twice. */
865 free (saved_string);
866 saved_string = 0;
867 }
868 else
869 read_c_string (infile, 1);
870 }
871 fclose (infile);
872 return 0;
873}