1 /*****************************************************************************
2 
3 	Search()
4 
5 	This function handles most of the special stuff that happens in
6 search commands (S, N, FS, FN, _, F_, E_, FB and FK).  It
7 
8 	1. Loads the search buffer (SBfBeg, SBfEnd, SBfPtr) with the text
9 	   argument or leaves the search buffer alone if there is no
10 	   text argument.
11 	2. Sets variable NArgmt with the numeric argument or 1 if there
12 	   is no numeric argument.
13 	3. Calls SrcLop to do the basic search loop.
14 	4. If the search command is colon modified or if the search command
15 	   is in a loop and the next character after the search command is
16 	   a semicolon,  then return appropriately.
17 	5. If successful search,  return successfully but worry about
18 	   the ES flag.
19 	6. If unsuccessful search,  return unsuccessfully but worry about
20 	   whether we need to skip to the end of a loop or not.
21 
22 	This function is called by ExeEUn, ExeFB, ExeFK, ExeFN, ExeFS, ExeFUn,
23 ExeN, ExeS and ExeUnd.  Each of those functions sets up the variable SrcTyp
24 before calling this function to do the search.
25 
26 *****************************************************************************/
27 
28 #include "zport.h"		/* define portability identifiers */
29 #include "tecoc.h"		/* define general identifiers */
30 #include "defext.h"		/* define external global variables */
31 #include "deferr.h"		/* define identifiers for error messages */
32 #include "dchars.h"		/* define identifiers for characters */
33 
Search(RepCmd)34 DEFAULT Search(RepCmd)		/* main search code */
35 BOOLEAN	RepCmd;			/* TRUE if the command has two arguments */
36 {
37 	DBGFEN(2,"Search",NULL);
38 
39 /*
40  * If there is a search argument,  put it into SBf,  otherwise use the
41  * string from the last search command.
42  */
43 
44 	if (*(CBfPtr+1) == ESCAPE) {		/* if it's s$, n$, etc. */
45 		++CBfPtr;			/* skip the escape */
46 	} else {
47 		if (BldStr(SBfBeg, SBfEnd, &SBfPtr) == FAILURE) {
48 			DBGFEX(2,DbgFNm,"FAILURE, BldStr() failed");
49 			return FAILURE;
50 		}
51 	}
52 /*
53  * If the search is one of the "search and replace" commands,  then parse the
54  * second argument (the replace string).  We need to do this here because we
55  * may later need to check if a semicolon follows the command,  and we need
56  * to be positioned at the end of the command to do so.
57  */
58 
59 	if (RepCmd) {				/* if FC, FN, FS or F_ */
60 /*
61  * If the command is @-modified,  then we need to move the command pointer
62  * back by one.  The call to Search will have eaten the first text argument
63  * of the command,  leaving the pointer on the delimiter between the arguments.
64  * We are about to call FindES,  which will call IncCBP to move to the next
65  * character.   Moving back by one cancels the IncCBp.
66  */
67 
68 		if (CmdMod & ATSIGN) {		/* if it's at-sign modified */
69 			--CBfPtr;
70 		}
71 
72 		if (FindES(ESCAPE) == FAILURE) {/* find end of 2nd argument */
73 			DBGFEX(2,DbgFNm,"FAILURE, FindES() failed");
74 			return FAILURE;
75 		}
76 	}
77 
78 	if (EStTop == EStBot) {			/* if no numeric argument */
79 		NArgmt = 1;			/* default is 1S */
80 	} else {
81 		UMinus();			/* if it's -S, make it -1S */
82 		if (GetNmA() == FAILURE) {	/* get numeric argument */
83 			DBGFEX(2,DbgFNm,"FAILURE, GetNmA() failed");
84 			return FAILURE;
85 		}
86 
87 		if (NArgmt == 0) {		/* if it's 0s, 0n, etc. */
88 			ErrMsg(ERR_ISA);	/* illegal search argument */
89 			DBGFEX(2,DbgFNm,"FAILURE, NArgmt == 0");
90 			return FAILURE;
91 			}
92 		}
93 
94 	if (SrcLop() == FAILURE) {
95 		DBGFEX(2,DbgFNm,"FAILURE, SrcLop failed");
96 		return FAILURE;
97 	}
98 
99 	if ((CmdMod & COLON) ||			/* if colon modifier or */
100 	    ((LStTop != LStBot) &&		/* (in loop and         */
101 	     (*(CBfPtr+1) == ';'))) {		/* next cmd = ;)        */
102 		if (Matchd) {			/* if successful search */
103 			if (EsFlag&& LStTop == LStBot && MStTop < 0) {
104 			        /* if ES flag is set, not in loop or macro */
105 				DoEvEs(EsFlag);	/* handle ES flag */
106 			}
107 			DBGFEX(2,DbgFNm,"PushEx(-1)");
108 			return PushEx(-1L, OPERAND);
109 		} else {			/* else unsuccessful search */
110 			DBGFEX(2,DbgFNm,"PushEx(0)");
111 			return PushEx(0L, OPERAND);
112 		}
113 	}
114 
115 	if (Matchd) {				/* if successful search */
116 		if (EsFlag&& LStTop == LStBot && MStTop < 0) {
117 			/* if ES flag is set, not in loop and not in macro */
118 			DoEvEs(EsFlag);		/* handle ES flag */
119 		}
120 		DBGFEX(2,DbgFNm,"SUCCESS");
121 		return SUCCESS;
122 	} else {				/* else unsuccessful search */
123 		*SBfPtr = '\0';
124 		ErrPSt(ERR_SRH, SBfBeg, SBfPtr);/* "search failure" */
125 		DBGFEX(2,DbgFNm,(LStTop==LStBot) ? "FAILURE"  : "FlowEL()");
126 		return (LStTop == LStBot) ? FAILURE : FlowEL();
127 	}
128 }
129