* Makefile.in (exec_prefix): New variable.
[bpt/emacs.git] / lib-src / make-docfile.c
CommitLineData
f2cc4248 1/* Generate doc-string file for GNU Emacs from source files.
e065a56e 2 Copyright (C) 1985, 1986, 1992 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>
35
36FILE *outfile;
37
38main (argc, argv)
39 int argc;
40 char **argv;
41{
42 int i;
43 int err_count = 0;
44
45 outfile = stdout;
46
47 /* If first two args are -o FILE, output to FILE. */
48 i = 1;
49 if (argc > i + 1 && !strcmp (argv[i], "-o"))
50 {
51 outfile = fopen (argv[i + 1], "w");
52 i += 2;
53 }
54 if (argc > i + 1 && !strcmp (argv[i], "-a"))
55 {
56 outfile = fopen (argv[i + 1], "a");
57 i += 2;
58 }
59
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
65}
66
a8a7afbe 67/* Read file FILENAME and output its doc strings to outfile. */
f2cc4248
RS
68/* Return 1 if file is not found, 0 if it is found. */
69
70scan_file (filename)
71 char *filename;
72{
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);
80}
81\f
82char buf[128];
83
84/* Skip a C string from INFILE,
85 and return the character that follows the closing ".
a8a7afbe 86 If printflag is positive, output string contents to outfile.
f2cc4248
RS
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. */
90
91read_c_string (infile, printflag)
92 FILE *infile;
93 int printflag;
94{
95 register int c;
96 char *p = buf;
97
98 c = getc (infile);
99 while (c != EOF)
100 {
101 while (c != '"' && c != EOF)
102 {
103 if (c == '\\')
104 {
105 c = getc (infile);
106 if (c == '\n')
107 {
108 c = getc (infile);
109 continue;
110 }
111 if (c == 'n')
112 c = '\n';
113 if (c == 't')
114 c = '\t';
115 }
116 if (printflag > 0)
117 putc (c, outfile);
118 else if (printflag < 0)
119 *p++ = c;
120 c = getc (infile);
121 }
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);
130 }
131
132 if (printflag < 0)
133 *p = 0;
134
135 return c;
136}
137\f
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. */
140
141write_c_args (out, buf, minargs, maxargs)
142 FILE *out;
143 char *buf;
144 int minargs, maxargs;
145{
f125a9e8 146 register char *p;
30e4c427
JB
147 int in_ident = 0;
148 int just_spaced = 0;
f2cc4248 149
772e2009 150 fprintf (out, "arguments: ");
f2cc4248 151
f125a9e8 152 for (p = buf; *p; p++)
f2cc4248 153 {
30e4c427
JB
154 char c = *p;
155
156 /* Notice when we start printing a new identifier. */
157 if ((('A' <= c && c <= 'Z')
158 || ('a' <= c && c <= 'z')
159 || ('0' <= c && c <= '9')
160 || c == '_')
161 != in_ident)
f2cc4248 162 {
30e4c427
JB
163 if (!in_ident)
164 {
165 in_ident = 1;
f125a9e8 166
30e4c427
JB
167 if (minargs == 0 && maxargs > 0)
168 fprintf (out, "&optional ");
169 just_spaced = 1;
f125a9e8 170
30e4c427
JB
171 minargs--;
172 maxargs--;
173 }
174 else
175 in_ident = 0;
f2cc4248 176 }
30e4c427
JB
177
178 /* Print the C argument list as it would appear in lisp:
179 print underscores as hyphens, and print commas as spaces.
180 Collapse adjacent spaces into one. */
181 if (c == '_') c = '-';
182 if (c == ',') c = ' ';
183
184 if (c != ' ' || ! just_spaced)
185 putc (c, out);
186
187 just_spaced = (c == ' ');
f2cc4248 188 }
f2cc4248
RS
189}
190\f
191/* Read through a c file. If a .o file is named,
192 the corresponding .c file is read instead.
193 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
194 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
195
196scan_c_file (filename)
197 char *filename;
198{
199 FILE *infile;
200 register int c;
201 register int commas;
202 register int defunflag;
203 register int defvarflag;
204 int minargs, maxargs;
205
206 if (filename[strlen (filename) - 1] == 'o')
207 filename[strlen (filename) - 1] = 'c';
208
209 infile = fopen (filename, "r");
210
211 /* No error if non-ex input file */
212 if (infile == NULL)
213 {
214 perror (filename);
215 return 0;
216 }
217
218 c = '\n';
219 while (!feof (infile))
220 {
221 if (c != '\n')
222 {
223 c = getc (infile);
224 continue;
225 }
226 c = getc (infile);
227 if (c == ' ')
228 {
229 while (c == ' ')
230 c = getc (infile);
231 if (c != 'D')
232 continue;
233 c = getc (infile);
234 if (c != 'E')
235 continue;
236 c = getc (infile);
237 if (c != 'F')
238 continue;
239 c = getc (infile);
240 if (c != 'V')
241 continue;
242 defvarflag = 1;
243 defunflag = 0;
244 c = getc (infile);
245 }
246 else if (c == 'D')
247 {
248 c = getc (infile);
249 if (c != 'E')
250 continue;
251 c = getc (infile);
252 if (c != 'F')
253 continue;
254 c = getc (infile);
255 defunflag = c == 'U';
256 defvarflag = 0;
257 }
258 else continue;
259
260 while (c != '(')
261 {
262 if (c < 0)
263 goto eof;
264 c = getc (infile);
265 }
266
267 c = getc (infile);
268 if (c != '"')
269 continue;
270 c = read_c_string (infile, -1);
271
272 if (defunflag)
273 commas = 5;
274 else if (defvarflag)
275 commas = 1;
276 else /* For DEFSIMPLE and DEFPRED */
277 commas = 2;
278
279 while (commas)
280 {
281 if (c == ',')
282 {
283 commas--;
284 if (defunflag && (commas == 1 || commas == 2))
285 {
286 do
287 c = getc (infile);
288 while (c == ' ' || c == '\n' || c == '\t');
289 if (c < 0)
290 goto eof;
291 ungetc (c, infile);
292 if (commas == 2) /* pick up minargs */
293 fscanf (infile, "%d", &minargs);
294 else /* pick up maxargs */
295 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
296 maxargs = -1;
297 else
298 fscanf (infile, "%d", &maxargs);
299 }
300 }
301 if (c < 0)
302 goto eof;
303 c = getc (infile);
304 }
305 while (c == ' ' || c == '\n' || c == '\t')
306 c = getc (infile);
307 if (c == '"')
308 c = read_c_string (infile, 0);
309 while (c != ',')
310 c = getc (infile);
311 c = getc (infile);
312 while (c == ' ' || c == '\n' || c == '\t')
313 c = getc (infile);
314
315 if (c == '"')
316 {
317 putc (037, outfile);
318 putc (defvarflag ? 'V' : 'F', outfile);
319 fprintf (outfile, "%s\n", buf);
772e2009
JB
320 c = read_c_string (infile, 1);
321
322 /* If this is a defun, find the arguments and print them. If
323 this function takes MANY or UNEVALLED args, then the C source
324 won't give the names of the arguments, so we shouldn't bother
325 trying to find them. */
326 if (defunflag && maxargs != -1)
f2cc4248
RS
327 {
328 char argbuf[1024], *p = argbuf;
329 while (c != ')')
330 {
331 if (c < 0)
332 goto eof;
333 c = getc (infile);
334 }
335 /* Skip into arguments. */
336 while (c != '(')
337 {
338 if (c < 0)
339 goto eof;
340 c = getc (infile);
341 }
342 /* Copy arguments into ARGBUF. */
343 *p++ = c;
344 do
345 *p++ = c = getc (infile);
346 while (c != ')');
347 *p = '\0';
348 /* Output them. */
349 fprintf (outfile, "\n\n");
350 write_c_args (outfile, argbuf, minargs, maxargs);
351 }
352 }
353 }
354 eof:
355 fclose (infile);
356 return 0;
357}
358\f
359/* Read a file of Lisp code, compiled or interpreted.
360 Looks for
361 (defun NAME ARGS DOCSTRING ...)
23d6b5a6
JB
362 (defmacro NAME ARGS DOCSTRING ...)
363 (autoload (quote NAME) FILE DOCSTRING ...)
f2cc4248
RS
364 (defvar NAME VALUE DOCSTRING)
365 (defconst NAME VALUE DOCSTRING)
23d6b5a6
JB
366 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
367 (fset (quote NAME) #[... DOCSTRING ...])
f2cc4248 368 starting in column zero.
23d6b5a6
JB
369 (quote NAME) may appear as 'NAME as well.
370 For defun, defmacro, and autoload, we know how to skip over the arglist.
371 For defvar, defconst, and fset we skip to the docstring with a klugey
372 formatting convention: all docstrings must appear on the same line as the
373 initial open-paren (the one in column zero) and must contain a backslash
374 and a double-quote immediately after the initial double-quote. No newlines
375 must appear between the beginning of the form and the first double-quote.
376 The only source file that must follow this convention is loaddefs.el; aside
377 from that, it is always the .elc file that we look at, and they are no
378 problem because byte-compiler output follows this convention.
f2cc4248
RS
379 The NAME and DOCSTRING are output.
380 NAME is preceded by `F' for a function or `V' for a variable.
381 An entry is output only if DOCSTRING has \ newline just after the opening "
382 */
383
23d6b5a6
JB
384void
385skip_white (infile)
386 FILE *infile;
387{
388 char c = ' ';
389 while (c == ' ' || c == '\t' || c == '\n')
390 c = getc (infile);
391 ungetc (c, infile);
392}
393
394void
395read_lisp_symbol (infile, buffer)
396 FILE *infile;
397 char *buffer;
398{
399 char c;
400 char *fillp = buffer;
401
402 skip_white (infile);
403 while (1)
404 {
405 c = getc (infile);
406 if (c == '\\')
407 *(++fillp) = getc (infile);
408 else if (c == ' ' || c == '\t' || c == '\n' || c == '(' || c == ')')
409 {
410 ungetc (c, infile);
411 *fillp = 0;
412 break;
413 }
414 else
415 *fillp++ = c;
416 }
417
418 if (! buffer[0])
419 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
420
421 skip_white (infile);
422}
423
424
f2cc4248
RS
425scan_lisp_file (filename)
426 char *filename;
427{
428 FILE *infile;
429 register int c;
f2cc4248
RS
430
431 infile = fopen (filename, "r");
432 if (infile == NULL)
433 {
434 perror (filename);
435 return 0; /* No error */
436 }
437
438 c = '\n';
439 while (!feof (infile))
440 {
23d6b5a6
JB
441 char buffer [BUFSIZ];
442 char *fillp = buffer;
443 char type;
444
f2cc4248
RS
445 if (c != '\n')
446 {
447 c = getc (infile);
448 continue;
449 }
450 c = getc (infile);
451 if (c != '(')
452 continue;
a8a7afbe 453
23d6b5a6
JB
454 read_lisp_symbol (infile, buffer);
455
456 if (! strcmp (buffer, "defun") ||
457 ! strcmp (buffer, "defmacro"))
f2cc4248 458 {
23d6b5a6
JB
459 type = 'F';
460 read_lisp_symbol (infile, buffer);
f2cc4248 461
23d6b5a6 462 /* Skip the arguments: either "nil" or a list in parens */
f2cc4248 463
23d6b5a6
JB
464 c = getc (infile);
465 if (c == 'n') /* nil */
f2cc4248 466 {
23d6b5a6
JB
467 if ((c = getc (infile)) != 'i' ||
468 (c = getc (infile)) != 'l')
469 {
470 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
471 buffer, filename);
472 continue;
473 }
f2cc4248 474 }
23d6b5a6 475 else if (c != '(')
f2cc4248 476 {
23d6b5a6
JB
477 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
478 buffer, filename);
479 continue;
f2cc4248 480 }
23d6b5a6
JB
481 else
482 while (c != ')')
f2cc4248 483 c = getc (infile);
23d6b5a6
JB
484 skip_white (infile);
485
486 /* If the next three characters aren't `dquote bslash newline'
487 then we're not reading a docstring.
488 */
489 if ((c = getc (infile)) != '"' ||
490 (c = getc (infile)) != '\\' ||
491 (c = getc (infile)) != '\n')
f2cc4248 492 {
23d6b5a6
JB
493#ifdef DEBUG
494 fprintf (stderr, "## non-docstring in %s (%s)\n",
495 buffer, filename);
496#endif
497 continue;
f2cc4248 498 }
f2cc4248 499 }
a8a7afbe 500
23d6b5a6
JB
501 else if (! strcmp (buffer, "defvar") ||
502 ! strcmp (buffer, "defconst"))
f2cc4248 503 {
23d6b5a6
JB
504 char c1 = 0, c2 = 0;
505 type = 'V';
506 read_lisp_symbol (infile, buffer);
a8a7afbe 507
23d6b5a6
JB
508 /* Skip until the first newline; remember the two previous chars. */
509 while (c != '\n' && c >= 0)
f2cc4248 510 {
23d6b5a6
JB
511 c2 = c1;
512 c1 = c;
f2cc4248 513 c = getc (infile);
f2cc4248 514 }
23d6b5a6
JB
515
516 /* If two previous characters were " and \,
517 this is a doc string. Otherwise, there is none. */
518 if (c2 != '"' || c1 != '\\')
f2cc4248 519 {
23d6b5a6
JB
520#ifdef DEBUG
521 fprintf (stderr, "## non-docstring in %s (%s)\n",
522 buffer, filename);
523#endif
524 continue;
f2cc4248 525 }
23d6b5a6
JB
526 }
527
528 else if (! strcmp (buffer, "fset"))
529 {
530 char c1 = 0, c2 = 0;
531 type = 'F';
a8a7afbe 532
23d6b5a6
JB
533 c = getc (infile);
534 if (c == '\'')
535 read_lisp_symbol (infile, buffer);
536 else
f2cc4248 537 {
23d6b5a6
JB
538 if (c != '(')
539 {
540 fprintf (stderr, "## unparsable name in fset in %s\n",
541 filename);
542 continue;
543 }
544 read_lisp_symbol (infile, buffer);
545 if (strcmp (buffer, "quote"))
546 {
547 fprintf (stderr, "## unparsable name in fset in %s\n",
548 filename);
549 continue;
550 }
551 read_lisp_symbol (infile, buffer);
f2cc4248 552 c = getc (infile);
23d6b5a6
JB
553 if (c != ')')
554 {
555 fprintf (stderr,
556 "## unparsable quoted name in fset in %s\n",
557 filename);
558 continue;
559 }
f2cc4248 560 }
f2cc4248 561
23d6b5a6
JB
562 /* Skip until the first newline; remember the two previous chars. */
563 while (c != '\n' && c >= 0)
f2cc4248 564 {
23d6b5a6
JB
565 c2 = c1;
566 c1 = c;
f2cc4248
RS
567 c = getc (infile);
568 }
23d6b5a6
JB
569
570 /* If two previous characters were " and \,
571 this is a doc string. Otherwise, there is none. */
572 if (c2 != '"' || c1 != '\\')
573 {
574#ifdef DEBUG
575 fprintf (stderr, "## non-docstring in %s (%s)\n",
576 buffer, filename);
577#endif
578 continue;
579 }
580 }
f2cc4248 581
23d6b5a6
JB
582 else if (! strcmp (buffer, "autoload"))
583 {
584 type = 'F';
585 c = getc (infile);
586 if (c == '\'')
587 read_lisp_symbol (infile, buffer);
588 else
f2cc4248 589 {
23d6b5a6 590 if (c != '(')
f2cc4248 591 {
23d6b5a6
JB
592 fprintf (stderr, "## unparsable name in autoload in %s\n",
593 filename);
594 continue;
f2cc4248 595 }
23d6b5a6
JB
596 read_lisp_symbol (infile, buffer);
597 if (strcmp (buffer, "quote"))
f2cc4248 598 {
23d6b5a6
JB
599 fprintf (stderr, "## unparsable name in autoload in %s\n",
600 filename);
601 continue;
f2cc4248 602 }
23d6b5a6 603 read_lisp_symbol (infile, buffer);
f2cc4248 604 c = getc (infile);
23d6b5a6 605 if (c != ')')
f2cc4248 606 {
23d6b5a6
JB
607 fprintf (stderr,
608 "## unparsable quoted name in autoload in %s\n",
609 filename);
610 continue;
f2cc4248 611 }
23d6b5a6
JB
612 }
613 skip_white (infile);
614 if ((c = getc (infile)) != '\"')
615 {
616 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
617 buffer, filename);
f2cc4248
RS
618 continue;
619 }
23d6b5a6
JB
620 read_c_string (infile, 0);
621 skip_white (infile);
622
623 /* If the next three characters aren't `dquote bslash newline'
624 then we're not reading a docstring.
625 */
626 if ((c = getc (infile)) != '"' ||
627 (c = getc (infile)) != '\\' ||
628 (c = getc (infile)) != '\n')
a8a7afbe 629 {
23d6b5a6
JB
630#ifdef DEBUG
631 fprintf (stderr, "## non-docstring in %s (%s)\n",
632 buffer, filename);
633#endif
634 continue;
a8a7afbe 635 }
a8a7afbe 636 }
f2cc4248 637
23d6b5a6
JB
638#ifdef DEBUG
639 else if (! strcmp (buffer, "if") ||
640 ! strcmp (buffer, "byte-code"))
641 ;
642#endif
f2cc4248 643
23d6b5a6
JB
644 else
645 {
646#ifdef DEBUG
647 fprintf (stderr, "## unrecognised top-level form, %s (%s)\n",
648 buffer, filename);
649#endif
650 continue;
651 }
f2cc4248 652
23d6b5a6
JB
653 /* At this point, there is a docstring that we should gobble.
654 The opening quote (and leading backslash-newline) have already
655 been read.
656 */
657 putc ('\n', outfile);
f2cc4248 658 putc (037, outfile);
23d6b5a6
JB
659 putc (type, outfile);
660 fprintf (outfile, "%s\n", buffer);
f2cc4248
RS
661 read_c_string (infile, 1);
662 }
663 fclose (infile);
664 return 0;
665}