]> code.delx.au - gnu-emacs/blob - lib-src/make-docfile.c
*** empty log message ***
[gnu-emacs] / lib-src / make-docfile.c
1 /* Generate doc-string file for GNU Emacs from source files.
2 Copyright (C) 1985, 1986 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 1, 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
36 FILE *outfile;
37
38 main (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
67 /* Read file FILENAME and output its doc strings to outfile. */
68 /* Return 1 if file is not found, 0 if it is found. */
69
70 scan_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
82 char buf[128];
83
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. */
90
91 read_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
141 write_c_args (out, buf, minargs, maxargs)
142 FILE *out;
143 char *buf;
144 int minargs, maxargs;
145 {
146 register int c;
147 register char *p = buf;
148 int space = 0;
149
150 fprintf (out, "arguments: ");
151
152 while (*p)
153 {
154 c = *p++;
155 if (c == ',')
156 {
157 minargs--;
158 maxargs--;
159 if (!space)
160 putc (' ', out);
161 if (minargs == 0 && maxargs > 0)
162 fprintf (out, "&optional ");
163 space = 1;
164 continue;
165 }
166 else if (c == ' ' && space)
167 continue;
168 space = (c == ' ');
169 putc (c, out);
170 }
171 putc ('\n', out);
172 }
173 \f
174 /* Read through a c file. If a .o file is named,
175 the corresponding .c file is read instead.
176 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
177 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
178
179 scan_c_file (filename)
180 char *filename;
181 {
182 FILE *infile;
183 register int c;
184 register int commas;
185 register int defunflag;
186 register int defvarflag;
187 int minargs, maxargs;
188
189 if (filename[strlen (filename) - 1] == 'o')
190 filename[strlen (filename) - 1] = 'c';
191
192 infile = fopen (filename, "r");
193
194 /* No error if non-ex input file */
195 if (infile == NULL)
196 {
197 perror (filename);
198 return 0;
199 }
200
201 c = '\n';
202 while (!feof (infile))
203 {
204 if (c != '\n')
205 {
206 c = getc (infile);
207 continue;
208 }
209 c = getc (infile);
210 if (c == ' ')
211 {
212 while (c == ' ')
213 c = getc (infile);
214 if (c != 'D')
215 continue;
216 c = getc (infile);
217 if (c != 'E')
218 continue;
219 c = getc (infile);
220 if (c != 'F')
221 continue;
222 c = getc (infile);
223 if (c != 'V')
224 continue;
225 defvarflag = 1;
226 defunflag = 0;
227 c = getc (infile);
228 }
229 else if (c == 'D')
230 {
231 c = getc (infile);
232 if (c != 'E')
233 continue;
234 c = getc (infile);
235 if (c != 'F')
236 continue;
237 c = getc (infile);
238 defunflag = c == 'U';
239 defvarflag = 0;
240 }
241 else continue;
242
243 while (c != '(')
244 {
245 if (c < 0)
246 goto eof;
247 c = getc (infile);
248 }
249
250 c = getc (infile);
251 if (c != '"')
252 continue;
253 c = read_c_string (infile, -1);
254
255 if (defunflag)
256 commas = 5;
257 else if (defvarflag)
258 commas = 1;
259 else /* For DEFSIMPLE and DEFPRED */
260 commas = 2;
261
262 while (commas)
263 {
264 if (c == ',')
265 {
266 commas--;
267 if (defunflag && (commas == 1 || commas == 2))
268 {
269 do
270 c = getc (infile);
271 while (c == ' ' || c == '\n' || c == '\t');
272 if (c < 0)
273 goto eof;
274 ungetc (c, infile);
275 if (commas == 2) /* pick up minargs */
276 fscanf (infile, "%d", &minargs);
277 else /* pick up maxargs */
278 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
279 maxargs = -1;
280 else
281 fscanf (infile, "%d", &maxargs);
282 }
283 }
284 if (c < 0)
285 goto eof;
286 c = getc (infile);
287 }
288 while (c == ' ' || c == '\n' || c == '\t')
289 c = getc (infile);
290 if (c == '"')
291 c = read_c_string (infile, 0);
292 while (c != ',')
293 c = getc (infile);
294 c = getc (infile);
295 while (c == ' ' || c == '\n' || c == '\t')
296 c = getc (infile);
297
298 if (c == '"')
299 {
300 putc (037, outfile);
301 putc (defvarflag ? 'V' : 'F', outfile);
302 fprintf (outfile, "%s\n", buf);
303 c = read_c_string (infile, 1);
304
305 /* If this is a defun, find the arguments and print them. If
306 this function takes MANY or UNEVALLED args, then the C source
307 won't give the names of the arguments, so we shouldn't bother
308 trying to find them. */
309 if (defunflag && maxargs != -1)
310 {
311 char argbuf[1024], *p = argbuf;
312 while (c != ')')
313 {
314 if (c < 0)
315 goto eof;
316 c = getc (infile);
317 }
318 /* Skip into arguments. */
319 while (c != '(')
320 {
321 if (c < 0)
322 goto eof;
323 c = getc (infile);
324 }
325 /* Copy arguments into ARGBUF. */
326 *p++ = c;
327 do
328 *p++ = c = getc (infile);
329 while (c != ')');
330 *p = '\0';
331 /* Output them. */
332 fprintf (outfile, "\n\n");
333 write_c_args (outfile, argbuf, minargs, maxargs);
334 }
335 }
336 }
337 eof:
338 fclose (infile);
339 return 0;
340 }
341 \f
342 /* Read a file of Lisp code, compiled or interpreted.
343 Looks for
344 (defun NAME ARGS DOCSTRING ...)
345 (autoload 'NAME FILE DOCSTRING ...)
346 (defvar NAME VALUE DOCSTRING)
347 (defconst NAME VALUE DOCSTRING)
348 (fset (quote NAME) (make-byte-code (quote ARGS) ... "\
349 DOCSTRING")
350 starting in column zero.
351 ARGS, FILE or VALUE is ignored. We do not know how to parse Lisp code
352 so we use a kludge to skip them:
353 In a function definition, the form of ARGS of FILE is known, and we
354 can skip it.
355 In a variable definition, we use a formatting convention:
356 the DOCSTRING, if present, must be followed by a closeparen and a newline,
357 and no newline must appear between the defvar or defconst and the docstring,
358 The only source file that must follow this convention is loaddefs.el;
359 aside from that, it is always the .elc file that we look at, and
360 they are no problem because byte-compiler output follows this convention.
361 The NAME and DOCSTRING are output.
362 NAME is preceded by `F' for a function or `V' for a variable.
363 An entry is output only if DOCSTRING has \ newline just after the opening "
364 */
365
366 scan_lisp_file (filename)
367 char *filename;
368 {
369 FILE *infile;
370 register int c;
371 register int commas;
372 register char *p;
373 int defvarflag;
374
375 infile = fopen (filename, "r");
376 if (infile == NULL)
377 {
378 perror (filename);
379 return 0; /* No error */
380 }
381
382 c = '\n';
383 while (!feof (infile))
384 {
385 if (c != '\n')
386 {
387 c = getc (infile);
388 continue;
389 }
390 c = getc (infile);
391 if (c != '(')
392 continue;
393
394 /* Handle an autoload. */
395 c = getc (infile);
396 if (c == 'a')
397 {
398 c = getc (infile);
399 if (c != 'u')
400 continue;
401 c = getc (infile);
402 if (c != 't')
403 continue;
404 c = getc (infile);
405 if (c != 'o')
406 continue;
407 c = getc (infile);
408 if (c != 'l')
409 continue;
410 c = getc (infile);
411 if (c != 'o')
412 continue;
413 c = getc (infile);
414 if (c != 'a')
415 continue;
416 c = getc (infile);
417 if (c != 'd')
418 continue;
419
420 c = getc (infile);
421 while (c == ' ')
422 c = getc (infile);
423
424 if (c == '\'')
425 {
426 c = getc (infile);
427 }
428 else
429 {
430 if (c != '(')
431 continue;
432 c = getc (infile);
433 if (c != 'q')
434 continue;
435 c = getc (infile);
436 if (c != 'u')
437 continue;
438 c = getc (infile);
439 if (c != 'o')
440 continue;
441 c = getc (infile);
442 if (c != 't')
443 continue;
444 c = getc (infile);
445 if (c != 'e')
446 continue;
447 c = getc (infile);
448 if (c != ' ')
449 continue;
450 while (c == ' ')
451 c = getc (infile);
452 }
453
454 p = buf;
455 while (c != ' ' && c != ')')
456 {
457 if (c == EOF)
458 return 1;
459 if (c == '\\')
460 c = getc (infile);
461 *p++ = c;
462 c = getc (infile);
463 }
464 *p = 0;
465
466 while (c != '"')
467 {
468 if (c == EOF)
469 return 1;
470 c = getc (infile);
471 }
472 c = read_c_string (infile, 0);
473 }
474
475 /* Handle def* clauses. */
476 else if (c == 'd')
477 {
478 c = getc (infile);
479 if (c != 'e')
480 continue;
481 c = getc (infile);
482 if (c != 'f')
483 continue;
484 c = getc (infile);
485
486 /* Is this a defun? */
487 if (c == 'u')
488 {
489 c = getc (infile);
490 if (c != 'n')
491 continue;
492 defvarflag = 0;
493 }
494
495 /* Or a defvar? */
496 else if (c == 'v')
497 {
498 c = getc (infile);
499 if (c != 'a')
500 continue;
501 c = getc (infile);
502 if (c != 'r')
503 continue;
504 defvarflag = 1;
505 }
506
507 /* Or a defconst? */
508 else if (c == 'c')
509 {
510 c = getc (infile);
511 if (c != 'o')
512 continue;
513 c = getc (infile);
514 if (c != 'n')
515 continue;
516 c = getc (infile);
517 if (c != 's')
518 continue;
519 c = getc (infile);
520 if (c != 't')
521 continue;
522 defvarflag = 1;
523 }
524 else
525 continue;
526
527 /* Now we have seen "defun" or "defvar" or "defconst". */
528
529 while (c != ' ' && c != '\n' && c != '\t')
530 c = getc (infile);
531
532 while (c == ' ' || c == '\n' || c == '\t')
533 c = getc (infile);
534
535 /* Read and store name of function or variable being defined
536 Discard backslashes that are for quoting. */
537 p = buf;
538 while (c != ' ' && c != '\n' && c != '\t')
539 {
540 if (c == '\\')
541 c = getc (infile);
542 *p++ = c;
543 c = getc (infile);
544 }
545 *p = 0;
546
547 while (c == ' ' || c == '\n' || c == '\t')
548 c = getc (infile);
549
550 if (! defvarflag)
551 {
552 /* A function: */
553 /* Skip the arguments: either "nil" or a list in parens */
554 if (c == 'n')
555 {
556 while (c != ' ' && c != '\n' && c != '\t')
557 c = getc (infile);
558 }
559 else
560 {
561 while (c != '(')
562 c = getc (infile);
563 while (c != ')')
564 c = getc (infile);
565 }
566 c = getc (infile);
567 }
568 else
569 {
570 /* A variable: */
571
572 /* Skip until the first newline; remember
573 the two previous characters. */
574 char c1 = 0, c2 = 0;
575
576 while (c != '\n' && c >= 0)
577 {
578 c2 = c1;
579 c1 = c;
580 c = getc (infile);
581 }
582
583 /* If two previous characters were " and \,
584 this is a doc string. Otherwise, there is none. */
585 if (c2 == '"' && c1 == '\\')
586 {
587 putc (037, outfile);
588 putc ('V', outfile);
589 fprintf (outfile, "%s\n", buf);
590 read_c_string (infile, 1);
591 }
592 continue;
593 }
594 }
595
596 /* Handle an fset clause. */
597 else if (c == 'f')
598 {
599 c = getc (infile);
600 if (c != 's')
601 continue;
602 c = getc (infile);
603 if (c != 'e')
604 continue;
605 c = getc (infile);
606 if (c != 't')
607 continue;
608
609 /* Skip white space */
610 do
611 c = getc (infile);
612 while (c == ' ' || c == '\n' || c == '\t');
613
614 /* Recognize "(quote". */
615 if (c != '(')
616 continue;
617 c = getc (infile);
618 if (c != 'q')
619 continue;
620 c = getc (infile);
621 if (c != 'u')
622 continue;
623 c = getc (infile);
624 if (c != 'o')
625 continue;
626 c = getc (infile);
627 if (c != 't')
628 continue;
629 c = getc (infile);
630 if (c != 'e')
631 continue;
632
633 /* Skip white space */
634 do
635 c = getc (infile);
636 while (c == ' ' || c == '\n' || c == '\t');
637
638 /* Read and store name of function or variable being defined
639 Discard backslashes that are for quoting. */
640 p = buf;
641 while (c != ')' && c != ' ' && c != '\n' && c != '\t')
642 {
643 if (c == '\\')
644 c = getc (infile);
645 *p++ = c;
646 c = getc (infile);
647 }
648 *p = '\0';
649
650 /* Skip white space */
651 do
652 c = getc (infile);
653 while (c == ' ' || c == '\n' || c == '\t');
654
655 /* Recognize "(make-byte-code". */
656 if (c != '(')
657 continue;
658 c = getc (infile);
659 if (c != 'm')
660 continue;
661 c = getc (infile);
662 if (c != 'a')
663 continue;
664 c = getc (infile);
665 if (c != 'k')
666 continue;
667 c = getc (infile);
668 if (c != 'e')
669 continue;
670 c = getc (infile);
671 if (c != '-')
672 continue;
673 c = getc (infile);
674 if (c != 'b')
675 continue;
676 c = getc (infile);
677 if (c != 'y')
678 continue;
679 c = getc (infile);
680 if (c != 't')
681 continue;
682 c = getc (infile);
683 if (c != 'e')
684 continue;
685 c = getc (infile);
686 if (c != '-')
687 continue;
688 c = getc (infile);
689 if (c != 'c')
690 continue;
691 c = getc (infile);
692 if (c != 'o')
693 continue;
694 c = getc (infile);
695 if (c != 'd')
696 continue;
697 c = getc (infile);
698 if (c != 'e')
699 continue;
700
701 /* Scan for a \" followed by a newline, or for )) followed by
702 a newline. If we find the latter first, this function has
703 no docstring. */
704 {
705 char c1 = 0, c2 = 0;
706
707 for (;;)
708 {
709
710 /* Find newlines, and remember the two previous characters. */
711 for (;;)
712 {
713 c = getc (infile);
714
715 if (c == '\n' || c < 0)
716 break;
717
718 c2 = c1;
719 c1 = c;
720 }
721
722 /* If we've hit eof, quit. */
723 if (c == EOF)
724 break;
725
726 /* If the last two characters were \", this is a docstring. */
727 else if (c2 == '"' && c1 == '\\')
728 {
729 putc (037, outfile);
730 putc ('F', outfile);
731 fprintf (outfile, "%s\n", buf);
732 read_c_string (infile, 1);
733 break;
734 }
735
736 /* If the last two characters were )), there is no
737 docstring. */
738 else if (c2 == ')' && c1 == ')')
739 break;
740 }
741 continue;
742 }
743 }
744 else
745 continue;
746
747 /* Here for a function definition.
748 We have skipped the file name or arguments
749 and arrived at where the doc string is,
750 if there is a doc string. */
751
752 /* Skip whitespace */
753
754 while (c == ' ' || c == '\n' || c == '\t')
755 c = getc (infile);
756
757 /* " followed by \ and newline means a doc string we should gobble */
758 if (c != '"')
759 continue;
760 c = getc (infile);
761 if (c != '\\')
762 continue;
763 c = getc (infile);
764 if (c != '\n')
765 continue;
766
767 putc (037, outfile);
768 putc ('F', outfile);
769 fprintf (outfile, "%s\n", buf);
770 read_c_string (infile, 1);
771 }
772 fclose (infile);
773 return 0;
774 }