*** empty log message ***
[emacs.git] / lib-src / make-docfile.c
blobbd6829365f28a231b45c60fff5b8071b92b8acc2
1 /* Generate doc-string file for GNU Emacs from source files.
2 Copyright (C) 1985, 1986 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 1, 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 stdout. */
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 stdout.
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 int c;
147 register char *p = buf;
148 int space = 0;
150 fprintf (out, "arguments:");
152 while (*p)
154 c = *p++;
155 if (c == ',')
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;
166 else if (c == ' ' && space)
167 continue;
168 space = (c == ' ');
169 putc (c, out);
171 putc ('\n', out);
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. */
179 scan_c_file (filename)
180 char *filename;
182 FILE *infile;
183 register int c;
184 register int commas;
185 register int defunflag;
186 register int defvarflag;
187 int minargs, maxargs;
189 if (filename[strlen (filename) - 1] == 'o')
190 filename[strlen (filename) - 1] = 'c';
192 infile = fopen (filename, "r");
194 /* No error if non-ex input file */
195 if (infile == NULL)
197 perror (filename);
198 return 0;
201 c = '\n';
202 while (!feof (infile))
204 if (c != '\n')
206 c = getc (infile);
207 continue;
209 c = getc (infile);
210 if (c == ' ')
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);
229 else if (c == 'D')
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;
241 else continue;
243 while (c != '(')
245 if (c < 0)
246 goto eof;
247 c = getc (infile);
250 c = getc (infile);
251 if (c != '"')
252 continue;
253 c = read_c_string (infile, -1);
255 if (defunflag)
256 commas = 5;
257 else if (defvarflag)
258 commas = 1;
259 else /* For DEFSIMPLE and DEFPRED */
260 commas = 2;
262 while (commas)
264 if (c == ',')
266 commas--;
267 if (defunflag && (commas == 1 || commas == 2))
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);
284 if (c < 0)
285 goto eof;
286 c = getc (infile);
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);
298 if (c == '"')
300 putc (037, outfile);
301 putc (defvarflag ? 'V' : 'F', outfile);
302 fprintf (outfile, "%s\n", buf);
303 read_c_string (infile, 1);
304 if (defunflag)
306 char argbuf[1024], *p = argbuf;
307 while (c != ')')
309 if (c < 0)
310 goto eof;
311 c = getc (infile);
313 /* Skip into arguments. */
314 while (c != '(')
316 if (c < 0)
317 goto eof;
318 c = getc (infile);
320 /* Copy arguments into ARGBUF. */
321 *p++ = c;
323 *p++ = c = getc (infile);
324 while (c != ')');
325 *p = '\0';
326 /* Output them. */
327 fprintf (outfile, "\n\n");
328 write_c_args (outfile, argbuf, minargs, maxargs);
332 eof:
333 fclose (infile);
334 return 0;
337 /* Read a file of Lisp code, compiled or interpreted.
338 Looks for
339 (defun NAME ARGS DOCSTRING ...)
340 (autoload 'NAME FILE DOCSTRING ...)
341 (defvar NAME VALUE DOCSTRING)
342 (defconst NAME VALUE DOCSTRING)
343 starting in column zero.
344 ARGS, FILE or VALUE is ignored. We do not know how to parse Lisp code
345 so we use a kludge to skip them:
346 In a function definition, the form of ARGS of FILE is known, and we
347 can skip it.
348 In a variable definition, we use a formatting convention:
349 the DOCSTRING, if present, must be followed by a closeparen and a newline,
350 and no newline must appear between the defvar or defconst and the docstring,
351 The only source file that must follow this convention is loaddefs.el;
352 aside from that, it is always the .elc file that we look at, and
353 they are no problem because byte-compiler output follows this convention.
354 The NAME and DOCSTRING are output.
355 NAME is preceded by `F' for a function or `V' for a variable.
356 An entry is output only if DOCSTRING has \ newline just after the opening "
359 scan_lisp_file (filename)
360 char *filename;
362 FILE *infile;
363 register int c;
364 register int commas;
365 register char *p;
366 int defvarflag;
368 infile = fopen (filename, "r");
369 if (infile == NULL)
371 perror (filename);
372 return 0; /* No error */
375 c = '\n';
376 while (!feof (infile))
378 if (c != '\n')
380 c = getc (infile);
381 continue;
383 c = getc (infile);
384 if (c != '(')
385 continue;
386 c = getc (infile);
387 if (c == 'a')
389 c = getc (infile);
390 if (c != 'u')
391 continue;
392 c = getc (infile);
393 if (c != 't')
394 continue;
395 c = getc (infile);
396 if (c != 'o')
397 continue;
398 c = getc (infile);
399 if (c != 'l')
400 continue;
401 c = getc (infile);
402 if (c != 'o')
403 continue;
404 c = getc (infile);
405 if (c != 'a')
406 continue;
407 c = getc (infile);
408 if (c != 'd')
409 continue;
411 c = getc (infile);
412 while (c == ' ')
413 c = getc (infile);
415 if (c == '\'')
417 c = getc (infile);
419 else
421 if (c != '(')
422 continue;
423 c = getc (infile);
424 if (c != 'q')
425 continue;
426 c = getc (infile);
427 if (c != 'u')
428 continue;
429 c = getc (infile);
430 if (c != 'o')
431 continue;
432 c = getc (infile);
433 if (c != 't')
434 continue;
435 c = getc (infile);
436 if (c != 'e')
437 continue;
438 c = getc (infile);
439 if (c != ' ')
440 continue;
441 while (c == ' ')
442 c = getc (infile);
445 p = buf;
446 while (c != ' ' && c != ')')
448 if (c == EOF)
449 return 1;
450 if (c == '\\')
451 c = getc (infile);
452 *p++ = c;
453 c = getc (infile);
455 *p = 0;
457 while (c != '"')
459 if (c == EOF)
460 return 1;
461 c = getc (infile);
463 c = read_c_string (infile, 0);
465 else if (c == 'd')
467 c = getc (infile);
468 if (c != 'e')
469 continue;
470 c = getc (infile);
471 if (c != 'f')
472 continue;
473 c = getc (infile);
474 if (c == 'u')
476 c = getc (infile);
477 if (c != 'n')
478 continue;
479 defvarflag = 0;
481 else if (c == 'v')
483 c = getc (infile);
484 if (c != 'a')
485 continue;
486 c = getc (infile);
487 if (c != 'r')
488 continue;
489 defvarflag = 1;
491 else if (c == 'c')
493 c = getc (infile);
494 if (c != 'o')
495 continue;
496 c = getc (infile);
497 if (c != 'n')
498 continue;
499 c = getc (infile);
500 if (c != 's')
501 continue;
502 c = getc (infile);
503 if (c != 't')
504 continue;
505 defvarflag = 1;
507 else
508 continue;
510 /* Now we have seen "defun" or "defvar" or "defconst". */
512 while (c != ' ' && c != '\n' && c != '\t')
513 c = getc (infile);
515 while (c == ' ' || c == '\n' || c == '\t')
516 c = getc (infile);
518 /* Read and store name of function or variable being defined
519 Discard backslashes that are for quoting. */
520 p = buf;
521 while (c != ' ' && c != '\n' && c != '\t')
523 if (c == '\\')
524 c = getc (infile);
525 *p++ = c;
526 c = getc (infile);
528 *p = 0;
530 while (c == ' ' || c == '\n' || c == '\t')
531 c = getc (infile);
533 if (! defvarflag)
535 /* A function: */
536 /* Skip the arguments: either "nil" or a list in parens */
537 if (c == 'n')
539 while (c != ' ' && c != '\n' && c != '\t')
540 c = getc (infile);
542 else
544 while (c != '(')
545 c = getc (infile);
546 while (c != ')')
547 c = getc (infile);
549 c = getc (infile);
551 else
553 /* A variable: */
555 /* Skip until the first newline; remember
556 the two previous characters. */
557 char c1 = 0, c2 = 0;
559 while (c != '\n' && c >= 0)
561 c2 = c1;
562 c1 = c;
563 c = getc (infile);
566 /* If two previous characters were " and \,
567 this is a doc string. Otherwise, there is none. */
568 if (c2 == '"' && c1 == '\\')
570 putc (037, outfile);
571 putc ('V', outfile);
572 fprintf (outfile, "%s\n", buf);
573 read_c_string (infile, 1);
575 continue;
578 else
579 continue;
581 /* Here for a function definition.
582 We have skipped the file name or arguments
583 and arrived at where the doc string is,
584 if there is a doc string. */
586 /* Skip whitespace */
588 while (c == ' ' || c == '\n' || c == '\t')
589 c = getc (infile);
591 /* " followed by \ and newline means a doc string we should gobble */
592 if (c != '"')
593 continue;
594 c = getc (infile);
595 if (c != '\\')
596 continue;
597 c = getc (infile);
598 if (c != '\n')
599 continue;
601 putc (037, outfile);
602 putc ('F', outfile);
603 fprintf (outfile, "%s\n", buf);
604 read_c_string (infile, 1);
606 fclose (infile);
607 return 0;