(blink-matching-delay): New variable.
[bpt/emacs.git] / lib-src / make-docfile.c
CommitLineData
f2cc4248 1/* Generate doc-string file for GNU Emacs from source files.
069ad9ea 2 Copyright (C) 1985, 1986, 1992, 1993, 1994 Free Software Foundation, Inc.
f2cc4248
RS
3
4This file is part of GNU Emacs.
5
93320c23
JA
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
e065a56e 8the Free Software Foundation; either version 2, or (at your option)
93320c23
JA
9any later version.
10
f2cc4248 11GNU Emacs is distributed in the hope that it will be useful,
93320c23
JA
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.
f2cc4248 15
93320c23
JA
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. */
f2cc4248
RS
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>
e3938952
RS
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 */
f2cc4248 46
340ff9de
DM
47int scan_file ();
48int scan_lisp_file ();
49int scan_c_file ();
50
f2cc4248
RS
51FILE *outfile;
52
340ff9de 53int
f2cc4248
RS
54main (argc, argv)
55 int argc;
56 char **argv;
57{
58 int i;
59 int err_count = 0;
a27897c9 60 int first_infile;
f2cc4248 61
e3938952
RS
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 */
f2cc4248
RS
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 }
d2d92f7a
JB
81 if (argc > i + 1 && !strcmp (argv[i], "-d"))
82 {
83 chdir (argv[i + 1]);
84 i += 2;
85 }
f2cc4248 86
a27897c9 87 first_infile = i;
f2cc4248 88 for (; i < argc; i++)
a27897c9
RS
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 }
f2cc4248 98#ifndef VMS
a27897c9 99 exit (err_count > 0);
a706b808 100#endif /* VMS */
a27897c9 101 return err_count > 0;
f2cc4248
RS
102}
103
a8a7afbe 104/* Read file FILENAME and output its doc strings to outfile. */
f2cc4248
RS
105/* Return 1 if file is not found, 0 if it is found. */
106
340ff9de 107int
f2cc4248
RS
108scan_file (filename)
109 char *filename;
110{
111 int len = strlen (filename);
112 if (!strcmp (filename + len - 4, ".elc"))
e3938952 113 return scan_lisp_file (filename, READ_BINARY);
f2cc4248 114 else if (!strcmp (filename + len - 3, ".el"))
e3938952 115 return scan_lisp_file (filename, READ_TEXT);
f2cc4248 116 else
e3938952 117 return scan_c_file (filename, READ_TEXT);
f2cc4248
RS
118}
119\f
120char buf[128];
121
122/* Skip a C string from INFILE,
123 and return the character that follows the closing ".
a8a7afbe 124 If printflag is positive, output string contents to outfile.
f2cc4248
RS
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
340ff9de 129int
f2cc4248
RS
130read_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;
d48e616e 164 /* If we had a "", concatenate the two strings. */
f2cc4248
RS
165 c = getc (infile);
166 }
167
168 if (printflag < 0)
169 *p = 0;
170
171 return c;
172}
173\f
069ad9ea 174/* Write to file OUT the argument names of function FUNC, whose text is in BUF.
f2cc4248
RS
175 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
176
340ff9de 177void
069ad9ea 178write_c_args (out, func, buf, minargs, maxargs)
f2cc4248 179 FILE *out;
069ad9ea 180 char *func, *buf;
f2cc4248
RS
181 int minargs, maxargs;
182{
f125a9e8 183 register char *p;
30e4c427
JB
184 int in_ident = 0;
185 int just_spaced = 0;
069ad9ea 186 int need_space = 1;
f2cc4248 187
069ad9ea
RM
188 fprintf (out, "(%s", func);
189
190 if (*buf == '(')
191 ++buf;
f2cc4248 192
f125a9e8 193 for (p = buf; *p; p++)
f2cc4248 194 {
30e4c427 195 char c = *p;
3941a179 196 int ident_start = 0;
30e4c427
JB
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)
f2cc4248 204 {
30e4c427
JB
205 if (!in_ident)
206 {
207 in_ident = 1;
3941a179 208 ident_start = 1;
f125a9e8 209
069ad9ea
RM
210 if (need_space)
211 putc (' ', out);
212
30e4c427
JB
213 if (minargs == 0 && maxargs > 0)
214 fprintf (out, "&optional ");
215 just_spaced = 1;
f125a9e8 216
30e4c427
JB
217 minargs--;
218 maxargs--;
219 }
220 else
221 in_ident = 0;
f2cc4248 222 }
30e4c427
JB
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
3941a179
JB
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 {
4607ea99 239 fprintf (out, "DEFAULT");
3941a179
JB
240 p += 5;
241 in_ident = 0;
242 just_spaced = 0;
243 }
244 else if (c != ' ' || ! just_spaced)
069ad9ea
RM
245 {
246 if (c >= 'a' && c <= 'z')
247 /* Upcase the letter. */
248 c += 'A' - 'a';
249 putc (c, out);
250 }
30e4c427
JB
251
252 just_spaced = (c == ' ');
069ad9ea 253 need_space = 0;
f2cc4248 254 }
f2cc4248
RS
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
340ff9de 262int
e3938952
RS
263scan_c_file (filename, mode)
264 char *filename, *mode;
f2cc4248
RS
265{
266 FILE *infile;
267 register int c;
268 register int commas;
269 register int defunflag;
84128dee 270 register int defvarperbufferflag;
f2cc4248
RS
271 register int defvarflag;
272 int minargs, maxargs;
273
274 if (filename[strlen (filename) - 1] == 'o')
275 filename[strlen (filename) - 1] = 'c';
276
e3938952 277 infile = fopen (filename, mode);
f2cc4248
RS
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;
84128dee
JB
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
f2cc4248
RS
320 defvarflag = 1;
321 defunflag = 0;
84128dee
JB
322
323 c = getc (infile);
324 defvarperbufferflag = (c == 'P');
325
f2cc4248
RS
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;
84128dee
JB
356 else if (defvarperbufferflag)
357 commas = 2;
f2cc4248
RS
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);
772e2009
JB
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)
f2cc4248
RS
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");
069ad9ea 434 write_c_args (outfile, buf, argbuf, minargs, maxargs);
f2cc4248
RS
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 ...)
23d6b5a6
JB
446 (defmacro NAME ARGS DOCSTRING ...)
447 (autoload (quote NAME) FILE DOCSTRING ...)
f2cc4248
RS
448 (defvar NAME VALUE DOCSTRING)
449 (defconst NAME VALUE DOCSTRING)
23d6b5a6
JB
450 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
451 (fset (quote NAME) #[... DOCSTRING ...])
2d6e2619 452 (defalias (quote NAME) #[... DOCSTRING ...])
f2cc4248 453 starting in column zero.
23d6b5a6
JB
454 (quote NAME) may appear as 'NAME as well.
455 For defun, defmacro, and autoload, we know how to skip over the arglist.
eb8c3be9 456 For defvar, defconst, and fset we skip to the docstring with a kludgy
23d6b5a6
JB
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.
f2cc4248
RS
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
23d6b5a6
JB
469void
470skip_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
479void
480read_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
340ff9de 509int
e3938952
RS
510scan_lisp_file (filename, mode)
511 char *filename, *mode;
f2cc4248
RS
512{
513 FILE *infile;
514 register int c;
f2cc4248 515
e3938952 516 infile = fopen (filename, mode);
f2cc4248
RS
517 if (infile == NULL)
518 {
519 perror (filename);
520 return 0; /* No error */
521 }
522
523 c = '\n';
524 while (!feof (infile))
525 {
23d6b5a6 526 char buffer [BUFSIZ];
23d6b5a6
JB
527 char type;
528
f2cc4248
RS
529 if (c != '\n')
530 {
531 c = getc (infile);
532 continue;
533 }
534 c = getc (infile);
535 if (c != '(')
536 continue;
a8a7afbe 537
23d6b5a6
JB
538 read_lisp_symbol (infile, buffer);
539
540 if (! strcmp (buffer, "defun") ||
541 ! strcmp (buffer, "defmacro"))
f2cc4248 542 {
23d6b5a6
JB
543 type = 'F';
544 read_lisp_symbol (infile, buffer);
f2cc4248 545
23d6b5a6 546 /* Skip the arguments: either "nil" or a list in parens */
f2cc4248 547
23d6b5a6
JB
548 c = getc (infile);
549 if (c == 'n') /* nil */
f2cc4248 550 {
23d6b5a6
JB
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 }
f2cc4248 558 }
23d6b5a6 559 else if (c != '(')
f2cc4248 560 {
23d6b5a6
JB
561 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
562 buffer, filename);
563 continue;
f2cc4248 564 }
23d6b5a6
JB
565 else
566 while (c != ')')
f2cc4248 567 c = getc (infile);
23d6b5a6
JB
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')
f2cc4248 576 {
23d6b5a6
JB
577#ifdef DEBUG
578 fprintf (stderr, "## non-docstring in %s (%s)\n",
579 buffer, filename);
580#endif
581 continue;
f2cc4248 582 }
f2cc4248 583 }
a8a7afbe 584
23d6b5a6
JB
585 else if (! strcmp (buffer, "defvar") ||
586 ! strcmp (buffer, "defconst"))
f2cc4248 587 {
23d6b5a6
JB
588 char c1 = 0, c2 = 0;
589 type = 'V';
590 read_lisp_symbol (infile, buffer);
a8a7afbe 591
23d6b5a6
JB
592 /* Skip until the first newline; remember the two previous chars. */
593 while (c != '\n' && c >= 0)
f2cc4248 594 {
23d6b5a6
JB
595 c2 = c1;
596 c1 = c;
f2cc4248 597 c = getc (infile);
f2cc4248 598 }
23d6b5a6
JB
599
600 /* If two previous characters were " and \,
601 this is a doc string. Otherwise, there is none. */
602 if (c2 != '"' || c1 != '\\')
f2cc4248 603 {
23d6b5a6
JB
604#ifdef DEBUG
605 fprintf (stderr, "## non-docstring in %s (%s)\n",
606 buffer, filename);
607#endif
608 continue;
f2cc4248 609 }
23d6b5a6
JB
610 }
611
2d6e2619 612 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
23d6b5a6
JB
613 {
614 char c1 = 0, c2 = 0;
615 type = 'F';
a8a7afbe 616
23d6b5a6
JB
617 c = getc (infile);
618 if (c == '\'')
619 read_lisp_symbol (infile, buffer);
620 else
f2cc4248 621 {
23d6b5a6
JB
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);
f2cc4248 636 c = getc (infile);
23d6b5a6
JB
637 if (c != ')')
638 {
639 fprintf (stderr,
640 "## unparsable quoted name in fset in %s\n",
641 filename);
642 continue;
643 }
f2cc4248 644 }
f2cc4248 645
23d6b5a6
JB
646 /* Skip until the first newline; remember the two previous chars. */
647 while (c != '\n' && c >= 0)
f2cc4248 648 {
23d6b5a6
JB
649 c2 = c1;
650 c1 = c;
f2cc4248
RS
651 c = getc (infile);
652 }
23d6b5a6
JB
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 }
f2cc4248 665
23d6b5a6
JB
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
f2cc4248 673 {
23d6b5a6 674 if (c != '(')
f2cc4248 675 {
23d6b5a6
JB
676 fprintf (stderr, "## unparsable name in autoload in %s\n",
677 filename);
678 continue;
f2cc4248 679 }
23d6b5a6
JB
680 read_lisp_symbol (infile, buffer);
681 if (strcmp (buffer, "quote"))
f2cc4248 682 {
23d6b5a6
JB
683 fprintf (stderr, "## unparsable name in autoload in %s\n",
684 filename);
685 continue;
f2cc4248 686 }
23d6b5a6 687 read_lisp_symbol (infile, buffer);
f2cc4248 688 c = getc (infile);
23d6b5a6 689 if (c != ')')
f2cc4248 690 {
23d6b5a6
JB
691 fprintf (stderr,
692 "## unparsable quoted name in autoload in %s\n",
693 filename);
694 continue;
f2cc4248 695 }
23d6b5a6
JB
696 }
697 skip_white (infile);
698 if ((c = getc (infile)) != '\"')
699 {
700 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
701 buffer, filename);
f2cc4248
RS
702 continue;
703 }
23d6b5a6
JB
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')
a8a7afbe 713 {
23d6b5a6
JB
714#ifdef DEBUG
715 fprintf (stderr, "## non-docstring in %s (%s)\n",
716 buffer, filename);
717#endif
718 continue;
a8a7afbe 719 }
a8a7afbe 720 }
f2cc4248 721
23d6b5a6
JB
722#ifdef DEBUG
723 else if (! strcmp (buffer, "if") ||
724 ! strcmp (buffer, "byte-code"))
725 ;
726#endif
f2cc4248 727
23d6b5a6
JB
728 else
729 {
730#ifdef DEBUG
731 fprintf (stderr, "## unrecognised top-level form, %s (%s)\n",
732 buffer, filename);
733#endif
734 continue;
735 }
f2cc4248 736
23d6b5a6
JB
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 */
f2cc4248 741 putc (037, outfile);
23d6b5a6
JB
742 putc (type, outfile);
743 fprintf (outfile, "%s\n", buffer);
f2cc4248
RS
744 read_c_string (infile, 1);
745 }
746 fclose (infile);
747 return 0;
748}