point to INSTALL
[emacs.git] / lib-src / make-docfile.c
blob793c5e4211a8ccb6c6df46d8152f95aac0244b21
1 /* Generate doc-string file for GNU Emacs from source files.
2 Copyright (C) 1985, 86, 92, 93, 94, 97, 1999, 2000, 2001
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
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.
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.
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., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
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.
27 The results, which go to standard output or to a file
28 specified with -a or -o (-a to append, -o to start from nothing),
29 are entries containing function or variable names and their documentation.
30 Each entry starts with a ^_ character.
31 Then comes F for a function or V for a variable.
32 Then comes the function or variable name, terminated with a newline.
33 Then comes the documentation for that function or variable.
36 #define NO_SHORTNAMES /* Tell config not to load remap.h */
37 #include <config.h>
39 /* defined to be emacs_main, sys_fopen, etc. in config.h */
40 #undef main
41 #undef fopen
42 #undef chdir
44 #include <stdio.h>
45 #ifdef MSDOS
46 #include <fcntl.h>
47 #endif /* MSDOS */
48 #ifdef WINDOWSNT
49 #include <stdlib.h>
50 #include <fcntl.h>
51 #include <direct.h>
52 #endif /* WINDOWSNT */
54 #ifdef DOS_NT
55 #define READ_TEXT "rt"
56 #define READ_BINARY "rb"
57 #else /* not DOS_NT */
58 #define READ_TEXT "r"
59 #define READ_BINARY "r"
60 #endif /* not DOS_NT */
62 int scan_file ();
63 int scan_lisp_file ();
64 int scan_c_file ();
66 #ifdef MSDOS
67 /* s/msdos.h defines this as sys_chdir, but we're not linking with the
68 file where that function is defined. */
69 #undef chdir
70 #endif
72 #ifdef HAVE_UNISTD_H
73 #include <unistd.h>
74 #endif
76 /* Stdio stream for output to the DOC file. */
77 FILE *outfile;
79 /* Name this program was invoked with. */
80 char *progname;
82 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
84 /* VARARGS1 */
85 void
86 error (s1, s2)
87 char *s1, *s2;
89 fprintf (stderr, "%s: ", progname);
90 fprintf (stderr, s1, s2);
91 fprintf (stderr, "\n");
94 /* Print error message and exit. */
96 /* VARARGS1 */
97 void
98 fatal (s1, s2)
99 char *s1, *s2;
101 error (s1, s2);
102 exit (1);
105 /* Like malloc but get fatal error if memory is exhausted. */
107 long *
108 xmalloc (size)
109 unsigned int size;
111 long *result = (long *) malloc (size);
112 if (result == NULL)
113 fatal ("virtual memory exhausted", 0);
114 return result;
118 main (argc, argv)
119 int argc;
120 char **argv;
122 int i;
123 int err_count = 0;
124 int first_infile;
126 progname = argv[0];
128 outfile = stdout;
130 /* Don't put CRs in the DOC file. */
131 #ifdef MSDOS
132 _fmode = O_BINARY;
133 #if 0 /* Suspicion is that this causes hanging.
134 So instead we require people to use -o on MSDOS. */
135 (stdout)->_flag &= ~_IOTEXT;
136 _setmode (fileno (stdout), O_BINARY);
137 #endif
138 outfile = 0;
139 #endif /* MSDOS */
140 #ifdef WINDOWSNT
141 _fmode = O_BINARY;
142 _setmode (fileno (stdout), O_BINARY);
143 #endif /* WINDOWSNT */
145 /* If first two args are -o FILE, output to FILE. */
146 i = 1;
147 if (argc > i + 1 && !strcmp (argv[i], "-o"))
149 outfile = fopen (argv[i + 1], "w");
150 i += 2;
152 if (argc > i + 1 && !strcmp (argv[i], "-a"))
154 outfile = fopen (argv[i + 1], "a");
155 i += 2;
157 if (argc > i + 1 && !strcmp (argv[i], "-d"))
159 chdir (argv[i + 1]);
160 i += 2;
163 if (outfile == 0)
164 fatal ("No output file specified", "");
166 first_infile = i;
167 for (; i < argc; i++)
169 int j;
170 /* Don't process one file twice. */
171 for (j = first_infile; j < i; j++)
172 if (! strcmp (argv[i], argv[j]))
173 break;
174 if (j == i)
175 err_count += scan_file (argv[i]);
177 #ifndef VMS
178 exit (err_count > 0);
179 #endif /* VMS */
180 return err_count > 0;
183 /* Read file FILENAME and output its doc strings to outfile. */
184 /* Return 1 if file is not found, 0 if it is found. */
187 scan_file (filename)
188 char *filename;
190 int len = strlen (filename);
191 if (len > 4 && !strcmp (filename + len - 4, ".elc"))
192 return scan_lisp_file (filename, READ_BINARY);
193 else if (len > 3 && !strcmp (filename + len - 3, ".el"))
194 return scan_lisp_file (filename, READ_TEXT);
195 else
196 return scan_c_file (filename, READ_TEXT);
199 char buf[128];
201 /* Skip a C string from INFILE,
202 and return the character that follows the closing ".
203 If printflag is positive, output string contents to outfile.
204 If it is negative, store contents in buf.
205 Convert escape sequences \n and \t to newline and tab;
206 discard \ followed by newline. */
209 read_c_string (infile, printflag)
210 FILE *infile;
211 int printflag;
213 register int c;
214 char *p = buf;
216 c = getc (infile);
217 while (c != EOF)
219 while (c != '"' && c != EOF)
221 if (c == '\\')
223 c = getc (infile);
224 if (c == '\n' || c == '\r')
226 c = getc (infile);
227 continue;
229 if (c == 'n')
230 c = '\n';
231 if (c == 't')
232 c = '\t';
234 if (printflag > 0)
235 putc (c, outfile);
236 else if (printflag < 0)
237 *p++ = c;
238 c = getc (infile);
240 c = getc (infile);
241 if (c != '"')
242 break;
243 /* If we had a "", concatenate the two strings. */
244 c = getc (infile);
247 if (printflag < 0)
248 *p = 0;
250 return c;
253 /* Write to file OUT the argument names of function FUNC, whose text is in BUF.
254 MINARGS and MAXARGS are the minimum and maximum number of arguments. */
256 void
257 write_c_args (out, func, buf, minargs, maxargs)
258 FILE *out;
259 char *func, *buf;
260 int minargs, maxargs;
262 register char *p;
263 int in_ident = 0;
264 int just_spaced = 0;
265 int need_space = 1;
267 fprintf (out, "(%s", func);
269 if (*buf == '(')
270 ++buf;
272 for (p = buf; *p; p++)
274 char c = *p;
275 int ident_start = 0;
277 /* Notice when we start printing a new identifier. */
278 if ((('A' <= c && c <= 'Z')
279 || ('a' <= c && c <= 'z')
280 || ('0' <= c && c <= '9')
281 || c == '_')
282 != in_ident)
284 if (!in_ident)
286 in_ident = 1;
287 ident_start = 1;
289 if (need_space)
290 putc (' ', out);
292 if (minargs == 0 && maxargs > 0)
293 fprintf (out, "&optional ");
294 just_spaced = 1;
296 minargs--;
297 maxargs--;
299 else
300 in_ident = 0;
303 /* Print the C argument list as it would appear in lisp:
304 print underscores as hyphens, and print commas and newlines
305 as spaces. Collapse adjacent spaces into one. */
306 if (c == '_')
307 c = '-';
308 else if (c == ',' || c == '\n')
309 c = ' ';
311 /* In C code, `default' is a reserved word, so we spell it
312 `defalt'; unmangle that here. */
313 if (ident_start
314 && strncmp (p, "defalt", 6) == 0
315 && ! (('A' <= p[6] && p[6] <= 'Z')
316 || ('a' <= p[6] && p[6] <= 'z')
317 || ('0' <= p[6] && p[6] <= '9')
318 || p[6] == '_'))
320 fprintf (out, "DEFAULT");
321 p += 5;
322 in_ident = 0;
323 just_spaced = 0;
325 else if (c != ' ' || !just_spaced)
327 if (c >= 'a' && c <= 'z')
328 /* Upcase the letter. */
329 c += 'A' - 'a';
330 putc (c, out);
333 just_spaced = c == ' ';
334 need_space = 0;
338 /* Read through a c file. If a .o file is named,
339 the corresponding .c file is read instead.
340 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
341 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
344 scan_c_file (filename, mode)
345 char *filename, *mode;
347 FILE *infile;
348 register int c;
349 register int commas;
350 register int defunflag;
351 register int defvarperbufferflag;
352 register int defvarflag;
353 int minargs, maxargs;
354 int extension = filename[strlen (filename) - 1];
356 if (extension == 'o')
357 filename[strlen (filename) - 1] = 'c';
359 infile = fopen (filename, mode);
361 /* No error if non-ex input file */
362 if (infile == NULL)
364 perror (filename);
365 return 0;
368 /* Reset extension to be able to detect duplicate files. */
369 filename[strlen (filename) - 1] = extension;
371 c = '\n';
372 while (!feof (infile))
374 if (c != '\n' && c != '\r')
376 c = getc (infile);
377 continue;
379 c = getc (infile);
380 if (c == ' ')
382 while (c == ' ')
383 c = getc (infile);
384 if (c != 'D')
385 continue;
386 c = getc (infile);
387 if (c != 'E')
388 continue;
389 c = getc (infile);
390 if (c != 'F')
391 continue;
392 c = getc (infile);
393 if (c != 'V')
394 continue;
395 c = getc (infile);
396 if (c != 'A')
397 continue;
398 c = getc (infile);
399 if (c != 'R')
400 continue;
401 c = getc (infile);
402 if (c != '_')
403 continue;
405 defvarflag = 1;
406 defunflag = 0;
408 c = getc (infile);
409 defvarperbufferflag = (c == 'P');
411 c = getc (infile);
413 else if (c == 'D')
415 c = getc (infile);
416 if (c != 'E')
417 continue;
418 c = getc (infile);
419 if (c != 'F')
420 continue;
421 c = getc (infile);
422 defunflag = c == 'U';
423 defvarflag = 0;
425 else continue;
427 while (c != '(')
429 if (c < 0)
430 goto eof;
431 c = getc (infile);
434 c = getc (infile);
435 if (c != '"')
436 continue;
437 c = read_c_string (infile, -1);
439 if (defunflag)
440 commas = 5;
441 else if (defvarperbufferflag)
442 commas = 2;
443 else if (defvarflag)
444 commas = 1;
445 else /* For DEFSIMPLE and DEFPRED */
446 commas = 2;
448 while (commas)
450 if (c == ',')
452 commas--;
453 if (defunflag && (commas == 1 || commas == 2))
456 c = getc (infile);
457 while (c == ' ' || c == '\n' || c == '\r' || c == '\t');
458 if (c < 0)
459 goto eof;
460 ungetc (c, infile);
461 if (commas == 2) /* pick up minargs */
462 fscanf (infile, "%d", &minargs);
463 else /* pick up maxargs */
464 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
465 maxargs = -1;
466 else
467 fscanf (infile, "%d", &maxargs);
470 if (c < 0)
471 goto eof;
472 c = getc (infile);
474 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
475 c = getc (infile);
476 if (c == '"')
477 c = read_c_string (infile, 0);
478 while (c != ',')
479 c = getc (infile);
480 c = getc (infile);
481 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
482 c = getc (infile);
484 if (c == '"')
486 putc (037, outfile);
487 putc (defvarflag ? 'V' : 'F', outfile);
488 fprintf (outfile, "%s\n", buf);
489 c = read_c_string (infile, 1);
491 /* If this is a defun, find the arguments and print them. If
492 this function takes MANY or UNEVALLED args, then the C source
493 won't give the names of the arguments, so we shouldn't bother
494 trying to find them. */
495 if (defunflag && maxargs != -1)
497 char argbuf[1024], *p = argbuf;
498 while (c != ')')
500 if (c < 0)
501 goto eof;
502 c = getc (infile);
504 /* Skip into arguments. */
505 while (c != '(')
507 if (c < 0)
508 goto eof;
509 c = getc (infile);
511 /* Copy arguments into ARGBUF. */
512 *p++ = c;
514 *p++ = c = getc (infile);
515 while (c != ')');
516 *p = '\0';
517 /* Output them. */
518 fprintf (outfile, "\n\n");
519 write_c_args (outfile, buf, argbuf, minargs, maxargs);
523 eof:
524 fclose (infile);
525 return 0;
528 /* Read a file of Lisp code, compiled or interpreted.
529 Looks for
530 (defun NAME ARGS DOCSTRING ...)
531 (defmacro NAME ARGS DOCSTRING ...)
532 (defsubst NAME ARGS DOCSTRING ...)
533 (autoload (quote NAME) FILE DOCSTRING ...)
534 (defvar NAME VALUE DOCSTRING)
535 (defconst NAME VALUE DOCSTRING)
536 (fset (quote NAME) (make-byte-code ... DOCSTRING ...))
537 (fset (quote NAME) #[... DOCSTRING ...])
538 (defalias (quote NAME) #[... DOCSTRING ...])
539 (custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
540 starting in column zero.
541 (quote NAME) may appear as 'NAME as well.
543 We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
544 When we find that, we save it for the following defining-form,
545 and we use that instead of reading a doc string within that defining-form.
547 For defvar, defconst, and fset we skip to the docstring with a kludgy
548 formatting convention: all docstrings must appear on the same line as the
549 initial open-paren (the one in column zero) and must contain a backslash
550 and a newline immediately after the initial double-quote. No newlines
551 must appear between the beginning of the form and the first double-quote.
552 For defun, defmacro, and autoload, we know how to skip over the
553 arglist, but the doc string must still have a backslash and newline
554 immediately after the double quote.
555 The only source files that must follow this convention are preloaded
556 uncompiled ones like loaddefs.el and bindings.el; aside
557 from that, it is always the .elc file that we look at, and they are no
558 problem because byte-compiler output follows this convention.
559 The NAME and DOCSTRING are output.
560 NAME is preceded by `F' for a function or `V' for a variable.
561 An entry is output only if DOCSTRING has \ newline just after the opening "
564 void
565 skip_white (infile)
566 FILE *infile;
568 char c = ' ';
569 while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
570 c = getc (infile);
571 ungetc (c, infile);
574 void
575 read_lisp_symbol (infile, buffer)
576 FILE *infile;
577 char *buffer;
579 char c;
580 char *fillp = buffer;
582 skip_white (infile);
583 while (1)
585 c = getc (infile);
586 if (c == '\\')
587 *(++fillp) = getc (infile);
588 else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '(' || c == ')')
590 ungetc (c, infile);
591 *fillp = 0;
592 break;
594 else
595 *fillp++ = c;
598 if (! buffer[0])
599 fprintf (stderr, "## expected a symbol, got '%c'\n", c);
601 skip_white (infile);
605 scan_lisp_file (filename, mode)
606 char *filename, *mode;
608 FILE *infile;
609 register int c;
610 char *saved_string = 0;
612 infile = fopen (filename, mode);
613 if (infile == NULL)
615 perror (filename);
616 return 0; /* No error */
619 c = '\n';
620 while (!feof (infile))
622 char buffer[BUFSIZ];
623 char type;
625 /* If not at end of line, skip till we get to one. */
626 if (c != '\n' && c != '\r')
628 c = getc (infile);
629 continue;
631 /* Skip the line break. */
632 while (c == '\n' || c == '\r')
633 c = getc (infile);
634 /* Detect a dynamic doc string and save it for the next expression. */
635 if (c == '#')
637 c = getc (infile);
638 if (c == '@')
640 int length = 0;
641 int i;
643 /* Read the length. */
644 while ((c = getc (infile),
645 c >= '0' && c <= '9'))
647 length *= 10;
648 length += c - '0';
651 /* The next character is a space that is counted in the length
652 but not part of the doc string.
653 We already read it, so just ignore it. */
654 length--;
656 /* Read in the contents. */
657 if (saved_string != 0)
658 free (saved_string);
659 saved_string = (char *) malloc (length);
660 for (i = 0; i < length; i++)
661 saved_string[i] = getc (infile);
662 /* The last character is a ^_.
663 That is needed in the .elc file
664 but it is redundant in DOC. So get rid of it here. */
665 saved_string[length - 1] = 0;
666 /* Skip the line break. */
667 while (c == '\n' && c == '\r')
668 c = getc (infile);
669 /* Skip the following line. */
670 while (c != '\n' && c != '\r')
671 c = getc (infile);
673 continue;
676 if (c != '(')
677 continue;
679 read_lisp_symbol (infile, buffer);
681 if (! strcmp (buffer, "defun")
682 || ! strcmp (buffer, "defmacro")
683 || ! strcmp (buffer, "defsubst"))
685 type = 'F';
686 read_lisp_symbol (infile, buffer);
688 /* Skip the arguments: either "nil" or a list in parens */
690 c = getc (infile);
691 if (c == 'n') /* nil */
693 if ((c = getc (infile)) != 'i'
694 || (c = getc (infile)) != 'l')
696 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
697 buffer, filename);
698 continue;
701 else if (c != '(')
703 fprintf (stderr, "## unparsable arglist in %s (%s)\n",
704 buffer, filename);
705 continue;
707 else
708 while (c != ')')
709 c = getc (infile);
710 skip_white (infile);
712 /* If the next three characters aren't `dquote bslash newline'
713 then we're not reading a docstring.
715 if ((c = getc (infile)) != '"'
716 || (c = getc (infile)) != '\\'
717 || ((c = getc (infile)) != '\n' && c != '\r'))
719 #ifdef DEBUG
720 fprintf (stderr, "## non-docstring in %s (%s)\n",
721 buffer, filename);
722 #endif
723 continue;
727 else if (! strcmp (buffer, "defvar")
728 || ! strcmp (buffer, "defconst"))
730 char c1 = 0, c2 = 0;
731 type = 'V';
732 read_lisp_symbol (infile, buffer);
734 if (saved_string == 0)
737 /* Skip until the end of line; remember two previous chars. */
738 while (c != '\n' && c != '\r' && c >= 0)
740 c2 = c1;
741 c1 = c;
742 c = getc (infile);
745 /* If two previous characters were " and \,
746 this is a doc string. Otherwise, there is none. */
747 if (c2 != '"' || c1 != '\\')
749 #ifdef DEBUG
750 fprintf (stderr, "## non-docstring in %s (%s)\n",
751 buffer, filename);
752 #endif
753 continue;
758 else if (! strcmp (buffer, "custom-declare-variable"))
760 char c1 = 0, c2 = 0;
761 type = 'V';
763 c = getc (infile);
764 if (c == '\'')
765 read_lisp_symbol (infile, buffer);
766 else
768 if (c != '(')
770 fprintf (stderr,
771 "## unparsable name in custom-declare-variable in %s\n",
772 filename);
773 continue;
775 read_lisp_symbol (infile, buffer);
776 if (strcmp (buffer, "quote"))
778 fprintf (stderr,
779 "## unparsable name in custom-declare-variable in %s\n",
780 filename);
781 continue;
783 read_lisp_symbol (infile, buffer);
784 c = getc (infile);
785 if (c != ')')
787 fprintf (stderr,
788 "## unparsable quoted name in custom-declare-variable in %s\n",
789 filename);
790 continue;
794 if (saved_string == 0)
796 /* Skip to end of line; remember the two previous chars. */
797 while (c != '\n' && c != '\r' && c >= 0)
799 c2 = c1;
800 c1 = c;
801 c = getc (infile);
804 /* If two previous characters were " and \,
805 this is a doc string. Otherwise, there is none. */
806 if (c2 != '"' || c1 != '\\')
808 #ifdef DEBUG
809 fprintf (stderr, "## non-docstring in %s (%s)\n",
810 buffer, filename);
811 #endif
812 continue;
817 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
819 char c1 = 0, c2 = 0;
820 type = 'F';
822 c = getc (infile);
823 if (c == '\'')
824 read_lisp_symbol (infile, buffer);
825 else
827 if (c != '(')
829 fprintf (stderr, "## unparsable name in fset in %s\n",
830 filename);
831 continue;
833 read_lisp_symbol (infile, buffer);
834 if (strcmp (buffer, "quote"))
836 fprintf (stderr, "## unparsable name in fset in %s\n",
837 filename);
838 continue;
840 read_lisp_symbol (infile, buffer);
841 c = getc (infile);
842 if (c != ')')
844 fprintf (stderr,
845 "## unparsable quoted name in fset in %s\n",
846 filename);
847 continue;
851 if (saved_string == 0)
853 /* Skip to end of line; remember the two previous chars. */
854 while (c != '\n' && c != '\r' && c >= 0)
856 c2 = c1;
857 c1 = c;
858 c = getc (infile);
861 /* If two previous characters were " and \,
862 this is a doc string. Otherwise, there is none. */
863 if (c2 != '"' || c1 != '\\')
865 #ifdef DEBUG
866 fprintf (stderr, "## non-docstring in %s (%s)\n",
867 buffer, filename);
868 #endif
869 continue;
874 else if (! strcmp (buffer, "autoload"))
876 type = 'F';
877 c = getc (infile);
878 if (c == '\'')
879 read_lisp_symbol (infile, buffer);
880 else
882 if (c != '(')
884 fprintf (stderr, "## unparsable name in autoload in %s\n",
885 filename);
886 continue;
888 read_lisp_symbol (infile, buffer);
889 if (strcmp (buffer, "quote"))
891 fprintf (stderr, "## unparsable name in autoload in %s\n",
892 filename);
893 continue;
895 read_lisp_symbol (infile, buffer);
896 c = getc (infile);
897 if (c != ')')
899 fprintf (stderr,
900 "## unparsable quoted name in autoload in %s\n",
901 filename);
902 continue;
905 skip_white (infile);
906 if ((c = getc (infile)) != '\"')
908 fprintf (stderr, "## autoload of %s unparsable (%s)\n",
909 buffer, filename);
910 continue;
912 read_c_string (infile, 0);
913 skip_white (infile);
915 if (saved_string == 0)
917 /* If the next three characters aren't `dquote bslash newline'
918 then we're not reading a docstring. */
919 if ((c = getc (infile)) != '"'
920 || (c = getc (infile)) != '\\'
921 || ((c = getc (infile)) != '\n' && c != '\r'))
923 #ifdef DEBUG
924 fprintf (stderr, "## non-docstring in %s (%s)\n",
925 buffer, filename);
926 #endif
927 continue;
932 #ifdef DEBUG
933 else if (! strcmp (buffer, "if")
934 || ! strcmp (buffer, "byte-code"))
936 #endif
938 else
940 #ifdef DEBUG
941 fprintf (stderr, "## unrecognised top-level form, %s (%s)\n",
942 buffer, filename);
943 #endif
944 continue;
947 /* At this point, we should either use the previous
948 dynamic doc string in saved_string
949 or gobble a doc string from the input file.
951 In the latter case, the opening quote (and leading
952 backslash-newline) have already been read. */
954 putc (037, outfile);
955 putc (type, outfile);
956 fprintf (outfile, "%s\n", buffer);
957 if (saved_string)
959 fputs (saved_string, outfile);
960 /* Don't use one dynamic doc string twice. */
961 free (saved_string);
962 saved_string = 0;
964 else
965 read_c_string (infile, 1);
967 fclose (infile);
968 return 0;