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)
Defined functions
bang
defined in line
8; used 1 times