|
|
1.1 ! root 1: /* ! 2: * File: fconv.c ! 3: * Contents: abs, cset, integer, list, numeric, proc, real, set, string, table ! 4: */ ! 5: ! 6: #include "../h/rt.h" ! 7: ! 8: /* ! 9: * abs(x) - absolute value of x. ! 10: */ ! 11: FncDcl(abs,1) ! 12: { ! 13: union numeric result; ! 14: ! 15: switch (cvnum(&Arg1, &result)) { ! 16: /* ! 17: * If x is convertible to a numeric, turn Arg0 into ! 18: * a descriptor for the appropriate type and value. If the ! 19: * conversion fails, produce an error. This code assumes that ! 20: * x = -x is always valid, but this assumption does not always ! 21: * hold. ! 22: */ ! 23: case T_Integer: ! 24: case T_Longint: ! 25: if (result.integer < 0L) ! 26: result.integer = -result.integer; ! 27: Mkint(result.integer, &Arg0); ! 28: break; ! 29: ! 30: case T_Real: ! 31: if (result.real < 0.0) ! 32: result.real = -result.real; ! 33: mkreal(result.real, &Arg0); ! 34: break; ! 35: ! 36: default: ! 37: runerr(102, &Arg1); ! 38: } ! 39: Return; ! 40: } ! 41: ! 42: ! 43: /* ! 44: * cset(x) - convert x to cset. ! 45: */ ! 46: ! 47: FncDcl(cset,1) ! 48: { ! 49: register int i, j; ! 50: register struct b_cset *bp; ! 51: int *cs, csbuf[CsetSize]; ! 52: extern struct b_cset *alccset(); ! 53: ! 54: blkreq((word)sizeof(struct b_cset)); ! 55: ! 56: if (Arg1.dword == D_Cset) ! 57: /* ! 58: * x is already a cset, just return it. ! 59: */ ! 60: Arg0 = Arg1; ! 61: else if (cvcset(&Arg1, &cs, csbuf) != NULL) { ! 62: /* ! 63: * x was convertible to cset and the result resides in csbuf. Allocate ! 64: * a cset, make Arg0 a descriptor for it and copy the bits from csbuf ! 65: * into it. ! 66: */ ! 67: Arg0.dword = D_Cset; ! 68: bp = alccset(0); ! 69: BlkLoc(Arg0) = (union block *) bp; ! 70: for (i = 0; i < CsetSize; i++) ! 71: bp->bits[i] = cs[i]; ! 72: j = 0; ! 73: for (i = 0; i < CsetSize*CIntSize; i++) { ! 74: if (Testb(i,cs)) ! 75: j++; ! 76: } ! 77: bp->size = j; ! 78: } ! 79: else /* Not a cset nor convertible to one. */ ! 80: Fail; ! 81: Return; ! 82: } ! 83: ! 84: ! 85: /* ! 86: * integer(x) - convert x to integer. ! 87: */ ! 88: ! 89: FncDcl(integer,1) ! 90: { ! 91: long l; ! 92: ! 93: switch (cvint(&Arg1, &l)) { ! 94: ! 95: case T_Integer: ! 96: case T_Longint: ! 97: Mkint(l, &Arg0); ! 98: break; ! 99: ! 100: default: ! 101: Fail; ! 102: } ! 103: Return; ! 104: } ! 105: ! 106: ! 107: /* ! 108: * list(n,x) - create a list of size n, with initial value x. ! 109: */ ! 110: ! 111: /* >list */ ! 112: FncDcl(list,2) ! 113: { ! 114: register word i, size; ! 115: word nelem; ! 116: register struct b_lelem *bp; ! 117: register struct b_list *hp; ! 118: extern struct b_list *alclist(); ! 119: extern struct b_lelem *alclstb(); ! 120: ! 121: defshort(&Arg1, 0); /* Size defaults to 0 */ ! 122: ! 123: nelem = size = IntVal(Arg1); ! 124: ! 125: ! 126: /* ! 127: * Ensure that the size is positive and that the list element block ! 128: * has at least MinListSlots element slots. ! 129: */ ! 130: if (size < 0) ! 131: runerr(205, &Arg1); ! 132: if (nelem < MinListSlots) ! 133: nelem = MinListSlots; ! 134: ! 135: /* ! 136: * Ensure space for a list header block, and a list element block ! 137: * with nelem element slots. ! 138: */ ! 139: blkreq(sizeof(struct b_list) + sizeof(struct b_lelem) + ! 140: nelem * sizeof(struct descrip)); ! 141: ! 142: /* ! 143: * Allocate the list header block and a list element block. ! 144: * Note that nelem is the number of elements in the list element ! 145: * block while size is the number of elements in the ! 146: * list. ! 147: */ ! 148: hp = alclist(size); ! 149: bp = alclstb(nelem, (word)0, size); ! 150: hp->listhead.dword = hp->listtail.dword = D_Lelem; ! 151: BlkLoc(hp->listhead) = BlkLoc(hp->listtail) = (union block *) bp; ! 152: ! 153: /* ! 154: * Initialize each list element. ! 155: */ ! 156: for (i = 0; i < size; i++) ! 157: bp->lslots[i] = Arg2; ! 158: ! 159: /* ! 160: * Return the new list. ! 161: */ ! 162: Arg0.dword = D_List; ! 163: BlkLoc(Arg0) = (union block *) hp; ! 164: Return; ! 165: } ! 166: /* <list */ ! 167: ! 168: ! 169: /* ! 170: * numeric(x) - convert x to numeric type. ! 171: */ ! 172: FncDcl(numeric,1) ! 173: { ! 174: union numeric n1; ! 175: ! 176: switch (cvnum(&Arg1, &n1)) { ! 177: ! 178: case T_Integer: ! 179: case T_Longint: ! 180: Mkint(n1.integer, &Arg0); ! 181: break; ! 182: ! 183: case T_Real: ! 184: mkreal(n1.real, &Arg0); ! 185: break; ! 186: ! 187: default: ! 188: Fail; ! 189: } ! 190: Return; ! 191: } ! 192: ! 193: ! 194: /* ! 195: * proc(x,args) - convert x to a procedure if possible; use args to ! 196: * resolve ambiguous string names. ! 197: */ ! 198: FncDcl(proc,2) ! 199: { ! 200: char sbuf[MaxCvtLen]; ! 201: ! 202: /* ! 203: * If x is already a proc, just return it in Arg0. ! 204: */ ! 205: Arg0 = Arg1; ! 206: if (Arg0.dword == D_Proc) { ! 207: Return; ! 208: } ! 209: if (cvstr(&Arg0, sbuf) == NULL) ! 210: Fail; ! 211: /* ! 212: * args defaults to 1. ! 213: */ ! 214: defshort(&Arg2, 1); ! 215: /* ! 216: * Attempt to convert Arg0 to a procedure descriptor using args to ! 217: * discriminate between procedures with the same names. Fail if ! 218: * the conversion isn't successful. ! 219: */ ! 220: if (strprc(&Arg0,IntVal(Arg2))) { ! 221: Return; ! 222: } ! 223: else ! 224: Fail; ! 225: } ! 226: ! 227: ! 228: /* ! 229: * real(x) - convert x to real. ! 230: */ ! 231: ! 232: FncDcl(real,1) ! 233: { ! 234: double r; ! 235: ! 236: /* ! 237: * If x is already a real, just return it. Otherwise convert it and ! 238: * return it, failing if the conversion is unsuccessful. ! 239: */ ! 240: if (Arg1.dword == D_Real) ! 241: Arg0 = Arg1; ! 242: else if (cvreal(&Arg1, &r) == T_Real) ! 243: mkreal(r, &Arg0); ! 244: else ! 245: Fail; ! 246: Return; ! 247: } ! 248: ! 249: ! 250: /* ! 251: * set(list) - create a set with members in list. ! 252: * The members are linked into hash chains which are ! 253: * arranged in increasing order by hash number. ! 254: */ ! 255: FncDcl(set,1) ! 256: { ! 257: register word hn; ! 258: register struct descrip *pd; ! 259: register struct b_set *ps; ! 260: union block *pb; ! 261: struct b_selem *ne; ! 262: struct descrip *pe; ! 263: int res; ! 264: word i, j; ! 265: extern struct descrip *memb(); ! 266: extern struct b_set *alcset(); ! 267: extern struct b_selem *alcselem(); ! 268: ! 269: if (Arg1.dword != D_List) ! 270: runerr(108,&Arg1); ! 271: ! 272: blkreq(sizeof(struct b_set) + (BlkLoc(Arg1)->list.size * ! 273: sizeof(struct b_selem))); ! 274: ! 275: pb = BlkLoc(Arg1); ! 276: Arg0.dword = D_Set; ! 277: ps = alcset(); ! 278: BlkLoc(Arg0) = (union block *) ps; ! 279: /* ! 280: * Chain through each list block and for ! 281: * each element contained in the block ! 282: * insert the element into the set if not there. ! 283: */ ! 284: for (Arg1 = pb->list.listhead; Arg1.dword == D_Lelem; ! 285: Arg1 = BlkLoc(Arg1)->lelem.listnext) { ! 286: pb = BlkLoc(Arg1); ! 287: for (i = 0; i < pb->lelem.nused; i++) { ! 288: j = pb->lelem.first + i; ! 289: if (j >= pb->lelem.nelem) ! 290: j -= pb->lelem.nelem; ! 291: pd = &pb->lelem.lslots[j]; ! 292: pe = memb(ps, pd, hn = hash(pd), &res); ! 293: if (res == 0) { ! 294: ne = alcselem(pd,hn); ! 295: addmem(ps,ne,pe); ! 296: } ! 297: } ! 298: } ! 299: Return; ! 300: } ! 301: ! 302: ! 303: /* ! 304: * string(x) - convert x to string. ! 305: */ ! 306: ! 307: /* >string */ ! 308: FncDcl(string,1) ! 309: { ! 310: char sbuf[MaxCvtLen]; ! 311: extern char *alcstr(); ! 312: ! 313: Arg0 = Arg1; ! 314: switch (cvstr(&Arg0, sbuf)) { ! 315: ! 316: /* ! 317: * If Arg1 is not a string, allocate it and return it; if it is a ! 318: * string, just return it; fail otherwise. ! 319: */ ! 320: case Cvt: ! 321: strreq(StrLen(Arg0)); /* allocate converted string */ ! 322: StrLoc(Arg0) = alcstr(StrLoc(Arg0), StrLen(Arg0)); ! 323: ! 324: case NoCvt: ! 325: Return; ! 326: ! 327: default: ! 328: Fail; ! 329: } ! 330: } ! 331: /* <string */ ! 332: ! 333: /* ! 334: * table(x) - create a table with default value x. ! 335: */ ! 336: FncDcl(table,1) ! 337: { ! 338: extern struct b_table *alctable(); ! 339: ! 340: blkreq((word)sizeof(struct b_table)); ! 341: Arg0.dword = D_Table; ! 342: BlkLoc(Arg0) = (union block *) alctable(&Arg1); ! 343: Return; ! 344: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.