Update FSF's address.
[bpt/emacs.git] / lib-src / make-docfile.c
CommitLineData
f2cc4248 1/* Generate doc-string file for GNU Emacs from source files.
d5d66b7e 2 Copyright (C) 1985, 86, 92, 93, 94, 97, 1999, 2000, 01, 2004
291c7e74 3 Free Software Foundation, Inc.
f2cc4248
RS
4
5This file is part of GNU Emacs.
6
93320c23
JA
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
e065a56e 9the Free Software Foundation; either version 2, or (at your option)
93320c23
JA
10any later version.
11
f2cc4248 12GNU Emacs is distributed in the hope that it will be useful,
93320c23
JA
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
f2cc4248 16
93320c23
JA
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
364c38d3
LK
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA. */
f2cc4248
RS
21
22/* The arguments given to this program are all the C and Lisp source files
23 of GNU Emacs. .elc and .el and .c files are allowed.
24 A .o file can also be specified; the .c file it was made from is used.
25 This helps the makefile pass the correct list of files.
08a39b83 26 Option -d DIR means change to DIR before looking for files.
f2cc4248
RS
27
28 The results, which go to standard output or to a file
29 specified with -a or -o (-a to append, -o to start from nothing),
30 are entries containing function or variable names and their documentation.
31 Each entry starts with a ^_ character.
32 Then comes F for a function or V for a variable.
33 Then comes the function or variable name, terminated with a newline.
34 Then comes the documentation for that function or variable.
35 */
36
34b4ece5 37#define NO_SHORTNAMES /* Tell config not to load remap.h */
433d333d
RS
38#include <config.h>
39
40/* defined to be emacs_main, sys_fopen, etc. in config.h */
41#undef main
42#undef fopen
43#undef chdir
34b4ece5 44
f2cc4248 45#include <stdio.h>
e3938952
RS
46#ifdef MSDOS
47#include <fcntl.h>
48#endif /* MSDOS */
86b0513a 49#ifdef WINDOWSNT
1376ed18 50#include <stdlib.h>
86b0513a
RS
51#include <fcntl.h>
52#include <direct.h>
53#endif /* WINDOWSNT */
e3938952 54
86b0513a 55#ifdef DOS_NT
e3938952
RS
56#define READ_TEXT "rt"
57#define READ_BINARY "rb"
86b0513a 58#else /* not DOS_NT */
e3938952
RS
59#define READ_TEXT "r"
60#define READ_BINARY "r"
86b0513a 61#endif /* not DOS_NT */
f2cc4248 62
ef7c480d
YM
63#ifndef DIRECTORY_SEP
64#ifdef MAC_OS8
65#define DIRECTORY_SEP ':'
66#else /* not MAC_OS8 */
67#define DIRECTORY_SEP '/'
68#endif /* not MAC_OS8 */
69#endif
70
b09c5608 71#ifndef IS_DIRECTORY_SEP
ef7c480d 72#define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
b09c5608
EZ
73#endif
74
340ff9de
DM
75int scan_file ();
76int scan_lisp_file ();
77int scan_c_file ();
78
2d1985a2
KH
79#ifdef MSDOS
80/* s/msdos.h defines this as sys_chdir, but we're not linking with the
81 file where that function is defined. */
82#undef chdir
83#endif
84
a0613c61
AS
85#ifdef HAVE_UNISTD_H
86#include <unistd.h>
87#endif
88
b5ff43cc 89/* Stdio stream for output to the DOC file. */
f2cc4248
RS
90FILE *outfile;
91
b5ff43cc
RS
92/* Name this program was invoked with. */
93char *progname;
94
fb2d3129 95/* Print error message. `s1' is printf control string, `s2' is arg for it. */
b5ff43cc
RS
96
97/* VARARGS1 */
98void
99error (s1, s2)
100 char *s1, *s2;
101{
102 fprintf (stderr, "%s: ", progname);
103 fprintf (stderr, s1, s2);
104 fprintf (stderr, "\n");
105}
106
107/* Print error message and exit. */
108
109/* VARARGS1 */
110void
111fatal (s1, s2)
112 char *s1, *s2;
113{
114 error (s1, s2);
65396510 115 exit (EXIT_FAILURE);
b5ff43cc
RS
116}
117
118/* Like malloc but get fatal error if memory is exhausted. */
119
d5d66b7e 120void *
b5ff43cc
RS
121xmalloc (size)
122 unsigned int size;
123{
d5d66b7e 124 void *result = (void *) malloc (size);
b5ff43cc
RS
125 if (result == NULL)
126 fatal ("virtual memory exhausted", 0);
127 return result;
128}
129\f
340ff9de 130int
f2cc4248
RS
131main (argc, argv)
132 int argc;
133 char **argv;
134{
135 int i;
136 int err_count = 0;
a27897c9 137 int first_infile;
f2cc4248 138
b5ff43cc
RS
139 progname = argv[0];
140
4e043ed3
RS
141 outfile = stdout;
142
86b0513a 143 /* Don't put CRs in the DOC file. */
e3938952 144#ifdef MSDOS
5281dea4 145 _fmode = O_BINARY;
4e043ed3
RS
146#if 0 /* Suspicion is that this causes hanging.
147 So instead we require people to use -o on MSDOS. */
e3938952
RS
148 (stdout)->_flag &= ~_IOTEXT;
149 _setmode (fileno (stdout), O_BINARY);
4e043ed3
RS
150#endif
151 outfile = 0;
e3938952 152#endif /* MSDOS */
86b0513a
RS
153#ifdef WINDOWSNT
154 _fmode = O_BINARY;
155 _setmode (fileno (stdout), O_BINARY);
156#endif /* WINDOWSNT */
157
f2cc4248
RS
158 /* If first two args are -o FILE, output to FILE. */
159 i = 1;
160 if (argc > i + 1 && !strcmp (argv[i], "-o"))
161 {
162 outfile = fopen (argv[i + 1], "w");
163 i += 2;
164 }
165 if (argc > i + 1 && !strcmp (argv[i], "-a"))
166 {
167 outfile = fopen (argv[i + 1], "a");
168 i += 2;
169 }
d2d92f7a
JB
170 if (argc > i + 1 && !strcmp (argv[i], "-d"))
171 {
172 chdir (argv[i + 1]);
173 i += 2;
174 }
f2cc4248 175
4e043ed3
RS
176 if (outfile == 0)
177 fatal ("No output file specified", "");
178
a27897c9 179 first_infile = i;
f2cc4248 180 for (; i < argc; i++)
a27897c9
RS
181 {
182 int j;
183 /* Don't process one file twice. */
184 for (j = first_infile; j < i; j++)
185 if (! strcmp (argv[i], argv[j]))
186 break;
187 if (j == i)
188 err_count += scan_file (argv[i]);
189 }
08a39b83 190 return (err_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
f2cc4248
RS
191}
192
d5d66b7e
SM
193/* Add a source file name boundary marker in the output file. */
194void
195put_filename (filename)
196 char *filename;
197{
b09c5608
EZ
198 char *tmp;
199
200 for (tmp = filename; *tmp; tmp++)
201 {
202 if (IS_DIRECTORY_SEP(*tmp))
203 filename = tmp + 1;
204 }
d5d66b7e
SM
205
206 putc (037, outfile);
207 putc ('S', outfile);
208 fprintf (outfile, "%s\n", filename);
209}
210
a8a7afbe 211/* Read file FILENAME and output its doc strings to outfile. */
f2cc4248
RS
212/* Return 1 if file is not found, 0 if it is found. */
213
340ff9de 214int
f2cc4248
RS
215scan_file (filename)
216 char *filename;
217{
218 int len = strlen (filename);
d5d66b7e
SM
219
220 put_filename (filename);
dc61cb9d 221 if (len > 4 && !strcmp (filename + len - 4, ".elc"))
e3938952 222 return scan_lisp_file (filename, READ_BINARY);
dc61cb9d 223 else if (len > 3 && !strcmp (filename + len - 3, ".el"))
e3938952 224 return scan_lisp_file (filename, READ_TEXT);
f2cc4248 225 else
e3938952 226 return scan_c_file (filename, READ_TEXT);
f2cc4248
RS
227}
228\f
229char buf[128];
230
52d8c529
MB
231/* Some state during the execution of `read_c_string_or_comment'. */
232struct rcsoc_state
233{
fb2d3129 234 /* A count of spaces and newlines that have been read, but not output. */
52d8c529
MB
235 unsigned pending_spaces, pending_newlines;
236
237 /* Where we're reading from. */
238 FILE *in_file;
239
240 /* If non-zero, a buffer into which to copy characters. */
241 char *buf_ptr;
242 /* If non-zero, a file into which to copy characters. */
243 FILE *out_file;
244
245 /* A keyword we look for at the beginning of lines. If found, it is
246 not copied, and SAW_KEYWORD is set to true. */
247 char *keyword;
248 /* The current point we've reached in an occurance of KEYWORD in
249 the input stream. */
250 char *cur_keyword_ptr;
251 /* Set to true if we saw an occurance of KEYWORD. */
252 int saw_keyword;
253};
254
255/* Output CH to the file or buffer in STATE. Any pending newlines or
256 spaces are output first. */
0c82822c
MB
257
258static INLINE void
52d8c529
MB
259put_char (ch, state)
260 int ch;
261 struct rcsoc_state *state;
0c82822c
MB
262{
263 int out_ch;
264 do
265 {
52d8c529 266 if (state->pending_newlines > 0)
0c82822c 267 {
52d8c529 268 state->pending_newlines--;
0c82822c
MB
269 out_ch = '\n';
270 }
52d8c529 271 else if (state->pending_spaces > 0)
0c82822c 272 {
52d8c529 273 state->pending_spaces--;
0c82822c
MB
274 out_ch = ' ';
275 }
276 else
277 out_ch = ch;
278
52d8c529
MB
279 if (state->out_file)
280 putc (out_ch, state->out_file);
281 if (state->buf_ptr)
282 *state->buf_ptr++ = out_ch;
0c82822c
MB
283 }
284 while (out_ch != ch);
285}
286
52d8c529
MB
287/* If in the middle of scanning a keyword, continue scanning with
288 character CH, otherwise output CH to the file or buffer in STATE.
289 Any pending newlines or spaces are output first, as well as any
290 previously scanned characters that were thought to be part of a
291 keyword, but were in fact not. */
292
293static void
294scan_keyword_or_put_char (ch, state)
295 int ch;
296 struct rcsoc_state *state;
297{
298 if (state->keyword
299 && *state->cur_keyword_ptr == ch
300 && (state->cur_keyword_ptr > state->keyword
301 || state->pending_newlines > 0))
302 /* We might be looking at STATE->keyword at some point.
303 Keep looking until we know for sure. */
304 {
305 if (*++state->cur_keyword_ptr == '\0')
306 /* Saw the whole keyword. Set SAW_KEYWORD flag to true. */
307 {
308 state->saw_keyword = 1;
309
310 /* Reset the scanning pointer. */
311 state->cur_keyword_ptr = state->keyword;
312
fb2d3129 313 /* Canonicalize whitespace preceding a usage string. */
52d8c529
MB
314 state->pending_newlines = 2;
315 state->pending_spaces = 0;
316
317 /* Skip any whitespace between the keyword and the
318 usage string. */
319 do
320 ch = getc (state->in_file);
321 while (ch == ' ' || ch == '\n');
322
56cf5162
SM
323 /* Output the open-paren we just read. */
324 put_char (ch, state);
325
326 /* Skip the function name and replace it with `fn'. */
327 do
328 ch = getc (state->in_file);
329 while (ch != ' ' && ch != ')');
330 put_char ('f', state);
331 put_char ('n', state);
177c0ea7 332
56cf5162 333 /* Put back the last character. */
52d8c529
MB
334 ungetc (ch, state->in_file);
335 }
336 }
337 else
338 {
339 if (state->keyword && state->cur_keyword_ptr > state->keyword)
340 /* We scanned the beginning of a potential usage
341 keyword, but it was a false alarm. Output the
342 part we scanned. */
343 {
344 char *p;
345
346 for (p = state->keyword; p < state->cur_keyword_ptr; p++)
347 put_char (*p, state);
348
349 state->cur_keyword_ptr = state->keyword;
350 }
351
352 put_char (ch, state);
353 }
354}
355
356
74c55c82
GM
357/* Skip a C string or C-style comment from INFILE, and return the
358 character that follows. COMMENT non-zero means skip a comment. If
359 PRINTFLAG is positive, output string contents to outfile. If it is
360 negative, store contents in buf. Convert escape sequences \n and
d097ad57
MB
361 \t to newline and tab; discard \ followed by newline.
362 If SAW_USAGE is non-zero, then any occurances of the string `usage:'
363 at the beginning of a line will be removed, and *SAW_USAGE set to
364 true if any were encountered. */
f2cc4248 365
340ff9de 366int
d097ad57 367read_c_string_or_comment (infile, printflag, comment, saw_usage)
f2cc4248
RS
368 FILE *infile;
369 int printflag;
d097ad57 370 int *saw_usage;
7a71a86d 371 int comment;
f2cc4248
RS
372{
373 register int c;
52d8c529
MB
374 struct rcsoc_state state;
375
376 state.in_file = infile;
377 state.buf_ptr = (printflag < 0 ? buf : 0);
378 state.out_file = (printflag > 0 ? outfile : 0);
379 state.pending_spaces = 0;
380 state.pending_newlines = 0;
381 state.keyword = (saw_usage ? "usage:" : 0);
382 state.cur_keyword_ptr = state.keyword;
383 state.saw_keyword = 0;
384
385 c = getc (infile);
74c55c82 386 if (comment)
52d8c529
MB
387 while (c == '\n' || c == '\r' || c == '\t' || c == ' ')
388 c = getc (infile);
d097ad57 389
f2cc4248
RS
390 while (c != EOF)
391 {
74c55c82 392 while (c != EOF && (comment ? c != '*' : c != '"'))
f2cc4248
RS
393 {
394 if (c == '\\')
395 {
396 c = getc (infile);
433d333d 397 if (c == '\n' || c == '\r')
f2cc4248
RS
398 {
399 c = getc (infile);
400 continue;
401 }
402 if (c == 'n')
403 c = '\n';
404 if (c == 't')
405 c = '\t';
406 }
a00e9335 407
0c82822c 408 if (c == ' ')
52d8c529 409 state.pending_spaces++;
0c82822c
MB
410 else if (c == '\n')
411 {
52d8c529
MB
412 state.pending_newlines++;
413 state.pending_spaces = 0;
0c82822c
MB
414 }
415 else
52d8c529 416 scan_keyword_or_put_char (c, &state);
0c82822c 417
f2cc4248
RS
418 c = getc (infile);
419 }
74c55c82 420
7dfd439c
GM
421 if (c != EOF)
422 c = getc (infile);
f2cc4248 423
74c55c82
GM
424 if (comment)
425 {
426 if (c == '/')
427 {
428 c = getc (infile);
429 break;
430 }
a00e9335 431
52d8c529 432 scan_keyword_or_put_char ('*', &state);
74c55c82
GM
433 }
434 else
435 {
436 if (c != '"')
437 break;
a00e9335 438
74c55c82
GM
439 /* If we had a "", concatenate the two strings. */
440 c = getc (infile);
441 }
442 }
a00e9335 443
f2cc4248 444 if (printflag < 0)
52d8c529
MB
445 *state.buf_ptr = 0;
446
447 if (saw_usage)
448 *saw_usage = state.saw_keyword;
f2cc4248
RS
449
450 return c;
451}
74c55c82
GM
452
453
f2cc4248 454\f
069ad9ea 455/* Write to file OUT the argument names of function FUNC, whose text is in BUF.
f2cc4248
RS
456 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
457
340ff9de 458void
069ad9ea 459write_c_args (out, func, buf, minargs, maxargs)
f2cc4248 460 FILE *out;
069ad9ea 461 char *func, *buf;
f2cc4248
RS
462 int minargs, maxargs;
463{
f125a9e8 464 register char *p;
30e4c427
JB
465 int in_ident = 0;
466 int just_spaced = 0;
069ad9ea 467 int need_space = 1;
f2cc4248 468
56cf5162 469 fprintf (out, "(fn");
069ad9ea
RM
470
471 if (*buf == '(')
472 ++buf;
f2cc4248 473
f125a9e8 474 for (p = buf; *p; p++)
f2cc4248 475 {
30e4c427 476 char c = *p;
3941a179 477 int ident_start = 0;
30e4c427
JB
478
479 /* Notice when we start printing a new identifier. */
480 if ((('A' <= c && c <= 'Z')
481 || ('a' <= c && c <= 'z')
482 || ('0' <= c && c <= '9')
483 || c == '_')
484 != in_ident)
f2cc4248 485 {
30e4c427
JB
486 if (!in_ident)
487 {
488 in_ident = 1;
3941a179 489 ident_start = 1;
f125a9e8 490
069ad9ea
RM
491 if (need_space)
492 putc (' ', out);
493
30e4c427
JB
494 if (minargs == 0 && maxargs > 0)
495 fprintf (out, "&optional ");
496 just_spaced = 1;
f125a9e8 497
30e4c427
JB
498 minargs--;
499 maxargs--;
500 }
501 else
502 in_ident = 0;
f2cc4248 503 }
30e4c427
JB
504
505 /* Print the C argument list as it would appear in lisp:
291c7e74
GM
506 print underscores as hyphens, and print commas and newlines
507 as spaces. Collapse adjacent spaces into one. */
508 if (c == '_')
509 c = '-';
510 else if (c == ',' || c == '\n')
511 c = ' ';
30e4c427 512
3941a179
JB
513 /* In C code, `default' is a reserved word, so we spell it
514 `defalt'; unmangle that here. */
515 if (ident_start
516 && strncmp (p, "defalt", 6) == 0
517 && ! (('A' <= p[6] && p[6] <= 'Z')
518 || ('a' <= p[6] && p[6] <= 'z')
519 || ('0' <= p[6] && p[6] <= '9')
520 || p[6] == '_'))
521 {
4607ea99 522 fprintf (out, "DEFAULT");
3941a179
JB
523 p += 5;
524 in_ident = 0;
525 just_spaced = 0;
526 }
291c7e74 527 else if (c != ' ' || !just_spaced)
069ad9ea
RM
528 {
529 if (c >= 'a' && c <= 'z')
530 /* Upcase the letter. */
531 c += 'A' - 'a';
532 putc (c, out);
533 }
30e4c427 534
291c7e74 535 just_spaced = c == ' ';
069ad9ea 536 need_space = 0;
f2cc4248 537 }
f2cc4248
RS
538}
539\f
540/* Read through a c file. If a .o file is named,
541 the corresponding .c file is read instead.
542 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
543 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
544
340ff9de 545int
e3938952
RS
546scan_c_file (filename, mode)
547 char *filename, *mode;
f2cc4248
RS
548{
549 FILE *infile;
550 register int c;
551 register int commas;
552 register int defunflag;
84128dee 553 register int defvarperbufferflag;
f2cc4248
RS
554 register int defvarflag;
555 int minargs, maxargs;
1feb8ae1 556 int extension = filename[strlen (filename) - 1];
f2cc4248 557
1feb8ae1 558 if (extension == 'o')
f2cc4248
RS
559 filename[strlen (filename) - 1] = 'c';
560
e3938952 561 infile = fopen (filename, mode);
f2cc4248
RS
562
563 /* No error if non-ex input file */
564 if (infile == NULL)
565 {
566 perror (filename);
567 return 0;
568 }
569
fb2d3129 570 /* Reset extension to be able to detect duplicate files. */
1feb8ae1
RS
571 filename[strlen (filename) - 1] = extension;
572
f2cc4248
RS
573 c = '\n';
574 while (!feof (infile))
575 {
a5979c0e
MB
576 int doc_keyword = 0;
577
433d333d 578 if (c != '\n' && c != '\r')
f2cc4248
RS
579 {
580 c = getc (infile);
581 continue;
582 }
583 c = getc (infile);
584 if (c == ' ')
585 {
586 while (c == ' ')
587 c = getc (infile);
588 if (c != 'D')
589 continue;
590 c = getc (infile);
591 if (c != 'E')
592 continue;
593 c = getc (infile);
594 if (c != 'F')
595 continue;
596 c = getc (infile);
597 if (c != 'V')
598 continue;
84128dee
JB
599 c = getc (infile);
600 if (c != 'A')
601 continue;
602 c = getc (infile);
603 if (c != 'R')
604 continue;
605 c = getc (infile);
606 if (c != '_')
607 continue;
608
f2cc4248
RS
609 defvarflag = 1;
610 defunflag = 0;
84128dee
JB
611
612 c = getc (infile);
613 defvarperbufferflag = (c == 'P');
614
f2cc4248
RS
615 c = getc (infile);
616 }
617 else if (c == 'D')
618 {
619 c = getc (infile);
620 if (c != 'E')
621 continue;
622 c = getc (infile);
623 if (c != 'F')
624 continue;
625 c = getc (infile);
626 defunflag = c == 'U';
627 defvarflag = 0;
bf17c6e6 628 defvarperbufferflag = 0;
f2cc4248
RS
629 }
630 else continue;
631
632 while (c != '(')
633 {
634 if (c < 0)
635 goto eof;
636 c = getc (infile);
637 }
638
74c55c82 639 /* Lisp variable or function name. */
f2cc4248
RS
640 c = getc (infile);
641 if (c != '"')
642 continue;
d097ad57 643 c = read_c_string_or_comment (infile, -1, 0, 0);
74c55c82 644
a5979c0e
MB
645 /* DEFVAR_LISP ("name", addr, "doc")
646 DEFVAR_LISP ("name", addr /\* doc *\/)
647 DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */
f2cc4248
RS
648
649 if (defunflag)
650 commas = 5;
84128dee
JB
651 else if (defvarperbufferflag)
652 commas = 2;
f2cc4248
RS
653 else if (defvarflag)
654 commas = 1;
655 else /* For DEFSIMPLE and DEFPRED */
656 commas = 2;
657
658 while (commas)
659 {
660 if (c == ',')
661 {
662 commas--;
74c55c82 663
f2cc4248
RS
664 if (defunflag && (commas == 1 || commas == 2))
665 {
666 do
667 c = getc (infile);
433d333d 668 while (c == ' ' || c == '\n' || c == '\r' || c == '\t');
f2cc4248
RS
669 if (c < 0)
670 goto eof;
671 ungetc (c, infile);
672 if (commas == 2) /* pick up minargs */
673 fscanf (infile, "%d", &minargs);
674 else /* pick up maxargs */
675 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
676 maxargs = -1;
677 else
678 fscanf (infile, "%d", &maxargs);
679 }
680 }
74c55c82
GM
681
682 if (c == EOF)
f2cc4248
RS
683 goto eof;
684 c = getc (infile);
685 }
a5979c0e 686
433d333d 687 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
f2cc4248 688 c = getc (infile);
a00e9335 689
f2cc4248 690 if (c == '"')
d097ad57 691 c = read_c_string_or_comment (infile, 0, 0, 0);
a00e9335 692
74c55c82 693 while (c != EOF && c != ',' && c != '/')
f2cc4248 694 c = getc (infile);
74c55c82
GM
695 if (c == ',')
696 {
a5979c0e
MB
697 c = getc (infile);
698 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
699 c = getc (infile);
700 while ((c >= 'a' && c <= 'z') || (c >= 'Z' && c <= 'Z'))
701 c = getc (infile);
702 if (c == ':')
703 {
704 doc_keyword = 1;
705 c = getc (infile);
706 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
707 c = getc (infile);
708 }
74c55c82 709 }
f2cc4248 710
74c55c82
GM
711 if (c == '"'
712 || (c == '/'
713 && (c = getc (infile),
714 ungetc (c, infile),
715 c == '*')))
f2cc4248 716 {
74c55c82 717 int comment = c != '"';
d097ad57 718 int saw_usage;
a00e9335 719
f2cc4248
RS
720 putc (037, outfile);
721 putc (defvarflag ? 'V' : 'F', outfile);
722 fprintf (outfile, "%s\n", buf);
74c55c82
GM
723
724 if (comment)
725 getc (infile); /* Skip past `*' */
d097ad57 726 c = read_c_string_or_comment (infile, 1, comment, &saw_usage);
772e2009
JB
727
728 /* If this is a defun, find the arguments and print them. If
729 this function takes MANY or UNEVALLED args, then the C source
730 won't give the names of the arguments, so we shouldn't bother
74c55c82
GM
731 trying to find them.
732
a5979c0e
MB
733 Various doc-string styles:
734 0: DEFUN (..., "DOC") (args) [!comment]
735 1: DEFUN (..., /\* DOC *\/ (args)) [comment && !doc_keyword]
736 2: DEFUN (..., doc: /\* DOC *\/) (args) [comment && doc_keyword]
737 */
d097ad57 738 if (defunflag && maxargs != -1 && !saw_usage)
f2cc4248
RS
739 {
740 char argbuf[1024], *p = argbuf;
74c55c82 741
a5979c0e 742 if (!comment || doc_keyword)
74c55c82
GM
743 while (c != ')')
744 {
745 if (c < 0)
746 goto eof;
747 c = getc (infile);
748 }
a00e9335 749
f2cc4248
RS
750 /* Skip into arguments. */
751 while (c != '(')
752 {
753 if (c < 0)
754 goto eof;
755 c = getc (infile);
756 }
757 /* Copy arguments into ARGBUF. */
758 *p++ = c;
759 do
760 *p++ = c = getc (infile);
761 while (c != ')');
762 *p = '\0';
763 /* Output them. */
764 fprintf (outfile, "\n\n");
069ad9ea 765 write_c_args (outfile, buf, argbuf, minargs, maxargs);
f2cc4248 766 }
1e042160
SM
767 else if (defunflag && maxargs == -1 && !saw_usage)
768 /* The DOC should provide the usage form. */
769 fprintf (stderr, "Missing `usage' for function `%s'.\n", buf);
f2cc4248
RS
770 }
771 }
772 eof:
773 fclose (infile);
774 return 0;
775}
776\f
777/* Read a file of Lisp code, compiled or interpreted.
778 Looks for
779 (defun NAME ARGS DOCSTRING ...)
23d6b5a6 780 (defmacro NAME ARGS DOCSTRING ...)
34e778a6 781 (defsubst NAME ARGS DOCSTRING ...)
23d6b5a6 782 (autoload (quote NAME) FILE DOCSTRING ...)
f2cc4248
RS
783 (defvar NAME VALUE DOCSTRING)
784 (defconst NAME VALUE DOCSTRING)
23d6b5a6
JB
785 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
786 (fset (quote NAME) #[... DOCSTRING ...])
2d6e2619 787 (defalias (quote NAME) #[... DOCSTRING ...])
3fe77f98 788 (custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
f2cc4248 789 starting in column zero.
23d6b5a6 790 (quote NAME) may appear as 'NAME as well.
b5ff43cc
RS
791
792 We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
793 When we find that, we save it for the following defining-form,
794 and we use that instead of reading a doc string within that defining-form.
795
a00e9335 796 For defvar, defconst, and fset we skip to the docstring with a kludgy
23d6b5a6 797 formatting convention: all docstrings must appear on the same line as the
a00e9335 798 initial open-paren (the one in column zero) and must contain a backslash
b0f08a24 799 and a newline immediately after the initial double-quote. No newlines
23d6b5a6 800 must appear between the beginning of the form and the first double-quote.
b0f08a24
DL
801 For defun, defmacro, and autoload, we know how to skip over the
802 arglist, but the doc string must still have a backslash and newline
a00e9335 803 immediately after the double quote.
b0f08a24
DL
804 The only source files that must follow this convention are preloaded
805 uncompiled ones like loaddefs.el and bindings.el; aside
23d6b5a6
JB
806 from that, it is always the .elc file that we look at, and they are no
807 problem because byte-compiler output follows this convention.
f2cc4248
RS
808 The NAME and DOCSTRING are output.
809 NAME is preceded by `F' for a function or `V' for a variable.
810 An entry is output only if DOCSTRING has \ newline just after the opening "
811 */
812
23d6b5a6
JB
813void
814skip_white (infile)
815 FILE *infile;
816{
817 char c = ' ';
433d333d 818 while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
23d6b5a6
JB
819 c = getc (infile);
820 ungetc (c, infile);
821}
822
823void
824read_lisp_symbol (infile, buffer)
825 FILE *infile;
826 char *buffer;
827{
828 char c;
829 char *fillp = buffer;
830
831 skip_white (infile);
832 while (1)
833 {
834 c = getc (infile);
835 if (c == '\\')
836 *(++fillp) = getc (infile);
433d333d 837 else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '(' || c == ')')
23d6b5a6
JB
838 {
839 ungetc (c, infile);
840 *fillp = 0;
841 break;
842 }
843 else
844 *fillp++ = c;
845 }
846
847 if (! buffer[0])
848 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
a00e9335 849
23d6b5a6
JB
850 skip_white (infile);
851}
852
340ff9de 853int
e3938952
RS
854scan_lisp_file (filename, mode)
855 char *filename, *mode;
f2cc4248
RS
856{
857 FILE *infile;
858 register int c;
b5ff43cc 859 char *saved_string = 0;
f2cc4248 860
e3938952 861 infile = fopen (filename, mode);
f2cc4248
RS
862 if (infile == NULL)
863 {
864 perror (filename);
865 return 0; /* No error */
866 }
867
868 c = '\n';
869 while (!feof (infile))
870 {
b5ff43cc 871 char buffer[BUFSIZ];
23d6b5a6
JB
872 char type;
873
66f54605 874 /* If not at end of line, skip till we get to one. */
433d333d 875 if (c != '\n' && c != '\r')
f2cc4248
RS
876 {
877 c = getc (infile);
878 continue;
879 }
66f54605 880 /* Skip the line break. */
7e6972e9 881 while (c == '\n' || c == '\r')
66f54605 882 c = getc (infile);
b5ff43cc
RS
883 /* Detect a dynamic doc string and save it for the next expression. */
884 if (c == '#')
885 {
886 c = getc (infile);
887 if (c == '@')
888 {
889 int length = 0;
890 int i;
891
892 /* Read the length. */
893 while ((c = getc (infile),
894 c >= '0' && c <= '9'))
895 {
896 length *= 10;
897 length += c - '0';
898 }
899
900 /* The next character is a space that is counted in the length
901 but not part of the doc string.
902 We already read it, so just ignore it. */
903 length--;
904
905 /* Read in the contents. */
906 if (saved_string != 0)
907 free (saved_string);
908 saved_string = (char *) malloc (length);
909 for (i = 0; i < length; i++)
910 saved_string[i] = getc (infile);
911 /* The last character is a ^_.
912 That is needed in the .elc file
913 but it is redundant in DOC. So get rid of it here. */
914 saved_string[length - 1] = 0;
66f54605
PR
915 /* Skip the line break. */
916 while (c == '\n' && c == '\r')
917 c = getc (infile);
918 /* Skip the following line. */
433d333d 919 while (c != '\n' && c != '\r')
b5ff43cc
RS
920 c = getc (infile);
921 }
922 continue;
923 }
924
f2cc4248
RS
925 if (c != '(')
926 continue;
a8a7afbe 927
23d6b5a6
JB
928 read_lisp_symbol (infile, buffer);
929
66f54605 930 if (! strcmp (buffer, "defun")
34e778a6
AS
931 || ! strcmp (buffer, "defmacro")
932 || ! strcmp (buffer, "defsubst"))
f2cc4248 933 {
23d6b5a6
JB
934 type = 'F';
935 read_lisp_symbol (infile, buffer);
f2cc4248 936
23d6b5a6 937 /* Skip the arguments: either "nil" or a list in parens */
f2cc4248 938
23d6b5a6
JB
939 c = getc (infile);
940 if (c == 'n') /* nil */
f2cc4248 941 {
66f54605
PR
942 if ((c = getc (infile)) != 'i'
943 || (c = getc (infile)) != 'l')
23d6b5a6
JB
944 {
945 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
946 buffer, filename);
947 continue;
948 }
f2cc4248 949 }
23d6b5a6 950 else if (c != '(')
f2cc4248 951 {
23d6b5a6
JB
952 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
953 buffer, filename);
954 continue;
f2cc4248 955 }
23d6b5a6
JB
956 else
957 while (c != ')')
f2cc4248 958 c = getc (infile);
23d6b5a6
JB
959 skip_white (infile);
960
961 /* If the next three characters aren't `dquote bslash newline'
962 then we're not reading a docstring.
963 */
66f54605
PR
964 if ((c = getc (infile)) != '"'
965 || (c = getc (infile)) != '\\'
966 || ((c = getc (infile)) != '\n' && c != '\r'))
f2cc4248 967 {
23d6b5a6
JB
968#ifdef DEBUG
969 fprintf (stderr, "## non-docstring in %s (%s)\n",
970 buffer, filename);
971#endif
972 continue;
f2cc4248 973 }
f2cc4248 974 }
a8a7afbe 975
66f54605
PR
976 else if (! strcmp (buffer, "defvar")
977 || ! strcmp (buffer, "defconst"))
f2cc4248 978 {
23d6b5a6
JB
979 char c1 = 0, c2 = 0;
980 type = 'V';
981 read_lisp_symbol (infile, buffer);
a8a7afbe 982
b5ff43cc 983 if (saved_string == 0)
f2cc4248 984 {
b5ff43cc 985
66f54605 986 /* Skip until the end of line; remember two previous chars. */
433d333d 987 while (c != '\n' && c != '\r' && c >= 0)
b5ff43cc
RS
988 {
989 c2 = c1;
990 c1 = c;
991 c = getc (infile);
992 }
a00e9335 993
b5ff43cc
RS
994 /* If two previous characters were " and \,
995 this is a doc string. Otherwise, there is none. */
996 if (c2 != '"' || c1 != '\\')
997 {
23d6b5a6 998#ifdef DEBUG
b5ff43cc
RS
999 fprintf (stderr, "## non-docstring in %s (%s)\n",
1000 buffer, filename);
23d6b5a6 1001#endif
b5ff43cc
RS
1002 continue;
1003 }
f2cc4248 1004 }
23d6b5a6
JB
1005 }
1006
3fe77f98
RS
1007 else if (! strcmp (buffer, "custom-declare-variable"))
1008 {
1009 char c1 = 0, c2 = 0;
1010 type = 'V';
1011
1012 c = getc (infile);
1013 if (c == '\'')
1014 read_lisp_symbol (infile, buffer);
1015 else
1016 {
1017 if (c != '(')
1018 {
1019 fprintf (stderr,
1020 "## unparsable name in custom-declare-variable in %s\n",
1021 filename);
1022 continue;
1023 }
1024 read_lisp_symbol (infile, buffer);
1025 if (strcmp (buffer, "quote"))
1026 {
1027 fprintf (stderr,
1028 "## unparsable name in custom-declare-variable in %s\n",
1029 filename);
1030 continue;
1031 }
1032 read_lisp_symbol (infile, buffer);
1033 c = getc (infile);
1034 if (c != ')')
1035 {
1036 fprintf (stderr,
1037 "## unparsable quoted name in custom-declare-variable in %s\n",
1038 filename);
1039 continue;
1040 }
1041 }
1042
1043 if (saved_string == 0)
1044 {
66f54605 1045 /* Skip to end of line; remember the two previous chars. */
433d333d 1046 while (c != '\n' && c != '\r' && c >= 0)
3fe77f98
RS
1047 {
1048 c2 = c1;
1049 c1 = c;
1050 c = getc (infile);
1051 }
a00e9335 1052
3fe77f98
RS
1053 /* If two previous characters were " and \,
1054 this is a doc string. Otherwise, there is none. */
1055 if (c2 != '"' || c1 != '\\')
1056 {
1057#ifdef DEBUG
1058 fprintf (stderr, "## non-docstring in %s (%s)\n",
1059 buffer, filename);
1060#endif
1061 continue;
1062 }
1063 }
1064 }
1065
2d6e2619 1066 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
23d6b5a6
JB
1067 {
1068 char c1 = 0, c2 = 0;
1069 type = 'F';
a8a7afbe 1070
23d6b5a6
JB
1071 c = getc (infile);
1072 if (c == '\'')
1073 read_lisp_symbol (infile, buffer);
1074 else
f2cc4248 1075 {
23d6b5a6
JB
1076 if (c != '(')
1077 {
1078 fprintf (stderr, "## unparsable name in fset in %s\n",
1079 filename);
1080 continue;
1081 }
1082 read_lisp_symbol (infile, buffer);
1083 if (strcmp (buffer, "quote"))
1084 {
1085 fprintf (stderr, "## unparsable name in fset in %s\n",
1086 filename);
1087 continue;
1088 }
1089 read_lisp_symbol (infile, buffer);
f2cc4248 1090 c = getc (infile);
23d6b5a6
JB
1091 if (c != ')')
1092 {
1093 fprintf (stderr,
1094 "## unparsable quoted name in fset in %s\n",
1095 filename);
1096 continue;
1097 }
f2cc4248 1098 }
f2cc4248 1099
b5ff43cc 1100 if (saved_string == 0)
f2cc4248 1101 {
66f54605 1102 /* Skip to end of line; remember the two previous chars. */
433d333d 1103 while (c != '\n' && c != '\r' && c >= 0)
b5ff43cc
RS
1104 {
1105 c2 = c1;
1106 c1 = c;
1107 c = getc (infile);
1108 }
a00e9335 1109
b5ff43cc
RS
1110 /* If two previous characters were " and \,
1111 this is a doc string. Otherwise, there is none. */
1112 if (c2 != '"' || c1 != '\\')
1113 {
23d6b5a6 1114#ifdef DEBUG
b5ff43cc
RS
1115 fprintf (stderr, "## non-docstring in %s (%s)\n",
1116 buffer, filename);
23d6b5a6 1117#endif
b5ff43cc
RS
1118 continue;
1119 }
23d6b5a6
JB
1120 }
1121 }
f2cc4248 1122
23d6b5a6
JB
1123 else if (! strcmp (buffer, "autoload"))
1124 {
1125 type = 'F';
1126 c = getc (infile);
1127 if (c == '\'')
1128 read_lisp_symbol (infile, buffer);
1129 else
f2cc4248 1130 {
23d6b5a6 1131 if (c != '(')
f2cc4248 1132 {
23d6b5a6
JB
1133 fprintf (stderr, "## unparsable name in autoload in %s\n",
1134 filename);
1135 continue;
f2cc4248 1136 }
23d6b5a6
JB
1137 read_lisp_symbol (infile, buffer);
1138 if (strcmp (buffer, "quote"))
f2cc4248 1139 {
23d6b5a6
JB
1140 fprintf (stderr, "## unparsable name in autoload in %s\n",
1141 filename);
1142 continue;
f2cc4248 1143 }
23d6b5a6 1144 read_lisp_symbol (infile, buffer);
f2cc4248 1145 c = getc (infile);
23d6b5a6 1146 if (c != ')')
f2cc4248 1147 {
23d6b5a6
JB
1148 fprintf (stderr,
1149 "## unparsable quoted name in autoload in %s\n",
1150 filename);
1151 continue;
f2cc4248 1152 }
23d6b5a6
JB
1153 }
1154 skip_white (infile);
1155 if ((c = getc (infile)) != '\"')
1156 {
1157 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
1158 buffer, filename);
f2cc4248
RS
1159 continue;
1160 }
d097ad57 1161 read_c_string_or_comment (infile, 0, 0, 0);
23d6b5a6
JB
1162 skip_white (infile);
1163
b5ff43cc 1164 if (saved_string == 0)
a8a7afbe 1165 {
b5ff43cc
RS
1166 /* If the next three characters aren't `dquote bslash newline'
1167 then we're not reading a docstring. */
66f54605
PR
1168 if ((c = getc (infile)) != '"'
1169 || (c = getc (infile)) != '\\'
1170 || ((c = getc (infile)) != '\n' && c != '\r'))
b5ff43cc 1171 {
23d6b5a6 1172#ifdef DEBUG
b5ff43cc
RS
1173 fprintf (stderr, "## non-docstring in %s (%s)\n",
1174 buffer, filename);
23d6b5a6 1175#endif
b5ff43cc
RS
1176 continue;
1177 }
a8a7afbe 1178 }
a8a7afbe 1179 }
f2cc4248 1180
23d6b5a6 1181#ifdef DEBUG
66f54605
PR
1182 else if (! strcmp (buffer, "if")
1183 || ! strcmp (buffer, "byte-code"))
23d6b5a6
JB
1184 ;
1185#endif
f2cc4248 1186
23d6b5a6
JB
1187 else
1188 {
1189#ifdef DEBUG
1190 fprintf (stderr, "## unrecognised top-level form, %s (%s)\n",
1191 buffer, filename);
1192#endif
1193 continue;
1194 }
f2cc4248 1195
b5ff43cc
RS
1196 /* At this point, we should either use the previous
1197 dynamic doc string in saved_string
1198 or gobble a doc string from the input file.
1199
1200 In the latter case, the opening quote (and leading
1201 backslash-newline) have already been read. */
1202
f2cc4248 1203 putc (037, outfile);
23d6b5a6
JB
1204 putc (type, outfile);
1205 fprintf (outfile, "%s\n", buffer);
b5ff43cc
RS
1206 if (saved_string)
1207 {
1208 fputs (saved_string, outfile);
1209 /* Don't use one dynamic doc string twice. */
1210 free (saved_string);
1211 saved_string = 0;
1212 }
1213 else
d097ad57 1214 read_c_string_or_comment (infile, 1, 0, 0);
f2cc4248
RS
1215 }
1216 fclose (infile);
1217 return 0;
1218}
ab5796a9
MB
1219
1220/* arch-tag: f7203aaf-991a-4238-acb5-601db56f2894
1221 (do not change this comment) */
65396510
TTN
1222
1223/* make-docfile.c ends here */