/* * File: lscan.c * Contents: bscan, escan */ #include "..\h\config.h" #include "..\h\rt.h" #include "rproto.h" /* * bscan - set &subject and &pos upon entry to a scanning expression. * * Arguments are: * Arg0 - new value for &subject * Arg1 - saved value of &subject * Arg2 - saved value of &pos * * A variable pointing to the saved &subject and &pos is returned to be * used by escan. */ LibDcl(bscan,2,"?") { char sbuf[MaxCvtLen]; int rc; struct pf_marker *cur_pfp; #if MACINTOSH #if MPW /* #pragma unused(nargs) */ #endif /* MPW */ #endif /* MACINTOSH */ /* * Convert the new value for &subject to a string. */ if (DeRef(Arg0) == Error) RunErr(0, NULL); switch (cvstr(&Arg0, sbuf)) { case Cvt: /* * The new value for &subject wasn't a string. Allocate the * new value and fall through. */ if (strreq(StrLen(Arg0)) == Error) RunErr(0, NULL); StrLoc(Arg0) = alcstr(StrLoc(Arg0), StrLen(Arg0)); case NoCvt: /* * Establish a new &subject value and set &pos to 1. */ k_subject = Arg0; k_pos = 1; break; default: RunErr(103, &Arg0); } /* If the saved scanning environment belongs to the current procedure * call, put a reference to it in the procedure frame. */ if (pfp->pf_scan == NULL) pfp->pf_scan = &Arg1; cur_pfp = pfp; /* * Suspend with a variable pointing to the saved &subject and &pos. */ ArgType(0) = D_Var; VarLoc(Arg0) = &Arg1; rc = interp(G_Csusp,cargp); if (pfp != cur_pfp) return rc; /* * Leaving scanning environment. Restore the old &subject and &pos values. */ k_subject = Arg1; k_pos = IntVal(Arg2); if (pfp->pf_scan == &Arg1) pfp->pf_scan = NULL; if (rc == A_Resumption) return A_Failure; else return rc; } /* * escan - restore &subject and &pos at the end of a scanning expression. * * Arguments: * Arg0 - variable pointing to old values of &subject and &pos * Arg1 - result of the scanning expression * * The two arguments are reversed, so that the result of the scanning * expression becomes the result of escan. This result is dereferenced * if it refers to &subject or &pos. Then the saved values of &subject * and &pos are exchanged with the current ones. * * Escan suspends once it has restored the old &subject; on failure * the new &subject and &pos are "unrestored", and the failure is * propagated into the using clause. */ LibDcl(escan,1,"escan") { struct descrip tmp; int rc; struct pf_marker *cur_pfp; #if MACINTOSH #if MPW /* #pragma unused(nargs) */ #endif /* MPW */ #endif /* MACINTOSH */ /* * Copy the result of the scanning expression into Arg0, which will * be the result of the scan. */ tmp = Arg0; Arg0 = Arg1; Arg1 = tmp; /* * If the result of the scanning expression is &subject or &pos, * it is dereferenced. */ if (((char *)BlkLoc(Arg0) == (char *)&tvky_sub) || ((char *)BlkLoc(Arg0) == (char *)&tvky_pos)) if (DeRef(Arg0) == Error) RunErr(0, NULL); /* * Swap new and old values of &subject */ tmp = k_subject; k_subject = *VarLoc(Arg1); *VarLoc(Arg1) = tmp; /* * Swap new and old values of &pos */ tmp = *(VarLoc(Arg1) + 1); IntVal(*(VarLoc(Arg1) + 1)) = k_pos; k_pos = IntVal(tmp); /* * If we are returning to the scanning environment of the current * procedure call, indicate that it is no longed in a saved state. */ if (pfp->pf_scan == VarLoc(Arg1)) pfp->pf_scan = NULL; cur_pfp = pfp; /* * Suspend the value of the scanning expression. */ rc = interp(G_Csusp,cargp); if (pfp != cur_pfp) return rc; /* * Re-entering scanning environment, exchange the values of &subject * and &pos again */ tmp = k_subject; k_subject = *VarLoc(Arg1); *VarLoc(Arg1) = tmp; tmp = *(VarLoc(Arg1) + 1); IntVal(*(VarLoc(Arg1) +1)) = k_pos; k_pos = IntVal(tmp); if (pfp->pf_scan == NULL) pfp->pf_scan = VarLoc(Arg1); if (rc == A_Resumption) return A_Failure; else return rc; }