1 /* $NetBSD: v_search.c,v 1.3 2013/11/25 22:43:46 christos Exp $ */ 2 /*- 3 * Copyright (c) 1992, 1993, 1994 4 * The Regents of the University of California. All rights reserved. 5 * Copyright (c) 1992, 1993, 1994, 1995, 1996 6 * Keith Bostic. All rights reserved. 7 * 8 * See the LICENSE file for redistribution information. 9 */ 10 11 #include "config.h" 12 13 #ifndef lint 14 static const char sccsid[] = "Id: v_search.c,v 10.30 2001/09/11 20:52:46 skimo Exp (Berkeley) Date: 2001/09/11 20:52:46 "; 15 #endif /* not lint */ 16 17 #include <sys/types.h> 18 #include <sys/queue.h> 19 #include <sys/time.h> 20 21 #include <bitstring.h> 22 #include <ctype.h> 23 #include <errno.h> 24 #include <limits.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 29 #include "../common/common.h" 30 #include "vi.h" 31 #include "../ipc/ip.h" 32 33 static int v_exaddr __P((SCR *, VICMD *, dir_t)); 34 static int v_search __P((SCR *, VICMD *, CHAR_T *, size_t, u_int, dir_t)); 35 36 /* 37 * v_srch -- [count]?RE[? offset] 38 * Ex address search backward. 39 * 40 * PUBLIC: int v_searchb __P((SCR *, VICMD *)); 41 */ 42 int 43 v_searchb(SCR *sp, VICMD *vp) 44 { 45 return (v_exaddr(sp, vp, BACKWARD)); 46 } 47 48 /* 49 * v_searchf -- [count]/RE[/ offset] 50 * Ex address search forward. 51 * 52 * PUBLIC: int v_searchf __P((SCR *, VICMD *)); 53 */ 54 int 55 v_searchf(SCR *sp, VICMD *vp) 56 { 57 return (v_exaddr(sp, vp, FORWARD)); 58 } 59 60 /* 61 * v_exaddr -- 62 * Do a vi search (which is really an ex address). 63 */ 64 static int 65 v_exaddr(SCR *sp, VICMD *vp, dir_t dir) 66 { 67 static EXCMDLIST fake = { .name = L("search") }; 68 EXCMD *cmdp; 69 WIN *wp; 70 TEXT *tp; 71 db_recno_t s_lno; 72 size_t len, s_cno, tlen; 73 int err, nb, type; 74 char buf[20]; 75 CHAR_T *cmd, *t; 76 const CHAR_T *w; 77 size_t wlen; 78 79 /* 80 * !!! 81 * If using the search command as a motion, any addressing components 82 * are lost, i.e. y/ptrn/+2, when repeated, is the same as y/ptrn/. 83 */ 84 if (F_ISSET(vp, VC_ISDOT)) 85 return (v_search(sp, vp, 86 NULL, 0, SEARCH_PARSE | SEARCH_MSG | SEARCH_SET, dir)); 87 88 /* Get the search pattern. */ 89 if (v_tcmd(sp, vp, dir == BACKWARD ? CH_BSEARCH : CH_FSEARCH, 90 TXT_BS | TXT_CR | TXT_ESCAPE | TXT_PROMPT | 91 (O_ISSET(sp, O_SEARCHINCR) ? TXT_SEARCHINCR : 0))) 92 return (1); 93 94 tp = TAILQ_FIRST(&sp->tiq); 95 96 /* If the user backspaced over the prompt, do nothing. */ 97 if (tp->term == TERM_BS) 98 return (1); 99 100 /* 101 * If the user was doing an incremental search, then we've already 102 * updated the cursor and moved to the right location. Return the 103 * correct values, we're done. 104 */ 105 if (tp->term == TERM_SEARCH) { 106 vp->m_stop.lno = sp->lno; 107 vp->m_stop.cno = sp->cno; 108 if (ISMOTION(vp)) 109 return (v_correct(sp, vp, 0)); 110 vp->m_final = vp->m_stop; 111 return (0); 112 } 113 114 /* 115 * If the user entered <escape> or <carriage-return>, the length is 116 * 1 and the right thing will happen, i.e. the prompt will be used 117 * as a command character. 118 * 119 * Build a fake ex command structure. 120 */ 121 wp = sp->wp; 122 wp->excmd.cp = tp->lb; 123 wp->excmd.clen = tp->len; 124 F_INIT(&wp->excmd, E_VISEARCH); 125 126 /* 127 * XXX 128 * Warn if the search wraps. This is a pretty special case, but it's 129 * nice feature that wasn't in the original implementations of ex/vi. 130 * (It was added at some point to System V's version.) This message 131 * is only displayed if there are no keys in the queue. The problem is 132 * the command is going to succeed, and the message is informational, 133 * not an error. If a macro displays it repeatedly, e.g., the pattern 134 * only occurs once in the file and wrapscan is set, you lose big. For 135 * example, if the macro does something like: 136 * 137 * :map K /pattern/^MjK 138 * 139 * Each search will display the message, but the following "/pattern/" 140 * will immediately overwrite it, with strange results. The System V 141 * vi displays the "wrapped" message multiple times, but because it's 142 * overwritten each time, it's not as noticeable. As we don't discard 143 * messages, it's a real problem for us. 144 */ 145 if (!KEYS_WAITING(sp)) 146 F_SET(&wp->excmd, E_SEARCH_WMSG); 147 148 /* Save the current line/column. */ 149 s_lno = sp->lno; 150 s_cno = sp->cno; 151 152 /* 153 * !!! 154 * Historically, vi / and ? commands were full-blown ex addresses, 155 * including ';' delimiters, trailing <blank>'s, multiple search 156 * strings (separated by semi-colons) and, finally, full-blown z 157 * commands after the / and ? search strings. (If the search was 158 * being used as a motion, the trailing z command was ignored. 159 * Also, we do some argument checking on the z command, to be sure 160 * that it's not some other random command.) For multiple search 161 * strings, leading <blank>'s at the second and subsequent strings 162 * were eaten as well. This has some (unintended?) side-effects: 163 * the command /ptrn/;3 is legal and results in moving to line 3. 164 * I suppose you could use it to optionally move to line 3... 165 * 166 * !!! 167 * Historically, if any part of the search command failed, the cursor 168 * remained unmodified (even if ; was used). We have to play games 169 * because the underlying ex parser thinks we're modifying the cursor 170 * as we go, but I think we're compatible with historic practice. 171 * 172 * !!! 173 * Historically, the command "/STRING/; " failed, apparently it 174 * confused the parser. We're not that compatible. 175 */ 176 cmdp = &wp->excmd; 177 if (ex_range(sp, cmdp, &err)) 178 return (1); 179 180 /* 181 * Remember where any remaining command information is, and clean 182 * up the fake ex command. 183 */ 184 cmd = cmdp->cp; 185 len = cmdp->clen; 186 wp->excmd.clen = 0; 187 188 if (err) 189 goto err2; 190 191 /* Copy out the new cursor position and make sure it's okay. */ 192 switch (cmdp->addrcnt) { 193 case 1: 194 vp->m_stop = cmdp->addr1; 195 break; 196 case 2: 197 vp->m_stop = cmdp->addr2; 198 break; 199 } 200 if (!db_exist(sp, vp->m_stop.lno)) { 201 ex_badaddr(sp, &fake, 202 vp->m_stop.lno == 0 ? A_ZERO : A_EOF, NUM_OK); 203 goto err2; 204 } 205 206 /* 207 * !!! 208 * Historic practice is that a trailing 'z' was ignored if it was a 209 * motion command. Should probably be an error, but not worth the 210 * effort. 211 */ 212 if (ISMOTION(vp)) 213 return (v_correct(sp, vp, F_ISSET(cmdp, E_DELTA))); 214 215 /* 216 * !!! 217 * Historically, if it wasn't a motion command, a delta in the search 218 * pattern turns it into a first nonblank movement. 219 */ 220 nb = F_ISSET(cmdp, E_DELTA); 221 222 /* Check for the 'z' command. */ 223 if (len != 0) { 224 if (*cmd != 'z') 225 goto err1; 226 227 /* No blanks, just like the z command. */ 228 for (t = cmd + 1, tlen = len - 1; tlen > 0; ++t, --tlen) 229 if (!ISDIGIT((UCHAR_T)*t)) 230 break; 231 if (tlen && 232 (*t == '-' || *t == '.' || *t == '+' || *t == '^')) { 233 ++t; 234 --tlen; 235 type = 1; 236 } else 237 type = 0; 238 if (tlen) 239 goto err1; 240 241 /* The z command will do the nonblank for us. */ 242 nb = 0; 243 244 /* Default to z+. */ 245 if (!type && 246 v_event_push(sp, NULL, L("+"), 1, CH_NOMAP | CH_QUOTED)) 247 return (1); 248 249 /* Push the user's command. */ 250 if (v_event_push(sp, NULL, cmd, len, CH_NOMAP | CH_QUOTED)) 251 return (1); 252 253 /* Push line number so get correct z display. */ 254 tlen = snprintf(buf, 255 sizeof(buf), "%lu", (u_long)vp->m_stop.lno); 256 CHAR2INT(sp, buf, tlen, w, wlen); 257 if (v_event_push(sp, NULL, w, wlen, CH_NOMAP | CH_QUOTED)) 258 return (1); 259 260 /* Don't refresh until after 'z' happens. */ 261 F_SET(VIP(sp), VIP_S_REFRESH); 262 } 263 264 /* Non-motion commands move to the end of the range. */ 265 vp->m_final = vp->m_stop; 266 if (nb) { 267 F_CLR(vp, VM_RCM_MASK); 268 F_SET(vp, VM_RCM_SETFNB); 269 } 270 return (0); 271 272 err1: msgq(sp, M_ERR, 273 "188|Characters after search string, line offset and/or z command"); 274 err2: vp->m_final.lno = s_lno; 275 vp->m_final.cno = s_cno; 276 return (1); 277 } 278 279 /* 280 * v_searchN -- N 281 * Reverse last search. 282 * 283 * PUBLIC: int v_searchN __P((SCR *, VICMD *)); 284 */ 285 int 286 v_searchN(SCR *sp, VICMD *vp) 287 { 288 dir_t dir; 289 290 switch (sp->searchdir) { 291 case BACKWARD: 292 dir = FORWARD; 293 break; 294 case FORWARD: 295 dir = BACKWARD; 296 break; 297 default: 298 dir = sp->searchdir; 299 break; 300 } 301 return (v_search(sp, vp, NULL, 0, SEARCH_PARSE, dir)); 302 } 303 304 /* 305 * v_searchn -- n 306 * Repeat last search. 307 * 308 * PUBLIC: int v_searchn __P((SCR *, VICMD *)); 309 */ 310 int 311 v_searchn(SCR *sp, VICMD *vp) 312 { 313 return (v_search(sp, vp, NULL, 0, SEARCH_PARSE, sp->searchdir)); 314 } 315 316 /* 317 * is_especial -- 318 * Test if the character is special in an extended RE. 319 */ 320 static int 321 is_especial(CHAR_T c) 322 { 323 /* 324 * !!! 325 * Right-brace is not an ERE special according to IEEE 1003.1-2001. 326 * Right-parenthesis is a special character (so quoting doesn't hurt), 327 * though it has no special meaning in this context, viz. at the 328 * beginning of the string. So we need not quote it. Then again, 329 * see the BUGS section in regex/re_format.7. 330 * The tilde is vi-specific, of course. 331 */ 332 return (STRCHR(L(".[\\()*+?{|^$~"), c) && c); 333 } 334 335 /* 336 * Rear delimiter for word search when the keyword ends in 337 * (i.e., consists of) a non-word character. See v_searchw below. 338 */ 339 #define RE_NWSTOP L("([^[:alnum:]_]|$)") 340 #define RE_NWSTOP_LEN (SIZE(RE_NWSTOP) - 1) 341 342 /* 343 * v_searchw -- [count]^A 344 * Search for the word under the cursor. 345 * 346 * PUBLIC: int v_searchw __P((SCR *, VICMD *)); 347 */ 348 int 349 v_searchw(SCR *sp, VICMD *vp) 350 { 351 size_t blen, len; 352 int rval; 353 CHAR_T *bp, *p; 354 355 len = VIP(sp)->klen + MAX(RE_WSTART_LEN, 1) 356 + MAX(RE_WSTOP_LEN, RE_NWSTOP_LEN); 357 358 GET_SPACE_RETW(sp, bp, blen, len); 359 p = bp; 360 361 /* Only the first character can be non-word, see v_curword. */ 362 if (inword(VIP(sp)->keyw[0])) 363 p = MEMPCPY(p, RE_WSTART, RE_WSTART_LEN); 364 else if (is_especial(VIP(sp)->keyw[0])) 365 p = MEMPCPY(p, L("\\"), 1); 366 367 p = MEMPCPY(p, VIP(sp)->keyw, VIP(sp)->klen); 368 369 if (inword(p[-1])) 370 p = MEMPCPY(p, RE_WSTOP, RE_WSTOP_LEN); 371 else 372 /* 373 * The keyword is a single non-word character. 374 * We want it to stay the same when typing ^A several times 375 * in a row, just the way the other cases behave. 376 */ 377 p = MEMPCPY(p, RE_NWSTOP, RE_NWSTOP_LEN); 378 379 len = p - bp; 380 rval = v_search(sp, vp, bp, len, SEARCH_SET | SEARCH_EXTEND, FORWARD); 381 382 FREE_SPACEW(sp, bp, blen); 383 return (rval); 384 } 385 386 /* 387 * v_esearch -- <dialog box> 388 * Search command from the screen. 389 * 390 * PUBLIC: int v_esearch __P((SCR *, VICMD *)); 391 */ 392 int 393 v_esearch(SCR *sp, VICMD *vp) 394 { 395 int flags; 396 397 LF_INIT(SEARCH_NOOPT); 398 if (FL_ISSET(vp->ev.e_flags, VI_SEARCH_EXT)) 399 LF_SET(SEARCH_EXTEND); 400 if (FL_ISSET(vp->ev.e_flags, VI_SEARCH_IC)) 401 LF_SET(SEARCH_IC); 402 if (FL_ISSET(vp->ev.e_flags, VI_SEARCH_ICL)) 403 LF_SET(SEARCH_ICL); 404 if (FL_ISSET(vp->ev.e_flags, VI_SEARCH_INCR)) 405 LF_SET(SEARCH_INCR); 406 if (FL_ISSET(vp->ev.e_flags, VI_SEARCH_LIT)) 407 LF_SET(SEARCH_LITERAL); 408 if (FL_ISSET(vp->ev.e_flags, VI_SEARCH_WR)) 409 LF_SET(SEARCH_WRAP); 410 return (v_search(sp, vp, vp->ev.e_csp, vp->ev.e_len, flags, 411 FL_ISSET(vp->ev.e_flags, VI_SEARCH_REV) ? BACKWARD : FORWARD)); 412 } 413 414 /* 415 * v_search -- 416 * The search commands. 417 */ 418 static int 419 v_search(SCR *sp, VICMD *vp, CHAR_T *ptrn, size_t plen, u_int flags, dir_t dir) 420 { 421 /* Display messages. */ 422 LF_SET(SEARCH_MSG); 423 424 /* If it's a motion search, offset past end-of-line is okay. */ 425 if (ISMOTION(vp)) 426 LF_SET(SEARCH_EOL); 427 428 /* 429 * XXX 430 * Warn if the search wraps. See the comment above, in v_exaddr(). 431 */ 432 if (!KEYS_WAITING(sp)) 433 LF_SET(SEARCH_WMSG); 434 435 switch (dir) { 436 case BACKWARD: 437 if (b_search(sp, 438 &vp->m_start, &vp->m_stop, ptrn, plen, NULL, flags)) 439 return (1); 440 break; 441 case FORWARD: 442 if (f_search(sp, 443 &vp->m_start, &vp->m_stop, ptrn, plen, NULL, flags)) 444 return (1); 445 break; 446 case NOTSET: 447 msgq(sp, M_ERR, "189|No previous search pattern"); 448 return (1); 449 default: 450 abort(); 451 } 452 453 /* Correct motion commands, otherwise, simply move to the location. */ 454 if (ISMOTION(vp)) { 455 if (v_correct(sp, vp, 0)) 456 return(1); 457 } else 458 vp->m_final = vp->m_stop; 459 return (0); 460 } 461 462 /* 463 * v_correct -- 464 * Handle command with a search as the motion. 465 * 466 * !!! 467 * Historically, commands didn't affect the line searched to/from if the 468 * motion command was a search and the final position was the start/end 469 * of the line. There were some special cases and vi was not consistent; 470 * it was fairly easy to confuse it. For example, given the two lines: 471 * 472 * abcdefghi 473 * ABCDEFGHI 474 * 475 * placing the cursor on the 'A' and doing y?$ would so confuse it that 'h' 476 * 'k' and put would no longer work correctly. In any case, we try to do 477 * the right thing, but it's not going to exactly match historic practice. 478 * 479 * PUBLIC: int v_correct __P((SCR *, VICMD *, int)); 480 */ 481 int 482 v_correct(SCR *sp, VICMD *vp, int isdelta) 483 { 484 MARK m; 485 size_t len; 486 487 /* 488 * !!! 489 * We may have wrapped if wrapscan was set, and we may have returned 490 * to the position where the cursor started. Historic vi didn't cope 491 * with this well. Yank wouldn't beep, but the first put after the 492 * yank would move the cursor right one column (without adding any 493 * text) and the second would put a copy of the current line. The 494 * change and delete commands would beep, but would leave the cursor 495 * on the colon command line. I believe that there are macros that 496 * depend on delete, at least, failing. For now, commands that use 497 * search as a motion component fail when the search returns to the 498 * original cursor position. 499 */ 500 if (vp->m_start.lno == vp->m_stop.lno && 501 vp->m_start.cno == vp->m_stop.cno) { 502 msgq(sp, M_BERR, "190|Search wrapped to original position"); 503 return (1); 504 } 505 506 /* 507 * !!! 508 * Searches become line mode operations if there was a delta specified 509 * to the search pattern. 510 */ 511 if (isdelta) 512 F_SET(vp, VM_LMODE); 513 514 /* 515 * If the motion is in the reverse direction, switch the start and 516 * stop MARK's so that it's in a forward direction. (There's no 517 * reason for this other than to make the tests below easier. The 518 * code in vi.c:vi() would have done the switch.) Both forward 519 * and backward motions can happen for any kind of search command 520 * because of the wrapscan option. 521 */ 522 if (vp->m_start.lno > vp->m_stop.lno || 523 (vp->m_start.lno == vp->m_stop.lno && 524 vp->m_start.cno > vp->m_stop.cno)) { 525 m = vp->m_start; 526 vp->m_start = vp->m_stop; 527 vp->m_stop = m; 528 } else 529 530 /* 531 * BACKWARD: 532 * Delete and yank commands move to the end of the range. 533 * Ignore others. 534 * 535 * FORWARD: 536 * Delete and yank commands don't move. Ignore others. 537 */ 538 vp->m_final = vp->m_start; 539 540 /* 541 * !!! 542 * Delta'd searches don't correct based on column positions. 543 */ 544 if (isdelta) 545 return (0); 546 547 /* 548 * !!! 549 * Backward searches starting at column 0, and forward searches ending 550 * at column 0 are corrected to the last column of the previous line. 551 * Otherwise, adjust the starting/ending point to the character before 552 * the current one (this is safe because we know the search had to move 553 * to succeed). 554 * 555 * Searches become line mode operations if they start at the first 556 * nonblank and end at column 0 of another line. 557 */ 558 if (vp->m_start.lno < vp->m_stop.lno && vp->m_stop.cno == 0) { 559 if (db_get(sp, --vp->m_stop.lno, DBG_FATAL, NULL, &len)) 560 return (1); 561 vp->m_stop.cno = len ? len - 1 : 0; 562 len = 0; 563 if (nonblank(sp, vp->m_start.lno, &len)) 564 return (1); 565 if (vp->m_start.cno <= len) 566 F_SET(vp, VM_LMODE); 567 } else 568 --vp->m_stop.cno; 569 570 return (0); 571 } 572