1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-04 08:47:11 +00:00
emacs/lib-src/make-docfile.c

967 lines
22 KiB
C
Raw Normal View History

1989-05-08 21:10:27 +00:00
/* Generate doc-string file for GNU Emacs from source files.
Copyright (C) 1985, 86, 92, 93, 94, 97, 1999 Free Software Foundation, Inc.
1989-05-08 21:10:27 +00:00
This file is part of GNU Emacs.
1989-10-31 16:00:17 +00:00
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
1992-05-10 18:15:10 +00:00
the Free Software Foundation; either version 2, or (at your option)
1989-10-31 16:00:17 +00:00
any later version.
1989-05-08 21:10:27 +00:00
GNU Emacs is distributed in the hope that it will be useful,
1989-10-31 16:00:17 +00:00
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
1989-05-08 21:10:27 +00:00
1989-10-31 16:00:17 +00:00
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
1996-01-15 09:18:04 +00:00
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
1989-05-08 21:10:27 +00:00
/* The arguments given to this program are all the C and Lisp source files
of GNU Emacs. .elc and .el and .c files are allowed.
A .o file can also be specified; the .c file it was made from is used.
This helps the makefile pass the correct list of files.
The results, which go to standard output or to a file
specified with -a or -o (-a to append, -o to start from nothing),
are entries containing function or variable names and their documentation.
Each entry starts with a ^_ character.
Then comes F for a function or V for a variable.
Then comes the function or variable name, terminated with a newline.
Then comes the documentation for that function or variable.
*/
#define NO_SHORTNAMES /* Tell config not to load remap.h */
#include <config.h>
/* defined to be emacs_main, sys_fopen, etc. in config.h */
#undef main
#undef fopen
#undef chdir
1989-05-08 21:10:27 +00:00
#include <stdio.h>
#ifdef MSDOS
#include <fcntl.h>
#endif /* MSDOS */
#ifdef WINDOWSNT
#include <stdlib.h>
#include <fcntl.h>
#include <direct.h>
#endif /* WINDOWSNT */
#ifdef DOS_NT
#define READ_TEXT "rt"
#define READ_BINARY "rb"
#else /* not DOS_NT */
#define READ_TEXT "r"
#define READ_BINARY "r"
#endif /* not DOS_NT */
1989-05-08 21:10:27 +00:00
1994-10-12 20:21:51 +00:00
int scan_file ();
int scan_lisp_file ();
int scan_c_file ();
1995-06-08 20:13:45 +00:00
#ifdef MSDOS
/* s/msdos.h defines this as sys_chdir, but we're not linking with the
file where that function is defined. */
#undef chdir
#endif
1998-04-27 09:22:29 +00:00
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
/* Stdio stream for output to the DOC file. */
1989-05-08 21:10:27 +00:00
FILE *outfile;
/* Name this program was invoked with. */
char *progname;
/* Print error message. `s1' is printf control string, `s2' is arg for it. */
/* VARARGS1 */
void
error (s1, s2)
char *s1, *s2;
{
fprintf (stderr, "%s: ", progname);
fprintf (stderr, s1, s2);
fprintf (stderr, "\n");
}
/* Print error message and exit. */
/* VARARGS1 */
void
fatal (s1, s2)
char *s1, *s2;
{
error (s1, s2);
exit (1);
}
/* Like malloc but get fatal error if memory is exhausted. */
long *
xmalloc (size)
unsigned int size;
{
long *result = (long *) malloc (size);
if (result == NULL)
fatal ("virtual memory exhausted", 0);
return result;
}
1994-10-12 20:21:51 +00:00
int
1989-05-08 21:10:27 +00:00
main (argc, argv)
int argc;
char **argv;
{
int i;
int err_count = 0;
int first_infile;
1989-05-08 21:10:27 +00:00
progname = argv[0];
outfile = stdout;
/* Don't put CRs in the DOC file. */
#ifdef MSDOS
_fmode = O_BINARY;
#if 0 /* Suspicion is that this causes hanging.
So instead we require people to use -o on MSDOS. */
(stdout)->_flag &= ~_IOTEXT;
_setmode (fileno (stdout), O_BINARY);
#endif
outfile = 0;
#endif /* MSDOS */
#ifdef WINDOWSNT
_fmode = O_BINARY;
_setmode (fileno (stdout), O_BINARY);
#endif /* WINDOWSNT */
1989-05-08 21:10:27 +00:00
/* If first two args are -o FILE, output to FILE. */
i = 1;
if (argc > i + 1 && !strcmp (argv[i], "-o"))
{
outfile = fopen (argv[i + 1], "w");
i += 2;
}
if (argc > i + 1 && !strcmp (argv[i], "-a"))
{
outfile = fopen (argv[i + 1], "a");
i += 2;
}
if (argc > i + 1 && !strcmp (argv[i], "-d"))
{
chdir (argv[i + 1]);
i += 2;
}
1989-05-08 21:10:27 +00:00
if (outfile == 0)
fatal ("No output file specified", "");
first_infile = i;
1989-05-08 21:10:27 +00:00
for (; i < argc; i++)
{
int j;
/* Don't process one file twice. */
for (j = first_infile; j < i; j++)
if (! strcmp (argv[i], argv[j]))
break;
if (j == i)
err_count += scan_file (argv[i]);
}
1989-05-08 21:10:27 +00:00
#ifndef VMS
exit (err_count > 0);
1993-05-24 18:05:21 +00:00
#endif /* VMS */
return err_count > 0;
1989-05-08 21:10:27 +00:00
}
1991-01-14 23:38:10 +00:00
/* Read file FILENAME and output its doc strings to outfile. */
1989-05-08 21:10:27 +00:00
/* Return 1 if file is not found, 0 if it is found. */
1994-10-12 20:21:51 +00:00
int
1989-05-08 21:10:27 +00:00
scan_file (filename)
char *filename;
{
int len = strlen (filename);
if (len > 4 && !strcmp (filename + len - 4, ".elc"))
return scan_lisp_file (filename, READ_BINARY);
else if (len > 3 && !strcmp (filename + len - 3, ".el"))
return scan_lisp_file (filename, READ_TEXT);
1989-05-08 21:10:27 +00:00
else
return scan_c_file (filename, READ_TEXT);
1989-05-08 21:10:27 +00:00
}
char buf[128];
/* Skip a C string from INFILE,
and return the character that follows the closing ".
1991-01-14 23:38:10 +00:00
If printflag is positive, output string contents to outfile.
1989-05-08 21:10:27 +00:00
If it is negative, store contents in buf.
Convert escape sequences \n and \t to newline and tab;
discard \ followed by newline. */
1994-10-12 20:21:51 +00:00
int
1989-05-08 21:10:27 +00:00
read_c_string (infile, printflag)
FILE *infile;
int printflag;
{
register int c;
char *p = buf;
c = getc (infile);
while (c != EOF)
{
while (c != '"' && c != EOF)
{
if (c == '\\')
{
c = getc (infile);
if (c == '\n' || c == '\r')
1989-05-08 21:10:27 +00:00
{
c = getc (infile);
continue;
}
if (c == 'n')
c = '\n';
if (c == 't')
c = '\t';
}
if (printflag > 0)
putc (c, outfile);
else if (printflag < 0)
*p++ = c;
c = getc (infile);
}
c = getc (infile);
if (c != '"')
break;
/* If we had a "", concatenate the two strings. */
1989-05-08 21:10:27 +00:00
c = getc (infile);
}
if (printflag < 0)
*p = 0;
return c;
}
/* Write to file OUT the argument names of function FUNC, whose text is in BUF.
1989-05-08 21:10:27 +00:00
MINARGS and MAXARGS are the minimum and maximum number of arguments. */
1994-10-12 20:21:51 +00:00
void
write_c_args (out, func, buf, minargs, maxargs)
1989-05-08 21:10:27 +00:00
FILE *out;
char *func, *buf;
1989-05-08 21:10:27 +00:00
int minargs, maxargs;
{
1992-09-23 10:33:26 +00:00
register char *p;
1992-09-29 03:14:35 +00:00
int in_ident = 0;
int just_spaced = 0;
int need_space = 1;
1989-05-08 21:10:27 +00:00
fprintf (out, "(%s", func);
if (*buf == '(')
++buf;
1989-05-08 21:10:27 +00:00
1992-09-23 10:33:26 +00:00
for (p = buf; *p; p++)
1989-05-08 21:10:27 +00:00
{
1992-09-29 03:14:35 +00:00
char c = *p;
int ident_start = 0;
1992-09-29 03:14:35 +00:00
/* Notice when we start printing a new identifier. */
if ((('A' <= c && c <= 'Z')
|| ('a' <= c && c <= 'z')
|| ('0' <= c && c <= '9')
|| c == '_')
!= in_ident)
1989-05-08 21:10:27 +00:00
{
1992-09-29 03:14:35 +00:00
if (!in_ident)
{
in_ident = 1;
ident_start = 1;
1992-09-23 10:33:26 +00:00
if (need_space)
putc (' ', out);
1992-09-29 03:14:35 +00:00
if (minargs == 0 && maxargs > 0)
fprintf (out, "&optional ");
just_spaced = 1;
1992-09-23 10:33:26 +00:00
1992-09-29 03:14:35 +00:00
minargs--;
maxargs--;
}
else
in_ident = 0;
1989-05-08 21:10:27 +00:00
}
1992-09-29 03:14:35 +00:00
/* Print the C argument list as it would appear in lisp:
print underscores as hyphens, and print commas as spaces.
Collapse adjacent spaces into one. */
if (c == '_') c = '-';
if (c == ',') c = ' ';
/* In C code, `default' is a reserved word, so we spell it
`defalt'; unmangle that here. */
if (ident_start
&& strncmp (p, "defalt", 6) == 0
&& ! (('A' <= p[6] && p[6] <= 'Z')
|| ('a' <= p[6] && p[6] <= 'z')
|| ('0' <= p[6] && p[6] <= '9')
|| p[6] == '_'))
{
fprintf (out, "DEFAULT");
p += 5;
in_ident = 0;
just_spaced = 0;
}
else if (c != ' ' || ! just_spaced)
{
if (c >= 'a' && c <= 'z')
/* Upcase the letter. */
c += 'A' - 'a';
putc (c, out);
}
1992-09-29 03:14:35 +00:00
just_spaced = (c == ' ');
need_space = 0;
1989-05-08 21:10:27 +00:00
}
}
/* Read through a c file. If a .o file is named,
the corresponding .c file is read instead.
Looks for DEFUN constructs such as are defined in ../src/lisp.h.
Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
1994-10-12 20:21:51 +00:00
int
scan_c_file (filename, mode)
char *filename, *mode;
1989-05-08 21:10:27 +00:00
{
FILE *infile;
register int c;
register int commas;
register int defunflag;
register int defvarperbufferflag;
1989-05-08 21:10:27 +00:00
register int defvarflag;
int minargs, maxargs;
int extension = filename[strlen (filename) - 1];
1989-05-08 21:10:27 +00:00
if (extension == 'o')
1989-05-08 21:10:27 +00:00
filename[strlen (filename) - 1] = 'c';
infile = fopen (filename, mode);
1989-05-08 21:10:27 +00:00
/* No error if non-ex input file */
if (infile == NULL)
{
perror (filename);
return 0;
}
/* Reset extension to be able to detect duplicate files. */
filename[strlen (filename) - 1] = extension;
1989-05-08 21:10:27 +00:00
c = '\n';
while (!feof (infile))
{
if (c != '\n' && c != '\r')
1989-05-08 21:10:27 +00:00
{
c = getc (infile);
continue;
}
c = getc (infile);
if (c == ' ')
{
while (c == ' ')
c = getc (infile);
if (c != 'D')
continue;
c = getc (infile);
if (c != 'E')
continue;
c = getc (infile);
if (c != 'F')
continue;
c = getc (infile);
if (c != 'V')
continue;
c = getc (infile);
if (c != 'A')
continue;
c = getc (infile);
if (c != 'R')
continue;
c = getc (infile);
if (c != '_')
continue;
1989-05-08 21:10:27 +00:00
defvarflag = 1;
defunflag = 0;
c = getc (infile);
defvarperbufferflag = (c == 'P');
1989-05-08 21:10:27 +00:00
c = getc (infile);
}
else if (c == 'D')
{
c = getc (infile);
if (c != 'E')
continue;
c = getc (infile);
if (c != 'F')
continue;
c = getc (infile);
defunflag = c == 'U';
defvarflag = 0;
}
else continue;
while (c != '(')
{
if (c < 0)
goto eof;
c = getc (infile);
}
c = getc (infile);
if (c != '"')
continue;
c = read_c_string (infile, -1);
if (defunflag)
commas = 5;
else if (defvarperbufferflag)
commas = 2;
1989-05-08 21:10:27 +00:00
else if (defvarflag)
commas = 1;
else /* For DEFSIMPLE and DEFPRED */
commas = 2;
while (commas)
{
if (c == ',')
{
commas--;
if (defunflag && (commas == 1 || commas == 2))
{
do
c = getc (infile);
while (c == ' ' || c == '\n' || c == '\r' || c == '\t');
1989-05-08 21:10:27 +00:00
if (c < 0)
goto eof;
ungetc (c, infile);
if (commas == 2) /* pick up minargs */
fscanf (infile, "%d", &minargs);
else /* pick up maxargs */
if (c == 'M' || c == 'U') /* MANY || UNEVALLED */
maxargs = -1;
else
fscanf (infile, "%d", &maxargs);
}
}
if (c < 0)
goto eof;
c = getc (infile);
}
while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
1989-05-08 21:10:27 +00:00
c = getc (infile);
if (c == '"')
c = read_c_string (infile, 0);
while (c != ',')
c = getc (infile);
c = getc (infile);
while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
1989-05-08 21:10:27 +00:00
c = getc (infile);
if (c == '"')
{
putc (037, outfile);
putc (defvarflag ? 'V' : 'F', outfile);
fprintf (outfile, "%s\n", buf);
1991-01-26 03:29:36 +00:00
c = read_c_string (infile, 1);
/* If this is a defun, find the arguments and print them. If
this function takes MANY or UNEVALLED args, then the C source
won't give the names of the arguments, so we shouldn't bother
trying to find them. */
if (defunflag && maxargs != -1)
1989-05-08 21:10:27 +00:00
{
char argbuf[1024], *p = argbuf;
while (c != ')')
{
if (c < 0)
goto eof;
c = getc (infile);
}
/* Skip into arguments. */
while (c != '(')
{
if (c < 0)
goto eof;
c = getc (infile);
}
/* Copy arguments into ARGBUF. */
*p++ = c;
do
*p++ = c = getc (infile);
while (c != ')');
*p = '\0';
/* Output them. */
fprintf (outfile, "\n\n");
write_c_args (outfile, buf, argbuf, minargs, maxargs);
1989-05-08 21:10:27 +00:00
}
}
}
eof:
fclose (infile);
return 0;
}
/* Read a file of Lisp code, compiled or interpreted.
Looks for
(defun NAME ARGS DOCSTRING ...)
1992-07-08 22:47:39 +00:00
(defmacro NAME ARGS DOCSTRING ...)
(defsubst NAME ARGS DOCSTRING ...)
1992-07-08 22:47:39 +00:00
(autoload (quote NAME) FILE DOCSTRING ...)
1989-05-08 21:10:27 +00:00
(defvar NAME VALUE DOCSTRING)
(defconst NAME VALUE DOCSTRING)
1992-07-08 22:47:39 +00:00
(fset (quote NAME) (make-byte-code ... DOCSTRING ...))
(fset (quote NAME) #[... DOCSTRING ...])
(defalias (quote NAME) #[... DOCSTRING ...])
(custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
1989-05-08 21:10:27 +00:00
starting in column zero.
1992-07-08 22:47:39 +00:00
(quote NAME) may appear as 'NAME as well.
We also look for #@LENGTH CONTENTS^_ at the beginning of the line.
When we find that, we save it for the following defining-form,
and we use that instead of reading a doc string within that defining-form.
1993-06-09 11:59:12 +00:00
For defvar, defconst, and fset we skip to the docstring with a kludgy
1992-07-08 22:47:39 +00:00
formatting convention: all docstrings must appear on the same line as the
initial open-paren (the one in column zero) and must contain a backslash
and a newline immediately after the initial double-quote. No newlines
1992-07-08 22:47:39 +00:00
must appear between the beginning of the form and the first double-quote.
For defun, defmacro, and autoload, we know how to skip over the
arglist, but the doc string must still have a backslash and newline
immediately after the double quote.
The only source files that must follow this convention are preloaded
uncompiled ones like loaddefs.el and bindings.el; aside
1992-07-08 22:47:39 +00:00
from that, it is always the .elc file that we look at, and they are no
problem because byte-compiler output follows this convention.
1989-05-08 21:10:27 +00:00
The NAME and DOCSTRING are output.
NAME is preceded by `F' for a function or `V' for a variable.
An entry is output only if DOCSTRING has \ newline just after the opening "
*/
1992-07-08 22:47:39 +00:00
void
skip_white (infile)
FILE *infile;
{
char c = ' ';
while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
1992-07-08 22:47:39 +00:00
c = getc (infile);
ungetc (c, infile);
}
void
read_lisp_symbol (infile, buffer)
FILE *infile;
char *buffer;
{
char c;
char *fillp = buffer;
skip_white (infile);
while (1)
{
c = getc (infile);
if (c == '\\')
*(++fillp) = getc (infile);
else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '(' || c == ')')
1992-07-08 22:47:39 +00:00
{
ungetc (c, infile);
*fillp = 0;
break;
}
else
*fillp++ = c;
}
if (! buffer[0])
fprintf (stderr, "## expected a symbol, got '%c'\n", c);
skip_white (infile);
}
1994-10-12 20:21:51 +00:00
int
scan_lisp_file (filename, mode)
char *filename, *mode;
1989-05-08 21:10:27 +00:00
{
FILE *infile;
register int c;
char *saved_string = 0;
1989-05-08 21:10:27 +00:00
infile = fopen (filename, mode);
1989-05-08 21:10:27 +00:00
if (infile == NULL)
{
perror (filename);
return 0; /* No error */
}
c = '\n';
while (!feof (infile))
{
char buffer[BUFSIZ];
1992-07-08 22:47:39 +00:00
char type;
1999-09-24 13:52:46 +00:00
/* If not at end of line, skip till we get to one. */
if (c != '\n' && c != '\r')
1989-05-08 21:10:27 +00:00
{
c = getc (infile);
continue;
}
1999-09-24 13:52:46 +00:00
/* Skip the line break. */
while (c == '\n' || c == '\r')
1999-09-24 13:52:46 +00:00
c = getc (infile);
/* Detect a dynamic doc string and save it for the next expression. */
if (c == '#')
{
c = getc (infile);
if (c == '@')
{
int length = 0;
int i;
/* Read the length. */
while ((c = getc (infile),
c >= '0' && c <= '9'))
{
length *= 10;
length += c - '0';
}
/* The next character is a space that is counted in the length
but not part of the doc string.
We already read it, so just ignore it. */
length--;
/* Read in the contents. */
if (saved_string != 0)
free (saved_string);
saved_string = (char *) malloc (length);
for (i = 0; i < length; i++)
saved_string[i] = getc (infile);
/* The last character is a ^_.
That is needed in the .elc file
but it is redundant in DOC. So get rid of it here. */
saved_string[length - 1] = 0;
1999-09-24 13:52:46 +00:00
/* Skip the line break. */
while (c == '\n' && c == '\r')
c = getc (infile);
/* Skip the following line. */
while (c != '\n' && c != '\r')
c = getc (infile);
}
continue;
}
1989-05-08 21:10:27 +00:00
if (c != '(')
continue;
1991-01-14 23:38:10 +00:00
1992-07-08 22:47:39 +00:00
read_lisp_symbol (infile, buffer);
1999-09-24 13:52:46 +00:00
if (! strcmp (buffer, "defun")
|| ! strcmp (buffer, "defmacro")
|| ! strcmp (buffer, "defsubst"))
1989-05-08 21:10:27 +00:00
{
1992-07-08 22:47:39 +00:00
type = 'F';
read_lisp_symbol (infile, buffer);
1989-05-08 21:10:27 +00:00
1992-07-08 22:47:39 +00:00
/* Skip the arguments: either "nil" or a list in parens */
1989-05-08 21:10:27 +00:00
1992-07-08 22:47:39 +00:00
c = getc (infile);
if (c == 'n') /* nil */
1989-05-08 21:10:27 +00:00
{
1999-09-24 13:52:46 +00:00
if ((c = getc (infile)) != 'i'
|| (c = getc (infile)) != 'l')
1992-07-08 22:47:39 +00:00
{
fprintf (stderr, "## unparsable arglist in %s (%s)\n",
buffer, filename);
continue;
}
1989-05-08 21:10:27 +00:00
}
1992-07-08 22:47:39 +00:00
else if (c != '(')
1989-05-08 21:10:27 +00:00
{
1992-07-08 22:47:39 +00:00
fprintf (stderr, "## unparsable arglist in %s (%s)\n",
buffer, filename);
continue;
1989-05-08 21:10:27 +00:00
}
1992-07-08 22:47:39 +00:00
else
while (c != ')')
1989-05-08 21:10:27 +00:00
c = getc (infile);
1992-07-08 22:47:39 +00:00
skip_white (infile);
/* If the next three characters aren't `dquote bslash newline'
then we're not reading a docstring.
*/
1999-09-24 13:52:46 +00:00
if ((c = getc (infile)) != '"'
|| (c = getc (infile)) != '\\'
|| ((c = getc (infile)) != '\n' && c != '\r'))
1989-05-08 21:10:27 +00:00
{
1992-07-08 22:47:39 +00:00
#ifdef DEBUG
fprintf (stderr, "## non-docstring in %s (%s)\n",
buffer, filename);
#endif
continue;
1989-05-08 21:10:27 +00:00
}
}
1991-01-14 23:38:10 +00:00
1999-09-24 13:52:46 +00:00
else if (! strcmp (buffer, "defvar")
|| ! strcmp (buffer, "defconst"))
1989-05-08 21:10:27 +00:00
{
1992-07-08 22:47:39 +00:00
char c1 = 0, c2 = 0;
type = 'V';
read_lisp_symbol (infile, buffer);
1991-01-14 23:38:10 +00:00
if (saved_string == 0)
1989-05-08 21:10:27 +00:00
{
1999-09-24 13:52:46 +00:00
/* Skip until the end of line; remember two previous chars. */
while (c != '\n' && c != '\r' && c >= 0)
{
c2 = c1;
c1 = c;
c = getc (infile);
}
1992-07-08 22:47:39 +00:00
/* If two previous characters were " and \,
this is a doc string. Otherwise, there is none. */
if (c2 != '"' || c1 != '\\')
{
1992-07-08 22:47:39 +00:00
#ifdef DEBUG
fprintf (stderr, "## non-docstring in %s (%s)\n",
buffer, filename);
1992-07-08 22:47:39 +00:00
#endif
continue;
}
1989-05-08 21:10:27 +00:00
}
1992-07-08 22:47:39 +00:00
}
else if (! strcmp (buffer, "custom-declare-variable"))
{
char c1 = 0, c2 = 0;
type = 'V';
c = getc (infile);
if (c == '\'')
read_lisp_symbol (infile, buffer);
else
{
if (c != '(')
{
fprintf (stderr,
"## unparsable name in custom-declare-variable in %s\n",
filename);
continue;
}
read_lisp_symbol (infile, buffer);
if (strcmp (buffer, "quote"))
{
fprintf (stderr,
"## unparsable name in custom-declare-variable in %s\n",
filename);
continue;
}
read_lisp_symbol (infile, buffer);
c = getc (infile);
if (c != ')')
{
fprintf (stderr,
"## unparsable quoted name in custom-declare-variable in %s\n",
filename);
continue;
}
}
if (saved_string == 0)
{
1999-09-24 13:52:46 +00:00
/* Skip to end of line; remember the two previous chars. */
while (c != '\n' && c != '\r' && c >= 0)
{
c2 = c1;
c1 = c;
c = getc (infile);
}
/* If two previous characters were " and \,
this is a doc string. Otherwise, there is none. */
if (c2 != '"' || c1 != '\\')
{
#ifdef DEBUG
fprintf (stderr, "## non-docstring in %s (%s)\n",
buffer, filename);
#endif
continue;
}
}
}
else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
1992-07-08 22:47:39 +00:00
{
char c1 = 0, c2 = 0;
type = 'F';
1991-01-14 23:38:10 +00:00
1992-07-08 22:47:39 +00:00
c = getc (infile);
if (c == '\'')
read_lisp_symbol (infile, buffer);
else
1989-05-08 21:10:27 +00:00
{
1992-07-08 22:47:39 +00:00
if (c != '(')
{
fprintf (stderr, "## unparsable name in fset in %s\n",
filename);
continue;
}
read_lisp_symbol (infile, buffer);
if (strcmp (buffer, "quote"))
{
fprintf (stderr, "## unparsable name in fset in %s\n",
filename);
continue;
}
read_lisp_symbol (infile, buffer);
1989-05-08 21:10:27 +00:00
c = getc (infile);
1992-07-08 22:47:39 +00:00
if (c != ')')
{
fprintf (stderr,
"## unparsable quoted name in fset in %s\n",
filename);
continue;
}
1989-05-08 21:10:27 +00:00
}
if (saved_string == 0)
1989-05-08 21:10:27 +00:00
{
1999-09-24 13:52:46 +00:00
/* Skip to end of line; remember the two previous chars. */
while (c != '\n' && c != '\r' && c >= 0)
{
c2 = c1;
c1 = c;
c = getc (infile);
}
1992-07-08 22:47:39 +00:00
/* If two previous characters were " and \,
this is a doc string. Otherwise, there is none. */
if (c2 != '"' || c1 != '\\')
{
1992-07-08 22:47:39 +00:00
#ifdef DEBUG
fprintf (stderr, "## non-docstring in %s (%s)\n",
buffer, filename);
1992-07-08 22:47:39 +00:00
#endif
continue;
}
1992-07-08 22:47:39 +00:00
}
}
1989-05-08 21:10:27 +00:00
1992-07-08 22:47:39 +00:00
else if (! strcmp (buffer, "autoload"))
{
type = 'F';
c = getc (infile);
if (c == '\'')
read_lisp_symbol (infile, buffer);
else
1989-05-08 21:10:27 +00:00
{
1992-07-08 22:47:39 +00:00
if (c != '(')
1989-05-08 21:10:27 +00:00
{
1992-07-08 22:47:39 +00:00
fprintf (stderr, "## unparsable name in autoload in %s\n",
filename);
continue;
1989-05-08 21:10:27 +00:00
}
1992-07-08 22:47:39 +00:00
read_lisp_symbol (infile, buffer);
if (strcmp (buffer, "quote"))
1989-05-08 21:10:27 +00:00
{
1992-07-08 22:47:39 +00:00
fprintf (stderr, "## unparsable name in autoload in %s\n",
filename);
continue;
1989-05-08 21:10:27 +00:00
}
1992-07-08 22:47:39 +00:00
read_lisp_symbol (infile, buffer);
1989-05-08 21:10:27 +00:00
c = getc (infile);
1992-07-08 22:47:39 +00:00
if (c != ')')
1989-05-08 21:10:27 +00:00
{
1992-07-08 22:47:39 +00:00
fprintf (stderr,
"## unparsable quoted name in autoload in %s\n",
filename);
continue;
1989-05-08 21:10:27 +00:00
}
1992-07-08 22:47:39 +00:00
}
skip_white (infile);
if ((c = getc (infile)) != '\"')
{
fprintf (stderr, "## autoload of %s unparsable (%s)\n",
buffer, filename);
1989-05-08 21:10:27 +00:00
continue;
}
1992-07-08 22:47:39 +00:00
read_c_string (infile, 0);
skip_white (infile);
if (saved_string == 0)
1991-01-14 23:38:10 +00:00
{
/* If the next three characters aren't `dquote bslash newline'
then we're not reading a docstring. */
1999-09-24 13:52:46 +00:00
if ((c = getc (infile)) != '"'
|| (c = getc (infile)) != '\\'
|| ((c = getc (infile)) != '\n' && c != '\r'))
{
1992-07-08 22:47:39 +00:00
#ifdef DEBUG
fprintf (stderr, "## non-docstring in %s (%s)\n",
buffer, filename);
1992-07-08 22:47:39 +00:00
#endif
continue;
}
1991-01-14 23:38:10 +00:00
}
}
1989-05-08 21:10:27 +00:00
1992-07-08 22:47:39 +00:00
#ifdef DEBUG
1999-09-24 13:52:46 +00:00
else if (! strcmp (buffer, "if")
|| ! strcmp (buffer, "byte-code"))
1992-07-08 22:47:39 +00:00
;
#endif
1989-05-08 21:10:27 +00:00
1992-07-08 22:47:39 +00:00
else
{
#ifdef DEBUG
fprintf (stderr, "## unrecognised top-level form, %s (%s)\n",
buffer, filename);
#endif
continue;
}
1989-05-08 21:10:27 +00:00
/* At this point, we should either use the previous
dynamic doc string in saved_string
or gobble a doc string from the input file.
In the latter case, the opening quote (and leading
backslash-newline) have already been read. */
1989-05-08 21:10:27 +00:00
putc (037, outfile);
1992-07-08 22:47:39 +00:00
putc (type, outfile);
fprintf (outfile, "%s\n", buffer);
if (saved_string)
{
fputs (saved_string, outfile);
/* Don't use one dynamic doc string twice. */
free (saved_string);
saved_string = 0;
}
else
read_c_string (infile, 1);
1989-05-08 21:10:27 +00:00
}
fclose (infile);
return 0;
}