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