Annotation of src/usr.bin/mg/search.c, Revision 1.6
1.6 ! art 1: /* $OpenBSD: search.c,v 1.5 2001/05/03 20:43:12 art Exp $ */
1.4 niklas 2:
1.1 deraadt 3: /*
4: * Search commands.
1.3 millert 5: * The functions in this file implement the search commands (both plain and
6: * incremental searches are supported) and the query-replace command.
1.1 deraadt 7: *
1.3 millert 8: * The plain old search code is part of the original MicroEMACS "distribution".
9: * The incremental search code and the query-replace code is by Rich Ellison.
1.1 deraadt 10: */
1.3 millert 11:
12: #include "def.h"
13:
1.1 deraadt 14: #ifndef NO_MACRO
1.3 millert 15: #include "macro.h"
16: #endif /* !NO_MACRO */
1.1 deraadt 17:
1.2 millert 18: #define SRCH_BEGIN (0) /* Search sub-codes. */
1.1 deraadt 19: #define SRCH_FORW (-1)
20: #define SRCH_BACK (-2)
21: #define SRCH_NOPR (-3)
22: #define SRCH_ACCM (-4)
23: #define SRCH_MARK (-5)
24:
1.2 millert 25: typedef struct {
1.3 millert 26: int s_code;
27: LINE *s_dotp;
28: int s_doto;
29: } SRCHCOM;
30:
31: static int isearch __P((int));
1.6 ! art 32: static void is_cpush __P((int));
! 33: static void is_lpush __P((void));
! 34: static void is_pop __P((void));
1.3 millert 35: static int is_peek __P((void));
1.6 ! art 36: static void is_undo __P((int *, int *));
1.3 millert 37: static int is_find __P((int));
1.6 ! art 38: static void is_prompt __P((int, int, int));
! 39: static void is_dspl __P((char *, int));
1.3 millert 40: static int eq __P((int, int));
41:
42: static SRCHCOM cmds[NSRCH];
43: static int cip;
44:
45: int srch_lastdir = SRCH_NOPR; /* Last search flags. */
46:
47: /*
48: * Search forward. Get a search string from the user, and search for it
49: * starting at ".". If found, "." gets moved to just after the matched
50: * characters, and display does all the hard stuff. If not found, it just
51: * prints a message.
1.1 deraadt 52: */
1.2 millert 53: /* ARGSUSED */
1.3 millert 54: int
1.1 deraadt 55: forwsearch(f, n)
1.3 millert 56: int f, n;
1.1 deraadt 57: {
1.3 millert 58: int s;
1.1 deraadt 59:
1.2 millert 60: if ((s = readpattern("Search")) != TRUE)
1.1 deraadt 61: return s;
62: if (forwsrch() == FALSE) {
63: ewprintf("Search failed: \"%s\"", pat);
64: return FALSE;
65: }
66: srch_lastdir = SRCH_FORW;
67: return TRUE;
68: }
69:
70: /*
1.3 millert 71: * Reverse search. Get a search string from the user, and search, starting
72: * at "." and proceeding toward the front of the buffer. If found "." is
73: * left pointing at the first character of the pattern [the last character
74: * that was matched].
1.1 deraadt 75: */
1.2 millert 76: /* ARGSUSED */
1.3 millert 77: int
1.1 deraadt 78: backsearch(f, n)
1.3 millert 79: int f, n;
1.1 deraadt 80: {
1.3 millert 81: int s;
1.1 deraadt 82:
1.2 millert 83: if ((s = readpattern("Search backward")) != TRUE)
1.1 deraadt 84: return (s);
85: if (backsrch() == FALSE) {
86: ewprintf("Search failed: \"%s\"", pat);
87: return FALSE;
88: }
89: srch_lastdir = SRCH_BACK;
90: return TRUE;
91: }
92:
93: /*
1.3 millert 94: * Search again, using the same search string and direction as the last
95: * search command. The direction has been saved in "srch_lastdir", so you
96: * know which way to go.
1.1 deraadt 97: */
1.2 millert 98: /* ARGSUSED */
1.3 millert 99: int
1.1 deraadt 100: searchagain(f, n)
1.3 millert 101: int f, n;
1.1 deraadt 102: {
103: if (srch_lastdir == SRCH_FORW) {
104: if (forwsrch() == FALSE) {
105: ewprintf("Search failed: \"%s\"", pat);
106: return FALSE;
107: }
108: return TRUE;
109: }
110: if (srch_lastdir == SRCH_BACK) {
111: if (backsrch() == FALSE) {
112: ewprintf("Search failed: \"%s\"", pat);
113: return FALSE;
114: }
115: return TRUE;
116: }
117: ewprintf("No last search");
118: return FALSE;
119: }
120:
121: /*
1.3 millert 122: * Use incremental searching, initially in the forward direction.
1.1 deraadt 123: * isearch ignores any explicit arguments.
124: */
1.2 millert 125: /* ARGSUSED */
1.3 millert 126: int
1.1 deraadt 127: forwisearch(f, n)
1.3 millert 128: int f, n;
1.1 deraadt 129: {
130: return isearch(SRCH_FORW);
131: }
132:
133: /*
134: * Use incremental searching, initially in the reverse direction.
135: * isearch ignores any explicit arguments.
136: */
1.2 millert 137: /* ARGSUSED */
1.3 millert 138: int
1.1 deraadt 139: backisearch(f, n)
1.3 millert 140: int f, n;
1.1 deraadt 141: {
142: return isearch(SRCH_BACK);
143: }
144:
145: /*
146: * Incremental Search.
147: * dir is used as the initial direction to search.
148: * ^S switch direction to forward
149: * ^R switch direction to reverse
150: * ^Q quote next character (allows searching for ^N etc.)
151: * <ESC> exit from Isearch
152: * <DEL> undoes last character typed. (tricky job to do this correctly).
153: * other ^ exit search, don't set mark
154: * else accumulate into search string
155: */
1.3 millert 156: static int
1.2 millert 157: isearch(dir)
1.3 millert 158: int dir;
1.2 millert 159: {
1.3 millert 160: LINE *clp;
161:
162: int c;
163: int cbo;
164: int success;
165: int pptr;
166:
167: char opat[NPAT];
1.1 deraadt 168:
169: #ifndef NO_MACRO
1.2 millert 170: if (macrodef) {
171: ewprintf("Can't isearch in macro");
172: return FALSE;
1.1 deraadt 173: }
1.3 millert 174: #endif /* !NO_MACRO */
1.2 millert 175: for (cip = 0; cip < NSRCH; cip++)
1.1 deraadt 176: cmds[cip].s_code = SRCH_NOPR;
1.3 millert 177:
1.6 ! art 178: (void)strcpy(opat, pat);
1.1 deraadt 179: cip = 0;
180: pptr = -1;
181: clp = curwp->w_dotp;
182: cbo = curwp->w_doto;
183: is_lpush();
184: is_cpush(SRCH_BEGIN);
185: success = TRUE;
186: is_prompt(dir, TRUE, success);
1.3 millert 187:
1.1 deraadt 188: for (;;) {
189: update();
1.3 millert 190:
1.1 deraadt 191: switch (c = getkey(FALSE)) {
192: case CCHR('['):
1.5 art 193: /*
194: * If new characters come in the next 300 msec,
195: * we can assume that they belong to a longer
196: * escaped sequence so we should ungetkey the
197: * ESC to avoid writing out garbage.
198: */
199: if (ttwait(300) == FALSE)
200: ungetkey(c);
1.1 deraadt 201: srch_lastdir = dir;
202: curwp->w_markp = clp;
203: curwp->w_marko = cbo;
204: ewprintf("Mark set");
205: return (TRUE);
206: case CCHR('G'):
207: if (success != TRUE) {
208: while (is_peek() == SRCH_ACCM)
209: is_undo(&pptr, &dir);
210: success = TRUE;
211: is_prompt(dir, pptr < 0, success);
212: break;
213: }
214: curwp->w_dotp = clp;
215: curwp->w_doto = cbo;
216: curwp->w_flag |= WFMOVE;
217: srch_lastdir = dir;
1.6 ! art 218: (void)ctrlg(FFRAND, 0);
! 219: (void)strcpy(pat, opat);
1.1 deraadt 220: return ABORT;
221: case CCHR(']'):
222: case CCHR('S'):
223: if (dir == SRCH_BACK) {
224: dir = SRCH_FORW;
225: is_lpush();
226: is_cpush(SRCH_FORW);
227: success = TRUE;
228: }
1.2 millert 229: if (success == FALSE && dir == SRCH_FORW)
1.1 deraadt 230: break;
231: is_lpush();
232: pptr = strlen(pat);
1.6 ! art 233: (void)forwchar(FFRAND, 1);
1.2 millert 234: if (is_find(SRCH_FORW) != FALSE)
235: is_cpush(SRCH_MARK);
1.1 deraadt 236: else {
1.6 ! art 237: (void)backchar(FFRAND, 1);
1.1 deraadt 238: ttbeep();
239: success = FALSE;
240: }
241: is_prompt(dir, pptr < 0, success);
242: break;
243: case CCHR('R'):
244: if (dir == SRCH_FORW) {
245: dir = SRCH_BACK;
246: is_lpush();
247: is_cpush(SRCH_BACK);
248: success = TRUE;
249: }
1.2 millert 250: if (success == FALSE && dir == SRCH_BACK)
1.1 deraadt 251: break;
252: is_lpush();
253: pptr = strlen(pat);
1.6 ! art 254: (void)backchar(FFRAND, 1);
1.2 millert 255: if (is_find(SRCH_BACK) != FALSE)
256: is_cpush(SRCH_MARK);
1.1 deraadt 257: else {
1.6 ! art 258: (void)forwchar(FFRAND, 1);
1.1 deraadt 259: ttbeep();
260: success = FALSE;
261: }
262: is_prompt(dir, pptr < 0, success);
263: break;
264: case CCHR('H'):
265: case CCHR('?'):
266: is_undo(&pptr, &dir);
1.2 millert 267: if (is_peek() != SRCH_ACCM)
268: success = TRUE;
1.1 deraadt 269: is_prompt(dir, pptr < 0, success);
270: break;
271: case CCHR('\\'):
272: case CCHR('Q'):
1.3 millert 273: c = (char)getkey(FALSE);
1.2 millert 274: goto addchar;
1.1 deraadt 275: case CCHR('M'):
276: c = CCHR('J');
1.2 millert 277: goto addchar;
1.1 deraadt 278: default:
279: if (ISCTRL(c)) {
280: ungetkey(c);
281: curwp->w_markp = clp;
282: curwp->w_marko = cbo;
283: ewprintf("Mark set");
284: curwp->w_flag |= WFMOVE;
1.2 millert 285: return TRUE;
1.1 deraadt 286: } /* and continue */
287: case CCHR('I'):
288: case CCHR('J'):
1.2 millert 289: addchar:
1.1 deraadt 290: if (pptr == -1)
291: pptr = 0;
292: if (pptr == 0)
293: success = TRUE;
294: pat[pptr++] = c;
295: if (pptr == NPAT) {
296: ewprintf("Pattern too long");
297: return FALSE;
298: }
299: pat[pptr] = '\0';
300: is_lpush();
301: if (success != FALSE) {
302: if (is_find(dir) != FALSE)
303: is_cpush(c);
304: else {
305: success = FALSE;
306: ttbeep();
307: is_cpush(SRCH_ACCM);
308: }
309: } else
310: is_cpush(SRCH_ACCM);
311: is_prompt(dir, FALSE, success);
312: }
313: }
1.2 millert 314: /* NOTREACHED */
1.1 deraadt 315: }
316:
1.6 ! art 317: static void
1.2 millert 318: is_cpush(cmd)
1.3 millert 319: int cmd;
1.2 millert 320: {
1.1 deraadt 321: if (++cip >= NSRCH)
322: cip = 0;
323: cmds[cip].s_code = cmd;
324: }
325:
1.6 ! art 326: static void
1.2 millert 327: is_lpush()
328: {
1.3 millert 329: int ctp;
1.1 deraadt 330:
1.2 millert 331: ctp = cip + 1;
1.1 deraadt 332: if (ctp >= NSRCH)
333: ctp = 0;
334: cmds[ctp].s_code = SRCH_NOPR;
335: cmds[ctp].s_doto = curwp->w_doto;
336: cmds[ctp].s_dotp = curwp->w_dotp;
337: }
338:
1.6 ! art 339: static void
1.2 millert 340: is_pop()
341: {
1.1 deraadt 342: if (cmds[cip].s_code != SRCH_NOPR) {
1.2 millert 343: curwp->w_doto = cmds[cip].s_doto;
344: curwp->w_dotp = cmds[cip].s_dotp;
1.1 deraadt 345: curwp->w_flag |= WFMOVE;
346: cmds[cip].s_code = SRCH_NOPR;
347: }
348: if (--cip <= 0)
1.2 millert 349: cip = NSRCH - 1;
1.1 deraadt 350: }
351:
352: static int
1.2 millert 353: is_peek()
354: {
1.1 deraadt 355: return cmds[cip].s_code;
356: }
357:
358: /* this used to always return TRUE (the return value was checked) */
1.6 ! art 359: static void
1.2 millert 360: is_undo(pptr, dir)
1.3 millert 361: int *pptr, *dir;
1.2 millert 362: {
1.3 millert 363: int redo = FALSE;
364:
1.1 deraadt 365: switch (cmds[cip].s_code) {
366: case SRCH_BEGIN:
367: case SRCH_NOPR:
368: *pptr = -1;
369: case SRCH_MARK:
370: break;
371: case SRCH_FORW:
372: *dir = SRCH_BACK;
373: redo = TRUE;
374: break;
375: case SRCH_BACK:
376: *dir = SRCH_FORW;
377: redo = TRUE;
378: break;
379: case SRCH_ACCM:
380: default:
381: *pptr -= 1;
382: if (*pptr < 0)
383: *pptr = 0;
384: pat[*pptr] = '\0';
385: break;
386: }
387: is_pop();
1.2 millert 388: if (redo)
389: is_undo(pptr, dir);
1.1 deraadt 390: }
391:
392: static int
1.2 millert 393: is_find(dir)
1.3 millert 394: int dir;
1.2 millert 395: {
1.3 millert 396: int plen, odoto;
397: LINE *odotp;
1.1 deraadt 398:
399: odoto = curwp->w_doto;
400: odotp = curwp->w_dotp;
401: plen = strlen(pat);
402: if (plen != 0) {
1.2 millert 403: if (dir == SRCH_FORW) {
1.6 ! art 404: (void)backchar(FFARG | FFRAND, plen);
1.1 deraadt 405: if (forwsrch() == FALSE) {
406: curwp->w_doto = odoto;
407: curwp->w_dotp = odotp;
408: return FALSE;
409: }
410: return TRUE;
411: }
1.2 millert 412: if (dir == SRCH_BACK) {
1.6 ! art 413: (void)forwchar(FFARG | FFRAND, plen);
1.1 deraadt 414: if (backsrch() == FALSE) {
415: curwp->w_doto = odoto;
416: curwp->w_dotp = odotp;
417: return FALSE;
418: }
419: return TRUE;
420: }
421: ewprintf("bad call to is_find");
422: return FALSE;
423: }
424: return FALSE;
425: }
426:
427: /*
1.3 millert 428: * If called with "dir" not one of SRCH_FORW or SRCH_BACK, this routine used
429: * to print an error message. It also used to return TRUE or FALSE, depending
430: * on if it liked the "dir". However, none of the callers looked at the
431: * status, so I just made the checking vanish.
1.1 deraadt 432: */
1.6 ! art 433: static void
1.2 millert 434: is_prompt(dir, flag, success)
1.3 millert 435: int dir, flag, success;
1.2 millert 436: {
1.1 deraadt 437: if (dir == SRCH_FORW) {
438: if (success != FALSE)
439: is_dspl("I-search", flag);
440: else
441: is_dspl("Failing I-search", flag);
442: } else if (dir == SRCH_BACK) {
443: if (success != FALSE)
444: is_dspl("I-search backward", flag);
445: else
446: is_dspl("Failing I-search backward", flag);
1.2 millert 447: } else
448: ewprintf("Broken call to is_prompt");
1.1 deraadt 449: }
450:
451: /*
1.3 millert 452: * Prompt writing routine for the incremental search. The "prompt" is just
453: * a string. The "flag" determines whether pat should be printed.
1.1 deraadt 454: */
1.6 ! art 455: static void
1.2 millert 456: is_dspl(prompt, flag)
1.3 millert 457: char *prompt;
458: int flag;
1.2 millert 459: {
1.1 deraadt 460: if (flag != FALSE)
461: ewprintf("%s: ", prompt);
462: else
463: ewprintf("%s: %s", prompt, pat);
464: }
465:
466: /*
467: * Query Replace.
468: * Replace strings selectively. Does a search and replace operation.
469: */
1.2 millert 470: /* ARGSUSED */
1.3 millert 471: int
1.1 deraadt 472: queryrepl(f, n)
1.3 millert 473: int f, n;
1.1 deraadt 474: {
1.3 millert 475: int s;
476: int rcnt = 0; /* replacements made so far */
477: int plen; /* length of found string */
478: char news[NPAT]; /* replacement string */
1.1 deraadt 479:
480: #ifndef NO_MACRO
1.2 millert 481: if (macrodef) {
482: ewprintf("Can't query replace in macro");
483: return FALSE;
1.1 deraadt 484: }
1.3 millert 485: #endif /* !NO_MACRO */
486:
1.2 millert 487: if ((s = readpattern("Query replace")) != TRUE)
1.1 deraadt 488: return (s);
1.2 millert 489: if ((s = ereply("Query replace %s with: ", news, NPAT, pat)) == ABORT)
1.1 deraadt 490: return (s);
491: if (s == FALSE)
492: news[0] = '\0';
493: ewprintf("Query replacing %s with %s:", pat, news);
494: plen = strlen(pat);
495:
496: /*
497: * Search forward repeatedly, checking each time whether to insert
498: * or not. The "!" case makes the check always true, so it gets put
499: * into a tighter loop for efficiency.
500: */
501: while (forwsrch() == TRUE) {
1.2 millert 502: retry:
1.1 deraadt 503: update();
504: switch (getkey(FALSE)) {
505: case ' ':
1.3 millert 506: if (lreplace((RSIZE)plen, news, f) == FALSE)
1.1 deraadt 507: return (FALSE);
508: rcnt++;
509: break;
510: case '.':
1.3 millert 511: if (lreplace((RSIZE)plen, news, f) == FALSE)
1.1 deraadt 512: return (FALSE);
513: rcnt++;
514: goto stopsearch;
1.3 millert 515: /* ^G or ESC */
516: case CCHR('G'):
1.6 ! art 517: (void)ctrlg(FFRAND, 0);
1.1 deraadt 518: case CCHR('['):
519: goto stopsearch;
520: case '!':
521: do {
1.3 millert 522: if (lreplace((RSIZE)plen, news, f) == FALSE)
1.1 deraadt 523: return (FALSE);
524: rcnt++;
525: } while (forwsrch() == TRUE);
526: goto stopsearch;
527: case CCHR('H'):
1.3 millert 528: /* To not replace */
529: case CCHR('?'):
1.1 deraadt 530: break;
531: default:
1.2 millert 532: ewprintf("<SP> replace, [.] rep-end, <DEL> don't, [!] repl rest <ESC> quit");
1.1 deraadt 533: goto retry;
534: }
535: }
536: stopsearch:
537: curwp->w_flag |= WFHARD;
538: update();
539: if (rcnt == 0)
540: ewprintf("(No replacements done)");
541: else if (rcnt == 1)
542: ewprintf("(1 replacement done)");
543: else
544: ewprintf("(%d replacements done)", rcnt);
545: return TRUE;
546: }
547:
548: /*
1.3 millert 549: * This routine does the real work of a forward search. The pattern is sitting
550: * in the external variable "pat". If found, dot is updated, the window system
551: * is notified of the change, and TRUE is returned. If the string isn't found,
552: * FALSE is returned.
1.1 deraadt 553: */
1.3 millert 554: int
1.2 millert 555: forwsrch()
556: {
1.3 millert 557: LINE *clp, *tlp;
558: int cbo, tbo, c;
559: char *pp;
1.1 deraadt 560:
561: clp = curwp->w_dotp;
562: cbo = curwp->w_doto;
1.2 millert 563: for (;;) {
1.1 deraadt 564: if (cbo == llength(clp)) {
1.2 millert 565: if ((clp = lforw(clp)) == curbp->b_linep)
566: break;
1.1 deraadt 567: cbo = 0;
568: c = CCHR('J');
569: } else
570: c = lgetc(clp, cbo++);
571: if (eq(c, pat[0]) != FALSE) {
572: tlp = clp;
573: tbo = cbo;
1.2 millert 574: pp = &pat[1];
1.1 deraadt 575: while (*pp != 0) {
576: if (tbo == llength(tlp)) {
577: tlp = lforw(tlp);
578: if (tlp == curbp->b_linep)
579: goto fail;
580: tbo = 0;
581: c = CCHR('J');
582: } else
583: c = lgetc(tlp, tbo++);
584: if (eq(c, *pp++) == FALSE)
585: goto fail;
586: }
1.2 millert 587: curwp->w_dotp = tlp;
588: curwp->w_doto = tbo;
1.1 deraadt 589: curwp->w_flag |= WFMOVE;
590: return TRUE;
591: }
1.2 millert 592: fail: ;
1.1 deraadt 593: }
594: return FALSE;
595: }
596:
597: /*
1.3 millert 598: * This routine does the real work of a backward search. The pattern is
599: * sitting in the external variable "pat". If found, dot is updated, the
600: * window system is notified of the change, and TRUE is returned. If the
1.1 deraadt 601: * string isn't found, FALSE is returned.
602: */
1.3 millert 603: int
1.2 millert 604: backsrch()
605: {
1.3 millert 606: LINE *clp, *tlp;
607: int cbo, tbo, c;
608: char *epp, *pp;
1.1 deraadt 609:
1.2 millert 610: for (epp = &pat[0]; epp[1] != 0; ++epp);
1.1 deraadt 611: clp = curwp->w_dotp;
612: cbo = curwp->w_doto;
613: for (;;) {
614: if (cbo == 0) {
615: clp = lback(clp);
616: if (clp == curbp->b_linep)
617: return FALSE;
1.2 millert 618: cbo = llength(clp) + 1;
1.1 deraadt 619: }
620: if (--cbo == llength(clp))
621: c = CCHR('J');
622: else
1.2 millert 623: c = lgetc(clp, cbo);
1.1 deraadt 624: if (eq(c, *epp) != FALSE) {
625: tlp = clp;
626: tbo = cbo;
1.2 millert 627: pp = epp;
1.1 deraadt 628: while (pp != &pat[0]) {
629: if (tbo == 0) {
630: tlp = lback(tlp);
631: if (tlp == curbp->b_linep)
632: goto fail;
1.2 millert 633: tbo = llength(tlp) + 1;
1.1 deraadt 634: }
635: if (--tbo == llength(tlp))
636: c = CCHR('J');
637: else
1.2 millert 638: c = lgetc(tlp, tbo);
1.1 deraadt 639: if (eq(c, *--pp) == FALSE)
640: goto fail;
641: }
1.2 millert 642: curwp->w_dotp = tlp;
643: curwp->w_doto = tbo;
1.1 deraadt 644: curwp->w_flag |= WFMOVE;
645: return TRUE;
646: }
1.2 millert 647: fail: ;
1.1 deraadt 648: }
1.2 millert 649: /* NOTREACHED */
1.1 deraadt 650: }
651:
652: /*
1.3 millert 653: * Compare two characters. The "bc" comes from the buffer. It has its case
654: * folded out. The "pc" is from the pattern.
1.1 deraadt 655: */
656: static int
657: eq(bc, pc)
1.3 millert 658: int bc, pc;
1.1 deraadt 659: {
660: bc = CHARMASK(bc);
661: pc = CHARMASK(pc);
1.2 millert 662: if (bc == pc)
663: return TRUE;
664: if (ISUPPER(bc))
665: return TOLOWER(bc) == pc;
666: if (ISUPPER(pc))
667: return bc == TOLOWER(pc);
1.1 deraadt 668: return FALSE;
669: }
670:
671: /*
1.3 millert 672: * Read a pattern. Stash it in the external variable "pat". The "pat" is not
673: * updated if the user types in an empty line. If the user typed an empty
674: * line, and there is no old pattern, it is an error. Display the old pattern,
675: * in the style of Jeff Lomicka. There is some do-it-yourself control
676: * expansion.
1.1 deraadt 677: */
1.3 millert 678: int
1.2 millert 679: readpattern(prompt)
1.3 millert 680: char *prompt;
1.2 millert 681: {
1.3 millert 682: int s;
683: char tpat[NPAT];
1.1 deraadt 684:
1.2 millert 685: if (tpat[0] == '\0')
686: s = ereply("%s: ", tpat, NPAT, prompt);
687: else
688: s = ereply("%s: (default %s) ", tpat, NPAT, prompt, pat);
1.1 deraadt 689:
1.3 millert 690: /* specified */
691: if (s == TRUE)
1.6 ! art 692: (void) strcpy(pat, tpat);
1.3 millert 693: /* CR, but old one */
694: else if (s == FALSE && pat[0] != 0)
1.1 deraadt 695: s = TRUE;
696: return s;
697: }