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
Last modified: 1984-11-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1103
Valid CSS Valid XHTML 1.0 Strict