rcfile: fully read each included file, so all its syntaxes are seen
An included file can contain multiple syntaxes. If reading would stop
as soon as a command different from 'syntax' and 'header' and 'magic'
is found, any later syntaxes would not be seen. So each nanorc file
needs to be fully scanned -- it's just the interpretation of all the
color commands that we want to delay until the syntax gets actually
used.
This fixes https://savannah.gnu.org/bugs/?56478.
Bug existed since commit cba9d8d0
from a month ago.
master
parent
d7df7c694a
commit
7028adf211
|
@ -224,6 +224,8 @@ typedef struct syntaxtype {
|
||||||
/* The name of this syntax. */
|
/* The name of this syntax. */
|
||||||
char *filename;
|
char *filename;
|
||||||
/* File where the syntax is defined, or NULL if not an included file. */
|
/* File where the syntax is defined, or NULL if not an included file. */
|
||||||
|
size_t lineno;
|
||||||
|
/* The line number where the 'syntax' command was found. */
|
||||||
struct augmentstruct *augmentations;
|
struct augmentstruct *augmentations;
|
||||||
/* List of extendsyntax commands to apply when loaded. */
|
/* List of extendsyntax commands to apply when loaded. */
|
||||||
regexlisttype *extensions;
|
regexlisttype *extensions;
|
||||||
|
|
51
src/rcfile.c
51
src/rcfile.c
|
@ -330,7 +330,8 @@ void begin_a_syntax(char *ptr, bool headers_only)
|
||||||
/* Initialize a new syntax struct. */
|
/* Initialize a new syntax struct. */
|
||||||
live_syntax = (syntaxtype *)nmalloc(sizeof(syntaxtype));
|
live_syntax = (syntaxtype *)nmalloc(sizeof(syntaxtype));
|
||||||
live_syntax->name = mallocstrcpy(NULL, nameptr);
|
live_syntax->name = mallocstrcpy(NULL, nameptr);
|
||||||
live_syntax->filename = (headers_only ? strdup(nanorc) : NULL);
|
live_syntax->filename = strdup(nanorc);
|
||||||
|
live_syntax->lineno = lineno;
|
||||||
live_syntax->augmentations = NULL;
|
live_syntax->augmentations = NULL;
|
||||||
live_syntax->extensions = NULL;
|
live_syntax->extensions = NULL;
|
||||||
live_syntax->headers = NULL;
|
live_syntax->headers = NULL;
|
||||||
|
@ -989,6 +990,7 @@ bool parse_syntax_commands(char *keyword, char *ptr)
|
||||||
* to contain only color syntax commands. */
|
* to contain only color syntax commands. */
|
||||||
void parse_rcfile(FILE *rcstream, bool syntax_only, bool headers_only)
|
void parse_rcfile(FILE *rcstream, bool syntax_only, bool headers_only)
|
||||||
{
|
{
|
||||||
|
bool seen_color_command = FALSE;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
|
@ -1003,6 +1005,11 @@ void parse_rcfile(FILE *rcstream, bool syntax_only, bool headers_only)
|
||||||
buf[len - 1] = '\0';
|
buf[len - 1] = '\0';
|
||||||
|
|
||||||
lineno++;
|
lineno++;
|
||||||
|
|
||||||
|
/* If doing a full parse, skip to after the 'syntax' command. */
|
||||||
|
if (!headers_only && syntax_only && lineno <= live_syntax->lineno)
|
||||||
|
continue;
|
||||||
|
|
||||||
ptr = buf;
|
ptr = buf;
|
||||||
while (isblank((unsigned char)*ptr))
|
while (isblank((unsigned char)*ptr))
|
||||||
ptr++;
|
ptr++;
|
||||||
|
@ -1063,32 +1070,44 @@ void parse_rcfile(FILE *rcstream, bool syntax_only, bool headers_only)
|
||||||
|
|
||||||
/* Try to parse the keyword. */
|
/* Try to parse the keyword. */
|
||||||
if (strcasecmp(keyword, "syntax") == 0) {
|
if (strcasecmp(keyword, "syntax") == 0) {
|
||||||
if (headers_only || !syntax_only) {
|
if (headers_only) {
|
||||||
if (opensyntax && lastcolor == NULL && live_syntax->filename == NULL)
|
if (opensyntax && !seen_color_command)
|
||||||
rcfile_error(N_("Syntax \"%s\" has no color commands"),
|
rcfile_error(N_("Syntax \"%s\" has no color commands"),
|
||||||
live_syntax->name);
|
live_syntax->name);
|
||||||
begin_a_syntax(ptr, headers_only);
|
begin_a_syntax(ptr, headers_only);
|
||||||
}
|
seen_color_command = FALSE;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
} else if (strcasecmp(keyword, "header") == 0) {
|
} else if (strcasecmp(keyword, "header") == 0) {
|
||||||
if (headers_only || !syntax_only)
|
if (headers_only)
|
||||||
grab_and_store("header", ptr, &live_syntax->headers);
|
grab_and_store("header", ptr, &live_syntax->headers);
|
||||||
} else if (strcasecmp(keyword, "magic") == 0) {
|
} else if (strcasecmp(keyword, "magic") == 0) {
|
||||||
#ifdef HAVE_LIBMAGIC
|
#ifdef HAVE_LIBMAGIC
|
||||||
if (headers_only || !syntax_only)
|
if (headers_only)
|
||||||
grab_and_store("magic", ptr, &live_syntax->magics);
|
grab_and_store("magic", ptr, &live_syntax->magics);
|
||||||
#endif
|
#endif
|
||||||
} else if (headers_only)
|
} else if (syntax_only && (strcasecmp(keyword, "set") == 0 ||
|
||||||
break;
|
|
||||||
else if (parse_syntax_commands(keyword, ptr))
|
|
||||||
;
|
|
||||||
else if (syntax_only && (strcasecmp(keyword, "set") == 0 ||
|
|
||||||
strcasecmp(keyword, "unset") == 0 ||
|
strcasecmp(keyword, "unset") == 0 ||
|
||||||
strcasecmp(keyword, "bind") == 0 ||
|
strcasecmp(keyword, "bind") == 0 ||
|
||||||
strcasecmp(keyword, "unbind") == 0 ||
|
strcasecmp(keyword, "unbind") == 0 ||
|
||||||
strcasecmp(keyword, "include") == 0 ||
|
strcasecmp(keyword, "include") == 0 ||
|
||||||
strcasecmp(keyword, "extendsyntax") == 0))
|
strcasecmp(keyword, "extendsyntax") == 0)) {
|
||||||
rcfile_error(N_("Command \"%s\" not allowed in included file"),
|
if (headers_only)
|
||||||
|
rcfile_error(N_("Command \"%s\" not allowed in included file"),
|
||||||
keyword);
|
keyword);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} else if (headers_only && opensyntax &&
|
||||||
|
(strcasecmp(keyword, "color") == 0 ||
|
||||||
|
strcasecmp(keyword, "icolor") == 0)) {
|
||||||
|
seen_color_command = TRUE;
|
||||||
|
continue;
|
||||||
|
} else if (headers_only && opensyntax &&
|
||||||
|
(strcasecmp(keyword, "comment") == 0 ||
|
||||||
|
strcasecmp(keyword, "linter") == 0)) {
|
||||||
|
continue;
|
||||||
|
} else if (parse_syntax_commands(keyword, ptr))
|
||||||
|
;
|
||||||
else if (strcasecmp(keyword, "include") == 0)
|
else if (strcasecmp(keyword, "include") == 0)
|
||||||
parse_includes(ptr);
|
parse_includes(ptr);
|
||||||
else
|
else
|
||||||
|
@ -1101,7 +1120,7 @@ void parse_rcfile(FILE *rcstream, bool syntax_only, bool headers_only)
|
||||||
parse_binding(ptr, TRUE);
|
parse_binding(ptr, TRUE);
|
||||||
else if (strcasecmp(keyword, "unbind") == 0)
|
else if (strcasecmp(keyword, "unbind") == 0)
|
||||||
parse_binding(ptr, FALSE);
|
parse_binding(ptr, FALSE);
|
||||||
else
|
else if (headers_only)
|
||||||
rcfile_error(N_("Command \"%s\" not understood"), keyword);
|
rcfile_error(N_("Command \"%s\" not understood"), keyword);
|
||||||
|
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_COLOR
|
||||||
|
@ -1270,7 +1289,7 @@ void parse_rcfile(FILE *rcstream, bool syntax_only, bool headers_only)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_COLOR
|
||||||
if (opensyntax && lastcolor == NULL && !headers_only)
|
if (headers_only && !seen_color_command)
|
||||||
rcfile_error(N_("Syntax \"%s\" has no color commands"),
|
rcfile_error(N_("Syntax \"%s\" has no color commands"),
|
||||||
live_syntax->name);
|
live_syntax->name);
|
||||||
|
|
||||||
|
@ -1298,7 +1317,7 @@ void parse_one_nanorc(void)
|
||||||
/* If opening the file succeeded, parse it. Otherwise, only
|
/* If opening the file succeeded, parse it. Otherwise, only
|
||||||
* complain if the file actually exists. */
|
* complain if the file actually exists. */
|
||||||
if (rcstream != NULL)
|
if (rcstream != NULL)
|
||||||
parse_rcfile(rcstream, FALSE, FALSE);
|
parse_rcfile(rcstream, FALSE, TRUE);
|
||||||
else if (errno != ENOENT)
|
else if (errno != ENOENT)
|
||||||
rcfile_error(N_("Error reading %s: %s"), nanorc, strerror(errno));
|
rcfile_error(N_("Error reading %s: %s"), nanorc, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue