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