1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-27 10:54:40 +00:00

Revert "Revert part of 59732a83c8 to fix bug#52969"

This reverts commit 460f35e96d.

Re-remove the code that scans .el files for docstrings, now
that even `lisp/loaddefs.el` is compiled.

* lib-src/make-docfile.c (scan_file): Don't call `scan_lisp_file`.
(scan_lisp_file, skip_white, read_lisp_symbol, search_lisp_doc_at_eol):
Delete functions.
This commit is contained in:
Stefan Monnier 2022-08-03 17:02:25 -04:00
parent eb2f394289
commit 9e9b0e13bc

View File

@ -19,8 +19,8 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
/* The arguments given to this program are all the C and some Lisp source files
of GNU Emacs. .el and .c files are allowed.
/* The arguments given to this program are all the C files
of GNU Emacs. .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.
Option -d DIR means change to DIR before looking for files.
@ -66,7 +66,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#endif /* not DOS_NT */
static void scan_file (char *filename);
static void scan_lisp_file (const char *filename, const char *mode);
static void scan_c_file (char *filename, const char *mode);
static void scan_c_stream (FILE *infile);
static void start_globals (void);
@ -236,13 +235,8 @@ put_filename (char *filename)
static void
scan_file (char *filename)
{
ptrdiff_t len = strlen (filename);
if (!generate_globals)
put_filename (filename);
if (len > 3 && !strcmp (filename + len - 3, ".el"))
scan_lisp_file (filename, "r");
else
scan_c_file (filename, "r");
}
@ -1221,352 +1215,4 @@ scan_c_stream (FILE *infile)
fatal ("read error");
}
/* Read a file of Lisp source code.
Looks for
(defun NAME ARGS DOCSTRING ...)
(defmacro NAME ARGS DOCSTRING ...)
(defsubst NAME ARGS DOCSTRING ...)
(autoload (quote NAME) FILE DOCSTRING ...)
(defvar NAME VALUE DOCSTRING)
(defconst NAME VALUE DOCSTRING)
(fset (quote NAME) (make-byte-code ... DOCSTRING ...))
(fset (quote NAME) #[... DOCSTRING ...])
(defalias (quote NAME) #[... DOCSTRING ...])
(custom-declare-variable (quote NAME) VALUE DOCSTRING ...)
starting in column zero.
(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.
For defvar, defconst, and fset we skip to the docstring with a kludgy
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
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 follow this convention are autoload-generated
files like loaddefs.el;
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 ".
*/
static void
skip_white (FILE *infile)
{
int c;
do
c = getc (infile);
while (c_isspace (c));
ungetc (c, infile);
}
static void
read_lisp_symbol (FILE *infile, char *buffer)
{
int c;
char *fillp = buffer;
skip_white (infile);
while (true)
{
c = getc (infile);
if (c == '\\')
{
c = getc (infile);
if (c < 0)
return;
*fillp++ = c;
}
else if (c_isspace (c) || c == '(' || c == ')' || c < 0)
{
ungetc (c, infile);
*fillp = 0;
break;
}
else
*fillp++ = c;
}
if (! buffer[0])
fprintf (stderr, "## expected a symbol, got '%c'\n", c);
skip_white (infile);
}
static bool
search_lisp_doc_at_eol (FILE *infile)
{
int c = 0, c1 = 0, c2 = 0;
/* Skip until the end of line; remember two previous chars. */
while (c != '\n' && c != '\r' && c != EOF)
{
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 found\n");
#endif
ungetc (c, infile);
return false;
}
return true;
}
static void
scan_lisp_file (const char *filename, const char *mode)
{
FILE *infile;
int c;
if (generate_globals)
fatal ("scanning lisp file when -g specified");
infile = fopen (filename, mode);
if (infile == NULL)
{
perror (filename);
exit (EXIT_FAILURE);
}
c = '\n';
while (!feof (infile))
{
char buffer[BUFSIZ];
char type;
/* If not at end of line, skip till we get to one. */
if (c != '\n' && c != '\r')
{
c = getc (infile);
continue;
}
/* Skip the line break. */
while (c == '\n' || c == '\r')
c = getc (infile);
if (c != '(')
continue;
read_lisp_symbol (infile, buffer);
if (! strcmp (buffer, "defun")
|| ! strcmp (buffer, "defmacro")
|| ! strcmp (buffer, "defsubst"))
{
type = 'F';
read_lisp_symbol (infile, buffer);
/* Skip the arguments: either "nil" or a list in parens. */
c = getc (infile);
if (c == 'n') /* nil */
{
if ((c = getc (infile)) != 'i'
|| (c = getc (infile)) != 'l')
{
fprintf (stderr, "## unparsable arglist in %s (%s)\n",
buffer, filename);
continue;
}
}
else if (c != '(')
{
fprintf (stderr, "## unparsable arglist in %s (%s)\n",
buffer, filename);
continue;
}
else
while (! (c == ')' || c < 0))
c = getc (infile);
skip_white (infile);
/* If the next three characters aren't `dquote bslash newline'
then we're not reading a docstring.
*/
if ((c = getc (infile)) != '"'
|| (c = getc (infile)) != '\\'
|| ((c = getc (infile)) != '\n' && c != '\r'))
{
#ifdef DEBUG
fprintf (stderr, "## non-docstring in %s (%s)\n",
buffer, filename);
#endif
continue;
}
}
else if (! strcmp (buffer, "defvar")
|| ! strcmp (buffer, "defconst")
|| ! strcmp (buffer, "defcustom"))
{
type = 'V';
read_lisp_symbol (infile, buffer);
if (!search_lisp_doc_at_eol (infile))
continue;
}
else if (! strcmp (buffer, "custom-declare-variable")
|| ! strcmp (buffer, "defvaralias")
)
{
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 (!search_lisp_doc_at_eol (infile))
continue;
}
else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias"))
{
type = 'F';
c = getc (infile);
if (c == '\'')
read_lisp_symbol (infile, buffer);
else
{
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);
c = getc (infile);
if (c != ')')
{
fprintf (stderr,
"## unparsable quoted name in fset in %s\n",
filename);
continue;
}
}
if (!search_lisp_doc_at_eol (infile))
continue;
}
else if (! strcmp (buffer, "autoload"))
{
type = 'F';
c = getc (infile);
if (c == '\'')
read_lisp_symbol (infile, buffer);
else
{
if (c != '(')
{
fprintf (stderr, "## unparsable name in autoload in %s\n",
filename);
continue;
}
read_lisp_symbol (infile, buffer);
if (strcmp (buffer, "quote"))
{
fprintf (stderr, "## unparsable name in autoload in %s\n",
filename);
continue;
}
read_lisp_symbol (infile, buffer);
c = getc (infile);
if (c != ')')
{
fprintf (stderr,
"## unparsable quoted name in autoload in %s\n",
filename);
continue;
}
}
skip_white (infile);
c = getc (infile);
if (c != '\"')
{
fprintf (stderr, "## autoload of %s unparsable (%s)\n",
buffer, filename);
continue;
}
read_c_string_or_comment (infile, 0, false, 0);
if (!search_lisp_doc_at_eol (infile))
continue;
}
#ifdef DEBUG
else if (! strcmp (buffer, "if")
|| ! strcmp (buffer, "byte-code"))
continue;
#endif
else
{
#ifdef DEBUG
fprintf (stderr, "## unrecognized top-level form, %s (%s)\n",
buffer, filename);
#endif
continue;
}
/* At this point, we should gobble a doc string from the input file.
The opening quote (and leading backslash-newline)
have already been read. */
printf ("\037%c%s\n", type, buffer);
read_c_string_or_comment (infile, 1, false, 0);
}
if (ferror (infile) || fclose (infile) != 0)
fatal ("%s: read error", filename);
}
/* make-docfile.c ends here */