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