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