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