|
|
1.1 ! root 1: #include "../h/rt.h" ! 2: #include "../h/record.h" ! 3: ! 4: /* ! 5: * !x - generate successive values from object x. ! 6: */ ! 7: ! 8: bang(nargs, arg1v, arg1, arg0) ! 9: int nargs; ! 10: struct descrip arg1v, arg1, arg0; ! 11: { ! 12: register int i, j, slen; ! 13: register union block *bp, *ep; ! 14: register struct descrip *dp; ! 15: int typ1; ! 16: char sbuf[MAXSTRING]; ! 17: FILE *fd; ! 18: extern char *alcstr(); ! 19: ! 20: SetBound; ! 21: arg1v = arg1; ! 22: ! 23: if ((typ1 = cvstr(&arg1, sbuf)) != NULL) { ! 24: /* ! 25: * A string is being banged. ! 26: */ ! 27: i = 1; ! 28: while (i <= STRLEN(arg1)) { ! 29: /* ! 30: * Loop through the string using i as an index. ! 31: */ ! 32: if (typ1 == 1) { ! 33: /* ! 34: * x was converted to a string, thus, the resulting string ! 35: * can't be modified and a trapped variable isn't needed. ! 36: * Make a one-character string out of the next character ! 37: * in x and suspend it. ! 38: */ ! 39: sneed(1); ! 40: STRLEN(arg0) = 1; ! 41: STRLOC(arg0) = alcstr(STRLOC(arg1)+i-1, 1); ! 42: suspend(); ! 43: } ! 44: else { ! 45: /* ! 46: * x a string and thus a trapped variable must be made ! 47: * for the one character string being suspended. ! 48: */ ! 49: hneed(sizeof(struct b_tvsubs)); ! 50: mksubs(&arg1v, &arg1, i, 1, &arg0); ! 51: suspend(); ! 52: arg1 = arg1v; ! 53: DeRef(arg1) ! 54: if (!QUAL(arg1)) ! 55: runerr(103, &arg1); ! 56: } ! 57: i++; ! 58: } ! 59: } ! 60: else { ! 61: /* ! 62: * x isn't a string. ! 63: */ ! 64: DeRef(arg1) ! 65: switch (TYPE(arg1)) { ! 66: case T_LIST: ! 67: /* ! 68: * x is a list. Chain through each list element block and for ! 69: * each one, suspend with a variable pointing to each ! 70: * element contained in the block. ! 71: */ ! 72: bp = BLKLOC(arg1); ! 73: for (arg1 = bp->list.listhead; arg1.type == D_LELEM; ! 74: arg1 = BLKLOC(arg1)->lelem.listnext) { ! 75: bp = BLKLOC(arg1); ! 76: for (i = 0; i < bp->lelem.nused; i++) { ! 77: j = bp->lelem.first + i; ! 78: if (j >= bp->lelem.nelem) ! 79: j -= bp->lelem.nelem; ! 80: dp = &bp->lelem.lslots[j]; ! 81: arg0.type = D_VAR + ((int *)dp - (int *)bp); ! 82: VARLOC(arg0) = dp; ! 83: suspend(); ! 84: bp = BLKLOC(arg1); /* bp is untended, must reset */ ! 85: } ! 86: } ! 87: break; ! 88: ! 89: ! 90: case T_FILE: ! 91: /* ! 92: * x is a file. Read the next line into the string space ! 93: * and suspend the newly allocated string. ! 94: */ ! 95: fd = BLKLOC(arg1)->file.fd; ! 96: if ((BLKLOC(arg1)->file.status & FS_READ) == 0) ! 97: runerr(212, &arg1); ! 98: while ((slen = getstr(sbuf,MAXSTRING,fd)) >= 0) { ! 99: sneed(slen); ! 100: STRLEN(arg0) = slen; ! 101: STRLOC(arg0) = alcstr(sbuf,slen); ! 102: suspend(); ! 103: } ! 104: break; ! 105: ! 106: case T_TABLE: ! 107: /* ! 108: * x is a table. Chain down the element list in each bucket ! 109: * and suspend a variable pointing to each element in turn. ! 110: */ ! 111: for (i = 0; i < NBUCKETS; i++) { ! 112: bp = BLKLOC(arg1); ! 113: for (arg1v = bp->table.buckets[i]; arg1v.type == D_TELEM; ! 114: arg1v = BLKLOC(arg1v)->telem.blink) { ! 115: ep = BLKLOC(arg1v); ! 116: dp = &ep->telem.tval; ! 117: arg0.type = D_VAR + ((int *)dp - (int *)bp); ! 118: VARLOC(arg0) = dp; ! 119: suspend(); ! 120: bp = BLKLOC(arg1); /* bp is untended, must reset */ ! 121: } ! 122: } ! 123: break; ! 124: ! 125: #ifdef SETS ! 126: case T_SET: ! 127: /* ! 128: * This is similar to the method for tables except that a ! 129: * value is returned instead of a variable. ! 130: */ ! 131: for(i = 0; i < NBUCKETS; i++) { ! 132: bp = BLKLOC(arg1); ! 133: for(arg1v = bp->set.sbucks[i]; arg1v.type == D_SELEM; ! 134: arg1v = BLKLOC(arg1v)->selem.sblink) { ! 135: arg0 = BLKLOC(arg1v)->selem.setmem; ! 136: suspend(); ! 137: bp = BLKLOC(arg1); /* bp untended, must be reset */ ! 138: } ! 139: } ! 140: break; ! 141: #endif SETS ! 142: ! 143: case T_RECORD: ! 144: /* ! 145: * x is a record. Loop through the fields and suspend ! 146: * a variable pointing to each one. ! 147: */ ! 148: bp = BLKLOC(arg1); ! 149: j = bp->record.recptr->nfields; ! 150: for (i = 0; i < j; i++) { ! 151: dp = &bp->record.fields[i]; ! 152: arg0.type = D_VAR + ((int *)dp - (int *)bp); ! 153: VARLOC(arg0) = dp; ! 154: suspend(); ! 155: bp = BLKLOC(arg1); /* bp is untended, must reset */ ! 156: } ! 157: break; ! 158: ! 159: default: /* This object can not be compromised. */ ! 160: runerr(116, &arg1); ! 161: } ! 162: } ! 163: ! 164: /* ! 165: * Eventually fail. ! 166: */ ! 167: fail(); ! 168: } ! 169: ! 170: Opblockx(bang,2,"!",1)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.