1 /*****************************************************************************
2
3 BldStr()
4
5 This function "builds" a string. This means converting string
6 build constructs in the input string into their intended equivalents
7 in the output string. The string build constructs are as follows:
8
9 ^Q use next character literally, not as a string build char
10 ^R use next character literally, not as a string build char
11 ^V lowercase the next character
12 ^V^V lowercase all following characters
13 ^W uppercase the next character
14 ^W^W uppercase all following characters
15 ^EQq use string in q-register q here
16 ^EUq use ASCII char for number in q-register q here
17
18 When this function is called, CBfPtr points to the first character
19 of the input string. It is assumed that the string is terminated by an ESCAPE
20 character (or something else if the calling command was @-modified). If the
21 string is not properly terminated this function will die with "unterminated
22 command" when it encounters CStEnd while looking for the terminator character.
23
24 When this function returns, CBfPtr points to the ESCAPE which
25 terminates the string, the built string is in the buffer pointed to by
26 XBfBeg, and XBfPtr points to the character after the last character in
27 the built string.
28
29 The commands which contain a filename (EB, EI, EN, ER and
30 EW) use this function. The EG command, which exits with an operating system
31 command line, uses this function. The O command, which jumps to a tag, uses
32 this function. The search commands (E_, FK, FN, FS, F_, N, S and _) use this
33 function.
34
35 *****************************************************************************/
36
37 #include "zport.h" /* define portability identifiers */
38 #include "tecoc.h" /* define general identifiers */
39 #include "defext.h" /* define external global variables */
40 #include "deferr.h" /* define identifiers for error messages */
41 #include "dchars.h" /* define identifiers for characters */
42 #include "chmacs.h" /* define character processing macros */
43
44 #if USE_PROTOTYPES
45 static DEFAULT DoCtVW(charptr EndArg, unsigned char TmpChr);
46 static DEFAULT DoCtE(charptr EndArg, charptr XBfEnd);
47 #endif
48
49 static charptr BBfPtr; /* pointer into XBf */
50 static int CaseCv; /* case conversion */
51 static unsigned char WVFlag; /* ^W or ^V flag */
52
DoCtVW(EndArg,TmpChr)53 static DEFAULT DoCtVW(EndArg, TmpChr) /* do a control-V or control-W */
54 charptr EndArg; /* ptr to end of string argument */
55 unsigned char TmpChr; /* temporary character */
56 {
57 DBGFEN(3,"DoCtVW",NULL);
58
59 WVFlag = TmpChr;
60 if (++CBfPtr == EndArg) { /* move past ^W or ^V, too far? */
61 ErrMsg(ERR_ISS); /* yes, illegal search string */
62 DBGFEX(2,DbgFNm,"FAILURE");
63 return FAILURE;
64 }
65 if ((*CBfPtr == '^') && ((EdFlag & ED_CARET_OK) == 0)) {
66 if (++CBfPtr == EndArg) {
67 ErrMsg(ERR_ISS);
68 DBGFEX(2,DbgFNm,"FAILURE");
69 return FAILURE;
70 }
71 TmpChr = To_Upper(*CBfPtr);
72 if ((TmpChr < '@') || (TmpChr > '_')) {
73 ErrChr(ERR_IUC, *CBfPtr);
74 DBGFEX(2,DbgFNm,"FAILURE");
75 return FAILURE;
76 }
77 TmpChr &= '\077';
78 } else {
79 TmpChr = *CBfPtr;
80 }
81 if (WVFlag == CTRL_V) {
82 if (TmpChr == CTRL_V) {
83 CaseCv = LOWER;
84 } else {
85 *BBfPtr++ = To_Lower(TmpChr);
86 }
87 } else {
88 if (TmpChr == CTRL_W) {
89 CaseCv = UPPER;
90 } else {
91 *BBfPtr++ = To_Upper(TmpChr);
92 }
93 }
94 WVFlag = '\0';
95 DBGFEX(2,DbgFNm,"SUCCESS");
96 return SUCCESS;
97 }
98
99
DoCtE(EndArg,XBfEnd)100 static DEFAULT DoCtE(EndArg, XBfEnd) /* do a control-E */
101 charptr EndArg; /* ptr to end of string argument */
102 charptr XBfEnd; /* end of build-string buffer */
103 {
104 DEFAULT Status; /* returned from FindQR */
105 charptr TCStEn; /* temporary holder of CStEnd */
106
107 DBGFEN(3,"DoCtE",NULL);
108 if (++CBfPtr == EndArg) { /* move past ^E, too far? */
109 ErrMsg(ERR_ICE); /* yes, illegal ^E command */
110 DBGFEX(2,DbgFNm,"FAILURE");
111 return FAILURE;
112 }
113 if ((*CBfPtr == 'Q') || (*CBfPtr == 'q')) {
114 if (++CBfPtr == EndArg) {
115 ErrMsg(ERR_ISS);
116 DBGFEX(2,DbgFNm,"FAILURE");
117 return FAILURE;
118 }
119
120 /*
121 * handle filespec buffer and search string buffer
122 */
123 if (*CBfPtr=='*' || *CBfPtr=='_') {
124 charptr BufPtr, BufBeg;
125 if (*CBfPtr=='*') {
126 BufPtr=FBfPtr;
127 BufBeg=FBfBeg;
128 } else {
129 BufPtr=SBfPtr;
130 BufBeg=SBfBeg;
131 }
132 if ((BufPtr-BufBeg) > (XBfEnd-BBfPtr)) {
133 ErrMsg(ERR_STL);
134 DBGFEX(2,DbgFNm,"FAILURE");
135 return FAILURE;
136 }
137 MEMMOVE(BBfPtr, BufBeg, (SIZE_T)(BufPtr - BufBeg));
138 BBfPtr += BufPtr-BufBeg;
139 } else {
140 /*
141 * it really must be a Q reg reference after all
142 */
143 TCStEn = CStEnd; /* save CStEnd */
144 CStEnd = EndArg;
145 Status = FindQR();
146 CStEnd = TCStEn; /* restore CStEnd */
147 if (Status == FAILURE) {
148 DBGFEX(2,DbgFNm,"FAILURE");
149 return FAILURE;
150 }
151 if ((QR->End_P1-QR->Start) > (XBfEnd-BBfPtr)) {
152 ErrMsg(ERR_STL);
153 DBGFEX(2,DbgFNm,"FAILURE");
154 return FAILURE;
155 }
156 MEMMOVE(BBfPtr, QR->Start, (SIZE_T)(QR->End_P1 - QR->Start));
157 BBfPtr += QR->End_P1 - QR->Start;
158 }
159 } else if ((*CBfPtr == 'U') || (*CBfPtr == 'u')) {
160 if (++CBfPtr == EndArg) {
161 ErrMsg(ERR_ISS);
162 DBGFEX(2,DbgFNm,"FAILURE");
163 return FAILURE;
164 }
165 TCStEn = CStEnd; /* save CStEnd */
166 CStEnd = EndArg;
167 Status = FindQR();
168 CStEnd = TCStEn; /* restore CStEnd */
169 if (Status == FAILURE) {
170 DBGFEX(2,DbgFNm,"FAILURE");
171 return FAILURE;
172 }
173 *BBfPtr++ = (char)QR->Number;
174 } else {
175 *BBfPtr++ = CTRL_E;
176 *BBfPtr++ = *CBfPtr;
177 }
178 DBGFEX(2,DbgFNm,"SUCCESS");
179 return SUCCESS;
180 }
181
182
BldStr(XBfBeg,XBfEnd,XBfPtr)183 DEFAULT BldStr(XBfBeg, XBfEnd, XBfPtr) /* build a string */
184 charptr XBfBeg; /* beginning of build-string buffer */
185 charptr XBfEnd; /* end of build-string buffer */
186 charptr (*XBfPtr); /* pointer into build-string buffer */
187 {
188 charptr EndArg; /* end of input string, plus 1 */
189 unsigned char TmpChr; /* temporary character */
190
191 DBGFEN(2,"BldStr",NULL);
192
193 if (FindES(ESCAPE) == FAILURE) { /* move CBfPtr to end of argument */
194 DBGFEX(2,DbgFNm,"FAILURE, FindES(ESCAPE) failed");
195 return FAILURE;
196 }
197
198 WVFlag = '\0'; /* initialize ^W and ^V flag */
199 CaseCv = IniSrM; /* initialize internal search mode */
200 BBfPtr = XBfBeg; /* initialize ptr into build-string buffer */
201 EndArg = CBfPtr; /* save pointer to end of argument */
202 CBfPtr = ArgPtr; /* reset to beginning of argument */
203
204 while (CBfPtr < EndArg) {
205 if ((*CBfPtr == '^') && ((EdFlag & ED_CARET_OK) == 0)) {
206 if (++CBfPtr == EndArg) {
207 ErrMsg(ERR_ISS);
208 DBGFEX(2,DbgFNm,"FAILURE, no char after ^");
209 return FAILURE;
210 }
211 TmpChr = To_Upper(*CBfPtr);
212 if ((TmpChr < '@') || (TmpChr > '_')) {
213 ErrChr(ERR_IUC, *CBfPtr);
214 DBGFEX(2,DbgFNm,"FAILURE, bad char after ^");
215 return FAILURE;
216 }
217 TmpChr &= '\077';
218 } else {
219 TmpChr = *CBfPtr;
220 }
221
222 switch (TmpChr) {
223
224 case CTRL_R:
225 case CTRL_Q:
226 if (++CBfPtr == EndArg) {
227 ErrMsg(ERR_ISS);
228 DBGFEX(2,DbgFNm,"FAILURE");
229 return FAILURE;
230 }
231 *BBfPtr++ = *CBfPtr;
232 break;
233
234 case CTRL_V:
235 case CTRL_W:
236 if (DoCtVW(EndArg, TmpChr) == FAILURE) {
237 DBGFEX(2,DbgFNm,"FAILURE, DoCtVW failed");
238 return FAILURE;
239 }
240 break;
241
242 case CTRL_E:
243 if (DoCtE(EndArg, XBfEnd) == FAILURE) {
244 DBGFEX(2,DbgFNm,"FAILURE, DoCtE failed");
245 return FAILURE;
246 }
247 break;
248
249 default:
250 if (CaseCv == LOWER) {
251 TmpChr = To_Lower(TmpChr);
252 } else if (CaseCv == UPPER) {
253 TmpChr = To_Upper(TmpChr);
254 }
255 *BBfPtr++ = TmpChr;
256 }
257 if (BBfPtr > XBfEnd) {
258 ErrMsg(ERR_STL); /* string too long */
259 DBGFEX(2,DbgFNm,"FAILURE, string too long");
260 return FAILURE;
261 }
262 ++CBfPtr;
263 }
264 *XBfPtr = BBfPtr;
265
266 #if DEBUGGING
267 sprintf(DbgSBf,"string = \"%.*s\"", (int)(BBfPtr-XBfBeg), XBfBeg);
268 DbgFEx(2,DbgFNm,DbgSBf);
269 #endif
270
271 return SUCCESS;
272 }
273