Remove useless if-before-free test.
[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,
f5d0ac07 3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
a5b68355 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,
edfda783 536 the corresponding .c or .m file is read instead.
f2cc4248
RS
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 557
edfda783
AR
558 if (infile == NULL && extension == 'o')
559 {
560 /* try .m */
561 filename[strlen (filename) - 1] = 'm';
562 infile = fopen (filename, mode);
563 if (infile == NULL)
564 filename[strlen (filename) - 1] = 'c'; /* don't confuse people */
565 }
566
f2cc4248
RS
567 /* No error if non-ex input file */
568 if (infile == NULL)
569 {
570 perror (filename);
571 return 0;
572 }
573
fb2d3129 574 /* Reset extension to be able to detect duplicate files. */
1feb8ae1
RS
575 filename[strlen (filename) - 1] = extension;
576
f2cc4248
RS
577 c = '\n';
578 while (!feof (infile))
579 {
a5979c0e
MB
580 int doc_keyword = 0;
581
433d333d 582 if (c != '\n' && c != '\r')
f2cc4248
RS
583 {
584 c = getc (infile);
585 continue;
586 }
587 c = getc (infile);
588 if (c == ' ')
589 {
590 while (c == ' ')
591 c = getc (infile);
592 if (c != 'D')
593 continue;
594 c = getc (infile);
595 if (c != 'E')
596 continue;
597 c = getc (infile);
598 if (c != 'F')
599 continue;
600 c = getc (infile);
601 if (c != 'V')
602 continue;
84128dee
JB
603 c = getc (infile);
604 if (c != 'A')
605 continue;
606 c = getc (infile);
607 if (c != 'R')
608 continue;
609 c = getc (infile);
610 if (c != '_')
611 continue;
612
f2cc4248
RS
613 defvarflag = 1;
614 defunflag = 0;
84128dee
JB
615
616 c = getc (infile);
617 defvarperbufferflag = (c == 'P');
618
f2cc4248
RS
619 c = getc (infile);
620 }
621 else if (c == 'D')
622 {
623 c = getc (infile);
624 if (c != 'E')
625 continue;
626 c = getc (infile);
627 if (c != 'F')
628 continue;
629 c = getc (infile);
630 defunflag = c == 'U';
631 defvarflag = 0;
bf17c6e6 632 defvarperbufferflag = 0;
f2cc4248
RS
633 }
634 else continue;
635
636 while (c != '(')
637 {
638 if (c < 0)
639 goto eof;
640 c = getc (infile);
641 }
642
74c55c82 643 /* Lisp variable or function name. */
f2cc4248
RS
644 c = getc (infile);
645 if (c != '"')
646 continue;
d097ad57 647 c = read_c_string_or_comment (infile, -1, 0, 0);
74c55c82 648
a5979c0e
MB
649 /* DEFVAR_LISP ("name", addr, "doc")
650 DEFVAR_LISP ("name", addr /\* doc *\/)
651 DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */
f2cc4248
RS
652
653 if (defunflag)
654 commas = 5;
84128dee
JB
655 else if (defvarperbufferflag)
656 commas = 2;
f2cc4248
RS
657 else if (defvarflag)
658 commas = 1;
659 else /* For DEFSIMPLE and DEFPRED */
660 commas = 2;
661
662 while (commas)
663 {
664 if (c == ',')
665 {
666 commas--;
74c55c82 667
f2cc4248
RS
668 if (defunflag && (commas == 1 || commas == 2))
669 {
670 do
671 c = getc (infile);
433d333d 672 while (c == ' ' || c == '\n' || c == '\r' || c == '\t');
f2cc4248
RS
673 if (c < 0)
674 goto eof;
675 ungetc (c, infile);
676 if (commas == 2) /* pick up minargs */
677 fscanf (infile, "%d", &minargs);
678 else /* pick up maxargs */
679 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
680 maxargs = -1;
681 else
682 fscanf (infile, "%d", &maxargs);
683 }
684 }
74c55c82
GM
685
686 if (c == EOF)
f2cc4248
RS
687 goto eof;
688 c = getc (infile);
689 }
a5979c0e 690
433d333d 691 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
f2cc4248 692 c = getc (infile);
a00e9335 693
f2cc4248 694 if (c == '"')
d097ad57 695 c = read_c_string_or_comment (infile, 0, 0, 0);
a00e9335 696
74c55c82 697 while (c != EOF && c != ',' && c != '/')
f2cc4248 698 c = getc (infile);
74c55c82
GM
699 if (c == ',')
700 {
a5979c0e
MB
701 c = getc (infile);
702 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
703 c = getc (infile);
704 while ((c >= 'a' && c <= 'z') || (c >= 'Z' && c <= 'Z'))
705 c = getc (infile);
706 if (c == ':')
707 {
708 doc_keyword = 1;
709 c = getc (infile);
710 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
711 c = getc (infile);
712 }
74c55c82 713 }
f2cc4248 714
74c55c82
GM
715 if (c == '"'
716 || (c == '/'
717 && (c = getc (infile),
718 ungetc (c, infile),
719 c == '*')))
f2cc4248 720 {
74c55c82 721 int comment = c != '"';
d097ad57 722 int saw_usage;
a00e9335 723
f2cc4248
RS
724 putc (037, outfile);
725 putc (defvarflag ? 'V' : 'F', outfile);
726 fprintf (outfile, "%s\n", buf);
74c55c82
GM
727
728 if (comment)
729 getc (infile); /* Skip past `*' */
d097ad57 730 c = read_c_string_or_comment (infile, 1, comment, &saw_usage);
772e2009
JB
731
732 /* If this is a defun, find the arguments and print them. If
733 this function takes MANY or UNEVALLED args, then the C source
734 won't give the names of the arguments, so we shouldn't bother
74c55c82
GM
735 trying to find them.
736
a5979c0e
MB
737 Various doc-string styles:
738 0: DEFUN (..., "DOC") (args) [!comment]
739 1: DEFUN (..., /\* DOC *\/ (args)) [comment && !doc_keyword]
740 2: DEFUN (..., doc: /\* DOC *\/) (args) [comment && doc_keyword]
741 */
d097ad57 742 if (defunflag && maxargs != -1 && !saw_usage)
f2cc4248
RS
743 {
744 char argbuf[1024], *p = argbuf;
74c55c82 745
a5979c0e 746 if (!comment || doc_keyword)
74c55c82
GM
747 while (c != ')')
748 {
749 if (c < 0)
750 goto eof;
751 c = getc (infile);
752 }
a00e9335 753
f2cc4248
RS
754 /* Skip into arguments. */
755 while (c != '(')
756 {
757 if (c < 0)
758 goto eof;
759 c = getc (infile);
760 }
761 /* Copy arguments into ARGBUF. */
762 *p++ = c;
763 do
764 *p++ = c = getc (infile);
765 while (c != ')');
766 *p = '\0';
767 /* Output them. */
768 fprintf (outfile, "\n\n");
069ad9ea 769 write_c_args (outfile, buf, argbuf, minargs, maxargs);
f2cc4248 770 }
1e042160
SM
771 else if (defunflag && maxargs == -1 && !saw_usage)
772 /* The DOC should provide the usage form. */
773 fprintf (stderr, "Missing `usage' for function `%s'.\n", buf);
f2cc4248
RS
774 }
775 }
776 eof:
777 fclose (infile);
778 return 0;
779}
780\f
781/* Read a file of Lisp code, compiled or interpreted.
782 Looks for
783 (defun NAME ARGS DOCSTRING ...)
23d6b5a6 784 (defmacro NAME ARGS DOCSTRING ...)
34e778a6 785 (defsubst NAME ARGS DOCSTRING ...)
23d6b5a6 786 (autoload (quote NAME) FILE DOCSTRING ...)
f2cc4248
RS
787 (defvar NAME VALUE DOCSTRING)
788 (defconst NAME VALUE DOCSTRING)
23d6b5a6
JB
789 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
790 (fset (quote NAME) #[... DOCSTRING ...])
2d6e2619 791 (defalias (quote NAME) #[... DOCSTRING ...])
3fe77f98 792 (custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
f2cc4248 793 starting in column zero.
23d6b5a6 794 (quote NAME) may appear as 'NAME as well.
b5ff43cc
RS
795
796 We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
797 When we find that, we save it for the following defining-form,
798 and we use that instead of reading a doc string within that defining-form.
799
a00e9335 800 For defvar, defconst, and fset we skip to the docstring with a kludgy
23d6b5a6 801 formatting convention: all docstrings must appear on the same line as the
a00e9335 802 initial open-paren (the one in column zero) and must contain a backslash
b0f08a24 803 and a newline immediately after the initial double-quote. No newlines
23d6b5a6 804 must appear between the beginning of the form and the first double-quote.
b0f08a24
DL
805 For defun, defmacro, and autoload, we know how to skip over the
806 arglist, but the doc string must still have a backslash and newline
a00e9335 807 immediately after the double quote.
b0f08a24
DL
808 The only source files that must follow this convention are preloaded
809 uncompiled ones like loaddefs.el and bindings.el; aside
23d6b5a6
JB
810 from that, it is always the .elc file that we look at, and they are no
811 problem because byte-compiler output follows this convention.
f2cc4248
RS
812 The NAME and DOCSTRING are output.
813 NAME is preceded by `F' for a function or `V' for a variable.
814 An entry is output only if DOCSTRING has \ newline just after the opening "
815 */
816
23d6b5a6
JB
817void
818skip_white (infile)
819 FILE *infile;
820{
821 char c = ' ';
433d333d 822 while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
23d6b5a6
JB
823 c = getc (infile);
824 ungetc (c, infile);
825}
826
827void
828read_lisp_symbol (infile, buffer)
829 FILE *infile;
830 char *buffer;
831{
832 char c;
833 char *fillp = buffer;
834
835 skip_white (infile);
836 while (1)
837 {
838 c = getc (infile);
839 if (c == '\\')
840 *(++fillp) = getc (infile);
433d333d 841 else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '(' || c == ')')
23d6b5a6
JB
842 {
843 ungetc (c, infile);
844 *fillp = 0;
845 break;
846 }
847 else
848 *fillp++ = c;
849 }
850
851 if (! buffer[0])
852 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
a00e9335 853
23d6b5a6
JB
854 skip_white (infile);
855}
856
340ff9de 857int
e3938952
RS
858scan_lisp_file (filename, mode)
859 char *filename, *mode;
f2cc4248
RS
860{
861 FILE *infile;
862 register int c;
b5ff43cc 863 char *saved_string = 0;
f2cc4248 864
e3938952 865 infile = fopen (filename, mode);
f2cc4248
RS
866 if (infile == NULL)
867 {
868 perror (filename);
869 return 0; /* No error */
870 }
871
872 c = '\n';
873 while (!feof (infile))
874 {
b5ff43cc 875 char buffer[BUFSIZ];
23d6b5a6
JB
876 char type;
877
66f54605 878 /* If not at end of line, skip till we get to one. */
433d333d 879 if (c != '\n' && c != '\r')
f2cc4248
RS
880 {
881 c = getc (infile);
882 continue;
883 }
66f54605 884 /* Skip the line break. */
7e6972e9 885 while (c == '\n' || c == '\r')
66f54605 886 c = getc (infile);
b5ff43cc
RS
887 /* Detect a dynamic doc string and save it for the next expression. */
888 if (c == '#')
889 {
890 c = getc (infile);
891 if (c == '@')
892 {
893 int length = 0;
894 int i;
895
896 /* Read the length. */
897 while ((c = getc (infile),
898 c >= '0' && c <= '9'))
899 {
900 length *= 10;
901 length += c - '0';
902 }
903
904 /* The next character is a space that is counted in the length
905 but not part of the doc string.
906 We already read it, so just ignore it. */
907 length--;
908
909 /* Read in the contents. */
e0f59195 910 free (saved_string);
938ebc4f 911 saved_string = (char *) xmalloc (length);
b5ff43cc
RS
912 for (i = 0; i < length; i++)
913 saved_string[i] = getc (infile);
914 /* The last character is a ^_.
915 That is needed in the .elc file
916 but it is redundant in DOC. So get rid of it here. */
917 saved_string[length - 1] = 0;
66f54605
PR
918 /* Skip the line break. */
919 while (c == '\n' && c == '\r')
920 c = getc (infile);
921 /* Skip the following line. */
433d333d 922 while (c != '\n' && c != '\r')
b5ff43cc
RS
923 c = getc (infile);
924 }
925 continue;
926 }
927
f2cc4248
RS
928 if (c != '(')
929 continue;
a8a7afbe 930
23d6b5a6
JB
931 read_lisp_symbol (infile, buffer);
932
66f54605 933 if (! strcmp (buffer, "defun")
34e778a6
AS
934 || ! strcmp (buffer, "defmacro")
935 || ! strcmp (buffer, "defsubst"))
f2cc4248 936 {
23d6b5a6
JB
937 type = 'F';
938 read_lisp_symbol (infile, buffer);
f2cc4248 939
23d6b5a6 940 /* Skip the arguments: either "nil" or a list in parens */
f2cc4248 941
23d6b5a6
JB
942 c = getc (infile);
943 if (c == 'n') /* nil */
f2cc4248 944 {
66f54605
PR
945 if ((c = getc (infile)) != 'i'
946 || (c = getc (infile)) != 'l')
23d6b5a6
JB
947 {
948 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
949 buffer, filename);
950 continue;
951 }
f2cc4248 952 }
23d6b5a6 953 else if (c != '(')
f2cc4248 954 {
23d6b5a6
JB
955 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
956 buffer, filename);
957 continue;
f2cc4248 958 }
23d6b5a6
JB
959 else
960 while (c != ')')
f2cc4248 961 c = getc (infile);
23d6b5a6
JB
962 skip_white (infile);
963
964 /* If the next three characters aren't `dquote bslash newline'
965 then we're not reading a docstring.
966 */
66f54605
PR
967 if ((c = getc (infile)) != '"'
968 || (c = getc (infile)) != '\\'
969 || ((c = getc (infile)) != '\n' && c != '\r'))
f2cc4248 970 {
23d6b5a6
JB
971#ifdef DEBUG
972 fprintf (stderr, "## non-docstring in %s (%s)\n",
973 buffer, filename);
974#endif
975 continue;
f2cc4248 976 }
f2cc4248 977 }
a8a7afbe 978
66f54605
PR
979 else if (! strcmp (buffer, "defvar")
980 || ! strcmp (buffer, "defconst"))
f2cc4248 981 {
23d6b5a6
JB
982 char c1 = 0, c2 = 0;
983 type = 'V';
984 read_lisp_symbol (infile, buffer);
a8a7afbe 985
b5ff43cc 986 if (saved_string == 0)
f2cc4248 987 {
b5ff43cc 988
66f54605 989 /* Skip until the end of line; remember two previous chars. */
433d333d 990 while (c != '\n' && c != '\r' && c >= 0)
b5ff43cc
RS
991 {
992 c2 = c1;
993 c1 = c;
994 c = getc (infile);
995 }
a00e9335 996
b5ff43cc
RS
997 /* If two previous characters were " and \,
998 this is a doc string. Otherwise, there is none. */
999 if (c2 != '"' || c1 != '\\')
1000 {
23d6b5a6 1001#ifdef DEBUG
b5ff43cc
RS
1002 fprintf (stderr, "## non-docstring in %s (%s)\n",
1003 buffer, filename);
23d6b5a6 1004#endif
b5ff43cc
RS
1005 continue;
1006 }
f2cc4248 1007 }
23d6b5a6
JB
1008 }
1009
3fe77f98
RS
1010 else if (! strcmp (buffer, "custom-declare-variable"))
1011 {
1012 char c1 = 0, c2 = 0;
1013 type = 'V';
1014
1015 c = getc (infile);
1016 if (c == '\'')
1017 read_lisp_symbol (infile, buffer);
1018 else
1019 {
1020 if (c != '(')
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 if (strcmp (buffer, "quote"))
1029 {
1030 fprintf (stderr,
1031 "## unparsable name in custom-declare-variable in %s\n",
1032 filename);
1033 continue;
1034 }
1035 read_lisp_symbol (infile, buffer);
1036 c = getc (infile);
1037 if (c != ')')
1038 {
1039 fprintf (stderr,
1040 "## unparsable quoted name in custom-declare-variable in %s\n",
1041 filename);
1042 continue;
1043 }
1044 }
1045
1046 if (saved_string == 0)
1047 {
66f54605 1048 /* Skip to end of line; remember the two previous chars. */
433d333d 1049 while (c != '\n' && c != '\r' && c >= 0)
3fe77f98
RS
1050 {
1051 c2 = c1;
1052 c1 = c;
1053 c = getc (infile);
1054 }
a00e9335 1055
3fe77f98
RS
1056 /* If two previous characters were " and \,
1057 this is a doc string. Otherwise, there is none. */
1058 if (c2 != '"' || c1 != '\\')
1059 {
1060#ifdef DEBUG
1061 fprintf (stderr, "## non-docstring in %s (%s)\n",
1062 buffer, filename);
1063#endif
1064 continue;
1065 }
1066 }
1067 }
1068
2d6e2619 1069 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
23d6b5a6
JB
1070 {
1071 char c1 = 0, c2 = 0;
1072 type = 'F';
a8a7afbe 1073
23d6b5a6
JB
1074 c = getc (infile);
1075 if (c == '\'')
1076 read_lisp_symbol (infile, buffer);
1077 else
f2cc4248 1078 {
23d6b5a6
JB
1079 if (c != '(')
1080 {
1081 fprintf (stderr, "## unparsable name in fset in %s\n",
1082 filename);
1083 continue;
1084 }
1085 read_lisp_symbol (infile, buffer);
1086 if (strcmp (buffer, "quote"))
1087 {
1088 fprintf (stderr, "## unparsable name in fset in %s\n",
1089 filename);
1090 continue;
1091 }
1092 read_lisp_symbol (infile, buffer);
f2cc4248 1093 c = getc (infile);
23d6b5a6
JB
1094 if (c != ')')
1095 {
1096 fprintf (stderr,
1097 "## unparsable quoted name in fset in %s\n",
1098 filename);
1099 continue;
1100 }
f2cc4248 1101 }
f2cc4248 1102
b5ff43cc 1103 if (saved_string == 0)
f2cc4248 1104 {
66f54605 1105 /* Skip to end of line; remember the two previous chars. */
433d333d 1106 while (c != '\n' && c != '\r' && c >= 0)
b5ff43cc
RS
1107 {
1108 c2 = c1;
1109 c1 = c;
1110 c = getc (infile);
1111 }
a00e9335 1112
b5ff43cc
RS
1113 /* If two previous characters were " and \,
1114 this is a doc string. Otherwise, there is none. */
1115 if (c2 != '"' || c1 != '\\')
1116 {
23d6b5a6 1117#ifdef DEBUG
b5ff43cc
RS
1118 fprintf (stderr, "## non-docstring in %s (%s)\n",
1119 buffer, filename);
23d6b5a6 1120#endif
b5ff43cc
RS
1121 continue;
1122 }
23d6b5a6
JB
1123 }
1124 }
f2cc4248 1125
23d6b5a6
JB
1126 else if (! strcmp (buffer, "autoload"))
1127 {
1128 type = 'F';
1129 c = getc (infile);
1130 if (c == '\'')
1131 read_lisp_symbol (infile, buffer);
1132 else
f2cc4248 1133 {
23d6b5a6 1134 if (c != '(')
f2cc4248 1135 {
23d6b5a6
JB
1136 fprintf (stderr, "## unparsable name in autoload in %s\n",
1137 filename);
1138 continue;
f2cc4248 1139 }
23d6b5a6
JB
1140 read_lisp_symbol (infile, buffer);
1141 if (strcmp (buffer, "quote"))
f2cc4248 1142 {
23d6b5a6
JB
1143 fprintf (stderr, "## unparsable name in autoload in %s\n",
1144 filename);
1145 continue;
f2cc4248 1146 }
23d6b5a6 1147 read_lisp_symbol (infile, buffer);
f2cc4248 1148 c = getc (infile);
23d6b5a6 1149 if (c != ')')
f2cc4248 1150 {
23d6b5a6
JB
1151 fprintf (stderr,
1152 "## unparsable quoted name in autoload in %s\n",
1153 filename);
1154 continue;
f2cc4248 1155 }
23d6b5a6
JB
1156 }
1157 skip_white (infile);
1158 if ((c = getc (infile)) != '\"')
1159 {
1160 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
1161 buffer, filename);
f2cc4248
RS
1162 continue;
1163 }
d097ad57 1164 read_c_string_or_comment (infile, 0, 0, 0);
23d6b5a6
JB
1165 skip_white (infile);
1166
b5ff43cc 1167 if (saved_string == 0)
a8a7afbe 1168 {
b5ff43cc
RS
1169 /* If the next three characters aren't `dquote bslash newline'
1170 then we're not reading a docstring. */
66f54605
PR
1171 if ((c = getc (infile)) != '"'
1172 || (c = getc (infile)) != '\\'
1173 || ((c = getc (infile)) != '\n' && c != '\r'))
b5ff43cc 1174 {
23d6b5a6 1175#ifdef DEBUG
b5ff43cc
RS
1176 fprintf (stderr, "## non-docstring in %s (%s)\n",
1177 buffer, filename);
23d6b5a6 1178#endif
b5ff43cc
RS
1179 continue;
1180 }
a8a7afbe 1181 }
a8a7afbe 1182 }
f2cc4248 1183
23d6b5a6 1184#ifdef DEBUG
66f54605
PR
1185 else if (! strcmp (buffer, "if")
1186 || ! strcmp (buffer, "byte-code"))
23d6b5a6
JB
1187 ;
1188#endif
f2cc4248 1189
23d6b5a6
JB
1190 else
1191 {
1192#ifdef DEBUG
bcfce2c7 1193 fprintf (stderr, "## unrecognized top-level form, %s (%s)\n",
23d6b5a6
JB
1194 buffer, filename);
1195#endif
1196 continue;
1197 }
f2cc4248 1198
b5ff43cc
RS
1199 /* At this point, we should either use the previous
1200 dynamic doc string in saved_string
1201 or gobble a doc string from the input file.
1202
1203 In the latter case, the opening quote (and leading
1204 backslash-newline) have already been read. */
1205
f2cc4248 1206 putc (037, outfile);
23d6b5a6
JB
1207 putc (type, outfile);
1208 fprintf (outfile, "%s\n", buffer);
b5ff43cc
RS
1209 if (saved_string)
1210 {
1211 fputs (saved_string, outfile);
1212 /* Don't use one dynamic doc string twice. */
1213 free (saved_string);
1214 saved_string = 0;
1215 }
1216 else
d097ad57 1217 read_c_string_or_comment (infile, 1, 0, 0);
f2cc4248
RS
1218 }
1219 fclose (infile);
1220 return 0;
1221}
ab5796a9
MB
1222
1223/* arch-tag: f7203aaf-991a-4238-acb5-601db56f2894
1224 (do not change this comment) */
65396510
TTN
1225
1226/* make-docfile.c ends here */