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