add DB's overhaul of the rcfile parsing code and related miscellaneous

bits


git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2345 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
This commit is contained in:
David Lawrence Ramsey 2005-03-10 20:55:11 +00:00
parent 40f11ae622
commit 202d3c2f97
10 changed files with 294 additions and 294 deletions

View File

@ -162,6 +162,15 @@ CVS code -
routine to get the current user's home directory into the new routine to get the current user's home directory into the new
function get_homedir(), and use it where necessary. Also add function get_homedir(), and use it where necessary. Also add
a few miscellaneous tweaks. a few miscellaneous tweaks.
- Overhaul the rcfile parsing code to make it simpler and more
accurate, remove now-redundant checks from the color code,
change the COLOR_SYNTAX toggle to the NO_COLOR_SYMTAX toggle,
and improve various debugging messsages. Changes to
set_colorpairs(), do_colorinit(), parse_next_word(),
parse_argument(), colortoint(), parse_next_regex(),
parse_syntax(), parse_colors(), parse_rcfile(), do_rcfile(),
etc. (David Benbennick) DLR: Rename colortoint() to
color_to_int(), and add a few miscellaneous tweaks.
- cut.c: - cut.c:
do_cut_text() do_cut_text()
- If keep_cutbuffer is FALSE, only blow away the text in the - If keep_cutbuffer is FALSE, only blow away the text in the

View File

@ -2,7 +2,7 @@
/************************************************************************** /**************************************************************************
* color.c * * color.c *
* * * *
* Copyright (C) 1999-2004 Chris Allegretta * * Copyright (C) 1999-2005 Chris Allegretta *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by * * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2, or (at your option) * * the Free Software Foundation; either version 2, or (at your option) *
@ -46,14 +46,14 @@ void set_colorpairs(void)
for (; this_color != NULL; this_color = this_color->next) { for (; this_color != NULL; this_color = this_color->next) {
const colortype *beforenow = this_syntax->color; const colortype *beforenow = this_syntax->color;
for (; beforenow != NULL && beforenow != this_color && for (; beforenow != this_color &&
(beforenow->fg != this_color->fg || (beforenow->fg != this_color->fg ||
beforenow->bg != this_color->bg || beforenow->bg != this_color->bg ||
beforenow->bright != this_color->bright); beforenow->bright != this_color->bright);
beforenow = beforenow->next) beforenow = beforenow->next)
; ;
if (beforenow != NULL && beforenow != this_color) if (beforenow != this_color)
this_color->pairnum = beforenow->pairnum; this_color->pairnum = beforenow->pairnum;
else { else {
this_color->pairnum = color_pair; this_color->pairnum = color_pair;
@ -68,14 +68,14 @@ void do_colorinit(void)
if (has_colors()) { if (has_colors()) {
const colortype *tmpcolor = NULL; const colortype *tmpcolor = NULL;
#ifdef HAVE_USE_DEFAULT_COLORS #ifdef HAVE_USE_DEFAULT_COLORS
int defok; bool defok;
#endif #endif
start_color(); start_color();
/* Add in colors, if available */
/* Add in colors, if available. */
#ifdef HAVE_USE_DEFAULT_COLORS #ifdef HAVE_USE_DEFAULT_COLORS
defok = use_default_colors() != ERR; defok = (use_default_colors() != ERR);
#endif #endif
for (tmpcolor = colorstrings; tmpcolor != NULL; for (tmpcolor = colorstrings; tmpcolor != NULL;
@ -91,8 +91,8 @@ void do_colorinit(void)
init_pair(tmpcolor->pairnum, tmpcolor->fg, background); init_pair(tmpcolor->pairnum, tmpcolor->fg, background);
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Running %s with fg = %d and bg = %d\n", fprintf(stderr, "init_pair(): fg = %d, bg = %d\n",
"init_pair()", tmpcolor->fg, tmpcolor->bg); tmpcolor->fg, tmpcolor->bg);
#endif #endif
} }
} }
@ -104,11 +104,12 @@ void update_color(void)
const syntaxtype *tmpsyntax; const syntaxtype *tmpsyntax;
colorstrings = NULL; colorstrings = NULL;
for (tmpsyntax = syntaxes; tmpsyntax != NULL; tmpsyntax = tmpsyntax->next) { for (tmpsyntax = syntaxes; tmpsyntax != NULL;
tmpsyntax = tmpsyntax->next) {
const exttype *e; const exttype *e;
for (e = tmpsyntax->extensions; e != NULL; e = e->next) { for (e = tmpsyntax->extensions; e != NULL; e = e->next) {
/* Set colorstrings if we matched the extension regex */ /* Set colorstrings if we matched the extension regex. */
if (regexec(&e->val, filename, 0, NULL, 0) == 0) if (regexec(&e->val, filename, 0, NULL, 0) == 0)
colorstrings = tmpsyntax->color; colorstrings = tmpsyntax->color;
@ -117,10 +118,10 @@ void update_color(void)
} }
} }
/* if we haven't found a match, use the override string */ /* If we haven't found a match, use the override string. */
if (colorstrings == NULL && syntaxstr != NULL) { if (colorstrings == NULL && syntaxstr != NULL) {
for (tmpsyntax = syntaxes; tmpsyntax != NULL; for (tmpsyntax = syntaxes; tmpsyntax != NULL;
tmpsyntax = tmpsyntax->next) { tmpsyntax = tmpsyntax->next) {
if (strcasecmp(tmpsyntax->desc, syntaxstr) == 0) if (strcasecmp(tmpsyntax->desc, syntaxstr) == 0)
colorstrings = tmpsyntax->color; colorstrings = tmpsyntax->color;
} }

View File

@ -54,7 +54,7 @@ void new_file(void)
#ifdef ENABLE_COLOR #ifdef ENABLE_COLOR
update_color(); update_color();
if (ISSET(COLOR_SYNTAX)) if (!ISSET(NO_COLOR_SYNTAX))
edit_refresh(); edit_refresh();
#endif #endif
} }
@ -675,7 +675,7 @@ void do_insertfile(
break; break;
} }
} /* while (TRUE) */ }
free(ans); free(ans);
} }
@ -1640,7 +1640,7 @@ int write_file(const char *name, bool tmp, int append, bool
filename = mallocstrcpy(filename, realname); filename = mallocstrcpy(filename, realname);
#ifdef ENABLE_COLOR #ifdef ENABLE_COLOR
update_color(); update_color();
if (ISSET(COLOR_SYNTAX)) if (!ISSET(NO_COLOR_SYNTAX))
edit_refresh(); edit_refresh();
#endif #endif
} }

View File

@ -1106,7 +1106,7 @@ void toggle_init(void)
SMART_HOME); SMART_HOME);
#ifdef ENABLE_COLOR #ifdef ENABLE_COLOR
toggle_init_one(TOGGLE_SYNTAX_KEY, N_("Color syntax highlighting"), toggle_init_one(TOGGLE_SYNTAX_KEY, N_("Color syntax highlighting"),
COLOR_SYNTAX); NO_COLOR_SYNTAX);
#endif #endif
#ifdef ENABLE_NANORC #ifdef ENABLE_NANORC
toggle_init_one(TOGGLE_WHITESPACE_KEY, N_("Whitespace display"), toggle_init_one(TOGGLE_WHITESPACE_KEY, N_("Whitespace display"),

View File

@ -1299,7 +1299,7 @@ void do_delete(void)
#ifdef ENABLE_COLOR #ifdef ENABLE_COLOR
/* If color syntaxes are turned on, we need to call /* If color syntaxes are turned on, we need to call
* edit_refresh(). */ * edit_refresh(). */
if (ISSET(COLOR_SYNTAX)) if (!ISSET(NO_COLOR_SYNTAX))
do_refresh = TRUE; do_refresh = TRUE;
#endif #endif
@ -3833,7 +3833,7 @@ void do_output(char *output, size_t output_len)
#ifdef ENABLE_COLOR #ifdef ENABLE_COLOR
/* If color syntaxes are turned on, we need to call /* If color syntaxes are turned on, we need to call
* edit_refresh(). */ * edit_refresh(). */
if (ISSET(COLOR_SYNTAX)) if (!ISSET(NO_COLOR_SYNTAX))
do_refresh = TRUE; do_refresh = TRUE;
#endif #endif
} }

View File

@ -291,7 +291,7 @@ typedef struct historyheadtype {
#define NO_CONVERT (1<<19) #define NO_CONVERT (1<<19)
#define BACKUP_FILE (1<<20) #define BACKUP_FILE (1<<20)
#define NO_RCFILE (1<<21) #define NO_RCFILE (1<<21)
#define COLOR_SYNTAX (1<<22) #define NO_COLOR_SYNTAX (1<<22)
#define PRESERVE (1<<23) #define PRESERVE (1<<23)
#define HISTORY_CHANGED (1<<24) #define HISTORY_CHANGED (1<<24)
#define HISTORYLOG (1<<25) #define HISTORYLOG (1<<25)

View File

@ -462,9 +462,9 @@ void rcfile_error(const char *msg, ...);
char *parse_next_word(char *ptr); char *parse_next_word(char *ptr);
char *parse_argument(char *ptr); char *parse_argument(char *ptr);
#ifdef ENABLE_COLOR #ifdef ENABLE_COLOR
int colortoint(const char *colorname, int *bright); int color_to_int(const char *colorname, bool *bright);
char *parse_next_regex(char *ptr); char *parse_next_regex(char *ptr);
int nregcomp(regex_t *preg, const char *regex, int eflags); bool nregcomp(regex_t *preg, const char *regex, int eflags);
void parse_syntax(char *ptr); void parse_syntax(char *ptr);
void parse_colors(char *ptr); void parse_colors(char *ptr);
#endif /* ENABLE_COLOR */ #endif /* ENABLE_COLOR */

View File

@ -29,7 +29,6 @@
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h>
#include <ctype.h> #include <ctype.h>
#include <assert.h> #include <assert.h>
#include "proto.h" #include "proto.h"
@ -102,10 +101,16 @@ const static rcoption rcopts[] = {
static bool errors = FALSE; static bool errors = FALSE;
static int lineno = 0; static int lineno = 0;
static const char *nanorc; static char *nanorc = NULL;
#ifdef ENABLE_COLOR
static syntaxtype *endsyntax = NULL;
/* The end of the list of syntaxes. */
static colortype *endcolor = NULL;
/* The end of the color list for the current syntax. */
#endif
/* We have an error in some part of the rcfile; put it on stderr and /* We have an error in some part of the rcfile. Put it on stderr and
make the user hit return to continue starting up nano. */ * make the user hit return to continue starting up nano. */
void rcfile_error(const char *msg, ...) void rcfile_error(const char *msg, ...)
{ {
va_list ap; va_list ap;
@ -123,17 +128,18 @@ void rcfile_error(const char *msg, ...)
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
/* Parse the next word from the string. Returns NULL if we hit EOL. */ /* Parse the next word from the string. Return points to '\0' if we hit
* the end of the line. */
char *parse_next_word(char *ptr) char *parse_next_word(char *ptr)
{ {
while (!is_blank_char(*ptr) && *ptr != '\n' && *ptr != '\0') while (!is_blank_char(*ptr) && *ptr != '\0')
ptr++; ptr++;
if (*ptr == '\0') if (*ptr == '\0')
return NULL; return ptr;
/* Null terminate and advance ptr */ /* Null-terminate and advance ptr. */
*ptr++ = 0; *ptr++ = '\0';
while (is_blank_char(*ptr)) while (is_blank_char(*ptr))
ptr++; ptr++;
@ -141,13 +147,13 @@ char *parse_next_word(char *ptr)
return ptr; return ptr;
} }
/* The keywords operatingdir, backupdir, fill, tabsize, speller, /* The keywords operatingdir, backupdir, fill, tabsize, speller, punct,
* punct, brackets, quotestr, and whitespace take an argument when set. * brackets, quotestr, and whitespace take an argument when set. Among
* Among these, operatingdir, backupdir, speller, punct, brackets, * these, operatingdir, backupdir, speller, punct, brackets, quotestr,
* quotestr, and whitespace have to allow tabs and spaces in the * and whitespace have to allow tabs and spaces in the argument. Thus,
* argument. Thus, if the next word starts with a ", we say it ends * if the next word starts with a ", we say it ends with the last " of
* with the last " of the line. Otherwise, the word is interpreted as * the line. Otherwise, the word is interpreted as usual. That is so
* usual. That is so the arguments can contain "s too. */ * the arguments can contain "s too. */
char *parse_argument(char *ptr) char *parse_argument(char *ptr)
{ {
const char *ptr_bak = ptr; const char *ptr_bak = ptr;
@ -162,7 +168,7 @@ char *parse_argument(char *ptr)
ptr++; ptr++;
if (*ptr == '"') if (*ptr == '"')
last_quote = ptr; last_quote = ptr;
} while (*ptr != '\n' && *ptr != '\0'); } while (*ptr != '\0');
if (last_quote == NULL) { if (last_quote == NULL) {
if (*ptr == '\0') if (*ptr == '\0')
@ -181,16 +187,19 @@ char *parse_argument(char *ptr)
} }
#ifdef ENABLE_COLOR #ifdef ENABLE_COLOR
int color_to_int(const char *colorname, bool *bright)
int colortoint(const char *colorname, int *bright)
{ {
int mcolor = 0; int mcolor = -1;
if (colorname == NULL) if (colorname == NULL) {
rcfile_error(N_("Missing color name"));
return -1; return -1;
}
assert(bright != NULL);
if (strncasecmp(colorname, "bright", 6) == 0) { if (strncasecmp(colorname, "bright", 6) == 0) {
*bright = 1; *bright = TRUE;
colorname += 6; colorname += 6;
} }
@ -210,25 +219,32 @@ int colortoint(const char *colorname, int *bright)
mcolor = COLOR_MAGENTA; mcolor = COLOR_MAGENTA;
else if (strcasecmp(colorname, "black") == 0) else if (strcasecmp(colorname, "black") == 0)
mcolor = COLOR_BLACK; mcolor = COLOR_BLACK;
else { else
rcfile_error(N_("Color %s not understood.\n" rcfile_error(N_("Color %s not understood.\n"
"Valid colors are \"green\", \"red\", \"blue\", \n" "Valid colors are \"green\", \"red\", \"blue\",\n"
"\"white\", \"yellow\", \"cyan\", \"magenta\" and \n" "\"white\", \"yellow\", \"cyan\", \"magenta\" and\n"
"\"black\", with the optional prefix \"bright\" \n" "\"black\", with the optional prefix \"bright\"\n"
"for foreground colors."), colorname); "for foreground colors."), colorname);
mcolor = -1;
}
return mcolor; return mcolor;
} }
char *parse_next_regex(char *ptr) char *parse_next_regex(char *ptr)
{ {
while ((*ptr != '"' || (*(ptr + 1) != ' ' && *(ptr + 1) != '\n')) assert(ptr != NULL);
&& *ptr != '\n' && *ptr != '\0')
/* Continue until the end of the line, or a " followed by a space, a
* blank character, or \0. */
while ((*ptr != '"' || (!is_blank_char(*(ptr + 1)) &&
*(ptr + 1) != '\0')) && *ptr != '\0')
ptr++; ptr++;
if (*ptr == '\0') assert(*ptr == '"' || *ptr == '\0');
if (*ptr == '\0') {
rcfile_error(N_("Regex strings must begin and end with a \" character"));
return NULL; return NULL;
}
/* Null terminate and advance ptr. */ /* Null terminate and advance ptr. */
*ptr++ = '\0'; *ptr++ = '\0';
@ -239,9 +255,9 @@ char *parse_next_regex(char *ptr)
return ptr; return ptr;
} }
/* Compile the regular expression regex to preg. Returns FALSE on /* Compile the regular expression regex to preg. Return FALSE on
* success, or TRUE if the expression is invalid. */ * success, or TRUE if the expression is invalid. */
int nregcomp(regex_t *preg, const char *regex, int eflags) bool nregcomp(regex_t *preg, const char *regex, int eflags)
{ {
int rc = regcomp(preg, regex, REG_EXTENDED | eflags); int rc = regcomp(preg, regex, REG_EXTENDED | eflags);
@ -259,75 +275,73 @@ int nregcomp(regex_t *preg, const char *regex, int eflags)
void parse_syntax(char *ptr) void parse_syntax(char *ptr)
{ {
syntaxtype *tmpsyntax = NULL;
const char *fileregptr = NULL, *nameptr = NULL; const char *fileregptr = NULL, *nameptr = NULL;
exttype *endext = NULL; exttype *endext = NULL;
/* The end of the extensions list for this syntax. */ /* The end of the extensions list for this syntax. */
while (*ptr == ' ') assert(ptr != NULL);
ptr++;
if (*ptr == '\n' || *ptr == '\0') if (*ptr == '\0') {
rcfile_error(N_("Missing syntax name"));
return; return;
}
if (*ptr != '"') { if (*ptr != '"') {
rcfile_error(N_("Regex strings must begin and end with a \" character")); rcfile_error(N_("Regex strings must begin and end with a \" character"));
return; return;
} }
ptr++; ptr++;
nameptr = ptr; nameptr = ptr;
ptr = parse_next_regex(ptr); ptr = parse_next_regex(ptr);
if (ptr == NULL) { if (ptr == NULL)
rcfile_error(N_("Missing syntax name"));
return; return;
}
if (syntaxes == NULL) { if (syntaxes == NULL) {
syntaxes = (syntaxtype *)nmalloc(sizeof(syntaxtype)); syntaxes = (syntaxtype *)nmalloc(sizeof(syntaxtype));
tmpsyntax = syntaxes; endsyntax = syntaxes;
SET(COLOR_SYNTAX);
} else { } else {
for (tmpsyntax = syntaxes; tmpsyntax->next != NULL; endsyntax->next = (syntaxtype *)nmalloc(sizeof(syntaxtype));
tmpsyntax = tmpsyntax->next) endsyntax = endsyntax->next;
;
tmpsyntax->next = (syntaxtype *)nmalloc(sizeof(syntaxtype));
tmpsyntax = tmpsyntax->next;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Adding new syntax after 1st\n"); fprintf(stderr, "Adding new syntax after first one\n");
#endif #endif
} }
tmpsyntax->desc = mallocstrcpy(NULL, nameptr); endsyntax->desc = mallocstrcpy(NULL, nameptr);
tmpsyntax->color = NULL; endsyntax->color = NULL;
tmpsyntax->extensions = NULL; endcolor = NULL;
tmpsyntax->next = NULL; endsyntax->extensions = NULL;
endsyntax->next = NULL;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Starting a new syntax type\n"); fprintf(stderr, "Starting a new syntax type: \"%s\"\n", nameptr);
fprintf(stderr, "string val=%s\n", nameptr);
#endif #endif
/* Now load in the extensions to their part of the struct */ /* Now load the extensions into their part of the struct. */
while (*ptr != '\n' && *ptr != '\0') { while (*ptr != '\0') {
exttype *newext; exttype *newext;
/* The new extension structure. */ /* The new extension structure. */
while (*ptr != '"' && *ptr != '\n' && *ptr != '\0') while (*ptr != '"' && *ptr != '\0')
ptr++; ptr++;
if (*ptr == '\n' || *ptr == '\0') if (*ptr == '\0')
return; return;
ptr++; ptr++;
fileregptr = ptr; fileregptr = ptr;
ptr = parse_next_regex(ptr); ptr = parse_next_regex(ptr);
if (ptr == NULL)
break;
newext = (exttype *)nmalloc(sizeof(exttype)); newext = (exttype *)nmalloc(sizeof(exttype));
if (nregcomp(&newext->val, fileregptr, REG_NOSUB) != 0) if (nregcomp(&newext->val, fileregptr, REG_NOSUB))
free(newext); free(newext);
else { else {
if (endext == NULL) if (endext == NULL)
tmpsyntax->extensions = newext; endsyntax->extensions = newext;
else else
endext->next = newext; endext->next = newext;
endext = newext; endext = newext;
@ -336,24 +350,24 @@ void parse_syntax(char *ptr)
} }
} }
/* Parse the color stuff into the colorstrings array */ /* Parse the color stuff into the colorstrings array. */
void parse_colors(char *ptr) void parse_colors(char *ptr)
{ {
int fg, bg, bright = 0; int fg, bg;
int expectend = 0; /* Do we expect an end= line? */ bool bright = FALSE;
char *fgstr; char *fgstr;
colortype *tmpcolor = NULL;
syntaxtype *tmpsyntax = NULL;
fgstr = ptr; assert(ptr != NULL);
ptr = parse_next_word(ptr);
if (ptr == NULL) { if (*ptr == '\0') {
rcfile_error(N_("Missing color name")); rcfile_error(N_("Missing color name"));
return; return;
} }
if (strstr(fgstr, ",")) { fgstr = ptr;
ptr = parse_next_word(ptr);
if (strchr(fgstr, ',') != NULL) {
char *bgcolorname; char *bgcolorname;
strtok(fgstr, ","); strtok(fgstr, ",");
bgcolorname = strtok(NULL, ","); bgcolorname = strtok(NULL, ",");
@ -361,13 +375,14 @@ void parse_colors(char *ptr)
rcfile_error(N_("Background color %s cannot be bright"), bgcolorname); rcfile_error(N_("Background color %s cannot be bright"), bgcolorname);
return; return;
} }
bg = colortoint(bgcolorname, &bright);
bg = color_to_int(bgcolorname, &bright);
} else } else
bg = -1; bg = -1;
fg = colortoint(fgstr, &bright); fg = color_to_int(fgstr, &bright);
/* Don't try and parse screwed up fg colors */ /* Don't try to parse screwed-up foreground colors. */
if (fg == -1) if (fg == -1)
return; return;
@ -376,28 +391,20 @@ void parse_colors(char *ptr)
return; return;
} }
for (tmpsyntax = syntaxes; tmpsyntax->next != NULL; /* Now for the fun part. Start adding regexps to individual strings
tmpsyntax = tmpsyntax->next) * in the colorstrings array, woo! */
;
/* Now the fun part, start adding regexps to individual strings while (ptr != NULL && *ptr != '\0') {
in the colorstrings array, woo! */
while (*ptr != '\0') {
colortype *newcolor; colortype *newcolor;
/* The new color structure. */ /* The new color structure. */
int cancelled = 0; bool cancelled = FALSE;
/* The start expression was bad. */ /* The start expression was bad. */
bool expectend = FALSE;
while (*ptr == ' ') /* Do we expect an end= line? */
ptr++;
if (*ptr == '\n' || *ptr == '\0')
break;
if (strncasecmp(ptr, "start=", 6) == 0) { if (strncasecmp(ptr, "start=", 6) == 0) {
ptr += 6; ptr += 6;
expectend = 1; expectend = TRUE;
} }
if (*ptr != '"') { if (*ptr != '"') {
@ -405,14 +412,18 @@ void parse_colors(char *ptr)
ptr = parse_next_regex(ptr); ptr = parse_next_regex(ptr);
continue; continue;
} }
ptr++; ptr++;
newcolor = (colortype *)nmalloc(sizeof(colortype)); newcolor = (colortype *)nmalloc(sizeof(colortype));
fgstr = ptr; fgstr = ptr;
ptr = parse_next_regex(ptr); ptr = parse_next_regex(ptr);
if (nregcomp(&newcolor->start, fgstr, 0) != 0) { if (ptr == NULL)
break;
if (nregcomp(&newcolor->start, fgstr, 0)) {
free(newcolor); free(newcolor);
cancelled = 1; cancelled = TRUE;
} else { } else {
newcolor->fg = fg; newcolor->fg = fg;
newcolor->bg = bg; newcolor->bg = bg;
@ -420,20 +431,18 @@ void parse_colors(char *ptr)
newcolor->next = NULL; newcolor->next = NULL;
newcolor->end = NULL; newcolor->end = NULL;
if (tmpsyntax->color == NULL) { if (endcolor == NULL) {
tmpsyntax->color = newcolor; endsyntax->color = newcolor;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Starting a new colorstring for fg %d bg %d\n", fg, bg); fprintf(stderr, "Starting a new colorstring for fg %d, bg %d\n", fg, bg);
#endif #endif
} else { } else {
for (tmpcolor = tmpsyntax->color; tmpcolor->next != NULL;
tmpcolor = tmpcolor->next)
;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Adding new entry for fg %d bg %d\n", fg, bg); fprintf(stderr, "Adding new entry for fg %d, bg %d\n", fg, bg);
#endif #endif
tmpcolor->next = newcolor; endcolor->next = newcolor;
} }
endcolor = newcolor;
} }
if (expectend) { if (expectend) {
@ -441,63 +450,63 @@ void parse_colors(char *ptr)
rcfile_error(N_("\"start=\" requires a corresponding \"end=\"")); rcfile_error(N_("\"start=\" requires a corresponding \"end=\""));
return; return;
} }
ptr += 4; ptr += 4;
if (*ptr != '"') { if (*ptr != '"') {
rcfile_error(N_("Regex strings must begin and end with a \" character")); rcfile_error(N_("Regex strings must begin and end with a \" character"));
continue; continue;
} }
ptr++; ptr++;
fgstr = ptr; fgstr = ptr;
ptr = parse_next_regex(ptr); ptr = parse_next_regex(ptr);
if (ptr == NULL)
break;
/* If the start regex was invalid, skip past the end regex to /* If the start regex was invalid, skip past the end regex to
* stay in sync. */ * stay in sync. */
if (cancelled) if (cancelled)
continue; continue;
newcolor->end = (regex_t *)nmalloc(sizeof(regex_t)); newcolor->end = (regex_t *)nmalloc(sizeof(regex_t));
if (nregcomp(newcolor->end, fgstr, 0) != 0) { if (nregcomp(newcolor->end, fgstr, 0)) {
free(newcolor->end); free(newcolor->end);
newcolor->end = NULL; newcolor->end = NULL;
} }
} }
} }
} }
#endif /* ENABLE_COLOR */ #endif /* ENABLE_COLOR */
/* Parse the RC file, once it has been opened successfully */ /* Parse the rcfile, once it has been opened successfully. */
void parse_rcfile(FILE *rcstream) void parse_rcfile(FILE *rcstream)
{ {
char *buf, *ptr, *keyword, *option; char *buf = NULL;
int set = 0, i; ssize_t len;
size_t n;
while ((len = getline(&buf, &n, rcstream)) > 0) {
char *ptr, *keyword, *option;
int set = 0, i;
/* Ignore the \n. */
buf[len - 1] = '\0';
buf = charalloc(1024);
while (fgets(buf, 1023, rcstream) != 0) {
lineno++; lineno++;
ptr = buf; ptr = buf;
while (is_blank_char(*ptr)) while (is_blank_char(*ptr))
ptr++; ptr++;
if (*ptr == '\n' || *ptr == '\0') /* If we have a blank line or a comment, skip to the next
* line. */
if (*ptr == '\0' || *ptr == '#')
continue; continue;
if (*ptr == '#') { /* Otherwise, skip to the next space. */
#ifdef DEBUG
fprintf(stderr, "%s: Read a comment\n", "parse_rcfile()");
#endif
continue; /* Skip past commented lines */
}
/* Else skip to the next space */
keyword = ptr; keyword = ptr;
ptr = parse_next_word(ptr); ptr = parse_next_word(ptr);
if (ptr == NULL)
continue;
/* Else try to parse the keyword */ /* Try to parse the keyword. */
if (strcasecmp(keyword, "set") == 0) if (strcasecmp(keyword, "set") == 0)
set = 1; set = 1;
else if (strcasecmp(keyword, "unset") == 0) else if (strcasecmp(keyword, "unset") == 0)
@ -507,135 +516,124 @@ void parse_rcfile(FILE *rcstream)
parse_syntax(ptr); parse_syntax(ptr);
else if (strcasecmp(keyword, "color") == 0) else if (strcasecmp(keyword, "color") == 0)
parse_colors(ptr); parse_colors(ptr);
#endif /* ENABLE_COLOR */ #endif /* ENABLE_COLOR */
else { else
rcfile_error(N_("Command %s not understood"), keyword); rcfile_error(N_("Command %s not understood"), keyword);
if (set == 0)
continue;
if (*ptr == '\0') {
rcfile_error(N_("Missing flag"));
continue; continue;
} }
option = ptr; option = ptr;
ptr = parse_next_word(ptr); ptr = parse_next_word(ptr);
/* We don't care if ptr == NULL, as it should if using proper syntax */
if (set != 0) { for (i = 0; rcopts[i].name != NULL; i++) {
for (i = 0; rcopts[i].name != NULL; i++) { if (strcasecmp(option, rcopts[i].name) == 0) {
if (strcasecmp(option, rcopts[i].name) == 0) {
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "%s: Parsing option %s\n", fprintf(stderr, "parse_rcfile(): name = \"%s\"\n", rcopts[i].name);
"parse_rcfile()", rcopts[i].name);
#endif #endif
if (set == 1) { if (set == 1) {
if (strcasecmp(rcopts[i].name, "tabsize") == 0 if (rcopts[i].flag != 0)
#ifndef DISABLE_OPERATINGDIR /* This option has a flag, so it doesn't take an
|| strcasecmp(rcopts[i].name, "operatingdir") == 0 * argument. */
#endif SET(rcopts[i].flag);
#ifndef DISABLE_WRAPJUSTIFY else {
|| strcasecmp(rcopts[i].name, "fill") == 0 /* This option doesn't have a flag, so it takes
#endif * an argument. */
#ifndef NANO_SMALL if (*ptr == '\0') {
|| strcasecmp(rcopts[i].name, "whitespace") == 0 rcfile_error(N_("Option %s requires an argument"), rcopts[i].name);
#endif break;
#ifndef DISABLE_JUSTIFY }
|| strcasecmp(rcopts[i].name, "punct") == 0 option = ptr;
|| strcasecmp(rcopts[i].name, "brackets") == 0 if (*option == '"')
|| strcasecmp(rcopts[i].name, "quotestr") == 0 option++;
#endif ptr = parse_argument(ptr);
#ifndef NANO_SMALL
|| strcasecmp(rcopts[i].name, "backupdir") == 0
#endif
#ifndef DISABLE_SPELLER
|| strcasecmp(rcopts[i].name, "speller") == 0
#endif
) {
if (*ptr == '\n' || *ptr == '\0') {
rcfile_error(N_("Option %s requires an argument"), rcopts[i].name);
continue;
}
option = ptr;
if (*option == '"')
option++;
ptr = parse_argument(ptr);
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "option = %s\n", option); fprintf(stderr, "option = \"%s\"\n", option);
#endif #endif
#ifndef DISABLE_OPERATINGDIR #ifndef DISABLE_OPERATINGDIR
if (strcasecmp(rcopts[i].name, "operatingdir") == 0) if (strcasecmp(rcopts[i].name, "operatingdir") == 0)
operating_dir = mallocstrcpy(NULL, option); operating_dir = mallocstrcpy(NULL, option);
else else
#endif #endif
#ifndef DISABLE_WRAPJUSTIFY #ifndef DISABLE_WRAPJUSTIFY
if (strcasecmp(rcopts[i].name, "fill") == 0) { if (strcasecmp(rcopts[i].name, "fill") == 0) {
if (!parse_num(option, &wrap_at)) { if (!parse_num(option, &wrap_at)) {
rcfile_error(N_("Requested fill size %s invalid"), option); rcfile_error(N_("Requested fill size %s invalid"), option);
wrap_at = -CHARS_FROM_EOL; wrap_at = -CHARS_FROM_EOL;
}
} else
#endif
#ifndef NANO_SMALL
if (strcasecmp(rcopts[i].name, "whitespace") == 0) {
size_t ws_len;
whitespace = mallocstrcpy(NULL, option);
ws_len = strlen(whitespace);
if (ws_len != 2 || (ws_len == 2 && (is_cntrl_char(whitespace[0]) || is_cntrl_char(whitespace[1])))) {
rcfile_error(N_("Two non-control characters required"));
free(whitespace);
whitespace = NULL;
}
} else
#endif
#ifndef DISABLE_JUSTIFY
if (strcasecmp(rcopts[i].name, "punct") == 0) {
punct = mallocstrcpy(NULL, option);
if (strchr(punct, '\t') != NULL || strchr(punct, ' ') != NULL) {
rcfile_error(N_("Non-tab and non-space characters required"));
free(punct);
punct = NULL;
}
} else if (strcasecmp(rcopts[i].name, "brackets") == 0) {
brackets = mallocstrcpy(NULL, option);
if (strchr(brackets, '\t') != NULL || strchr(brackets, ' ') != NULL) {
rcfile_error(N_("Non-tab and non-space characters required"));
free(brackets);
brackets = NULL;
}
} else if (strcasecmp(rcopts[i].name, "quotestr") == 0)
quotestr = mallocstrcpy(NULL, option);
else
#endif
#ifndef NANO_SMALL
if (strcasecmp(rcopts[i].name, "backupdir") == 0)
backup_dir = mallocstrcpy(NULL, option);
else
#endif
#ifndef DISABLE_SPELLER
if (strcasecmp(rcopts[i].name, "speller") == 0)
alt_speller = mallocstrcpy(NULL, option);
else
#endif
if (strcasecmp(rcopts[i].name, "tabsize") == 0) {
if (!parse_num(option, &tabsize) || tabsize <= 0) {
rcfile_error(N_("Requested tab size %s invalid"), option);
tabsize = -1;
}
} }
} else } else
SET(rcopts[i].flag);
#ifdef DEBUG
fprintf(stderr, "set flag %ld!\n",
rcopts[i].flag);
#endif #endif
} else { #ifndef NANO_SMALL
UNSET(rcopts[i].flag); if (strcasecmp(rcopts[i].name, "whitespace") == 0) {
#ifdef DEBUG size_t ws_len;
fprintf(stderr, "unset flag %ld!\n", whitespace = mallocstrcpy(NULL, option);
rcopts[i].flag); ws_len = strlen(whitespace);
if (ws_len != 2 || (ws_len == 2 && (is_cntrl_char(whitespace[0]) || is_cntrl_char(whitespace[1])))) {
rcfile_error(N_("Two non-control characters required"));
free(whitespace);
whitespace = NULL;
}
} else
#endif #endif
#ifndef DISABLE_JUSTIFY
if (strcasecmp(rcopts[i].name, "punct") == 0) {
punct = mallocstrcpy(NULL, option);
if (strchr(punct, '\t') != NULL || strchr(punct, ' ') != NULL) {
rcfile_error(N_("Non-tab and non-space characters required"));
free(punct);
punct = NULL;
}
} else if (strcasecmp(rcopts[i].name, "brackets") == 0) {
brackets = mallocstrcpy(NULL, option);
if (strchr(brackets, '\t') != NULL || strchr(brackets, ' ') != NULL) {
rcfile_error(N_("Non-tab and non-space characters required"));
free(brackets);
brackets = NULL;
}
} else if (strcasecmp(rcopts[i].name, "quotestr") == 0)
quotestr = mallocstrcpy(NULL, option);
else
#endif
#ifndef NANO_SMALL
if (strcasecmp(rcopts[i].name, "backupdir") == 0)
backup_dir = mallocstrcpy(NULL, option);
else
#endif
#ifndef DISABLE_SPELLER
if (strcasecmp(rcopts[i].name, "speller") == 0)
alt_speller = mallocstrcpy(NULL, option);
else
#endif
if (strcasecmp(rcopts[i].name, "tabsize") == 0) {
if (!parse_num(option, &tabsize) || tabsize <= 0) {
rcfile_error(N_("Requested tab size %s invalid"), option);
tabsize = -1;
}
} else
assert(FALSE);
} }
} #ifdef DEBUG
fprintf(stderr, "flag = %d\n", rcopts[i].flag);
#endif
} else if (rcopts[i].flag != 0)
UNSET(rcopts[i].flag);
else
rcfile_error(N_("Cannot unset flag %s"), rcopts[i].name);
break;
} }
} }
if (rcopts[i].name == NULL)
rcfile_error(N_("Unknown flag %s"), option);
} }
free(buf); free(buf);
fclose(rcstream);
lineno = 0;
if (errors) { if (errors) {
errors = FALSE; errors = FALSE;
@ -655,52 +653,40 @@ void do_rcfile(void)
#ifdef SYSCONFDIR #ifdef SYSCONFDIR
assert(sizeof(SYSCONFDIR) == strlen(SYSCONFDIR) + 1); assert(sizeof(SYSCONFDIR) == strlen(SYSCONFDIR) + 1);
nanorc = SYSCONFDIR "/nanorc"; nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc");
/* Try to open system nanorc */ /* Try to open the system-wide nanorc. */
rcstream = fopen(nanorc, "r"); rcstream = fopen(nanorc, "r");
if (rcstream != NULL) { if (rcstream != NULL)
/* Parse it! */
parse_rcfile(rcstream); parse_rcfile(rcstream);
fclose(rcstream);
}
#endif #endif
lineno = 0; #if defined(DISABLE_ROOTWRAP) && !defined(DISABLE_WRAPPING)
/* We've already read SYSCONFDIR/nanorc, if it's there. If we're
* root and --disable-wrapping-as-root is used, turn wrapping
* off now. */
if (geteuid() == NANO_ROOT_UID)
SET(NO_WRAP);
#endif
get_homedir(); get_homedir();
if (homedir == NULL) { if (homedir == NULL)
rcfile_error(N_("I can't find my home directory! Wah!")); rcfile_error(N_("I can't find my home directory! Wah!"));
SET(NO_RCFILE); else {
} else { nanorc = charealloc(nanorc, strlen(homedir) + 9);
size_t homelen = strlen(homedir); sprintf(nanorc, "%s/.nanorc", homedir);
char *nanorcf = charalloc(homelen + 9);
nanorc = nanorcf;
strcpy(nanorcf, homedir);
strcpy(nanorcf + homelen, "/.nanorc");
#if defined(DISABLE_ROOTWRAP) && !defined(DISABLE_WRAPPING)
/* If we've already read SYSCONFDIR/nanorc (if it's there), we're
root, and --disable-wrapping-as-root is used, turn wrapping off */
if (geteuid() == NANO_ROOT_UID)
SET(NO_WRAP);
#endif
rcstream = fopen(nanorc, "r"); rcstream = fopen(nanorc, "r");
if (rcstream == NULL) { if (rcstream == NULL) {
/* Don't complain about the file not existing */ /* Don't complain about the file's not existing. */
if (errno != ENOENT) { if (errno != ENOENT)
rcfile_error(N_("Error reading %s: %s"), nanorc, strerror(errno)); rcfile_error(N_("Error reading %s: %s"), nanorc, strerror(errno));
SET(NO_RCFILE); } else
}
} else {
parse_rcfile(rcstream); parse_rcfile(rcstream);
fclose(rcstream);
}
free(nanorcf);
} }
lineno = 0; free(nanorc);
nanorc = NULL;
#ifdef ENABLE_COLOR #ifdef ENABLE_COLOR
set_colorpairs(); set_colorpairs();

View File

@ -844,7 +844,7 @@ ssize_t do_replace_loop(const char *needle, const filestruct
if (!replaceall) { if (!replaceall) {
#ifdef ENABLE_COLOR #ifdef ENABLE_COLOR
if (ISSET(COLOR_SYNTAX)) if (!ISSET(NO_COLOR_SYNTAX))
edit_refresh(); edit_refresh();
else else
#endif #endif

View File

@ -2658,7 +2658,7 @@ int statusq(bool allow_tabs, const shortcut *s, const char *def,
blank_statusbar(); blank_statusbar();
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "I got \"%s\"\n", answer); fprintf(stderr, "answer = \"%s\"\n", answer);
#endif #endif
#ifndef DISABLE_TABCOMP #ifndef DISABLE_TABCOMP
@ -3052,7 +3052,7 @@ void edit_add(const filestruct *fileptr, const char *converted, int
mvwaddstr(edit, yval, 0, converted); mvwaddstr(edit, yval, 0, converted);
#ifdef ENABLE_COLOR #ifdef ENABLE_COLOR
if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) { if (colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
const colortype *tmpcolor = colorstrings; const colortype *tmpcolor = colorstrings;
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) { for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
@ -3087,17 +3087,19 @@ void edit_add(const filestruct *fileptr, const char *converted, int
* unless k is 0. If regexec() returns REG_NOMATCH, * unless k is 0. If regexec() returns REG_NOMATCH,
* there are no more matches in the line. */ * there are no more matches in the line. */
if (regexec(&tmpcolor->start, &fileptr->data[k], 1, if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
&startmatch, k == 0 ? 0 : &startmatch, (k == 0) ? 0 :
REG_NOTBOL) == REG_NOMATCH) REG_NOTBOL) == REG_NOMATCH)
break; break;
/* Translate the match to the beginning of the line. */ /* Translate the match to the beginning of the
* line. */
startmatch.rm_so += k; startmatch.rm_so += k;
startmatch.rm_eo += k; startmatch.rm_eo += k;
if (startmatch.rm_so == startmatch.rm_eo) { if (startmatch.rm_so == startmatch.rm_eo) {
startmatch.rm_eo++; startmatch.rm_eo++;
statusbar(_("Refusing 0 length regex match")); statusbar(
_("Refusing zero-length regex match"));
} else if (startmatch.rm_so < endpos && } else if (startmatch.rm_so < endpos &&
startmatch.rm_eo > startpos) { startmatch.rm_eo > startpos) {
if (startmatch.rm_so <= startpos) if (startmatch.rm_so <= startpos)
x_start = 0; x_start = 0;
else else
@ -3157,7 +3159,7 @@ void edit_add(const filestruct *fileptr, const char *converted, int
startmatch.rm_eo -= startmatch.rm_so; startmatch.rm_eo -= startmatch.rm_so;
if (regexec(tmpcolor->end, start_line->data + if (regexec(tmpcolor->end, start_line->data +
start_col + startmatch.rm_eo, 0, NULL, start_col + startmatch.rm_eo, 0, NULL,
start_col + startmatch.rm_eo == 0 ? 0 : (start_col + startmatch.rm_eo == 0) ? 0 :
REG_NOTBOL) == REG_NOMATCH) REG_NOTBOL) == REG_NOMATCH)
/* No end found after this start. */ /* No end found after this start. */
break; break;
@ -3209,7 +3211,8 @@ void edit_add(const filestruct *fileptr, const char *converted, int
while (start_col < endpos) { while (start_col < endpos) {
if (regexec(&tmpcolor->start, if (regexec(&tmpcolor->start,
fileptr->data + start_col, 1, &startmatch, fileptr->data + start_col, 1, &startmatch,
start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH || (start_col == 0) ? 0 :
REG_NOTBOL) == REG_NOMATCH ||
start_col + startmatch.rm_so >= endpos) start_col + startmatch.rm_so >= endpos)
/* No more starts on this line. */ /* No more starts on this line. */
break; break;
@ -3228,7 +3231,8 @@ void edit_add(const filestruct *fileptr, const char *converted, int
if (regexec(tmpcolor->end, if (regexec(tmpcolor->end,
fileptr->data + startmatch.rm_eo, 1, &endmatch, fileptr->data + startmatch.rm_eo, 1, &endmatch,
startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) { (startmatch.rm_eo == 0) ? 0 :
REG_NOTBOL) == 0) {
/* Translate the end match to be relative to the /* Translate the end match to be relative to the
* beginning of the line. */ * beginning of the line. */
endmatch.rm_so += startmatch.rm_eo; endmatch.rm_so += startmatch.rm_eo;
@ -3268,12 +3272,12 @@ void edit_add(const filestruct *fileptr, const char *converted, int
} }
} }
start_col = startmatch.rm_so + 1; start_col = startmatch.rm_so + 1;
} /* while start_col < endpos */ }
} /* if (tmp_color->end != NULL) */ }
wattroff(edit, A_BOLD); wattroff(edit, A_BOLD);
wattroff(edit, COLOR_PAIR(tmpcolor->pairnum)); wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
} /* for tmpcolor in colorstrings */ }
} }
#endif /* ENABLE_COLOR */ #endif /* ENABLE_COLOR */