All fsets changed to defaliases.
[emacs.git] / lib-src / make-docfile.c
blobc71fafb887bdd8e306ecd0ec0649c1c166e16043
1 /* Generate doc-string file for GNU Emacs from source files.
2 Copyright (C) 1985, 1986, 1992 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>
36 FILE *outfile;
38 main (argc, argv)
39 int argc;
40 char **argv;
42 int i;
43 int err_count = 0;
45 outfile = stdout;
47 /* If first two args are -o FILE, output to FILE. */
48 i = 1;
49 if (argc > i + 1 && !strcmp (argv[i], "-o"))
51 outfile = fopen (argv[i + 1], "w");
52 i += 2;
54 if (argc > i + 1 && !strcmp (argv[i], "-a"))
56 outfile = fopen (argv[i + 1], "a");
57 i += 2;
60 for (; i < argc; i++)
61 err_count += scan_file (argv[i]); /* err_count seems to be {mis,un}used */
62 #ifndef VMS
63 exit (err_count); /* see below - shane */
64 #endif VMS
67 /* Read file FILENAME and output its doc strings to outfile. */
68 /* Return 1 if file is not found, 0 if it is found. */
70 scan_file (filename)
71 char *filename;
73 int len = strlen (filename);
74 if (!strcmp (filename + len - 4, ".elc"))
75 return scan_lisp_file (filename);
76 else if (!strcmp (filename + len - 3, ".el"))
77 return scan_lisp_file (filename);
78 else
79 return scan_c_file (filename);
82 char buf[128];
84 /* Skip a C string from INFILE,
85 and return the character that follows the closing ".
86 If printflag is positive, output string contents to outfile.
87 If it is negative, store contents in buf.
88 Convert escape sequences \n and \t to newline and tab;
89 discard \ followed by newline. */
91 read_c_string (infile, printflag)
92 FILE *infile;
93 int printflag;
95 register int c;
96 char *p = buf;
98 c = getc (infile);
99 while (c != EOF)
101 while (c != '"' && c != EOF)
103 if (c == '\\')
105 c = getc (infile);
106 if (c == '\n')
108 c = getc (infile);
109 continue;
111 if (c == 'n')
112 c = '\n';
113 if (c == 't')
114 c = '\t';
116 if (printflag > 0)
117 putc (c, outfile);
118 else if (printflag < 0)
119 *p++ = c;
120 c = getc (infile);
122 c = getc (infile);
123 if (c != '"')
124 break;
125 if (printflag > 0)
126 putc (c, outfile);
127 else if (printflag < 0)
128 *p++ = c;
129 c = getc (infile);
132 if (printflag < 0)
133 *p = 0;
135 return c;
138 /* Write to file OUT the argument names of the function whose text is in BUF.
139 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
141 write_c_args (out, buf, minargs, maxargs)
142 FILE *out;
143 char *buf;
144 int minargs, maxargs;
146 register char *p;
147 int in_ident = 0;
148 int just_spaced = 0;
150 fprintf (out, "arguments: ");
152 for (p = buf; *p; p++)
154 char c = *p;
155 int ident_start = 0;
157 /* Notice when we start printing a new identifier. */
158 if ((('A' <= c && c <= 'Z')
159 || ('a' <= c && c <= 'z')
160 || ('0' <= c && c <= '9')
161 || c == '_')
162 != in_ident)
164 if (!in_ident)
166 in_ident = 1;
167 ident_start = 1;
169 if (minargs == 0 && maxargs > 0)
170 fprintf (out, "&optional ");
171 just_spaced = 1;
173 minargs--;
174 maxargs--;
176 else
177 in_ident = 0;
180 /* Print the C argument list as it would appear in lisp:
181 print underscores as hyphens, and print commas as spaces.
182 Collapse adjacent spaces into one. */
183 if (c == '_') c = '-';
184 if (c == ',') c = ' ';
186 /* In C code, `default' is a reserved word, so we spell it
187 `defalt'; unmangle that here. */
188 if (ident_start
189 && strncmp (p, "defalt", 6) == 0
190 && ! (('A' <= p[6] && p[6] <= 'Z')
191 || ('a' <= p[6] && p[6] <= 'z')
192 || ('0' <= p[6] && p[6] <= '9')
193 || p[6] == '_'))
195 fprintf (out, "default");
196 p += 5;
197 in_ident = 0;
198 just_spaced = 0;
200 else if (c != ' ' || ! just_spaced)
201 putc (c, out);
203 just_spaced = (c == ' ');
207 /* Read through a c file. If a .o file is named,
208 the corresponding .c file is read instead.
209 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
210 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
212 scan_c_file (filename)
213 char *filename;
215 FILE *infile;
216 register int c;
217 register int commas;
218 register int defunflag;
219 register int defvarperbufferflag;
220 register int defvarflag;
221 int minargs, maxargs;
223 if (filename[strlen (filename) - 1] == 'o')
224 filename[strlen (filename) - 1] = 'c';
226 infile = fopen (filename, "r");
228 /* No error if non-ex input file */
229 if (infile == NULL)
231 perror (filename);
232 return 0;
235 c = '\n';
236 while (!feof (infile))
238 if (c != '\n')
240 c = getc (infile);
241 continue;
243 c = getc (infile);
244 if (c == ' ')
246 while (c == ' ')
247 c = getc (infile);
248 if (c != 'D')
249 continue;
250 c = getc (infile);
251 if (c != 'E')
252 continue;
253 c = getc (infile);
254 if (c != 'F')
255 continue;
256 c = getc (infile);
257 if (c != 'V')
258 continue;
259 c = getc (infile);
260 if (c != 'A')
261 continue;
262 c = getc (infile);
263 if (c != 'R')
264 continue;
265 c = getc (infile);
266 if (c != '_')
267 continue;
269 defvarflag = 1;
270 defunflag = 0;
272 c = getc (infile);
273 defvarperbufferflag = (c == 'P');
275 c = getc (infile);
277 else if (c == 'D')
279 c = getc (infile);
280 if (c != 'E')
281 continue;
282 c = getc (infile);
283 if (c != 'F')
284 continue;
285 c = getc (infile);
286 defunflag = c == 'U';
287 defvarflag = 0;
289 else continue;
291 while (c != '(')
293 if (c < 0)
294 goto eof;
295 c = getc (infile);
298 c = getc (infile);
299 if (c != '"')
300 continue;
301 c = read_c_string (infile, -1);
303 if (defunflag)
304 commas = 5;
305 else if (defvarperbufferflag)
306 commas = 2;
307 else if (defvarflag)
308 commas = 1;
309 else /* For DEFSIMPLE and DEFPRED */
310 commas = 2;
312 while (commas)
314 if (c == ',')
316 commas--;
317 if (defunflag && (commas == 1 || commas == 2))
320 c = getc (infile);
321 while (c == ' ' || c == '\n' || c == '\t');
322 if (c < 0)
323 goto eof;
324 ungetc (c, infile);
325 if (commas == 2) /* pick up minargs */
326 fscanf (infile, "%d", &minargs);
327 else /* pick up maxargs */
328 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
329 maxargs = -1;
330 else
331 fscanf (infile, "%d", &maxargs);
334 if (c < 0)
335 goto eof;
336 c = getc (infile);
338 while (c == ' ' || c == '\n' || c == '\t')
339 c = getc (infile);
340 if (c == '"')
341 c = read_c_string (infile, 0);
342 while (c != ',')
343 c = getc (infile);
344 c = getc (infile);
345 while (c == ' ' || c == '\n' || c == '\t')
346 c = getc (infile);
348 if (c == '"')
350 putc (037, outfile);
351 putc (defvarflag ? 'V' : 'F', outfile);
352 fprintf (outfile, "%s\n", buf);
353 c = read_c_string (infile, 1);
355 /* If this is a defun, find the arguments and print them. If
356 this function takes MANY or UNEVALLED args, then the C source
357 won't give the names of the arguments, so we shouldn't bother
358 trying to find them. */
359 if (defunflag && maxargs != -1)
361 char argbuf[1024], *p = argbuf;
362 while (c != ')')
364 if (c < 0)
365 goto eof;
366 c = getc (infile);
368 /* Skip into arguments. */
369 while (c != '(')
371 if (c < 0)
372 goto eof;
373 c = getc (infile);
375 /* Copy arguments into ARGBUF. */
376 *p++ = c;
378 *p++ = c = getc (infile);
379 while (c != ')');
380 *p = '\0';
381 /* Output them. */
382 fprintf (outfile, "\n\n");
383 write_c_args (outfile, argbuf, minargs, maxargs);
387 eof:
388 fclose (infile);
389 return 0;
392 /* Read a file of Lisp code, compiled or interpreted.
393 Looks for
394 (defun NAME ARGS DOCSTRING ...)
395 (defmacro NAME ARGS DOCSTRING ...)
396 (autoload (quote NAME) FILE DOCSTRING ...)
397 (defvar NAME VALUE DOCSTRING)
398 (defconst NAME VALUE DOCSTRING)
399 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
400 (fset (quote NAME) #[... DOCSTRING ...])
401 starting in column zero.
402 (quote NAME) may appear as 'NAME as well.
403 For defun, defmacro, and autoload, we know how to skip over the arglist.
404 For defvar, defconst, and fset we skip to the docstring with a klugey
405 formatting convention: all docstrings must appear on the same line as the
406 initial open-paren (the one in column zero) and must contain a backslash
407 and a double-quote immediately after the initial double-quote. No newlines
408 must appear between the beginning of the form and the first double-quote.
409 The only source file that must follow this convention is loaddefs.el; aside
410 from that, it is always the .elc file that we look at, and they are no
411 problem because byte-compiler output follows this convention.
412 The NAME and DOCSTRING are output.
413 NAME is preceded by `F' for a function or `V' for a variable.
414 An entry is output only if DOCSTRING has \ newline just after the opening "
417 void
418 skip_white (infile)
419 FILE *infile;
421 char c = ' ';
422 while (c == ' ' || c == '\t' || c == '\n')
423 c = getc (infile);
424 ungetc (c, infile);
427 void
428 read_lisp_symbol (infile, buffer)
429 FILE *infile;
430 char *buffer;
432 char c;
433 char *fillp = buffer;
435 skip_white (infile);
436 while (1)
438 c = getc (infile);
439 if (c == '\\')
440 *(++fillp) = getc (infile);
441 else if (c == ' ' || c == '\t' || c == '\n' || c == '(' || c == ')')
443 ungetc (c, infile);
444 *fillp = 0;
445 break;
447 else
448 *fillp++ = c;
451 if (! buffer[0])
452 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
454 skip_white (infile);
458 scan_lisp_file (filename)
459 char *filename;
461 FILE *infile;
462 register int c;
464 infile = fopen (filename, "r");
465 if (infile == NULL)
467 perror (filename);
468 return 0; /* No error */
471 c = '\n';
472 while (!feof (infile))
474 char buffer [BUFSIZ];
475 char *fillp = buffer;
476 char type;
478 if (c != '\n')
480 c = getc (infile);
481 continue;
483 c = getc (infile);
484 if (c != '(')
485 continue;
487 read_lisp_symbol (infile, buffer);
489 if (! strcmp (buffer, "defun") ||
490 ! strcmp (buffer, "defmacro"))
492 type = 'F';
493 read_lisp_symbol (infile, buffer);
495 /* Skip the arguments: either "nil" or a list in parens */
497 c = getc (infile);
498 if (c == 'n') /* nil */
500 if ((c = getc (infile)) != 'i' ||
501 (c = getc (infile)) != 'l')
503 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
504 buffer, filename);
505 continue;
508 else if (c != '(')
510 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
511 buffer, filename);
512 continue;
514 else
515 while (c != ')')
516 c = getc (infile);
517 skip_white (infile);
519 /* If the next three characters aren't `dquote bslash newline'
520 then we're not reading a docstring.
522 if ((c = getc (infile)) != '"' ||
523 (c = getc (infile)) != '\\' ||
524 (c = getc (infile)) != '\n')
526 #ifdef DEBUG
527 fprintf (stderr, "## non-docstring in %s (%s)\n",
528 buffer, filename);
529 #endif
530 continue;
534 else if (! strcmp (buffer, "defvar") ||
535 ! strcmp (buffer, "defconst"))
537 char c1 = 0, c2 = 0;
538 type = 'V';
539 read_lisp_symbol (infile, buffer);
541 /* Skip until the first newline; remember the two previous chars. */
542 while (c != '\n' && c >= 0)
544 c2 = c1;
545 c1 = c;
546 c = getc (infile);
549 /* If two previous characters were " and \,
550 this is a doc string. Otherwise, there is none. */
551 if (c2 != '"' || c1 != '\\')
553 #ifdef DEBUG
554 fprintf (stderr, "## non-docstring in %s (%s)\n",
555 buffer, filename);
556 #endif
557 continue;
561 else if (! strcmp (buffer, "fset"))
563 char c1 = 0, c2 = 0;
564 type = 'F';
566 c = getc (infile);
567 if (c == '\'')
568 read_lisp_symbol (infile, buffer);
569 else
571 if (c != '(')
573 fprintf (stderr, "## unparsable name in fset in %s\n",
574 filename);
575 continue;
577 read_lisp_symbol (infile, buffer);
578 if (strcmp (buffer, "quote"))
580 fprintf (stderr, "## unparsable name in fset in %s\n",
581 filename);
582 continue;
584 read_lisp_symbol (infile, buffer);
585 c = getc (infile);
586 if (c != ')')
588 fprintf (stderr,
589 "## unparsable quoted name in fset in %s\n",
590 filename);
591 continue;
595 /* Skip until the first newline; remember the two previous chars. */
596 while (c != '\n' && c >= 0)
598 c2 = c1;
599 c1 = c;
600 c = getc (infile);
603 /* If two previous characters were " and \,
604 this is a doc string. Otherwise, there is none. */
605 if (c2 != '"' || c1 != '\\')
607 #ifdef DEBUG
608 fprintf (stderr, "## non-docstring in %s (%s)\n",
609 buffer, filename);
610 #endif
611 continue;
615 else if (! strcmp (buffer, "autoload"))
617 type = 'F';
618 c = getc (infile);
619 if (c == '\'')
620 read_lisp_symbol (infile, buffer);
621 else
623 if (c != '(')
625 fprintf (stderr, "## unparsable name in autoload in %s\n",
626 filename);
627 continue;
629 read_lisp_symbol (infile, buffer);
630 if (strcmp (buffer, "quote"))
632 fprintf (stderr, "## unparsable name in autoload in %s\n",
633 filename);
634 continue;
636 read_lisp_symbol (infile, buffer);
637 c = getc (infile);
638 if (c != ')')
640 fprintf (stderr,
641 "## unparsable quoted name in autoload in %s\n",
642 filename);
643 continue;
646 skip_white (infile);
647 if ((c = getc (infile)) != '\"')
649 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
650 buffer, filename);
651 continue;
653 read_c_string (infile, 0);
654 skip_white (infile);
656 /* If the next three characters aren't `dquote bslash newline'
657 then we're not reading a docstring.
659 if ((c = getc (infile)) != '"' ||
660 (c = getc (infile)) != '\\' ||
661 (c = getc (infile)) != '\n')
663 #ifdef DEBUG
664 fprintf (stderr, "## non-docstring in %s (%s)\n",
665 buffer, filename);
666 #endif
667 continue;
671 #ifdef DEBUG
672 else if (! strcmp (buffer, "if") ||
673 ! strcmp (buffer, "byte-code"))
675 #endif
677 else
679 #ifdef DEBUG
680 fprintf (stderr, "## unrecognised top-level form, %s (%s)\n",
681 buffer, filename);
682 #endif
683 continue;
686 /* At this point, there is a docstring that we should gobble.
687 The opening quote (and leading backslash-newline) have already
688 been read.
690 putc ('\n', outfile);
691 putc (037, outfile);
692 putc (type, outfile);
693 fprintf (outfile, "%s\n", buffer);
694 read_c_string (infile, 1);
696 fclose (infile);
697 return 0;