(rmail-summary-scroll-msg-up, rmail-summary-scroll-msg-down): Scroll
[emacs.git] / lib-src / make-docfile.c
blobb865845cfcf067263b2c9d7552f80d2e33078ee4
1 /* Generate doc-string file for GNU Emacs from source files.
2 Copyright (C) 1985, 1986, 1992, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
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.
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.
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. */
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.
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.
34 #include <stdio.h>
35 #ifdef MSDOS
36 #include <fcntl.h>
37 #endif /* MSDOS */
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 */
47 FILE *outfile;
49 main (argc, argv)
50 int argc;
51 char **argv;
53 int i;
54 int err_count = 0;
56 #ifdef MSDOS
57 _fmode = O_BINARY; /* all of files are treated as binary files */
58 (stdout)->_flag &= ~_IOTEXT;
59 _setmode (fileno (stdout), O_BINARY);
60 #endif /* MSDOS */
61 outfile = stdout;
63 /* If first two args are -o FILE, output to FILE. */
64 i = 1;
65 if (argc > i + 1 && !strcmp (argv[i], "-o"))
67 outfile = fopen (argv[i + 1], "w");
68 i += 2;
70 if (argc > i + 1 && !strcmp (argv[i], "-a"))
72 outfile = fopen (argv[i + 1], "a");
73 i += 2;
75 if (argc > i + 1 && !strcmp (argv[i], "-d"))
77 chdir (argv[i + 1]);
78 i += 2;
81 for (; i < argc; i++)
82 err_count += scan_file (argv[i]); /* err_count seems to be {mis,un}used */
83 #ifndef VMS
84 exit (err_count); /* see below - shane */
85 #endif /* VMS */
88 /* Read file FILENAME and output its doc strings to outfile. */
89 /* Return 1 if file is not found, 0 if it is found. */
91 scan_file (filename)
92 char *filename;
94 int len = strlen (filename);
95 if (!strcmp (filename + len - 4, ".elc"))
96 return scan_lisp_file (filename, READ_BINARY);
97 else if (!strcmp (filename + len - 3, ".el"))
98 return scan_lisp_file (filename, READ_TEXT);
99 else
100 return scan_c_file (filename, READ_TEXT);
103 char buf[128];
105 /* Skip a C string from INFILE,
106 and return the character that follows the closing ".
107 If printflag is positive, output string contents to outfile.
108 If it is negative, store contents in buf.
109 Convert escape sequences \n and \t to newline and tab;
110 discard \ followed by newline. */
112 read_c_string (infile, printflag)
113 FILE *infile;
114 int printflag;
116 register int c;
117 char *p = buf;
119 c = getc (infile);
120 while (c != EOF)
122 while (c != '"' && c != EOF)
124 if (c == '\\')
126 c = getc (infile);
127 if (c == '\n')
129 c = getc (infile);
130 continue;
132 if (c == 'n')
133 c = '\n';
134 if (c == 't')
135 c = '\t';
137 if (printflag > 0)
138 putc (c, outfile);
139 else if (printflag < 0)
140 *p++ = c;
141 c = getc (infile);
143 c = getc (infile);
144 if (c != '"')
145 break;
146 /* If we had a "", concatenate the two strings. */
147 c = getc (infile);
150 if (printflag < 0)
151 *p = 0;
153 return c;
156 /* Write to file OUT the argument names of function FUNC, whose text is in BUF.
157 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
159 write_c_args (out, func, buf, minargs, maxargs)
160 FILE *out;
161 char *func, *buf;
162 int minargs, maxargs;
164 register char *p;
165 int in_ident = 0;
166 int just_spaced = 0;
167 int need_space = 1;
169 fprintf (out, "(%s", func);
171 if (*buf == '(')
172 ++buf;
174 for (p = buf; *p; p++)
176 char c = *p;
177 int ident_start = 0;
179 /* Notice when we start printing a new identifier. */
180 if ((('A' <= c && c <= 'Z')
181 || ('a' <= c && c <= 'z')
182 || ('0' <= c && c <= '9')
183 || c == '_')
184 != in_ident)
186 if (!in_ident)
188 in_ident = 1;
189 ident_start = 1;
191 if (need_space)
192 putc (' ', out);
194 if (minargs == 0 && maxargs > 0)
195 fprintf (out, "&optional ");
196 just_spaced = 1;
198 minargs--;
199 maxargs--;
201 else
202 in_ident = 0;
205 /* Print the C argument list as it would appear in lisp:
206 print underscores as hyphens, and print commas as spaces.
207 Collapse adjacent spaces into one. */
208 if (c == '_') c = '-';
209 if (c == ',') c = ' ';
211 /* In C code, `default' is a reserved word, so we spell it
212 `defalt'; unmangle that here. */
213 if (ident_start
214 && strncmp (p, "defalt", 6) == 0
215 && ! (('A' <= p[6] && p[6] <= 'Z')
216 || ('a' <= p[6] && p[6] <= 'z')
217 || ('0' <= p[6] && p[6] <= '9')
218 || p[6] == '_'))
220 fprintf (out, "default");
221 p += 5;
222 in_ident = 0;
223 just_spaced = 0;
225 else if (c != ' ' || ! just_spaced)
227 if (c >= 'a' && c <= 'z')
228 /* Upcase the letter. */
229 c += 'A' - 'a';
230 putc (c, out);
233 just_spaced = (c == ' ');
234 need_space = 0;
238 /* Read through a c file. If a .o file is named,
239 the corresponding .c file is read instead.
240 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
241 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
243 scan_c_file (filename, mode)
244 char *filename, *mode;
246 FILE *infile;
247 register int c;
248 register int commas;
249 register int defunflag;
250 register int defvarperbufferflag;
251 register int defvarflag;
252 int minargs, maxargs;
254 if (filename[strlen (filename) - 1] == 'o')
255 filename[strlen (filename) - 1] = 'c';
257 infile = fopen (filename, mode);
259 /* No error if non-ex input file */
260 if (infile == NULL)
262 perror (filename);
263 return 0;
266 c = '\n';
267 while (!feof (infile))
269 if (c != '\n')
271 c = getc (infile);
272 continue;
274 c = getc (infile);
275 if (c == ' ')
277 while (c == ' ')
278 c = getc (infile);
279 if (c != 'D')
280 continue;
281 c = getc (infile);
282 if (c != 'E')
283 continue;
284 c = getc (infile);
285 if (c != 'F')
286 continue;
287 c = getc (infile);
288 if (c != 'V')
289 continue;
290 c = getc (infile);
291 if (c != 'A')
292 continue;
293 c = getc (infile);
294 if (c != 'R')
295 continue;
296 c = getc (infile);
297 if (c != '_')
298 continue;
300 defvarflag = 1;
301 defunflag = 0;
303 c = getc (infile);
304 defvarperbufferflag = (c == 'P');
306 c = getc (infile);
308 else if (c == 'D')
310 c = getc (infile);
311 if (c != 'E')
312 continue;
313 c = getc (infile);
314 if (c != 'F')
315 continue;
316 c = getc (infile);
317 defunflag = c == 'U';
318 defvarflag = 0;
320 else continue;
322 while (c != '(')
324 if (c < 0)
325 goto eof;
326 c = getc (infile);
329 c = getc (infile);
330 if (c != '"')
331 continue;
332 c = read_c_string (infile, -1);
334 if (defunflag)
335 commas = 5;
336 else if (defvarperbufferflag)
337 commas = 2;
338 else if (defvarflag)
339 commas = 1;
340 else /* For DEFSIMPLE and DEFPRED */
341 commas = 2;
343 while (commas)
345 if (c == ',')
347 commas--;
348 if (defunflag && (commas == 1 || commas == 2))
351 c = getc (infile);
352 while (c == ' ' || c == '\n' || c == '\t');
353 if (c < 0)
354 goto eof;
355 ungetc (c, infile);
356 if (commas == 2) /* pick up minargs */
357 fscanf (infile, "%d", &minargs);
358 else /* pick up maxargs */
359 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
360 maxargs = -1;
361 else
362 fscanf (infile, "%d", &maxargs);
365 if (c < 0)
366 goto eof;
367 c = getc (infile);
369 while (c == ' ' || c == '\n' || c == '\t')
370 c = getc (infile);
371 if (c == '"')
372 c = read_c_string (infile, 0);
373 while (c != ',')
374 c = getc (infile);
375 c = getc (infile);
376 while (c == ' ' || c == '\n' || c == '\t')
377 c = getc (infile);
379 if (c == '"')
381 putc (037, outfile);
382 putc (defvarflag ? 'V' : 'F', outfile);
383 fprintf (outfile, "%s\n", buf);
384 c = read_c_string (infile, 1);
386 /* If this is a defun, find the arguments and print them. If
387 this function takes MANY or UNEVALLED args, then the C source
388 won't give the names of the arguments, so we shouldn't bother
389 trying to find them. */
390 if (defunflag && maxargs != -1)
392 char argbuf[1024], *p = argbuf;
393 while (c != ')')
395 if (c < 0)
396 goto eof;
397 c = getc (infile);
399 /* Skip into arguments. */
400 while (c != '(')
402 if (c < 0)
403 goto eof;
404 c = getc (infile);
406 /* Copy arguments into ARGBUF. */
407 *p++ = c;
409 *p++ = c = getc (infile);
410 while (c != ')');
411 *p = '\0';
412 /* Output them. */
413 fprintf (outfile, "\n\n");
414 write_c_args (outfile, buf, argbuf, minargs, maxargs);
418 eof:
419 fclose (infile);
420 return 0;
423 /* Read a file of Lisp code, compiled or interpreted.
424 Looks for
425 (defun NAME ARGS DOCSTRING ...)
426 (defmacro NAME ARGS DOCSTRING ...)
427 (autoload (quote NAME) FILE DOCSTRING ...)
428 (defvar NAME VALUE DOCSTRING)
429 (defconst NAME VALUE DOCSTRING)
430 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
431 (fset (quote NAME) #[... DOCSTRING ...])
432 (defalias (quote NAME) #[... DOCSTRING ...])
433 starting in column zero.
434 (quote NAME) may appear as 'NAME as well.
435 For defun, defmacro, and autoload, we know how to skip over the arglist.
436 For defvar, defconst, and fset we skip to the docstring with a kludgy
437 formatting convention: all docstrings must appear on the same line as the
438 initial open-paren (the one in column zero) and must contain a backslash
439 and a double-quote immediately after the initial double-quote. No newlines
440 must appear between the beginning of the form and the first double-quote.
441 The only source file that must follow this convention is loaddefs.el; aside
442 from that, it is always the .elc file that we look at, and they are no
443 problem because byte-compiler output follows this convention.
444 The NAME and DOCSTRING are output.
445 NAME is preceded by `F' for a function or `V' for a variable.
446 An entry is output only if DOCSTRING has \ newline just after the opening "
449 void
450 skip_white (infile)
451 FILE *infile;
453 char c = ' ';
454 while (c == ' ' || c == '\t' || c == '\n')
455 c = getc (infile);
456 ungetc (c, infile);
459 void
460 read_lisp_symbol (infile, buffer)
461 FILE *infile;
462 char *buffer;
464 char c;
465 char *fillp = buffer;
467 skip_white (infile);
468 while (1)
470 c = getc (infile);
471 if (c == '\\')
472 *(++fillp) = getc (infile);
473 else if (c == ' ' || c == '\t' || c == '\n' || c == '(' || c == ')')
475 ungetc (c, infile);
476 *fillp = 0;
477 break;
479 else
480 *fillp++ = c;
483 if (! buffer[0])
484 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
486 skip_white (infile);
490 scan_lisp_file (filename, mode)
491 char *filename, *mode;
493 FILE *infile;
494 register int c;
496 infile = fopen (filename, mode);
497 if (infile == NULL)
499 perror (filename);
500 return 0; /* No error */
503 c = '\n';
504 while (!feof (infile))
506 char buffer [BUFSIZ];
507 char *fillp = buffer;
508 char type;
510 if (c != '\n')
512 c = getc (infile);
513 continue;
515 c = getc (infile);
516 if (c != '(')
517 continue;
519 read_lisp_symbol (infile, buffer);
521 if (! strcmp (buffer, "defun") ||
522 ! strcmp (buffer, "defmacro"))
524 type = 'F';
525 read_lisp_symbol (infile, buffer);
527 /* Skip the arguments: either "nil" or a list in parens */
529 c = getc (infile);
530 if (c == 'n') /* nil */
532 if ((c = getc (infile)) != 'i' ||
533 (c = getc (infile)) != 'l')
535 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
536 buffer, filename);
537 continue;
540 else if (c != '(')
542 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
543 buffer, filename);
544 continue;
546 else
547 while (c != ')')
548 c = getc (infile);
549 skip_white (infile);
551 /* If the next three characters aren't `dquote bslash newline'
552 then we're not reading a docstring.
554 if ((c = getc (infile)) != '"' ||
555 (c = getc (infile)) != '\\' ||
556 (c = getc (infile)) != '\n')
558 #ifdef DEBUG
559 fprintf (stderr, "## non-docstring in %s (%s)\n",
560 buffer, filename);
561 #endif
562 continue;
566 else if (! strcmp (buffer, "defvar") ||
567 ! strcmp (buffer, "defconst"))
569 char c1 = 0, c2 = 0;
570 type = 'V';
571 read_lisp_symbol (infile, buffer);
573 /* Skip until the first newline; remember the two previous chars. */
574 while (c != '\n' && c >= 0)
576 c2 = c1;
577 c1 = c;
578 c = getc (infile);
581 /* If two previous characters were " and \,
582 this is a doc string. Otherwise, there is none. */
583 if (c2 != '"' || c1 != '\\')
585 #ifdef DEBUG
586 fprintf (stderr, "## non-docstring in %s (%s)\n",
587 buffer, filename);
588 #endif
589 continue;
593 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
595 char c1 = 0, c2 = 0;
596 type = 'F';
598 c = getc (infile);
599 if (c == '\'')
600 read_lisp_symbol (infile, buffer);
601 else
603 if (c != '(')
605 fprintf (stderr, "## unparsable name in fset in %s\n",
606 filename);
607 continue;
609 read_lisp_symbol (infile, buffer);
610 if (strcmp (buffer, "quote"))
612 fprintf (stderr, "## unparsable name in fset in %s\n",
613 filename);
614 continue;
616 read_lisp_symbol (infile, buffer);
617 c = getc (infile);
618 if (c != ')')
620 fprintf (stderr,
621 "## unparsable quoted name in fset in %s\n",
622 filename);
623 continue;
627 /* Skip until the first newline; remember the two previous chars. */
628 while (c != '\n' && c >= 0)
630 c2 = c1;
631 c1 = c;
632 c = getc (infile);
635 /* If two previous characters were " and \,
636 this is a doc string. Otherwise, there is none. */
637 if (c2 != '"' || c1 != '\\')
639 #ifdef DEBUG
640 fprintf (stderr, "## non-docstring in %s (%s)\n",
641 buffer, filename);
642 #endif
643 continue;
647 else if (! strcmp (buffer, "autoload"))
649 type = 'F';
650 c = getc (infile);
651 if (c == '\'')
652 read_lisp_symbol (infile, buffer);
653 else
655 if (c != '(')
657 fprintf (stderr, "## unparsable name in autoload in %s\n",
658 filename);
659 continue;
661 read_lisp_symbol (infile, buffer);
662 if (strcmp (buffer, "quote"))
664 fprintf (stderr, "## unparsable name in autoload in %s\n",
665 filename);
666 continue;
668 read_lisp_symbol (infile, buffer);
669 c = getc (infile);
670 if (c != ')')
672 fprintf (stderr,
673 "## unparsable quoted name in autoload in %s\n",
674 filename);
675 continue;
678 skip_white (infile);
679 if ((c = getc (infile)) != '\"')
681 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
682 buffer, filename);
683 continue;
685 read_c_string (infile, 0);
686 skip_white (infile);
688 /* If the next three characters aren't `dquote bslash newline'
689 then we're not reading a docstring.
691 if ((c = getc (infile)) != '"' ||
692 (c = getc (infile)) != '\\' ||
693 (c = getc (infile)) != '\n')
695 #ifdef DEBUG
696 fprintf (stderr, "## non-docstring in %s (%s)\n",
697 buffer, filename);
698 #endif
699 continue;
703 #ifdef DEBUG
704 else if (! strcmp (buffer, "if") ||
705 ! strcmp (buffer, "byte-code"))
707 #endif
709 else
711 #ifdef DEBUG
712 fprintf (stderr, "## unrecognised top-level form, %s (%s)\n",
713 buffer, filename);
714 #endif
715 continue;
718 /* At this point, there is a docstring that we should gobble.
719 The opening quote (and leading backslash-newline) have already
720 been read.
722 putc (037, outfile);
723 putc (type, outfile);
724 fprintf (outfile, "%s\n", buffer);
725 read_c_string (infile, 1);
727 fclose (infile);
728 return 0;