2
* Copyright (C) 1984-2000 Mark Nudelman
4
* You may distribute under the terms of either the GNU General Public
5
* License or the Less License, as specified in the README file.
7
* For more information about less, or for information on how to
8
* contact the author, see the README file.
13
* Routines to search a file for a pattern.
19
#define MINPOS(a,b) (((a) < (b)) ? (a) : (b))
20
#define MAXPOS(a,b) (((a) > (b)) ? (a) : (b))
22
#if HAVE_POSIX_REGCOMP
25
#define REGCOMP_FLAG REG_EXTENDED
27
#define REGCOMP_FLAG 0
49
extern int how_search;
53
extern int jump_sline;
55
extern int status_col;
56
extern POSITION start_attnpos;
57
extern POSITION end_attnpos;
59
extern int hilite_search;
60
extern int screen_trashed;
61
extern int size_linebuf;
63
extern int can_goto_line;
64
static int hide_hilite;
65
static POSITION prep_startpos;
66
static POSITION prep_endpos;
70
struct hilite *hl_next;
74
static struct hilite hilite_anchor = { NULL, NULL_POSITION, NULL_POSITION };
75
#define hl_first hl_next
79
* These are the static variables that represent the "remembered"
82
#if HAVE_POSIX_REGCOMP
83
static regex_t *regpattern = NULL;
86
pcre *regpattern = NULL;
92
static char *cpattern = NULL;
95
static struct regexp *regpattern = NULL;
98
static int is_caseless;
99
static int is_ucase_pattern;
100
static int last_search_type;
101
static char *last_pattern = NULL;
104
* Convert text. Perform one or more of these transformations:
106
#define CVT_TO_LC 01 /* Convert upper-case to lower-case */
107
#define CVT_BS 02 /* Do backspace processing */
108
#define CVT_CRLF 04 /* Remove CR after LF */
111
cvt_text(odst, osrc, ops)
119
for (src = osrc, dst = odst; *src != '\0'; src++, dst++)
121
if ((ops & CVT_TO_LC) && isupper((unsigned char) *src))
122
/* Convert uppercase to lowercase. */
123
*dst = tolower((unsigned char) *src);
124
else if ((ops & CVT_BS) && *src == '\b' && dst > odst)
125
/* Delete BS and preceding char. */
131
if ((ops & CVT_CRLF) && dst > odst && dst[-1] == '\r')
137
* Are there any uppercase letters in this string?
145
for (p = s; *p != '\0'; p++)
146
if (isupper((unsigned char) *p))
152
* Is there a previous (remembered) search pattern?
157
if (last_search_type & SRCH_NO_REGEX)
158
return (last_pattern != NULL);
159
#if HAVE_POSIX_REGCOMP
160
return (regpattern != NULL);
163
return (regpattern != NULL);
166
return (re_pattern != 0);
169
return (cpattern != NULL);
172
return (regpattern != NULL);
175
return (last_pattern != NULL);
181
* Repaint the hilites currently displayed on the screen.
182
* Repaint each line which contains highlighted text.
183
* If on==0, force all hilites off.
192
int save_hide_hilite;
197
save_hide_hilite = hide_hilite;
208
hide_hilite = save_hide_hilite;
212
for (slinenum = TOP; slinenum < TOP + sc_height-1; slinenum++)
214
pos = position(slinenum);
215
if (pos == NULL_POSITION)
217
epos = position(slinenum+1);
219
* If any character in the line is highlighted,
222
if (is_hilited(pos, epos, 1))
224
(void) forw_line(pos);
229
hide_hilite = save_hide_hilite;
233
* Clear the attn hilite.
239
POSITION old_start_attnpos;
240
POSITION old_end_attnpos;
244
if (start_attnpos == NULL_POSITION)
246
old_start_attnpos = start_attnpos;
247
old_end_attnpos = end_attnpos;
248
start_attnpos = end_attnpos = NULL_POSITION;
258
for (slinenum = TOP; slinenum < TOP + sc_height-1; slinenum++)
260
pos = position(slinenum);
261
if (pos == NULL_POSITION)
263
epos = position(slinenum+1);
264
if (pos < old_end_attnpos &&
265
(epos == NULL_POSITION || epos > old_start_attnpos))
267
(void) forw_line(pos);
276
* Hide search string highlighting.
283
error("No previous regular expression", NULL_PARG);
287
hide_hilite = !hide_hilite;
293
* Compile a search pattern, for future use by match_pattern.
296
compile_pattern(pattern, search_type)
300
if ((search_type & SRCH_NO_REGEX) == 0)
302
#if HAVE_POSIX_REGCOMP
303
regex_t *s = (regex_t *) ecalloc(1, sizeof(regex_t));
304
if (regcomp(s, pattern, REGCOMP_FLAG))
307
error("Invalid pattern", NULL_PARG);
310
if (regpattern != NULL)
316
const char *errstring;
319
comp = pcre_compile(pattern, 0,
320
&errstring, &erroffset, NULL);
323
parg.p_string = (char *) errstring;
331
if ((parg.p_string = re_comp(pattern)) != NULL)
340
if ((s = regcmp(pattern, 0)) == NULL)
342
error("Invalid pattern", NULL_PARG);
345
if (cpattern != NULL)
351
if ((s = regcomp(pattern)) == NULL)
354
* regcomp has already printed an error message
359
if (regpattern != NULL)
365
if (last_pattern != NULL)
367
last_pattern = (char *) calloc(1, strlen(pattern)+1);
368
if (last_pattern != NULL)
369
strcpy(last_pattern, pattern);
371
last_search_type = search_type;
376
* Forget that we have a compiled pattern.
381
#if HAVE_POSIX_REGCOMP
382
if (regpattern != NULL)
387
if (regpattern != NULL)
388
pcre_free(regpattern);
395
if (cpattern != NULL)
400
if (regpattern != NULL)
408
* Perform a pattern match with the previously compiled pattern.
409
* Set sp and ep to the start and end of the matched string.
412
match_pattern(line, sp, ep, notbol)
420
if (last_search_type & SRCH_NO_REGEX)
421
return (match(last_pattern, line, sp, ep));
423
#if HAVE_POSIX_REGCOMP
426
int flags = (notbol) ? REG_NOTBOL : 0;
427
matched = !regexec(regpattern, line, 1, &rm, flags);
431
*sp = line + rm.rm_so;
432
*ep = line + rm.rm_eo;
441
int flags = (notbol) ? PCRE_NOTBOL : 0;
443
matched = pcre_exec(regpattern, NULL, line, strlen(line),
444
0, flags, ovector, 3) >= 0;
447
*sp = line + ovector[0];
448
*ep = line + ovector[1];
452
matched = (re_exec(line) == 1);
454
* re_exec doesn't seem to provide a way to get the matched string.
459
*ep = regex(cpattern, line);
460
matched = (*ep != NULL);
467
matched = regexec2(regpattern, line, notbol);
469
matched = regexec(regpattern, line);
473
*sp = regpattern->startp[0];
474
*ep = regpattern->endp[0];
477
matched = match(last_pattern, line, sp, ep);
484
* Clear the hilite list.
490
struct hilite *nexthl;
492
for (hl = hilite_anchor.hl_first; hl != NULL; hl = nexthl)
494
nexthl = hl->hl_next;
497
hilite_anchor.hl_first = NULL;
498
prep_startpos = prep_endpos = NULL_POSITION;
502
* Should any characters in a specified range be highlighted?
503
* If nohide is nonzero, don't consider hide_hilite.
506
is_hilited(pos, epos, nohide)
514
start_attnpos != NULL_POSITION &&
516
(epos == NULL_POSITION || epos > start_attnpos))
518
* The attn line overlaps this range.
522
if (hilite_search == 0)
524
* Not doing highlighting.
528
if (!nohide && hide_hilite)
530
* Highlighting is hidden.
535
* Look at each highlight and see if any part of it falls in the range.
537
for (hl = hilite_anchor.hl_first; hl != NULL; hl = hl->hl_next)
539
if (hl->hl_endpos > pos &&
540
(epos == NULL_POSITION || epos > hl->hl_startpos))
547
* Add a new hilite to a hilite list.
550
add_hilite(anchor, hl)
551
struct hilite *anchor;
557
* Hilites are sorted in the list; find where new one belongs.
558
* Insert new one after ihl.
560
for (ihl = anchor; ihl->hl_next != NULL; ihl = ihl->hl_next)
562
if (ihl->hl_next->hl_startpos > hl->hl_startpos)
567
* Truncate hilite so it doesn't overlap any existing ones
568
* above and below it.
571
hl->hl_startpos = MAXPOS(hl->hl_startpos, ihl->hl_endpos);
572
if (ihl->hl_next != NULL)
573
hl->hl_endpos = MINPOS(hl->hl_endpos, ihl->hl_next->hl_startpos);
574
if (hl->hl_startpos >= hl->hl_endpos)
577
* Hilite was truncated out of existence.
582
hl->hl_next = ihl->hl_next;
587
* Adjust hl_startpos & hl_endpos to account for backspace processing.
590
adj_hilite(anchor, linepos)
591
struct hilite *anchor;
601
* The line was already scanned and hilites were added (in hilite_line).
602
* But it was assumed that each char position in the line
603
* correponds to one char position in the file.
604
* This may not be true if there are backspaces in the line.
605
* Get the raw line again. Look at each character.
607
(void) forw_raw_line(linepos, &line);
608
opos = npos = linepos;
609
hl = anchor->hl_first;
614
* See if we need to adjust the current hl_startpos or
615
* hl_endpos. After adjusting startpos[i], move to endpos[i].
616
* After adjusting endpos[i], move to startpos[i+1].
617
* The hilite list must be sorted thus:
618
* startpos[0] < endpos[0] <= startpos[1] < endpos[1] <= etc.
620
if (checkstart && hl->hl_startpos == opos)
622
hl->hl_startpos = npos;
624
continue; /* {{ not really necessary }} */
625
} else if (!checkstart && hl->hl_endpos == opos)
627
hl->hl_endpos = npos;
630
continue; /* {{ necessary }} */
637
while (line[0] == '\b' && line[1] != '\0')
640
* Found a backspace. The file position moves
641
* forward by 2 relative to the processed line
642
* which was searched in hilite_line.
651
* Make a hilite for each string in a physical line which matches
652
* the current pattern.
653
* sp,ep delimit the first match already found.
656
hilite_line(linepos, line, sp, ep)
664
struct hilite hilites;
666
if (sp == NULL || ep == NULL)
669
* sp and ep delimit the first match in the line.
670
* Mark the corresponding file positions, then
671
* look for further matches and mark them.
672
* {{ This technique, of calling match_pattern on subsequent
673
* substrings of the line, may mark more than is correct
674
* if the pattern starts with "^". This bug is fixed
675
* for those regex functions that accept a notbol parameter
676
* (currently POSIX and V8-with-regexec2). }}
680
* Put the hilites into a temporary list until they're adjusted.
682
hilites.hl_first = NULL;
687
* Assume that each char position in the "line"
688
* buffer corresponds to one char position in the file.
689
* This is not quite true; we need to adjust later.
691
hl = (struct hilite *) ecalloc(1, sizeof(struct hilite));
692
hl->hl_startpos = linepos + (sp-line);
693
hl->hl_endpos = linepos + (ep-line);
694
add_hilite(&hilites, hl);
697
* If we matched more than zero characters,
698
* move to the first char after the string we matched.
699
* If we matched zero, just move to the next char.
703
else if (*searchp != '\0')
705
else /* end of line */
707
} while (match_pattern(searchp, &sp, &ep, 1));
709
if (bs_mode == BS_SPECIAL)
712
* If there were backspaces in the original line, they
713
* were removed, and hl_startpos/hl_endpos are not correct.
714
* {{ This is very ugly. }}
716
adj_hilite(&hilites, linepos);
719
* Now put the hilites into the real list.
721
while ((hl = hilites.hl_next) != NULL)
723
hilites.hl_next = hl->hl_next;
724
add_hilite(&hilite_anchor, hl);
730
* Change the caseless-ness of searches.
731
* Updates the internal search state to reflect a change in the -i flag.
736
if (!is_ucase_pattern)
738
* Pattern did not have uppercase.
739
* Just set the search caselessness to the global caselessness.
741
is_caseless = caseless;
744
* Pattern did have uppercase.
745
* Discard the pattern; we can't change search caselessness now.
752
* Find matching text which is currently on screen and highlight it.
757
struct scrpos scrpos;
760
if (scrpos.pos == NULL_POSITION)
762
prep_hilite(scrpos.pos, position(BOTTOM_PLUS_ONE), -1);
767
* Change highlighting parameters.
773
* Erase any highlights currently on screen.
778
if (hilite_search == OPT_ONPLUS)
780
* Display highlights.
787
* Figure out where to start a search.
790
search_pos(search_type)
799
* Start at the beginning (or end) of the file.
800
* The empty_screen() case is mainly for
801
* command line initiated searches;
802
* for example, "+/xyz" on the command line.
803
* Also for multi-file (SRCH_PAST_EOF) searches.
805
if (search_type & SRCH_FORW)
811
if (pos == NULL_POSITION)
813
(void) ch_end_seek();
822
* Search does not include current screen.
824
if (search_type & SRCH_FORW)
825
linenum = BOTTOM_PLUS_ONE;
828
pos = position(linenum);
832
* Search includes current screen.
833
* It starts at the jump target (if searching backwards),
834
* or at the jump target plus one (if forwards).
836
linenum = adjsline(jump_sline);
837
pos = position(linenum);
838
if (search_type & SRCH_FORW)
840
pos = forw_raw_line(pos, (char **)NULL);
841
while (pos == NULL_POSITION)
843
if (++linenum >= sc_height)
845
pos = position(linenum);
849
while (pos == NULL_POSITION)
853
pos = position(linenum);
861
* Search a subset of the file, specified by start/end position.
864
search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos)
877
POSITION linepos, oldpos;
879
linenum = find_linenum(pos);
884
* Get lines until we find a matching one or until
885
* we hit end-of-file (or beginning-of-file if we're
886
* going backwards), or until we hit the end position.
891
* A signal aborts the search.
896
if ((endpos != NULL_POSITION && pos >= endpos) || maxlines == 0)
899
* Reached end position without a match.
908
if (search_type & SRCH_FORW)
911
* Read the next line, and save the
912
* starting position of that line in linepos.
915
pos = forw_raw_line(pos, &line);
921
* Read the previous line and save the
922
* starting position of that line in linepos.
924
pos = back_raw_line(pos, &line);
930
if (pos == NULL_POSITION)
933
* Reached EOF/BOF without a match.
941
* If we're using line numbers, we might as well
942
* remember the information we have now (the position
943
* and line number of the current line).
944
* Don't do it for every line because it slows down
945
* the search. Remember the line number only if
946
* we're "far" from the last place we remembered it.
948
if (linenums && abs((int)(pos - oldpos)) > 1024)
949
add_lnum(linenum, pos);
953
* If it's a caseless search, convert the line to lowercase.
954
* If we're doing backspace processing, delete backspaces.
956
if (is_caseless || bs_mode == BS_SPECIAL)
961
if (bs_mode == BS_SPECIAL)
963
if (bs_mode != BS_CONTROL)
965
cvt_text(line, line, ops);
966
} else if (bs_mode != BS_CONTROL)
968
cvt_text(line, line, CVT_CRLF);
972
* Test the next line to see if we have a match.
973
* We are successful if we either want a match and got one,
974
* or if we want a non-match and got one.
976
line_match = match_pattern(line, &sp, &ep, 0);
977
line_match = (!(search_type & SRCH_NO_MATCH) && line_match) ||
978
((search_type & SRCH_NO_MATCH) && !line_match);
984
if (search_type & SRCH_FIND_ALL)
988
* We are supposed to find all matches in the range.
989
* Just add the matches in this line to the
990
* hilite list and keep searching.
993
hilite_line(linepos, line, sp, ep);
995
} else if (--matches <= 0)
998
* Found the one match we're looking for.
1002
if (hilite_search == 1)
1005
* Clear the hilite list and add only
1006
* the matches in this one line.
1010
hilite_line(linepos, line, sp, ep);
1013
if (plinepos != NULL)
1014
*plinepos = linepos;
1021
* Search for the n-th occurrence of a specified pattern,
1022
* either forward or backward.
1023
* Return the number of matches not yet found in this file
1024
* (that is, n minus the number of matches found).
1025
* Return -1 if the search should be aborted.
1026
* Caller may continue the search in another file
1027
* if less than n matches are found in this file.
1030
search(search_type, pattern, n)
1038
if (pattern == NULL || *pattern == '\0')
1041
* A null pattern means use the previously compiled pattern.
1043
if (!prev_pattern())
1045
error("No previous regular expression", NULL_PARG);
1048
if ((search_type & SRCH_NO_REGEX) !=
1049
(last_search_type & SRCH_NO_REGEX))
1051
error("Please re-enter search pattern", NULL_PARG);
1055
if (hilite_search == OPT_ON)
1058
* Erase the highlights currently on screen.
1059
* If the search fails, we'll redisplay them later.
1063
if (hilite_search == OPT_ONPLUS && hide_hilite)
1066
* Highlight any matches currently on screen,
1067
* before we actually start the search.
1077
* Compile the pattern.
1079
ucase = is_ucase(pattern);
1080
if (caseless == OPT_ONPLUS)
1081
cvt_text(pattern, pattern, CVT_TO_LC);
1082
if (compile_pattern(pattern, search_type) < 0)
1085
* Ignore case if -I is set OR
1086
* -i is set AND the pattern is all lowercase.
1088
is_ucase_pattern = ucase;
1089
if (is_ucase_pattern && caseless != OPT_ONPLUS)
1092
is_caseless = caseless;
1097
* Erase the highlights currently on screen.
1098
* Also permanently delete them from the hilite list.
1104
if (hilite_search == OPT_ONPLUS)
1107
* Highlight any matches currently on screen,
1108
* before we actually start the search.
1116
* Figure out where to start the search.
1118
pos = search_pos(search_type);
1119
if (pos == NULL_POSITION)
1122
* Can't find anyplace to start searching from.
1124
if (search_type & SRCH_PAST_EOF)
1126
/* repaint(); -- why was this here? */
1127
error("Nothing to search", NULL_PARG);
1131
n = search_range(pos, NULL_POSITION, search_type, n, -1,
1132
&pos, (POSITION*)NULL);
1136
* Search was unsuccessful.
1139
if (hilite_search == OPT_ON && n > 0)
1141
* Redisplay old hilites.
1148
if (!(search_type & SRCH_NO_MOVE))
1151
* Go to the matching line.
1153
jump_loc(pos, jump_sline);
1157
if (hilite_search == OPT_ON)
1159
* Display new hilites in the matching line.
1169
* Prepare hilites in a given range of the file.
1171
* The pair (prep_startpos,prep_endpos) delimits a contiguous region
1172
* of the file that has been "prepared"; that is, scanned for matches for
1173
* the current search pattern, and hilites have been created for such matches.
1174
* If prep_startpos == NULL_POSITION, the prep region is empty.
1175
* If prep_endpos == NULL_POSITION, the prep region extends to EOF.
1176
* prep_hilite asks that the range (spos,epos) be covered by the prep region.
1179
prep_hilite(spos, epos, maxlines)
1184
POSITION nprep_startpos = prep_startpos;
1185
POSITION nprep_endpos = prep_endpos;
1191
* Search beyond where we're asked to search, so the prep region covers
1192
* more than we need. Do one big search instead of a bunch of small ones.
1194
#define SEARCH_MORE (3*size_linebuf)
1196
if (!prev_pattern())
1200
* If we're limited to a max number of lines, figure out the
1201
* file position we should stop at.
1204
max_epos = NULL_POSITION;
1208
for (i = 0; i < maxlines; i++)
1209
max_epos = forw_raw_line(max_epos, (char **)NULL);
1214
* The range that we need to search (spos,epos); and the range that
1215
* the "prep" region will then cover (nprep_startpos,nprep_endpos).
1218
if (prep_startpos == NULL_POSITION ||
1219
(epos != NULL_POSITION && epos < prep_startpos) ||
1223
* New range is not contiguous with old prep region.
1224
* Discard the old prep region and start a new one.
1227
if (epos != NULL_POSITION)
1228
epos += SEARCH_MORE;
1229
nprep_startpos = spos;
1233
* New range partially or completely overlaps old prep region.
1235
if (epos == NULL_POSITION)
1238
* New range goes to end of file.
1241
} else if (epos > prep_endpos)
1244
* New range ends after old prep region.
1245
* Extend prep region to end at end of new range.
1247
epos += SEARCH_MORE;
1248
} else /* (epos <= prep_endpos) */
1251
* New range ends within old prep region.
1252
* Truncate search to end at start of old prep region.
1254
epos = prep_startpos;
1257
if (spos < prep_startpos)
1260
* New range starts before old prep region.
1261
* Extend old prep region backwards to start at
1262
* start of new range.
1264
if (spos < SEARCH_MORE)
1267
spos -= SEARCH_MORE;
1268
nprep_startpos = spos;
1269
} else /* (spos >= prep_startpos) */
1272
* New range starts within or after old prep region.
1273
* Trim search to start at end of old prep region.
1279
if (epos != NULL_POSITION && max_epos != NULL_POSITION &&
1282
* Don't go past the max position we're allowed.
1286
if (epos == NULL_POSITION || epos > spos)
1288
result = search_range(spos, epos, SRCH_FORW|SRCH_FIND_ALL, 0,
1289
maxlines, (POSITION*)NULL, &new_epos);
1292
if (prep_endpos == NULL_POSITION || new_epos > prep_endpos)
1293
nprep_endpos = new_epos;
1295
prep_startpos = nprep_startpos;
1296
prep_endpos = nprep_endpos;
1301
* Simple pattern matching function.
1302
* It supports no metacharacters like *, etc.
1305
match(pattern, buf, pfound, pend)
1306
char *pattern, *buf;
1307
char **pfound, **pend;
1309
register char *pp, *lp;
1311
for ( ; *buf != '\0'; buf++)
1313
for (pp = pattern, lp = buf; *pp == *lp; pp++, lp++)
1314
if (*pp == '\0' || *lp == '\0')
1330
* This function is called by the V8 regcomp to report
1331
* errors in regular expressions.