1 /*****************************************************************************
2 
3 	ZFrSrc()
4 
5 	This recursive function does a forward search in the edit buffer,
6 looking for a string which will match the first match construct in the search
7 buffer.  Basically,  it is the high-speed part of the search algorithm: it
8 scans the edit buffer looking for the first character in the search string.
9 	The VAX SCANC instruction implements most of the meat of this
10 function so well that I couldn't resist using it.  For environments other
11 than VMS,  the generic code exists to do the search.  That's why this has to
12 be a system-dependent piece of code.  Note that I did not use SCANC for some
13 of the match constructs,  including the "default" case.  I started to,  but
14 the resulting code was real clumsy and in timing tests it didn't seem worth
15 the confusion.
16 	On entry, SStPtr points to the first match construct in the search
17 buffer.  On exit,  SStPtr points to the last character of the first match
18 construct in the search buffer.
19 	SBfPtr points to the character following the last character in
20 the search string.  This function does not modify SBfPtr.
21 	On entry,  EBPtr1 points to the place in the edit buffer where
22 the search starts.  On exit,  if the search was successful,  EBPtr1 will
23 point to the found character.  If the search was unsuccessful,  EBPtr1 will
24 be greater than EndSAr.
25 	On entry,  EBPtr2 is undefined.  On exit,  if the search was
26 successful,  EBPtr2 points to the last character of the found string.  If
27 the search was unsuccessful,  EBPtr2 is undefined.
28 	EndSAr points to the end of the search area (where the search ends).
29 This function does not modify EndSAr.
30 
31 	Match constructs are:
32 
33 	^X		match any character
34 	^S		match a separator character (not letter or digit)
35 	^N		match anything but following match construct
36 	^EA		match any alphabetic
37 	^EB		match a separator character (not letter or digit)
38 	^EC		match symbol constituent
39 	^ED		match any digit
40 	^EGq		match any character in q-register q
41 	^EL		match any line terminator (LF, VT, FF)
42 	^EM		match non-null string of following match construct
43 	^ER		match any alphanumeric
44 	^ES		match non-null string of spaces and/or tabs
45 	^EV		match lowercase alphabetic
46 	^EW		match uppercase alphabetic
47 	^EX		match any character
48 	^E<nnn>		match character with ASCII code nnn (octal)
49 	^E[x1,x2,...xn]	match any of the match constructs x1, x2, etc.
50 	else		match the character itself
51 
52 *****************************************************************************/
53 
54 #include "zport.h"		/* define portability identifiers */
55 #include "tecoc.h"		/* define general identifiers */
56 #include "defext.h"		/* define external global variables */
57 #include "dchars.h"		/* define identifiers for characters */
58 #include "chmacs.h"		/* define character processing macros */
59 #include "deferr.h"		/* define identifiers for error messages */
60 
61 
62 #if defined(VAX11C)
63 #include descrip		/* define "$descriptor" macro */
64 
65 
66 int	lib$scanc();		/* scan for characters */
67 
ZFrSrc()68 DEFAULT ZFrSrc()		/* forward search for 1st search charptr */
69 {
70 	char	Charac;		/* holds a character */
71 	int	indx;		/* returned by lib$scanc */
72 	charptr	LstBeg;		/* beginning of ^E[x,x,x] list */
73 	char	mask;
74 	char	OtCase;		/* "other" case character */
75 	charptr	QTPtr;		/* pointer into q-register text */
76 	int	real_length;	/* length of area to be searched */
77 	BOOLEAN	SamChr;		/* same character indicator */
78 	charptr	SavEP2;		/* temporary holder of EBPtr2 */
79 	charptr	SavSSP;		/* temporary holder of SStPtr */
80 	struct	dsc$descriptor_s src_str = {
81 		0,		/* dsc$w_length */
82 		DSC$K_DTYPE_T,	/* dsc$b_dtype */
83 		DSC$K_CLASS_S,	/* dsc$b_class */
84 		0		/* dsc$a_pointer */
85 	};
86 	DEFAULT	Status;
87 	charptr	TCBfPt;		/* temporary holder of CBfPtr */
88 	charptr	TCStEn;		/* temporary holder of CStEnd */
89 	LONG	TmpLng;
90 
91 
92 #define SEPARATOR	'\001'	/* separators (not a letter or digit) */
93 #define ALPHA		'\002'	/* alphabetics */
94 #define SYMBOL		'\004'	/* symbol constituents */
95 #define DIGIT		'\010'	/* digits */
96 #define LINE_TERMINATOR	'\020'	/* line terminators (lf, vt, ff) */
97 #define ALPHANUMERIC	'\040'	/* alphanumerics */
98 #define LOWER		'\100'	/* lowercase */
99 #define UPPER		'\200'	/* uppercase */
100 static readonly char table_1[256] =
101 		{
102 		SEPARATOR,				/* null */
103 		SEPARATOR,				/* ^A */
104 		SEPARATOR,				/* ^B */
105 		SEPARATOR,				/* ^C */
106 		SEPARATOR,				/* ^D */
107 		SEPARATOR,				/* ^E */
108 		SEPARATOR,				/* ^F */
109 		SEPARATOR,				/* ^G (bell) */
110 		SEPARATOR,				/* ^H (bs) */
111 		SEPARATOR,				/* ^I (tab) */
112 		LINE_TERMINATOR | SEPARATOR,		/* ^J (lf) */
113 		LINE_TERMINATOR | SEPARATOR,		/* ^K (vt) */
114 		LINE_TERMINATOR | SEPARATOR,		/* ^L (ff) */
115 		SEPARATOR,				/* ^M (cr) */
116 		SEPARATOR,				/* ^N */
117 		SEPARATOR,				/* ^O */
118 		SEPARATOR,				/* ^P */
119 		SEPARATOR,				/* ^Q */
120 		SEPARATOR,				/* ^R */
121 		SEPARATOR,				/* ^S */
122 		SEPARATOR,				/* ^T */
123 		SEPARATOR,				/* ^U */
124 		SEPARATOR,				/* ^V */
125 		SEPARATOR,				/* ^W */
126 		SEPARATOR,				/* ^X */
127 		SEPARATOR,				/* ^Y */
128 		SEPARATOR,				/* ^Z */
129 		SEPARATOR,				/* escape */
130 		SEPARATOR,				/* FS */
131 		SEPARATOR,				/* GS */
132 		SEPARATOR,				/* RS */
133 		SEPARATOR,				/* US */
134 		SEPARATOR,				/* space */
135 		SEPARATOR,				/* ! */
136 		SEPARATOR,				/* " */
137 		SEPARATOR,				/* # */
138 		SYMBOL & SEPARATOR,			/* $ */
139 		SEPARATOR,				/* % */
140 		SEPARATOR,				/* | */
141 		SEPARATOR,				/* ' */
142 		SEPARATOR,				/* ( */
143 		SEPARATOR,				/* ) */
144 		SEPARATOR,				/* * */
145 		SEPARATOR,				/* + */
146 		SEPARATOR,				/* , */
147 		SEPARATOR,				/* - */
148 		SYMBOL | SEPARATOR,			/* . */
149 		SEPARATOR,				/* / */
150 		ALPHANUMERIC | DIGIT | SYMBOL,		/* 0 */
151 		ALPHANUMERIC | DIGIT | SYMBOL,		/* 1 */
152 		ALPHANUMERIC | DIGIT | SYMBOL,		/* 2 */
153 		ALPHANUMERIC | DIGIT | SYMBOL,		/* 3 */
154 		ALPHANUMERIC | DIGIT | SYMBOL,		/* 4 */
155 		ALPHANUMERIC | DIGIT | SYMBOL,		/* 5 */
156 		ALPHANUMERIC | DIGIT | SYMBOL,		/* 6 */
157 		ALPHANUMERIC | DIGIT | SYMBOL,		/* 7 */
158 		ALPHANUMERIC | DIGIT | SYMBOL,		/* 8 */
159 		ALPHANUMERIC | DIGIT | SYMBOL,		/* 9 */
160 		SEPARATOR,				/* : */
161 		SEPARATOR,				/* ; */
162 		SEPARATOR,				/* < */
163 		SEPARATOR,				/* = */
164 		SEPARATOR,				/* > */
165 		SEPARATOR,				/* ? */
166 		SEPARATOR,				/* @ */
167 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* A */
168 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* B */
169 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* C */
170 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* D */
171 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* E */
172 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* F */
173 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* G */
174 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* H */
175 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* I */
176 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* J */
177 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* K */
178 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* L */
179 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* M */
180 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* N */
181 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* O */
182 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* P */
183 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* Q */
184 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* R */
185 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* S */
186 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* T */
187 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* U */
188 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* V */
189 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* W */
190 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* X */
191 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* Y */
192 		UPPER | ALPHANUMERIC | SYMBOL | ALPHA,	/* Z */
193 		SEPARATOR,				/* [ */
194 		SEPARATOR,				/* \ */
195 		SEPARATOR,				/* ] */
196 		SEPARATOR,				/* ^ */
197 		SYMBOL | SEPARATOR,			/* _ */
198 		SEPARATOR,				/* ` */
199 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* a */
200 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* b */
201 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* c */
202 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* d */
203 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* e */
204 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* f */
205 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* g */
206 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* h */
207 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* i */
208 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* j */
209 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* k */
210 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* l */
211 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* m */
212 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* n */
213 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* o */
214 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* p */
215 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* q */
216 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* r */
217 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* s */
218 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* t */
219 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* u */
220 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* v */
221 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* w */
222 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* x */
223 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* y */
224 		LOWER | ALPHANUMERIC | SYMBOL | ALPHA,	/* z */
225 		SEPARATOR,				/* { */
226 		SEPARATOR,				/* | */
227 		SEPARATOR,				/* } */
228 		SEPARATOR,				/* ~ */
229 		SEPARATOR,				/* delete */
230 		'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
231 		'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
232 		'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
233 		'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
234 		'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
235 		'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
236 		'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
237 		'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
238 		};
239 
240 
241 #if DEBUGGING
242 	static char *DbgFNm = "ZFrSrc";
243 	sprintf(DbgSBf,"*SStPtr = '%c', *EBPtr1 = '%c'", *SStPtr, *EBPtr1);
244 	DbgFEn(3,DbgFNm,DbgSBf);
245 #endif
246 
247 	switch (*SStPtr) {
248 	case CTRL_X:
249 		break;
250 
251 	case CTRL_S:
252 		mask = SEPARATOR;
253 		goto scanc;
254 
255 	case CTRL_N:
256 		if (++SStPtr == SBfPtr) {
257 			ErrMsg(ERR_ISS);	/* ill. search str. */
258 			DBGFEX(3,DbgFNm,"FAILURE");
259 			return FAILURE;
260 		}
261 		SavSSP = SStPtr;
262 		for (; EBPtr1 <= EndSAr; ++EBPtr1) {
263 			EBPtr2 = EBPtr1;
264 			SStPtr = SavSSP;
265 			if (CMatch(&SamChr) == FAILURE) {
266 				DBGFEX(3,DbgFNm,"FAILURE, CMatch() failed");
267 				return FAILURE;
268 			}
269 			if (!SamChr)
270 				break;
271 		}
272 		break;
273 
274 	case CTRL_E:
275 		if (++SStPtr == SBfPtr) {
276 			ErrMsg(ERR_ICE);	/* ICE = illegal ^E */
277 			DBGFEX(3,DbgFNm,"FAILURE");
278 			return FAILURE;
279 		}
280 		switch (To_Upper(*SStPtr)) {
281 		case 'A':
282 			mask = ALPHA;
283 			goto scanc;
284 
285 		case 'B':
286 			mask = SEPARATOR;
287 			goto scanc;
288 
289 		case 'C':
290 			mask = SYMBOL;
291 			goto scanc;
292 
293 		case 'D':
294 			mask = DIGIT;
295 			goto scanc;
296 
297 		case 'G':
298 			if (++SStPtr == SBfPtr) {
299 				ErrMsg(ERR_ICE);
300 				DBGFEX(3,DbgFNm,"FAILURE");
301 				return FAILURE;
302 			}
303 			TCBfPt = CBfPtr;	/* save CBfPtr */
304 			TCStEn = CStEnd;	/* save CStEnd */
305 			CBfPtr = SStPtr;
306 			CStEnd = SBfPtr;
307 			Status = FindQR();
308 			SStPtr = CBfPtr;
309 			SBfPtr = CStEnd;
310 			CBfPtr = TCBfPt;	/* restore CBfPtr */
311 			CStEnd = TCStEn;	/* restore CStEnd */
312 			if (Status == FAILURE) {
313 				DBGFEX(3,DbgFNm,"FAILURE");
314 				return FAILURE;
315 			}
316 			for (;EBPtr1<=EndSAr;++EBPtr1) {
317 				QTPtr = QR->Start;
318 				while (QTPtr < QR->End_P1)
319 					if (*QTPtr++ == *EBPtr1)
320 						goto kludge;
321 			}
322 kludge:			break;
323 		case 'L':
324 			mask = LINE_TERMINATOR;
325 			goto scanc;
326 
327 		case 'M':
328 			if (++SStPtr == SBfPtr) {
329 				ErrMsg(ERR_ICE);
330 				DBGFEX(3,DbgFNm,"FAILURE");
331 				return FAILURE;
332 			}
333 			SavSSP = SStPtr;
334 			if (ZFrSrc() == FAILURE) {
335 				DBGFEX(3,DbgFNm,"FAILURE");
336 				return FAILURE;
337 			}
338 			if (EBPtr1 > EndSAr) {	/* if not found */
339 				break;
340 			}
341 			while (EBPtr2 < EndSAr) {
342 				SavEP2 = EBPtr2++;
343 				SStPtr = SavSSP;
344 				if (CMatch(&SamChr) == FAILURE) {
345 					DBGFEX(3,DbgFNm,"FAILURE");
346 					return FAILURE;
347 				}
348 				if (!SamChr) {
349 					EBPtr2 = SavEP2;
350 					break;
351 				}
352 			}
353 			DBGFEX(3,DbgFNm,"SUCCESS");
354 			return SUCCESS;
355 
356 		case 'R':
357 			mask = ALPHANUMERIC;
358 			goto scanc;
359 
360 		case 'S':
361 			for (;EBPtr1<=EndSAr;++EBPtr1) {
362 				if ((*EBPtr1 == SPACE) || (*EBPtr1 == TABCHR)) {
363 					EBPtr2 = EBPtr1;
364 					while (EBPtr2 < EndSAr) {
365 						++EBPtr2;
366 						if ((*EBPtr2 != SPACE) && (*EBPtr2 != TABCHR)) {
367 							EBPtr2--;
368 							break;
369 						}
370 					}
371 					DBGFEX(3,DbgFNm,"SUCCESS");
372 					return SUCCESS;
373 				}
374 			}
375 			break;
376 
377 		case 'V':
378 			mask = LOWER;
379 			goto scanc;
380 
381 		case 'W':
382 			mask = UPPER;
383 			goto scanc;
384 
385 		case 'X':
386 			break;
387 
388 		case '<':
389 			if (++SStPtr == SBfPtr) {
390 				ErrMsg(ERR_ICE);
391 				DBGFEX(3,DbgFNm,"FAILURE");
392 				return FAILURE;
393 			}
394 			TmpLng = 0;
395 			while (Is_Digit(*SStPtr)) {
396 				TmpLng *= 8;
397 				TmpLng += *SStPtr - '0';
398 				if (TmpLng > 127) {
399 					ErrMsg(ERR_ICE);
400 					DBGFEX(3,DbgFNm,"FAILURE");
401 					return FAILURE;
402 				}
403 				if (++SStPtr == SBfPtr) {
404 					ErrMsg(ERR_ICE);
405 					DBGFEX(3,DbgFNm,"FAILURE");
406 					return FAILURE;
407 				}
408 			}
409 			if (*SStPtr != '>') {
410 				ErrMsg(ERR_ICE);
411 				DBGFEX(3,DbgFNm,"FAILURE");
412 				return FAILURE;
413 			}
414 			Charac = (char)TmpLng;
415 			for (; EBPtr1 <= EndSAr; ++EBPtr1) {
416 				if (*EBPtr1 == Charac) {
417 					break;
418 				}
419 			}
420 			break;
421 
422 		case '[':
423 			if (++SStPtr == SBfPtr) {
424 				ErrMsg(ERR_ICE);
425 				DBGFEX(3,DbgFNm,"FAILURE");
426 				return FAILURE;
427 			}
428 			LstBeg = SStPtr;
429 			for (;EBPtr1<=EndSAr;++EBPtr1) {
430 				while (*SStPtr != ']') {
431 					if (*SStPtr == ', ') {
432 						if (++SStPtr == SBfPtr) {
433 							ErrMsg(ERR_ICE);
434 							DBGFEX(3,DbgFNm,"FAILURE");
435 							return FAILURE;
436 						}
437 					} else {
438 						EBPtr2 = EBPtr1;
439 						if (CMatch(&SamChr) == FAILURE) {
440 							DBGFEX(3,DbgFNm,"FAILURE");
441 							return FAILURE;
442 						}
443 						if (SamChr) {
444 							while (*SStPtr != ']') {
445 								if (++SStPtr == SBfPtr) {
446 									ErrMsg(ERR_ICE);
447 									DBGFEX(3,DbgFNm,"FAILURE");
448 									return FAILURE;
449 								}
450 							}
451 							EBPtr2 = EBPtr1;
452 							DBGFEX(3,DbgFNm,"SUCCESS");
453 							return SUCCESS;
454 						}
455 					}
456 					if (++SStPtr == SBfPtr) {
457 						ErrMsg(ERR_ISS);
458 						DBGFEX(3,DbgFNm,"FAILURE");
459 						return FAILURE;
460 					}
461 				}
462 				SStPtr = LstBeg;
463 			}
464 			break;
465 
466 		default:
467 			ErrMsg(ERR_ICE);
468 			DBGFEX(3,DbgFNm,"FAILURE");
469 			return FAILURE;
470 		}
471 		break;
472 
473 	default:
474 		if (SMFlag) {		/* if case dependence */
475 			for (;EBPtr1<=EndSAr;++EBPtr1) {
476 				if (*EBPtr1 == *SStPtr) {
477 					break;
478 				}
479 			}
480 		} else {			/* else case independence */
481 			OtCase = (Is_Upper(*SStPtr)) ?
482 					To_Lower(*SStPtr) :
483 					To_Upper(*SStPtr);
484 			for (;EBPtr1<=EndSAr;++EBPtr1) {
485 				if ((*EBPtr1 == *SStPtr) ||
486 				    (*EBPtr1 == OtCase)) {
487 					break;
488 				}
489 			}
490 		}
491 		break;
492 	} /* end of switch */
493 
494 	EBPtr2 = EBPtr1;
495 
496 #if DEBUGGING
497 	sprintf(DbgSBf,"SUCCESS, EBPtr1 = %ld, EndSAr = %ld",
498 		Zcp2ul(EBPtr1), Zcp2ul(EndSAr));
499 	DbgFEx(3,DbgFNm,DbgSBf);
500 #endif
501 	return SUCCESS;
502 
503 
504 scanc:	real_length = EndSAr - EBPtr1;
505 	real_length++;
506 	src_str.dsc$a_pointer = EBPtr1;
507 	while (real_length > 0) {
508 		src_str.dsc$w_length = (real_length > 65535) ?
509 						65535 :
510 						real_length;
511 		indx = lib$scanc(&src_str, table_1, &mask);
512 		if (indx) {			/* if scan succeeded */
513 			EBPtr1 += indx;
514 			EBPtr1--;
515 			EBPtr2 = EBPtr1;
516 			DBGFEX(3,DbgFNm,"SUCCESS");
517 			return SUCCESS;
518 		}
519 		real_length -= 65535;
520 		src_str.dsc$a_pointer += 65535;
521 	}
522 	EBPtr1 = EndSAr;
523 	EBPtr1++;
524 
525 	DBGFEX(3,DbgFNm,"SUCCESS");
526 	return SUCCESS;
527 }
528 
529 
530 
531 
532 
533 #else
534 
535 
536 
ZFrSrc()537 DEFAULT ZFrSrc()		/* forward search for 1st search charptr */
538 {
539 	char	Charac;		/* holds a character */
540 	charptr	LstBeg;		/* beginning of ^E[x,x,x] list */
541 	char	OtCase;		/* "other" case character */
542 	charptr	QTPtr;		/* pointer into q-register text */
543 	BOOLEAN	SamChr;		/* same character indicator */
544 	charptr	SavEP2;		/* temporary holder of EBPtr2 */
545 	charptr	SavSSP;		/* temporary holder of SStPtr */
546 	DEFAULT	Status;
547 	charptr	TCBfPt;		/* temporary holder of CBfPtr */
548 	charptr	TCStEn;		/* temporary holder of CStEnd */
549 	LONG	TmpLng;
550 
551 #if DEBUGGING
552 	static char *DbgFNm = "ZFrSrc";
553 	sprintf(DbgSBf,"*SStPtr = '%c', *EBPtr1 = '%c'", *SStPtr, *EBPtr1);
554 	DbgFEn(3,DbgFNm,DbgSBf);
555 #endif
556 
557 	switch (*SStPtr) {
558 		case CTRL_X:
559 			break;
560 		case CTRL_S:
561 			for (;EBPtr1<=EndSAr;++EBPtr1)
562 				if (!Is_Alnum(*EBPtr1))
563 					break;
564 			break;
565 		case CTRL_N:
566 			if (++SStPtr == SBfPtr)
567 				{
568 				ErrMsg(ERR_ISS);	/* ill. search str. */
569 				DBGFEX(3,DbgFNm,"FAILURE");
570 				return FAILURE;
571 				}
572 			SavSSP = SStPtr;
573 			for (;EBPtr1<=EndSAr;++EBPtr1)
574 				{
575 				EBPtr2 = EBPtr1;
576 				SStPtr = SavSSP;
577 				if (CMatch(&SamChr) == FAILURE) {
578 					DBGFEX(3,DbgFNm,"FAILURE");
579 					return FAILURE;
580 				}
581 				if (!SamChr)
582 					break;
583 				}
584 			break;
585 		case CTRL_E:
586 			if (++SStPtr == SBfPtr)
587 				{
588 				ErrMsg(ERR_ICE);	/* ICE = illegal ^E */
589 				DBGFEX(3,DbgFNm,"FAILURE");
590 				return FAILURE;
591 				}
592 			switch (To_Upper(*SStPtr)) {
593 			case 'A':
594 				for (;EBPtr1<=EndSAr;++EBPtr1)
595 					if (Is_Alpha(*EBPtr1))
596 						break;
597 				break;
598 			case 'B':
599 				for (;EBPtr1<=EndSAr;++EBPtr1)
600 					if (!Is_Alnum(*EBPtr1))
601 						break;
602 				break;
603 			case 'C':
604 				for (;EBPtr1<=EndSAr;++EBPtr1)
605 					if (Is_SyCon(*EBPtr1))
606 						break;
607 				break;
608 			case 'D':
609 				for (;EBPtr1<=EndSAr;++EBPtr1)
610 					if (Is_Digit(*EBPtr1))
611 						break;
612 				break;
613 			case 'G':
614 				if (++SStPtr == SBfPtr)
615 					{
616 					ErrMsg(ERR_ICE);
617 					DBGFEX(3,DbgFNm,"FAILURE");
618 					return FAILURE;
619 					}
620 				TCBfPt = CBfPtr;	/* save CBfPtr */
621 				TCStEn = CStEnd;	/* save CStEnd */
622 				CBfPtr = SStPtr;
623 				CStEnd = SBfPtr;
624 				Status = FindQR();
625 				SStPtr = CBfPtr;
626 				SBfPtr = CStEnd;
627 				CBfPtr = TCBfPt;	/* restore CBfPtr */
628 				CStEnd = TCStEn;	/* restore CStEnd */
629 				if (Status == FAILURE) {
630 					DBGFEX(3,DbgFNm,"FAILURE");
631 					return FAILURE;
632 				}
633 				for (;EBPtr1<=EndSAr;++EBPtr1)
634 					{
635 					QTPtr = QR->Start;
636 					while (QTPtr < QR->End_P1)
637 						if (*QTPtr++ == *EBPtr1)
638 							goto kludge;
639 					}
640 kludge:				break;
641 			case 'L':
642 				for (;EBPtr1<=EndSAr;++EBPtr1)
643 					if (IsEOL(*EBPtr1))
644 						break;
645 				break;
646 			case 'M':
647 				if (++SStPtr == SBfPtr)
648 					{
649 					ErrMsg(ERR_ICE);
650 					DBGFEX(3,DbgFNm,"FAILURE");
651 					return FAILURE;
652 					}
653 				SavSSP = SStPtr;
654 				if (ZFrSrc() == FAILURE) {
655 					DBGFEX(3,DbgFNm,"FAILURE");
656 					return FAILURE;
657 				}
658 				if (EBPtr1 > EndSAr)	/* if not found */
659 					break;
660 				while (EBPtr2 < EndSAr)
661 					{
662 					SavEP2 = EBPtr2++;
663 					SStPtr = SavSSP;
664 					if (CMatch(&SamChr) == FAILURE) {
665 						DBGFEX(3,DbgFNm,"FAILURE");
666 						return FAILURE;
667 					}
668 					if (!SamChr)
669 						{
670 						EBPtr2 = SavEP2;
671 						break;
672 						}
673 					}
674 				DBGFEX(3,DbgFNm,"SUCCESS");
675 				return SUCCESS;
676 			case 'R':
677 				for (;EBPtr1<=EndSAr;++EBPtr1)
678 					if (Is_Alnum(*EBPtr1))
679 						break;
680 				break;
681 			case 'S':
682 				for (;EBPtr1<=EndSAr;++EBPtr1)
683 					if ((*EBPtr1 == SPACE) ||
684 					    (*EBPtr1 == TABCHR))
685 						{
686 						EBPtr2 = EBPtr1;
687 						while (EBPtr2 < EndSAr)
688 						    {
689 						    ++EBPtr2;
690 						    if ((*EBPtr2 != SPACE) &&
691 							(*EBPtr2 != TABCHR))
692 							    {
693 							    EBPtr2--;
694 							    break;
695 							    }
696 						    }
697 						DBGFEX(3,DbgFNm,"SUCCESS");
698 						return SUCCESS;
699 						}
700 				break;
701 			case 'V':
702 				for (;EBPtr1<=EndSAr;++EBPtr1)
703 					if (Is_Lower(*EBPtr1))
704 						break;
705 				break;
706 			case 'W':
707 				for (;EBPtr1<=EndSAr;++EBPtr1)
708 					if (Is_Upper(*EBPtr1))
709 						break;
710 				break;
711 			case 'X':
712 				break;
713 			case '<':
714 				if (++SStPtr == SBfPtr)
715 					{
716 					ErrMsg(ERR_ICE);
717 					DBGFEX(3,DbgFNm,"FAILURE");
718 					return FAILURE;
719 					}
720 				TmpLng = 0;
721 				while (Is_Digit(*SStPtr))
722 					{
723 					TmpLng *= 8;
724 					TmpLng += *SStPtr - '0';
725 					if (TmpLng > 127)
726 						{
727 						ErrMsg(ERR_ICE);
728 						DBGFEX(3,DbgFNm,"FAILURE");
729 						return FAILURE;
730 						}
731 					if (++SStPtr == SBfPtr)
732 						{
733 						ErrMsg(ERR_ICE);
734 						DBGFEX(3,DbgFNm,"FAILURE");
735 						return FAILURE;
736 						}
737 					}
738 				if (*SStPtr != '>')
739 					{
740 					ErrMsg(ERR_ICE);
741 					DBGFEX(3,DbgFNm,"SUCCESS");
742 					return FAILURE;
743 					}
744 				Charac = (char)TmpLng;
745 				for (;EBPtr1<=EndSAr;++EBPtr1)
746 					if (*EBPtr1 == Charac)
747 						break;
748 				break;
749 			case '[':
750 				if (++SStPtr == SBfPtr)
751 					{
752 					ErrMsg(ERR_ICE);
753 					DBGFEX(3,DbgFNm,"FAILURE");
754 					return FAILURE;
755 					}
756 				LstBeg = SStPtr;
757 				for (;EBPtr1<=EndSAr;++EBPtr1)
758 					{
759 					while (*SStPtr != ']')
760 						if (*SStPtr == ',')
761 							{
762 							if (++SStPtr == SBfPtr)
763 								{
764 								ErrMsg(ERR_ICE);
765 								DBGFEX(3,DbgFNm,"FAILURE");
766 								return FAILURE;
767 								}
768 							}
769 						else
770 							{
771 						EBPtr2 = EBPtr1;
772 						if (CMatch(&SamChr) == FAILURE) {
773 							DBGFEX(3,DbgFNm,"FAILURE");
774 							return FAILURE;
775 						}
776 						if (SamChr)
777 							{
778 							while (*SStPtr != ']')
779 							if (++SStPtr == SBfPtr)
780 								{
781 								ErrMsg(ERR_ICE);
782 								DBGFEX(3,DbgFNm,"FAILURE");
783 								return FAILURE;
784 								}
785 							EBPtr2 = EBPtr1;
786 							DBGFEX(3,DbgFNm,"SUCCESS");
787 							return SUCCESS;
788 							}
789 						if (++SStPtr == SBfPtr)
790 							{
791 							ErrMsg(ERR_ISS);
792 							DBGFEX(3,DbgFNm,"FAILURE");
793 							return FAILURE;
794 							}
795 						}
796 					SStPtr = LstBeg;
797 					}
798 				break;
799 			default:
800 				ErrMsg(ERR_ICE);
801 				DBGFEX(3,DbgFNm,"FAILURE");
802 				return FAILURE;
803 			}
804 			break;
805 		default:
806 			if (SMFlag)		/* if case dependence */
807 				{
808 				for (;EBPtr1<=EndSAr;++EBPtr1)
809 					if (*EBPtr1 == *SStPtr)
810 						break;
811 				}
812 			else			/* else case independence */
813 				{
814 				OtCase = (Is_Upper(*SStPtr)) ?
815 						To_Lower(*SStPtr) :
816 						To_Upper(*SStPtr);
817 				for (;EBPtr1<=EndSAr;++EBPtr1)
818 					if ((*EBPtr1 == *SStPtr) ||
819 					    (*EBPtr1 == OtCase))
820 						break;
821 				}
822 	}	/* end of switch */
823 	EBPtr2 = EBPtr1;
824 
825 #if DEBUGGING
826 	sprintf(DbgSBf,"SUCCESS, EBPtr1 = %ld, EndSAr = %ld",
827 		Zcp2ul(EBPtr1), Zcp2ul(EndSAr));
828 	DbgFEx(3,DbgFNm,DbgSBf);
829 #endif
830 	return SUCCESS;
831 }
832 #endif
833