/* * fconv.c -- abs, cset, integer, numeric, proc, real, string. */ #include "..\h\config.h" #include "..\h\rt.h" #include "rproto.h" /* * abs(x) - absolute value of x. */ FncDcl(abs,1) { switch (cvnum(&Arg1)) { /* * If Arg1 is convertible to a numeric, turn Arg0 into * a descriptor for the appropriate type and value. If the * conversion fails, produce an error. This code assumes that * n = -n is always valid, which is not necessarily correct. */ case T_Integer: MakeInt(Abs(IntVal(Arg1)), &Arg0); break; case T_Real: makereal(BlkLoc(Arg1)->realblk.realval, &Arg0); if (BlkLoc(Arg0)->realblk.realval < 0.0) BlkLoc(Arg0)->realblk.realval = -BlkLoc(Arg0)->realblk.realval; break; #ifdef LargeInts case T_Bignum: cpbignum(&Arg1, &Arg0); BlkLoc(Arg0)->bignumblk.sign = 0; break; #endif /* LargeInts */ default: RunErr(102, &Arg1); } Return; } /* * cset(x) - convert x to cset. */ FncDcl(cset,1) { register int i; register struct b_cset *bp; int *cs, csbuf[CsetSize]; if (blkreq((word)sizeof(struct b_cset)) == Error) RunErr(0, NULL); if (Arg1.dword == D_Cset) /* * Arg1 already a cset, just return it. */ Arg0 = Arg1; else if (cvcset(&Arg1, &cs, csbuf) != CvtFail) { /* * Arg1 was convertible to cset and the result resides in csbuf. * Allocate * a cset, make Arg0 a descriptor for it and copy the * bits from csbuf into it. */ Arg0.dword = D_Cset; bp = alccset(); BlkLoc(Arg0) = (union block *) bp; for (i = 0; i < CsetSize; i++) bp->bits[i] = cs[i]; } else /* Not a cset nor convertible to one. */ Fail; Return; } /* * integer(x) - convert x to integer. */ FncDcl(integer,1) { #ifdef LargeInts switch (cvnum(&Arg1)) { case T_Integer: case T_Bignum: Arg0 = Arg1; break; case T_Real: if (realtobig(&Arg1, &Arg0) == Error) /* alcbignum failed */ RunErr(0, NULL); break; #else /* LargeInts */ switch (cvint(&Arg1)) { case T_Integer: Arg0 = Arg1; break; #endif /* LargeInts */ default: Fail; } Return; } /* * numeric(x) - convert x to numeric type. */ FncDcl(numeric,1) { switch (cvnum(&Arg1)) { case T_Integer: #ifdef LargeInts case T_Bignum: #endif /* LargeInts */ case T_Real: Arg0 = Arg1; break; default: Fail; } Return; } /* * proc(x,i) - convert x to a procedure if possible; use i to * resolve ambiguous string names. */ FncDcl(proc,2) { char sbuf[MaxCvtLen]; long i; /* * If Arg1 is already a proc, just return it in Arg0. */ Arg0 = Arg1; if (Arg0.dword == D_Proc) Return; if (cvstr(&Arg0, sbuf) == CvtFail) Fail; /* * Arg2 defaults to 1. */ if (defshort(&Arg2, 1) == Error) RunErr(0, NULL); i = IntVal(Arg2); if (i < 1 || i > 3) RunErr(205, &Arg2); /* * Attempt to convert Arg0 to a procedure descriptor using args to * discriminate between procedures with the same names. Fail if * the conversion isn't successful. */ if (strprc(&Arg0,i) == CvtFail) Fail; Return; } /* * real(x) - convert x to real. */ FncDcl(real,1) { /* * If Arg1 is already a real, just return it. Otherwise convert it and * return it, failing if the conversion is unsuccessful. */ if (Arg1.dword == D_Real) Arg0 = Arg1; else if (cvreal(&Arg1) == T_Real) Arg0 = Arg1; else Fail; Return; } /* * string(x) - convert x to string. */ FncDcl(string,1) { char sbuf[MaxCvtLen]; Arg0 = Arg1; switch (cvstr(&Arg0, sbuf)) { /* * If Arg1 is not a string, allocate it and return it; if it is a * string, just return it; fail otherwise. */ case Cvt: /* * Allocate converted string */ if (strreq(StrLen(Arg0)) == Error) RunErr(0, NULL); StrLoc(Arg0) = alcstr(StrLoc(Arg0), StrLen(Arg0)); case NoCvt: Return; default: Fail; } }