mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-06 06:20:55 -08:00
Revert part of 59732a83c8 to fix bug#52969
While we don't need to put docstrings of .elc files into etc/DOC, we still need to put those of `loaddefs.el` there since we don't have a "dynamic docstring" feature for the non-compiled files and keeping the actual docstrings in the heap would be prohibitive. * src/Makefile.in ($(etc)/DOC): Scan `lisp/loaddefs.el` still. * lib-src/make-docfile.c (scan_lisp_file): New function. (scan_file): Use it. (skip_white, read_lisp_symbol, search_lisp_doc_at_eol): New functions.
This commit is contained in:
parent
ab5ee3e29e
commit
460f35e96d
2 changed files with 362 additions and 4 deletions
|
|
@ -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/>. */
|
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
|
||||||
/* The arguments given to this program are all the C files
|
/* The arguments given to this program are all the C and some Lisp source files
|
||||||
of GNU Emacs. .c files are allowed.
|
of GNU Emacs. .el and .c files are allowed.
|
||||||
A .o file can also be specified; the .c file it was made from is used.
|
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.
|
This helps the makefile pass the correct list of files.
|
||||||
Option -d DIR means change to DIR before looking for files.
|
Option -d DIR means change to DIR before looking for files.
|
||||||
|
|
@ -65,6 +65,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
#endif /* not DOS_NT */
|
#endif /* not DOS_NT */
|
||||||
|
|
||||||
static void scan_file (char *filename);
|
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_file (char *filename, const char *mode);
|
||||||
static void scan_c_stream (FILE *infile);
|
static void scan_c_stream (FILE *infile);
|
||||||
static void start_globals (void);
|
static void start_globals (void);
|
||||||
|
|
@ -234,9 +235,14 @@ put_filename (char *filename)
|
||||||
static void
|
static void
|
||||||
scan_file (char *filename)
|
scan_file (char *filename)
|
||||||
{
|
{
|
||||||
|
ptrdiff_t len = strlen (filename);
|
||||||
|
|
||||||
if (!generate_globals)
|
if (!generate_globals)
|
||||||
put_filename (filename);
|
put_filename (filename);
|
||||||
scan_c_file (filename, "r");
|
if (len > 3 && !strcmp (filename + len - 3, ".el"))
|
||||||
|
scan_lisp_file (filename, "r");
|
||||||
|
else
|
||||||
|
scan_c_file (filename, "r");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1214,4 +1220,354 @@ scan_c_stream (FILE *infile)
|
||||||
fatal ("read error");
|
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;
|
||||||
|
int i;
|
||||||
|
int flen = strlen (filename);
|
||||||
|
|
||||||
|
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 */
|
/* make-docfile.c ends here */
|
||||||
|
|
|
||||||
|
|
@ -642,11 +642,13 @@ endif
|
||||||
## for the first time, this prevents any variation between configurations
|
## for the first time, this prevents any variation between configurations
|
||||||
## in the contents of the DOC file.
|
## in the contents of the DOC file.
|
||||||
##
|
##
|
||||||
$(etc)/DOC: $(libsrc)/make-docfile$(EXEEXT) $(doc_obj)
|
$(etc)/DOC: $(libsrc)/make-docfile$(EXEEXT) $(doc_obj) $(lispsource)/loaddefs.el
|
||||||
$(AM_V_GEN)$(MKDIR_P) $(etc)
|
$(AM_V_GEN)$(MKDIR_P) $(etc)
|
||||||
$(AM_V_at)rm -f $(etc)/DOC
|
$(AM_V_at)rm -f $(etc)/DOC
|
||||||
$(AM_V_at)$(libsrc)/make-docfile -d $(srcdir) \
|
$(AM_V_at)$(libsrc)/make-docfile -d $(srcdir) \
|
||||||
$(SOME_MACHINE_OBJECTS) $(doc_obj) > $(etc)/DOC
|
$(SOME_MACHINE_OBJECTS) $(doc_obj) > $(etc)/DOC
|
||||||
|
$(AM_V_at)$(libsrc)/make-docfile -a $(etc)/DOC -d $(lispsource) \
|
||||||
|
loaddefs.el
|
||||||
|
|
||||||
$(libsrc)/make-docfile$(EXEEXT) $(libsrc)/make-fingerprint$(EXEEXT): \
|
$(libsrc)/make-docfile$(EXEEXT) $(libsrc)/make-fingerprint$(EXEEXT): \
|
||||||
$(lib)/libgnu.a
|
$(lib)/libgnu.a
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue