diff --git a/configure.ac b/configure.ac index 762dea6e..88d1ef85 100644 --- a/configure.ac +++ b/configure.ac @@ -233,6 +233,8 @@ AX_GCC_FUNC_ATTRIBUTE([fallthrough]) AX_GCC_FUNC_ATTRIBUTE([malloc]) AX_GCC_FUNC_ATTRIBUTE([malloc_args]) AX_GCC_FUNC_ATTRIBUTE([alloc_size]) +AX_GCC_FUNC_ATTRIBUTE([nonnull]) +AX_GCC_FUNC_ATTRIBUTE([returns_nonnull]) AC_CONFIG_FILES([Makefile joe/Makefile joe/util/Makefile rc/Makefile man/Makefile man/ru/Makefile syntax/Makefile po/Makefile colors/Makefile diff --git a/joe/blocks.c b/joe/blocks.c index 97fe3009..0f89cc50 100644 --- a/joe/blocks.c +++ b/joe/blocks.c @@ -13,10 +13,15 @@ #if SIZEOF_INT == 8 # define SHFT 3 +# define INTFILL_CHAR 0x0101010101010101 #elif SIZEOF_INT == 4 # define SHFT 2 +# define INTFILL_CHAR 0x01010101 #elif SIZEOF_INT == 2 # define SHFT 1 +# define INTFILL_CHAR 0x0101 +#else +# error I do not know how to handle your strange integers #endif /* Set 'sz' 'int's beginning at 'd' to the value 'c' */ @@ -206,17 +211,7 @@ char *mset(char *dest, char c, ptrdiff_t sz) d += z; sz -= z; } - msetI((int *)d, -#if SIZEOF_INT >= 8 - (c << (BITS * 7)) + (c << (BITS * 6)) + (c << (BITS * 5)) + (c << (BITS * 4)) + -#endif -#if SIZEOF_INT >= 4 - (c << (BITS * 3)) + (c << (BITS * 2)) + -#endif -#if SIZEOF_INT >= 2 - (c << BITS) + -#endif - c, sz >> SHFT); + msetI((int *)d, ((int)c & 255) * INTFILL_CHAR, sz >> SHFT); d += sz & ~(SIZEOF_INT - 1); switch (sz & (SIZEOF_INT - 1)) { case 7: d[6] = c; FALLTHROUGH diff --git a/joe/charmap.c b/joe/charmap.c index 93583d72..663fc497 100644 --- a/joe/charmap.c +++ b/joe/charmap.c @@ -91,8 +91,8 @@ int from_utf8(struct charmap *map,const char *s) /* Aliases */ static const struct { - const char *alias; - const char *builtin; + const char alias[12]; + const char builtin[12]; } alias_table[] = { { "c", "ascii" }, { "posix", "ascii" }, @@ -129,7 +129,7 @@ static const struct { { "latin8", "iso-8859-14" }, { "latin9", "iso-8859-15" }, { "latin10", "iso-8859-16" }, - { 0, 0 } + {} }; /* I took all the ISO-8859- ones, plus any ones referenced by a locale */ @@ -1368,7 +1368,7 @@ struct charmap *find_charmap(const char *name) load_builtins(); /* Alias? */ - for (y=0; alias_table[y].alias; ++y) + for (y=0; alias_table[y].alias[0]; ++y) if (!map_name_cmp(alias_table[y].alias,name)) { name = alias_table[y].builtin; break; @@ -1435,7 +1435,7 @@ char **get_encodings(void) /* Aliases */ - for (y=0; alias_table[y].alias; ++y) { + for (y=0; alias_table[y].alias[0]; ++y) { r = vsncpy(NULL,0,sz(alias_table[y].alias)); encodings = vaadd(encodings, r); } diff --git a/joe/syntax.c b/joe/syntax.c index 8391f52d..122533f6 100644 --- a/joe/syntax.c +++ b/joe/syntax.c @@ -189,12 +189,23 @@ static HIGHLIGHT_STATE ansi_parse(P *line, HIGHLIGHT_STATE h_state) return h_state; } +static struct high_cmd *test_cmd(const int statebits, struct high_cmd *cmd) +{ + if (!cmd) return NULL; + /* NULL if a test fails */ + if (cmd->state_test_all && (statebits & cmd->state_test_all ) != cmd->state_test_all) return NULL; + if (cmd->state_test_any && (statebits & cmd->state_test_any ) == 0) return NULL; + if (cmd->state_test_none && (statebits & cmd->state_test_none) != 0) return NULL; + return cmd; +} + HIGHLIGHT_STATE parse(struct high_syntax *syntax,P *line,HIGHLIGHT_STATE h_state,struct charmap *charmap) { struct high_frame *stack; struct high_delim_frame *delim_stack; struct high_state *h; /* Current state */ + int statebits; int buf[SAVED_SIZE]; /* Name buffer (trunc after 23 characters) */ int lbuf[3*SAVED_SIZE]; /* Lower case version of name buffer */ int lsaved_s[3*SAVED_SIZE]; /* Lower case version of delimiter match buffer */ @@ -224,6 +235,7 @@ HIGHLIGHT_STATE parse(struct high_syntax *syntax,P *line,HIGHLIGHT_STATE h_state stack = h_state.stack; delim_stack = h_state.delim_stack; + statebits = h_state.statebits; h = (stack ? stack->syntax : syntax)->states[h_state.state]; buf_idx = 0; attr = attr_buf; @@ -240,7 +252,8 @@ HIGHLIGHT_STATE parse(struct high_syntax *syntax,P *line,HIGHLIGHT_STATE h_state /* Get next character */ while((c=pgetc(line))!=NO_MORE_DATA) { - struct high_cmd *cmd, *kw_cmd; + struct high_cmd *cmd = NULL; + struct high_cmd *kw_cmd; int iters = -8; /* +8 extra iterations before cycle detect. */ ptrdiff_t x; @@ -283,8 +296,13 @@ HIGHLIGHT_STATE parse(struct high_syntax *syntax,P *line,HIGHLIGHT_STATE h_state cmd = h->same_delim; else { cmd = (struct high_cmd *)rtree_lookup(&h->rtree, c); - if (!cmd) - cmd = h->dflt; + if (!cmd) { + for (int i = h->test_count - 1; i >= 0; --i) + if ((cmd = test_cmd(statebits, h->test_states[i]))) + break; + if (!cmd) + cmd = h->dflt; + } } /* Lowerize strings for case-insensitive matching */ @@ -308,12 +326,16 @@ HIGHLIGHT_STATE parse(struct high_syntax *syntax,P *line,HIGHLIGHT_STATE h_state recolor_delimiter_or_keyword = 1; } + /* Uodate state word */ + statebits &= cmd->statekeep; + statebits ^= cmd->stateflip; + /* Determine new state */ if (cmd->call) { /* Call */ struct high_frame **frame_ptr = stack ? &stack->child : &syntax->stack_base; /* Search for an existing stack frame for this call */ - while (*frame_ptr && !((*frame_ptr)->syntax == cmd->call && (*frame_ptr)->return_state == cmd->new_state)) + while (*frame_ptr && !((*frame_ptr)->syntax == cmd->call && (*frame_ptr)->return_state == cmd->new_state && (*frame_ptr)->statebits == statebits)) frame_ptr = &(*frame_ptr)->sibling; if (*frame_ptr) stack = *frame_ptr; @@ -324,6 +346,7 @@ HIGHLIGHT_STATE parse(struct high_syntax *syntax,P *line,HIGHLIGHT_STATE h_state frame->sibling = 0; frame->syntax = cmd->call; frame->return_state = cmd->new_state; + frame->statebits = statebits; *frame_ptr = frame; stack = frame; ++stack_count; @@ -332,12 +355,15 @@ HIGHLIGHT_STATE parse(struct high_syntax *syntax,P *line,HIGHLIGHT_STATE h_state } else if (cmd->rtn) { /* Return */ if (stack) { + if (!cmd->keep_statebits) + statebits = stack->statebits; h = stack->return_state; stack = stack->parent; } else /* Not in a subroutine, so ignore the return */ h = cmd->new_state; } else if (cmd->reset) { + /* do NOT reset statebits here! */ h = syntax->states[0]; } else { /* Normal edge */ @@ -470,6 +496,7 @@ HIGHLIGHT_STATE parse(struct high_syntax *syntax,P *line,HIGHLIGHT_STATE h_state h_state.stack = stack; h_state.delim_stack = delim_stack; h_state.state = h->no; + h_state.statebits = statebits; return h_state; } @@ -512,6 +539,7 @@ static struct high_state *find_state(struct high_syntax *syntax,char *name) syntax->states[syntax->nstates++]=state; rtree_init(&state->rtree); state->dflt = &syntax->default_cmd; + state->test_count = 0; state->delim = 0; state->same_delim = 0; htadd(syntax->ht_states, state_names[state->name], state); @@ -558,6 +586,10 @@ static void iz_cmd(struct high_cmd *cmd) cmd->rtn = 0; cmd->reset = 0; cmd->call = 0; + cmd->state_test_all = cmd->state_test_any = cmd->state_test_none = 0; + cmd->keep_statebits = false; + cmd->statekeep = -1; + cmd->stateflip = 0; } static struct high_cmd *mkcmd(void) @@ -653,6 +685,7 @@ void dump_syntax(BW *bw) } #endif joe_snprintf_2(buf, SIZEOF(buf), " default -> %s %d\n",(s->dflt->new_state ? state_names[s->dflt->new_state->name] : "ERROR! Unknown state!"),(int)s->dflt->recolor); + // FIXME: print tests too binss(bw->cursor, buf); pnextl(bw->cursor); } @@ -727,7 +760,77 @@ struct high_syntax *load_syntax_subr(const char *name,char *subr,struct high_par /* Parse options */ -static int parse_options(struct high_syntax *syntax,struct high_cmd *cmd,JFILE *f,const char *p,int parsing_strings,char *name,int line) +enum { USE_ALL = 1, USE_ANY = 2, USE_NONE = 4 }; /* bitmask */ + +static int parse_flagbits(const char **p, const char *name, const int line, const struct high_cmd *cmd, int use, int dflt) +{ + int value = 0; + parse_ws(p, '#'); + if (cmd && !parse_char(p, '~')) { + char buf[256]; + parse_ws(p, '#'); + if (parse_ident(p, buf, SIZEOF(buf))) + goto badflag; + if (!zcmp(buf, "all")) + return ~cmd->state_test_all; + else if (!zcmp(buf, "any")) + return ~cmd->state_test_any; + else if (!zcmp(buf, "none")) + return ~cmd->state_test_none; + else if (!zcmp(buf, "other")) { + value = 0; + if (use & USE_ALL) value |= cmd->state_test_all; + if (use & USE_ANY) value |= cmd->state_test_any; + if (use & USE_NONE) value |= cmd->state_test_none; + return ~value; + } else { + logerror_2(joe_gettext(_("%s %d: Unknown class\n")), name, line); + return 0; + } + } else if (!parse_char(p, '=')) { + /* integer mask */ + parse_ws(p, '#'); + if (parse_int(p, &value)) goto badflag; + return value; + } else if (!parse_char(p, '@')) { + /* list of bit positions */ + for (;;) { + int v1 = 0, v2 = 0; + parse_ws(p, '#'); + if (parse_int(p, &v1)) goto badflag; /* expected int */ + if (v1 < 0 || v1 > 31) goto bitrange; /* range 0..31 */ + value |= 1 << v1; + parse_ws(p, '#'); + if (!parse_char(p, ',')) continue; /* comma -> read next bit no. */ + if (parse_char(p, '-')) break; /* hyphen = range -> read other end's bit no. */ + /* range (inclusive) */ + parse_ws(p, '#'); + if (parse_int(p, &v2)) goto badflag; /* expected int */ + if (v2 < 0 || v2 > 31) goto bitrange; /* range 0..31 again */ + if (v2 > v1) + while (v1 <= v2 && v1 < 32) + value |= 1 << v1++; + else + while (v2 <= v1 && v2 < 32) + value |= 1 << v2++; + parse_ws(p, '#'); + if (parse_char(p, ',')) break; /* comma -> read next bit no. */ + } + return value; + } else if (dflt) + return dflt; + + badflag: + logerror_2(joe_gettext(_("%s %d: Missing value for option\n")), name, line); + return 0; + + bitrange: + logerror_3("%s %d: %s\n", name, line, joe_gettext(_("Value out of range"))); + return 0; +} + + +static int parse_options(struct high_syntax *syntax,struct high_cmd *cmd,JFILE *f,const char *p,int parsing_strings,char *name,int line, int is_test_cmd) { char buf[1024]; char bf[256]; @@ -780,9 +883,40 @@ static int parse_options(struct high_syntax *syntax,struct high_cmd *cmd,JFILE * logerror_2(joe_gettext(_("%s %d: Missing value for option\n")),name,line); } else if(!zcmp(bf,"return")) { cmd->rtn = 1; - } else if(!zcmp(bf,"reset")) { - cmd->reset = 1; - } else if(!parsing_strings && (!zcmp(bf,"strings") || !zcmp(bf,"istrings"))) { + } else if(!zcmp(bf,"returnstate")) { + cmd->keep_statebits = cmd->rtn = 1; + } else if(!zcmp(bf,"sset")) { + int bits = parse_flagbits(&p, name, line, NULL, 0, 0); + cmd->statekeep &= ~bits; + cmd->stateflip |= bits; + } else if(!zcmp(bf,"sclear")) { + int bits = parse_flagbits(&p, name, line, NULL, 0, -1); + cmd->statekeep &= ~bits; + cmd->stateflip &= ~bits; + } else if(!zcmp(bf,"sflip")) { + int bits = parse_flagbits(&p, name, line, NULL, 0, -1); + cmd->statekeep |= bits; + cmd->stateflip |= bits; + } else if(!zcmp(bf,"sifall")) { + if (is_test_cmd) + cmd->state_test_all |= parse_flagbits(&p, name, line, cmd, USE_ANY | USE_NONE, 0); + else + logerror_3(joe_gettext(_("%s %d: '%s' found outside a test command\n")), name, line, bf); + } else if(is_test_cmd && !zcmp(bf,"sifany")) { + if (is_test_cmd) + cmd->state_test_any |= parse_flagbits(&p, name, line, cmd, USE_ALL | USE_NONE, 0); + else + logerror_3(joe_gettext(_("%s %d: '%s' found outside a test command\n")), name, line, bf); + } else if(is_test_cmd && !zcmp(bf,"sifnone")) { + if (is_test_cmd) + cmd->state_test_none |= parse_flagbits(&p, name, line, cmd, USE_ALL | USE_ANY, 0); + else + logerror_3(joe_gettext(_("%s %d: '%s' found outside a test command\n")), name, line, bf); + } else if(!zcmp(bf,"strings") || !zcmp(bf,"istrings")) { + if (parsing_strings) { + logerror_3(joe_gettext(_("%s %d: '%s' found but already in strings mode\n")), name, line, bf); + continue; + } if (bf[0]=='i') cmd->ignore = 1; while(jfgets(buf,sizeof(buf),f)) { @@ -809,7 +943,7 @@ static int parse_options(struct high_syntax *syntax,struct high_cmd *cmd,JFILE * cmd->keywords = Zhtmk(64); Zhtadd(cmd->keywords, (cmd->ignore ? Zdup(lkwbuf) : Zdup(kwbuf)), kw_cmd); } - line = parse_options(syntax,kw_cmd,f,p,1,name,line); + line = parse_options(syntax,kw_cmd,f,p,1,name,line,is_test_cmd); } else logerror_2(joe_gettext(_("%s %d: Missing state name\n")),name,line); } else @@ -826,9 +960,19 @@ static int parse_options(struct high_syntax *syntax,struct high_cmd *cmd,JFILE * cmd->recolor_mark = 1; } else logerror_2(joe_gettext(_("%s %d: Unknown option\n")),name,line); + + if (is_test_cmd && cmd->state_test_all == 0 && cmd->state_test_any == 0 && cmd->state_test_none == 0) + logerror_2(joe_gettext(_("%s %d: bit-test has no valid bit tests\n")), name, line); + return line; } +static void check_state_bugs(const struct high_state *state, const struct high_syntax *syntax, const char *name, int line) +{ + if (state->test_count && state->dflt == &syntax->default_cmd) + logerror_2(joe_gettext(_("%s %d: state has bit tests but no default command\n")), name, line); +} + struct ifstack { struct ifstack *next; int ignore; /* Ignore input lines if set */ @@ -850,6 +994,7 @@ static struct high_state *load_dfa(struct high_syntax *syntax) struct ifstack *stack=0; struct high_state *state=0; /* Current state */ struct high_state *first=0; /* First state */ + int state_start_line = 0; int line = 0; int this_one = 0; int inside_subr = 0; @@ -934,7 +1079,10 @@ static struct high_state *load_dfa(struct high_syntax *syntax) /* Ignore this line because it's not the code we want */ } else if(!parse_char(&p, ':')) { if(!parse_ident(&p, bf, SIZEOF(bf))) { + if (state) + check_state_bugs(state, syntax, fullpath, state_start_line); + state_start_line = line; state = find_state(syntax,bf); if (!first) @@ -971,11 +1119,19 @@ static struct high_state *load_dfa(struct high_syntax *syntax) c = parse_ws(&p,'#'); if (!c) { - } else if (c=='"' || c=='*' || c=='&' || c =='%') { + } else if (c=='"' || c=='*' || c == '~' || c=='&' || c =='%') { if (state) { struct high_cmd *cmd = mkcmd(); + int/*bool*/ testcmd = 0; if(!parse_field(&p, "*")) { state->dflt = cmd; + } else if(!parse_field(&p, "~")) { + /* allocate 8 at a time, extend by 8 at need */ + if (state->test_count % 8 == 0) + state->test_states = state->test_count ? joe_realloc(state->test_states, (unsigned int)(state->test_count + 8) * sizeof(*state->test_states)) : joe_calloc(8, sizeof(*state->test_states)); + /* store, increment count */ + state->test_states[state->test_count++] = cmd; + testcmd = 1; } else if(!parse_field(&p, "&")) { state->delim = cmd; } else if(!parse_field(&p, "%")) { @@ -998,7 +1154,7 @@ static struct high_state *load_dfa(struct high_syntax *syntax) parse_ws(&p,'#'); if(!parse_ident(&p,bf,SIZEOF(bf))) { cmd->new_state = find_state(syntax,bf); - line = parse_options(syntax,cmd,f,p,0,fullpath,line); + line = parse_options(syntax,cmd,f,p,0,fullpath,line,testcmd); } else logerror_2(joe_gettext(_("%s %d: Missing jump\n")),fullpath,line); } else @@ -1014,6 +1170,8 @@ static struct high_state *load_dfa(struct high_syntax *syntax) logerror_2(joe_gettext(_("%s %d: ifdef with no matching endif\n")),fullpath,st->line); joe_free(st); } + if (state) + check_state_bugs(state, syntax, fullpath, state_start_line); jfclose(f); diff --git a/joe/syntax.h b/joe/syntax.h index dd4fd094..49218bbc 100644 --- a/joe/syntax.h +++ b/joe/syntax.h @@ -14,12 +14,17 @@ struct high_state { ptrdiff_t no; /* State number */ int name; /* Highlight state name (index into state_names) */ int color; /* Color for this state */ - struct color_def *colorp; /* Mapped color definition */ + int statebits; /* For use in the state machine */ - struct Rtree rtree; /* Character map (character ->struct high_cmd *) */ - struct high_cmd *dflt; /* Default for no match */ + int test_count; /* number of state word tests */ + struct high_cmd *dflt; /* Defaults for no match (if only one) */ + struct high_cmd **test_states; /* For state word tests */ struct high_cmd *same_delim; /* Same delimiter */ struct high_cmd *delim; /* Matching delimiter */ + + struct color_def *colorp; /* Mapped color definition */ + + struct Rtree rtree; /* Character map (character ->struct high_cmd *) */ }; /* Parameter list */ @@ -46,7 +51,14 @@ struct high_cmd { bool stop_mark; /* Set to end marked area excluding this char */ bool recolor_mark; /* Set to recolor marked area with new state */ bool rtn; /* Set to return */ + bool keep_statebits; /* Set to preserve statebits if returning */ bool reset; /* Set to reset the call stack */ + + int stateflip, statekeep; /* Mask words for altering statebits */ + int state_test_all; /* statebits test words, used if non-zero, fail match if false */ + int state_test_any; + int state_test_none; + ptrdiff_t recolor; /* No. chars to recolor if <0. */ struct high_state *new_state; /* The new state */ ZHASH *keywords; /* Hash table of keywords */ @@ -62,6 +74,7 @@ struct high_frame { struct high_frame *sibling; /* Caller's next callee's frame */ struct high_syntax *syntax; /* Current syntax subroutine */ struct high_state *return_state; /* Return state in the caller's subroutine */ + int statebits; /* Saved data */ }; /* delimiter stack frame */ @@ -105,10 +118,13 @@ struct state_debug_data { extern attr_data *attr_buf; extern struct state_debug_data *syndebug_buf; -#define clear_state(s) (((s)->saved_s = 0), ((s)->state = 0), ((s)->stack = 0), ((s)->delim_stack = 0)) -#define invalidate_state(s) (((s)->state = -1), ((s)->saved_s = 0), ((s)->stack = 0), ((s)->delim_stack = 0)) +#define clear_state(s) (((s)->saved_s = 0), ((s)->state = 0), ((s)->stack = 0), ((s)->delim_stack = 0), ((s)->statebits = 0)) +#define invalidate_state(s) (((s)->state = -1), ((s)->saved_s = 0), ((s)->stack = 0), ((s)->delim_stack = 0), ((s)->statebits = 0)) #define move_state(to,from) (*(to)= *(from)) +/* #define eq_state(x,y) ((x)->state == (y)->state && (x)->stack == (y)->stack && (x)->delim_stack == (y)->delim_stack && (x)->saved_s == (y)->saved_s) +*/ +#define eq_state(x,y) (0) extern struct high_syntax *syntax_list; diff --git a/joe/types.h b/joe/types.h index be7f451a..378497f1 100644 --- a/joe/types.h +++ b/joe/types.h @@ -33,6 +33,19 @@ #define ATTR_ALLOC_SIZE(arg) #endif +/* Also doubled parentheses */ +#ifdef HAVE_FUNC_ATTRIBUTE_NONNULL +#define NONNULL(arg) __attribute__((nonnull arg)) +#else +#define NONNULL(arg) +#endif + +#ifdef HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL +#define RETURNS_NONNULL __attribute__((returns_nonnull)) +#else +#define RETURNS_NONNULL +#endif + #define TO_DIFF_OK(a) ((ptrdiff_t)(a)) /* Means it's OK that we are converting off_t to ptrdiff_t in this case */ #define TO_CHAR_OK(a) ((char)(a)) /* Means it's OK that we are converting int to char */ #define SIZEOF(a) ((ptrdiff_t)sizeof(a)) /* Signed version of sizeof() */ @@ -329,6 +342,7 @@ struct highlight_state { struct high_delim_frame *delim_stack; /* Pointer to the previously pushed delimiter buffer */ const int *saved_s; /* Interned Z-string for saved delimiter */ ptrdiff_t state; /* Current state in the current subroutine */ + int statebits; }; /* It's a good idea to optimize the size of struct highlight_state since there are N of diff --git a/joe/usearch.c b/joe/usearch.c index 48440f12..02712849 100644 --- a/joe/usearch.c +++ b/joe/usearch.c @@ -407,7 +407,7 @@ static SRCH *setmark(SRCH *srch) return srch; } -SRCH *mksrch(char *pattern, char *replacement, int ignore, int backwards, int repeat, int replace, int rest, int all, int regex) +SRCH *mksrch(char *pattern, char *replacement, int ignore, int backwards, int repeat, int replace, int rest, enum searches all, int regex) { SRCH *srch = (SRCH *) joe_malloc(SIZEOF(SRCH)); int x; @@ -727,9 +727,9 @@ static int set_options(W *w, char *s, void *obj, int *notify) while (*t) { int c = fwrd_c(locale_map, &t, NULL); if (yncheck(all_key, c)) - srch->all = 1; + srch->all = SEARCH_ALL; else if (yncheck(list_key, c)) - srch->all = 2; + srch->all = SEARCH_ERROR_LIST; else if (yncheck(replace_key, c)) srch->replace = 1; else if (yncheck(backwards_key, c)) @@ -869,7 +869,7 @@ int dofirst(BW *bw, int back, int repl, char *hint) prgetc(bw->cursor); return urtn(bw->parent, -1); } - srch = mksrch(NULL, NULL, 0, back, -1, repl, 0, 0, std_regex); + srch = mksrch(NULL, NULL, 0, back, -1, repl, 0, SEARCH_ONE, std_regex); srch->addr = bw->cursor->byte; srch->wrap_p = pdup(bw->cursor, "dofirst"); srch->wrap_p->owner = &srch->wrap_p; @@ -1140,9 +1140,9 @@ static int fnext(BW *bw, SRCH *srch) sta = searchb(bw, srch, bw->cursor); else sta = searchf(bw, srch, bw->cursor); - if (!sta && srch->all) { + if (!sta && srch->all != SEARCH_ONE) { B *b; - if (srch->all == 2) + if (srch->all == SEARCH_ERROR_LIST) b = beafter(srch->current); else { berror = 0; @@ -1378,6 +1378,6 @@ void load_srch(FILE *f) parse_int(&p,&block_restrict); } } - globalsrch = mksrch(pattern,replacement,ignore,backwards,-1,replace,0,0,regex); + globalsrch = mksrch(pattern,replacement,ignore,backwards,-1,replace,0,SEARCH_ONE,regex); globalsrch->block_restrict = block_restrict; } diff --git a/joe/usearch.h b/joe/usearch.h index 58a4cbdb..78197875 100644 --- a/joe/usearch.h +++ b/joe/usearch.h @@ -17,6 +17,12 @@ struct srchrec { #define NMATCHES 26 +enum searches { + SEARCH_ONE, + SEARCH_ALL, + SEARCH_ERROR_LIST, +}; + struct search { char *pattern; /* Search pattern */ struct regcomp *comp; /* Compiled pattern */ @@ -34,7 +40,7 @@ struct search { bool allow_wrap; /* Set to allow wrapping */ bool valid; /* Set if original marks are a valid block */ bool block_restrict; /* Search restricted to marked block */ - int all; /* Set to continue in other windows */ + enum searches all; /* Set to continue in other windows */ Regmatch_t pieces[NMATCHES]; /* Sub-matches we found */ Regmatch_t entire; /* Entire matching string */ @@ -49,7 +55,7 @@ struct search { extern bool std_regex; /* Standard regex format by default */ -SRCH *mksrch(char *pattern, char *replacement, int ignore, int backwards, int repeat, int replace, int rest, int all, int regex); +SRCH *mksrch(char *pattern, char *replacement, int ignore, int backwards, int repeat, int replace, int rest, enum searches all, int regex); void rmsrch(SRCH *srch); void setpat(SRCH *srch, char *pattern); diff --git a/joe/utag.c b/joe/utag.c index a85578a4..72f19cef 100644 --- a/joe/utag.c +++ b/joe/utag.c @@ -92,7 +92,7 @@ static int dotagjump(BW *bw, int flag) } else { if (flag) smode = 2; - return dopfnext(bw, mksrch(vsncpy(NULL, 0, sv(srch)), NULL, 0, 0, -1, 0, 0, 0, 0), NULL); + return dopfnext(bw, mksrch(vsncpy(NULL, 0, sv(srch)), NULL, 0, 0, -1, 0, 0, SEARCH_ONE, 0), NULL); } } @@ -140,7 +140,7 @@ static int dotagmenu(MENU *m, ptrdiff_t x, void *obj, int k) return 0; } else { smode = 2; - return dopfnext(bw, mksrch(vsncpy(NULL, 0, sv(srch)), NULL, 0, 0, -1, 0, 0, 0, 0), NULL); + return dopfnext(bw, mksrch(vsncpy(NULL, 0, sv(srch)), NULL, 0, 0, -1, 0, 0, SEARCH_ONE, 0), NULL); } } diff --git a/syntax/c.jsf b/syntax/c.jsf index 492268c0..d8f3b69f 100644 --- a/syntax/c.jsf +++ b/syntax/c.jsf @@ -30,16 +30,30 @@ # Within a state, define transitions (jumps) to other states. Each # jump has the form: [