Coverage Report

Created: 2026-10-28 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/r-source/src/main/subset.c
Line
Count
Source
1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1997--2026  The R Core Team
4
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, a copy is available at
18
 *  https://www.R-project.org/Licenses/
19
 *
20
 *
21
 *  Vector and List Subsetting
22
 *
23
 *  There are three kinds of subscripting [, [[, and $.
24
 *  We have three different functions to compute these.
25
 *
26
 *
27
 *  Note on Matrix Subscripts
28
 *
29
 *  The special [ subscripting where dim(x) == ncol(subscript matrix)
30
 *  is handled inside VectorSubset. The subscript matrix is turned
31
 *  into a subscript vector of the appropriate size and then
32
 *  VectorSubset continues.  This provides coherence especially
33
 *  regarding attributes etc. (it would be quicker to handle this case
34
 *  separately, but then we would have more to keep in step.
35
 */
36
37
#ifdef HAVE_CONFIG_H
38
#include <config.h>
39
#endif
40
41
#include <Defn.h>
42
#include <Internal.h>
43
44
/* JMC convinced MM that this was not a good idea: */
45
#undef _S4_subsettable
46
47
48
1.58M
static R_INLINE SEXP VECTOR_ELT_FIX_NAMED(SEXP y, R_xlen_t i) {
49
    /* if RHS (container or element) has NAMED > 0 set NAMED = NAMEDMAX.
50
       Duplicating might be safer/more consistent (fix bug reported by
51
       Radford Neal; similar to PR15098) */
52
1.58M
    SEXP val = VECTOR_ELT(y, i);
53
1.58M
    if ((NAMED(y) || NAMED(val)))
54
1.58M
  ENSURE_NAMEDMAX(val);
55
1.58M
    return val;
56
1.58M
}
57
58
/* ExtractSubset allocates "result" and does the transfer of elements
59
   from "x" to "result" according to the integer/real subscripts given
60
   in "indx".
61
62
   The EXTRACT_SUBSET_LOOP macro allows the branches based on index
63
   type and vector type to happen outside the loop.
64
65
   This could avoid using data pointers, but there is little point as
66
   currently the subscript code forces allocation.
67
*/
68
69
14.3M
#define EXTRACT_SUBSET_LOOP(STDCODE, NACODE) do { \
70
14.3M
  if (TYPEOF(indx) == INTSXP) {     \
71
13.9M
      const int *pindx = INTEGER_RO(indx);  \
72
140M
      for (i = 0; i < n; i++) {     \
73
126M
    ii = pindx[i];        \
74
126M
    if (0 < ii && ii <= nx) {   \
75
123M
        ii--;       \
76
123M
        STDCODE;        \
77
123M
    }          \
78
126M
    else /* out of bounds or NA */    \
79
126M
        NACODE;       \
80
126M
      }            \
81
13.9M
  }            \
82
14.3M
  else {           \
83
382k
      const double *pindx = REAL_RO(indx);  \
84
1.00M
      for (i = 0; i < n; i++) {     \
85
626k
    double di = pindx[i];     \
86
626k
    ii = (R_xlen_t) (di - 1);   \
87
626k
    if (R_FINITE(di) &&     \
88
626k
        0 <= ii && ii < nx)     \
89
626k
        STDCODE;       \
90
626k
    else          \
91
626k
        NACODE;       \
92
626k
      }            \
93
382k
  }            \
94
14.3M
    } while (0)
95
96
NORET static void errorcallNotSubsettable(SEXP x, SEXP call)
97
7
{
98
7
    SEXP cond = R_makeNotSubsettableError(x, call);
99
7
    PROTECT(cond);
100
7
    R_signalErrorCondition(cond, call);
101
7
    UNPROTECT(1); /* cond; not reached */
102
7
}
103
104
NORET static void errorcallMissingSubs(SEXP x, SEXP call)
105
1
{
106
1
    if (call == R_NilValue)
107
0
  call = R_CurrentExpression;
108
1
    SEXP cond = R_makeMissingSubscriptError(x, call);
109
1
    PROTECT(cond);
110
1
    R_signalErrorCondition(cond, call);
111
1
    UNPROTECT(1); /* cond; not reached */
112
1
}
113
114
115
attribute_hidden SEXP ExtractSubset(SEXP x, SEXP indx, SEXP call)
116
14.4M
{
117
14.4M
    if (x == R_NilValue)
118
148k
  return x;
119
120
14.3M
    SEXP result;
121
122
14.3M
    if (ALTREP(x)) {
123
3.87k
  result = ALTVEC_EXTRACT_SUBSET(x, indx, call);
124
3.87k
  if (result != NULL)
125
105
      return result;
126
3.87k
    }
127
128
14.3M
    R_xlen_t i, ii, n, nx;
129
14.3M
    n = XLENGTH(indx);
130
14.3M
    nx = xlength(x);
131
14.3M
    int mode = TYPEOF(x);
132
133
    /* protect allocation in case _ELT operations need to allocate */
134
14.3M
    PROTECT(result = allocVector(mode, n));
135
14.3M
    switch(mode) {
136
62.8k
    case LGLSXP:
137
62.8k
  EXTRACT_SUBSET_LOOP(LOGICAL0(result)[i] = LOGICAL_ELT(x, ii),
138
62.8k
          LOGICAL0(result)[i] = NA_INTEGER);
139
62.8k
  break;
140
2.90M
    case INTSXP:
141
2.90M
  EXTRACT_SUBSET_LOOP(INTEGER0(result)[i] = INTEGER_ELT(x, ii),
142
2.90M
          INTEGER0(result)[i] = NA_INTEGER);
143
2.90M
  break;
144
3.00M
    case REALSXP:
145
3.00M
  EXTRACT_SUBSET_LOOP(REAL0(result)[i] = REAL_ELT(x, ii),
146
3.00M
          REAL0(result)[i] = NA_REAL);
147
3.00M
  break;
148
1.09k
    case CPLXSXP:
149
1.09k
  {
150
1.09k
      Rcomplex NA_CPLX = { .r = NA_REAL, .i = NA_REAL };
151
1.09k
      EXTRACT_SUBSET_LOOP(COMPLEX0(result)[i] = COMPLEX_ELT(x, ii),
152
1.09k
        COMPLEX0(result)[i] = NA_CPLX);
153
1.09k
  }
154
1.09k
  break;
155
7.64M
    case STRSXP:
156
7.64M
  EXTRACT_SUBSET_LOOP(SET_STRING_ELT(result, i, STRING_ELT(x, ii)),
157
7.64M
          SET_STRING_ELT(result, i, NA_STRING));
158
7.64M
  break;
159
730k
    case VECSXP:
160
730k
    case EXPRSXP:
161
730k
  EXTRACT_SUBSET_LOOP(SET_VECTOR_ELT(result, i,
162
730k
             VECTOR_ELT_FIX_NAMED(x, ii)),
163
730k
          SET_VECTOR_ELT(result, i, R_NilValue));
164
730k
  break;
165
58
    case RAWSXP:
166
58
  EXTRACT_SUBSET_LOOP(RAW0(result)[i] = RAW_ELT(x, ii),
167
58
          RAW0(result)[i] = (Rbyte) 0);
168
58
  break;
169
0
    case LISTSXP:
170
  /* cannot happen: pairlists are coerced to lists */
171
0
    case LANGSXP:
172
  /* cannot happen: LANGSXPs are coerced to lists */
173
0
    default:
174
0
  errorcallNotSubsettable(x, call);
175
14.3M
    }
176
14.3M
    UNPROTECT(1); /* result */
177
14.3M
    return result;
178
14.3M
}
179
180
181
/* This is for all cases with a single index, including 1D arrays and
182
   matrix indexing of arrays */
183
static SEXP VectorSubset(SEXP x, SEXP s, SEXP call)
184
14.1M
{
185
14.1M
    if (s == R_MissingArg) return duplicate(x);
186
187
    /* Check to see if we have special matrix subscripting. */
188
    /* If we do, make a real subscript vector and protect it. */
189
190
14.1M
    PROTECT(s);
191
14.1M
    if (ATTRIB(s) != R_NilValue) { /* pretest to speed up simple case */
192
71.1k
  SEXP dim = getAttrib(x, R_DimSymbol);
193
71.1k
  if (isMatrix(s) && isArray(x) && ncols(s) == length(dim)) {
194
0
      if (isString(s)) {
195
0
    SEXP dnames = PROTECT(GetArrayDimnames(x));
196
0
    s = strmat2intmat(s, dnames, call, x);
197
0
    UNPROTECT(2); /* dnames, s */
198
0
    PROTECT(s);
199
0
      }
200
0
      if (isInteger(s) || isReal(s)) {
201
0
    s = mat2indsub(dim, s, call, x);
202
0
    UNPROTECT(1);
203
0
    PROTECT(s);
204
0
      }
205
0
  }
206
71.1k
    }
207
208
    /* Convert to a vector of integer subscripts */
209
    /* in the range 1:length(x). */
210
14.1M
    R_xlen_t stretch = 1;
211
14.1M
    SEXP indx = PROTECT(makeSubscript(x, s, &stretch, call));
212
213
    /* Allocate the result. */
214
215
14.1M
    int mode = TYPEOF(x);
216
14.1M
    SEXP result = PROTECT(ExtractSubset(x, indx, call));
217
14.1M
    if (mode == VECSXP || mode == EXPRSXP)
218
  /* we do not duplicate the values when extracting the subset,
219
     so to be conservative mark the result as NAMED = NAMEDMAX */
220
730k
  ENSURE_NAMEDMAX(result);
221
222
14.1M
    if (result != R_NilValue) {
223
14.1M
  SEXP attrib, nattrib;
224
14.1M
  if (
225
14.1M
      ((attrib = getAttrib(x, R_NamesSymbol)) != R_NilValue) ||
226
14.0M
      ( /* here we might have an array.  Use row names if 1D */
227
14.0M
    isArray(x) && length(getAttrib(x, R_DimNamesSymbol)) == 1 &&
228
0
    (attrib = getAttrib(x, R_DimNamesSymbol)) != R_NilValue &&
229
0
    (attrib = GetRowNames(attrib)) != R_NilValue
230
14.0M
    )
231
14.1M
      ) {
232
86.1k
      PROTECT(attrib);
233
86.1k
      PROTECT(nattrib = ExtractSubset(attrib, indx, call));
234
86.1k
      setAttrib(result, R_NamesSymbol, nattrib);
235
86.1k
      UNPROTECT(2); /* attrib, nattrib */
236
86.1k
  }
237
14.1M
  if ((attrib = getAttrib(x, R_SrcrefSymbol)) != R_NilValue &&
238
0
      TYPEOF(attrib) == VECSXP) {
239
0
      PROTECT(nattrib = ExtractSubset(attrib, indx, call));
240
0
      setAttrib(result, R_SrcrefSymbol, nattrib);
241
0
      UNPROTECT(1);
242
0
  }
243
  /* FIXME:  this is wrong, because the slots are gone, so result is an invalid object of the S4 class! JMC 3/3/09 */
244
#ifdef _S4_subsettable
245
  if(IS_S4_OBJECT(x)) { /* e.g. contains = "list" */
246
      setAttrib(result, R_ClassSymbol, getAttrib(x, R_ClassSymbol));
247
      SET_S4_OBJECT(result);
248
  }
249
#endif
250
14.1M
    }
251
14.1M
    UNPROTECT(3);
252
14.1M
    return result;
253
14.1M
}
254
255
NORET static void errorcallOutOfBounds(SEXP x, int subscript,
256
               R_xlen_t index, SEXP call)
257
0
{
258
0
    SEXP sindex = ScalarReal((double) index);
259
0
    PROTECT(sindex);
260
0
    SEXP cond = R_makeOutOfBoundsError(x, subscript, sindex, call, NULL);
261
0
    PROTECT(cond);
262
0
    R_signalErrorCondition(cond, call);
263
0
    UNPROTECT(2); /* sindex, cond; not reached */
264
0
}
265
266
NORET static void errorcallOutOfBoundsSEXP(SEXP x, int subscript,
267
             SEXP sindex, SEXP call)
268
17
{
269
17
    SEXP cond = R_makeOutOfBoundsError(x, subscript, sindex, call, NULL);
270
17
    PROTECT(cond);
271
17
    R_signalErrorCondition(cond, call);
272
17
    UNPROTECT(1); /* cond; not reached */
273
17
}
274
275
// in ./subscript.c :
276
SEXP int_arraySubscript(int dim, SEXP s, SEXP dims, SEXP x, SEXP call);
277
278
/* The MATRIX_SUBSET_LOOP macro allows the branches based on index
279
   type and vector type to happen outside the loop. Running through
280
   the indices in column-major order also improves cache locality. */
281
282
145k
#define MATRIX_SUBSET_LOOP(STDCODE, NACODE) do {   \
283
292k
  for (j = 0; j < ncs; j++) {       \
284
147k
      jj = psc[j];          \
285
147k
      if (jj != NA_INTEGER) {       \
286
147k
    if (jj < 1 || jj > nc)       \
287
147k
        errorcallOutOfBounds(x, 0, jj, call); \
288
147k
    jj--;           \
289
147k
      }             \
290
24.0M
      for (i = 0; i < nrs; i++) {       \
291
23.9M
    ii = psr[i];          \
292
23.9M
    if (ii != NA_INTEGER) {       \
293
23.9M
        if (ii < 1 || ii > nr)     \
294
23.9M
      errorcallOutOfBounds(x, 1, ii, call); \
295
23.9M
        ii--;         \
296
23.9M
    }           \
297
23.9M
    ij = i + j * nrs;       \
298
23.9M
    if (ii == NA_INTEGER || jj == NA_INTEGER) \
299
23.9M
        NACODE;         \
300
23.9M
    else {           \
301
23.9M
        iijj = ii + jj * nr;      \
302
23.9M
        STDCODE;          \
303
23.9M
    }            \
304
23.9M
      }              \
305
147k
  }              \
306
145k
    } while (0)
307
308
static SEXP MatrixSubset(SEXP x, SEXP s, SEXP call, int drop)
309
145k
{
310
145k
    SEXP attr, result, sr, sc, dim;
311
145k
    int nr, nc, nrs, ncs;
312
145k
    R_xlen_t i, j, ii, jj, ij, iijj;
313
314
145k
    nr = nrows(x);
315
145k
    nc = ncols(x);
316
317
    /* Note that "s" is protected on entry. */
318
    /* The following ensures that pointers remain protected. */
319
145k
    dim = getAttrib(x, R_DimSymbol);
320
321
145k
    sr = SETCAR (s, int_arraySubscript(0, CAR(s),  dim, x, call));
322
145k
    sc = SETCADR(s, int_arraySubscript(1, CADR(s), dim, x, call));
323
145k
    nrs = LENGTH(sr);
324
145k
    ncs = LENGTH(sc);
325
    /* Check this does not overflow: currently only possible on 32-bit */
326
145k
    if ((double)nrs * (double)ncs > R_XLEN_T_MAX)
327
0
  error(_("dimensions would exceed maximum size of array"));
328
145k
    PROTECT(sr);
329
145k
    PROTECT(sc);
330
145k
    result = allocVector(TYPEOF(x), (R_xlen_t) nrs * (R_xlen_t) ncs);
331
145k
    const int *psr = INTEGER_RO(sr);
332
145k
    const int *psc = INTEGER_RO(sc);
333
145k
    PROTECT(result);
334
145k
    switch(TYPEOF(x)) {
335
0
    case LGLSXP:
336
0
  MATRIX_SUBSET_LOOP(LOGICAL0(result)[ij] = LOGICAL_ELT(x, iijj),
337
0
         LOGICAL0(result)[ij] = NA_LOGICAL);
338
0
  break;
339
0
    case INTSXP:
340
0
  MATRIX_SUBSET_LOOP(INTEGER0(result)[ij] = INTEGER_ELT(x, iijj),
341
0
         INTEGER0(result)[ij] = NA_INTEGER);
342
0
  break;
343
0
    case REALSXP:
344
0
  MATRIX_SUBSET_LOOP(REAL0(result)[ij] = REAL_ELT(x, iijj),
345
0
         REAL0(result)[ij] = NA_REAL);
346
0
  break;
347
0
    case CPLXSXP:
348
0
  {
349
0
      Rcomplex NA_CPLX = { .r = NA_REAL, .i = NA_REAL };
350
0
      MATRIX_SUBSET_LOOP(COMPLEX0(result)[ij] = COMPLEX_ELT(x, iijj),
351
0
             COMPLEX0(result)[ij] = NA_CPLX);
352
0
  }
353
0
  break;
354
145k
    case STRSXP:
355
145k
  MATRIX_SUBSET_LOOP(SET_STRING_ELT(result, ij, STRING_ELT(x, iijj)),
356
145k
         SET_STRING_ELT(result, ij, NA_STRING));
357
145k
  break;
358
0
    case VECSXP:
359
0
    case EXPRSXP:
360
0
  MATRIX_SUBSET_LOOP(SET_VECTOR_ELT(result, ij,
361
0
            VECTOR_ELT_FIX_NAMED(x, iijj)),
362
0
         SET_VECTOR_ELT(result, ij, R_NilValue));
363
0
  break;
364
0
    case RAWSXP:
365
0
  MATRIX_SUBSET_LOOP(RAW0(result)[ij] = RAW_ELT(x, iijj),
366
0
         RAW0(result)[ij] = (Rbyte) 0);
367
0
  break;
368
0
    default:
369
0
  errorcall(call, _("matrix subscripting not handled for this type"));
370
0
  break;
371
145k
    }
372
373
145k
    if(nrs >= 0 && ncs >= 0) {
374
145k
  PROTECT(attr = allocVector(INTSXP, 2));
375
145k
  INTEGER0(attr)[0] = nrs;
376
145k
  INTEGER0(attr)[1] = ncs;
377
145k
  if(!isNull(getAttrib(dim, R_NamesSymbol)))
378
0
      setAttrib(attr, R_NamesSymbol, getAttrib(dim, R_NamesSymbol));
379
145k
  setAttrib(result, R_DimSymbol, attr);
380
145k
  UNPROTECT(1);
381
145k
    }
382
383
    /* The matrix elements have been transferred.  Now we need to */
384
    /* transfer the attributes.  Most importantly, we need to subset */
385
    /* the dimnames of the returned value. */
386
387
145k
    if (nrs >= 0 && ncs >= 0) {
388
145k
  SEXP dimnames, dimnamesnames, newdimnames;
389
145k
  dimnames = getAttrib(x, R_DimNamesSymbol);
390
145k
  PROTECT(dimnamesnames = getAttrib(dimnames, R_NamesSymbol));
391
145k
  if (!isNull(dimnames)) {
392
144k
      PROTECT(newdimnames = allocVector(VECSXP, 2));
393
144k
      if (TYPEOF(dimnames) == VECSXP) {
394
144k
        SET_VECTOR_ELT(newdimnames, 0,
395
144k
        ExtractSubset(VECTOR_ELT(dimnames, 0), sr, call));
396
144k
        SET_VECTOR_ELT(newdimnames, 1,
397
144k
        ExtractSubset(VECTOR_ELT(dimnames, 1), sc, call));
398
144k
      }
399
0
      else {
400
0
        SET_VECTOR_ELT(newdimnames, 0,
401
0
        ExtractSubset(CAR(dimnames), sr, call));
402
0
        SET_VECTOR_ELT(newdimnames, 1,
403
0
        ExtractSubset(CADR(dimnames), sc, call));
404
0
      }
405
144k
      setAttrib(newdimnames, R_NamesSymbol, dimnamesnames);
406
144k
      setAttrib(result, R_DimNamesSymbol, newdimnames);
407
144k
      UNPROTECT(1); /* newdimnames */
408
144k
  }
409
145k
  UNPROTECT(1); /* dimnamesnames */
410
145k
    }
411
    /*  Probably should not do this:
412
    copyMostAttrib(x, result); */
413
145k
    if (drop)
414
144k
  DropDims(result);
415
145k
    UNPROTECT(3);
416
145k
    return result;
417
145k
}
418
419
static R_INLINE R_xlen_t findASubIndex(R_xlen_t k, const int * const *subs,
420
               const int *indx, const int *pxdims,
421
               const R_xlen_t *offset,
422
               SEXP call)
423
0
{
424
0
    R_xlen_t ii = 0;
425
0
    for (int j = 0; j < k; j++) {
426
0
  int jj = subs[j][indx[j]];
427
0
  if (jj == NA_INTEGER)
428
0
      return NA_INTEGER;
429
0
  ii += (jj - 1) * offset[j];
430
0
    }
431
0
    return ii;
432
0
}
433
434
0
#define ARRAY_SUBSET_LOOP(STDCODE, NACODE) do {     \
435
0
  for (R_xlen_t i = 0; i < n; i++) {     \
436
0
      R_xlen_t ii = findASubIndex(k, subs, indx,    \
437
0
          pxdims, offset, call);  \
438
0
      if (ii != NA_INTEGER)       \
439
0
    STDCODE;         \
440
0
      else            \
441
0
    NACODE;           \
442
0
      if (n > 1) {         \
443
0
    int j = 0;          \
444
0
    while (++indx[j] >= bound[j]) {     \
445
0
        indx[j] = 0;        \
446
0
        j = (j + 1) % k;        \
447
0
    }            \
448
0
      }             \
449
0
  }             \
450
0
    } while (0)
451
452
static SEXP ArraySubset(SEXP x, SEXP s, SEXP call, int drop)
453
0
{
454
0
    int k, mode;
455
0
    SEXP dimnames, dimnamesnames, p, q, r, result, xdims;
456
0
    const void *vmaxsave = vmaxget();
457
458
0
    mode = TYPEOF(x);
459
0
    xdims = getAttrib(x, R_DimSymbol);
460
0
    k = length(xdims);
461
0
    const int *pxdims = INTEGER_RO(xdims);
462
463
    /* k is now the number of dims */
464
0
    const int **subs = (const int**)R_alloc(k, sizeof(int*));
465
0
    int *indx = (int*)R_alloc(k, sizeof(int));
466
0
    int *bound = (int*)R_alloc(k, sizeof(int));
467
0
    R_xlen_t *offset = (R_xlen_t*)R_alloc(k, sizeof(R_xlen_t));
468
469
    /* Construct a vector to contain the returned values. */
470
    /* Store its extents. */
471
472
0
    R_xlen_t n = 1;
473
0
    r = s;
474
0
    for (int i = 0; i < k; i++) {
475
0
  SETCAR(r, int_arraySubscript(i, CAR(r), xdims, x, call));
476
0
  bound[i] = LENGTH(CAR(r));
477
0
  n *= bound[i];
478
0
  r = CDR(r);
479
0
    }
480
481
0
    r = s;
482
0
    for (int i = 0; i < k; i++) {
483
0
  indx[i] = 0;
484
0
  subs[i] = INTEGER_RO(CAR(r));
485
0
  r = CDR(r);
486
0
    }
487
0
    offset[0] = 1;
488
0
    for (int i = 1; i < k; i++)
489
0
  offset[i] = offset[i - 1] * pxdims[i - 1];
490
491
    /* range check on indices -- the lower bound check may not be needed */
492
0
    for (int i = 0; i < k; i++)
493
0
  for (int j = 0; j < bound[i]; j++) {
494
0
      int jj = subs[i][j];
495
0
      if (jj > pxdims[i] ||
496
    /* this should not be needed as indices reaching this
497
       point should be positive or NA_INTEGER, which is
498
       negative */
499
0
    (jj < 1 && jj != NA_INTEGER))
500
0
    errorcallOutOfBounds(x, i, jj, call);
501
0
  }
502
503
    /* Transfer the subset elements from "x" to "a". */
504
0
    PROTECT(result = allocVector(mode, n));
505
0
    switch (mode) {
506
0
    case LGLSXP:
507
0
  ARRAY_SUBSET_LOOP(LOGICAL0(result)[i] = LOGICAL_ELT(x, ii),
508
0
        LOGICAL0(result)[i] = NA_LOGICAL);
509
0
  break;
510
0
    case INTSXP:
511
0
  ARRAY_SUBSET_LOOP(INTEGER0(result)[i] = INTEGER_ELT(x, ii),
512
0
        INTEGER0(result)[i] = NA_INTEGER);
513
0
  break;
514
0
    case REALSXP:
515
0
  ARRAY_SUBSET_LOOP(REAL0(result)[i] = REAL_ELT(x, ii),
516
0
        REAL0(result)[i] = NA_REAL);
517
0
  break;
518
0
    case CPLXSXP:
519
0
  {
520
0
      Rcomplex NA_CPLX = { .r = NA_REAL, .i = NA_REAL };
521
0
      ARRAY_SUBSET_LOOP(COMPLEX0(result)[i] = COMPLEX_ELT(x, ii),
522
0
            COMPLEX0(result)[i] = NA_CPLX);
523
0
  }
524
0
  break;
525
0
    case STRSXP:
526
0
  ARRAY_SUBSET_LOOP(SET_STRING_ELT(result, i, STRING_ELT(x, ii)),
527
0
        SET_STRING_ELT(result, i, NA_STRING));
528
0
  break;
529
0
    case VECSXP:
530
0
    case EXPRSXP:
531
0
  ARRAY_SUBSET_LOOP(SET_VECTOR_ELT(result, i,
532
0
           VECTOR_ELT_FIX_NAMED(x, ii)),
533
0
        SET_VECTOR_ELT(result, i, R_NilValue));
534
0
  break;
535
0
    case RAWSXP:
536
0
  ARRAY_SUBSET_LOOP(RAW0(result)[i] = RAW_ELT(x, ii),
537
0
        RAW0(result)[i] = (Rbyte) 0);
538
0
  break;
539
0
    default:
540
0
  errorcall(call, _("array subscripting not handled for this type"));
541
0
  break;
542
0
    }
543
544
0
    SEXP new_dim = PROTECT(allocVector(INTSXP, k));
545
0
    for(int i = 0 ; i < k ; i++)
546
0
  INTEGER0(new_dim)[i] = bound[i];
547
0
    if(!isNull(getAttrib(xdims, R_NamesSymbol)))
548
0
  setAttrib(new_dim, R_NamesSymbol, getAttrib(xdims, R_NamesSymbol));
549
0
    setAttrib(result, R_DimSymbol, new_dim);
550
0
    UNPROTECT(1); // new_dim
551
552
    /* The array elements have been transferred. */
553
    /* Now we need to transfer the attributes. */
554
    /* Most importantly, we need to subset the */
555
    /* dimnames of the returned value. */
556
557
0
    dimnames = getAttrib(x, R_DimNamesSymbol);
558
0
    PROTECT(dimnamesnames = getAttrib(dimnames, R_NamesSymbol));
559
0
    if (dimnames != R_NilValue) {
560
0
  int j = 0;
561
0
  PROTECT(xdims = allocVector(VECSXP, k));
562
0
  if (TYPEOF(dimnames) == VECSXP) {
563
0
      r = s;
564
0
      for (int i = 0; i < k ; i++) {
565
0
    if (bound[i] > 0) {
566
0
      SET_VECTOR_ELT(xdims, j++,
567
0
      ExtractSubset(VECTOR_ELT(dimnames, i), CAR(r), call));
568
0
    } else { /* 0-length dims have NULL dimnames */
569
0
        SET_VECTOR_ELT(xdims, j++, R_NilValue);
570
0
    }
571
0
    r = CDR(r);
572
0
      }
573
0
  }
574
0
  else {
575
0
      p = dimnames;
576
0
      q = xdims;
577
0
      r = s;
578
0
      for(int i = 0 ; i < k; i++) {
579
0
    SETCAR(q, ExtractSubset(CAR(p), CAR(r), call));
580
0
    p = CDR(p);
581
0
    q = CDR(q);
582
0
    r = CDR(r);
583
0
      }
584
0
  }
585
0
  setAttrib(xdims, R_NamesSymbol, dimnamesnames);
586
0
  setAttrib(result, R_DimNamesSymbol, xdims);
587
0
  UNPROTECT(1); /* xdims */
588
0
    }
589
    /* This was removed for matrices in 1998
590
       copyMostAttrib(x, result); */
591
    /* Free temporary memory */
592
0
    vmaxset(vmaxsave);
593
0
    if (drop)
594
0
  DropDims(result);
595
0
    UNPROTECT(2); /* dimnamesnames, result */
596
0
    return result;
597
0
}
598
599
600
/* Returns and removes a named argument from argument list args.
601
   The search ends as soon as a matching argument is found.  If
602
   the argument is not found, the argument list is not modified
603
   and R_NilValue is returned.
604
 */
605
static SEXP ExtractArg(SEXP args, SEXP arg_sym)
606
42.5M
{
607
42.5M
    SEXP arg, prev_arg;
608
42.5M
    int found = 0;
609
610
132M
    for (arg = prev_arg = args; arg != R_NilValue; arg = CDR(arg)) {
611
94.4M
  if(TAG(arg) == arg_sym) {
612
4.63M
      if (arg == prev_arg) /* found at head of args */
613
0
    args = CDR(args);
614
4.63M
      else
615
4.63M
    SETCDR(prev_arg, CDR(arg));
616
4.63M
      found = 1;
617
4.63M
      break;
618
4.63M
  }
619
89.8M
  else  prev_arg = arg;
620
94.4M
    }
621
42.5M
    return found ? CAR(arg) : R_NilValue;
622
42.5M
}
623
624
/* Extracts the drop argument, if present, from the argument list.
625
   The object being subsetted must be the first argument. */
626
static void ExtractDropArg(SEXP el, int *drop)
627
28.3M
{
628
28.3M
    *drop = asLogical(ExtractArg(el, R_DropSymbol));
629
28.3M
    if (*drop == NA_LOGICAL) *drop = 1;
630
28.3M
}
631
632
633
/* Extracts and, if present, removes the 'exact' argument from the
634
   argument list.  An integer code giving the desired exact matching
635
   behavior is returned:
636
       0  not exact
637
       1  exact
638
      -1  not exact, but warn when partial matching is used
639
 */
640
static int ExtractExactArg(SEXP args)
641
14.1M
{
642
14.1M
    SEXP argval = ExtractArg(args, R_ExactSymbol);
643
14.1M
    if(isNull(argval)) return 1; /* Default is true as from R 2.7.0 */
644
4.63M
    int exact = asLogical(argval);
645
4.63M
    if (exact == NA_LOGICAL) exact = -1;
646
4.63M
    return exact;
647
14.1M
}
648
649
/* Version of DispatchOrEval for "[" and friends that speeds up simple cases.
650
   Also defined in subassign.c */
651
static R_INLINE
652
int R_DispatchOrEvalSP(SEXP call, SEXP op, const char *generic, SEXP args,
653
        SEXP rho, SEXP *ans)
654
9.64M
{
655
9.64M
    SEXP prom = NULL;
656
9.64M
    if (args != R_NilValue && CAR(args) != R_DotsSymbol) {
657
9.64M
  SEXP x = eval(CAR(args), rho);
658
9.64M
  PROTECT(x);
659
9.64M
  INCREMENT_LINKS(x);
660
9.64M
  if (! OBJECT(x)) {
661
9.62M
      *ans = CONS_NR(x, evalListKeepMissing(CDR(args), rho));
662
9.62M
      DECREMENT_LINKS(x);
663
9.62M
      UNPROTECT(1);
664
9.62M
      return FALSE;
665
9.62M
  }
666
24.5k
  prom = R_mkEVPROMISE_NR(CAR(args), x);
667
24.5k
  args = CONS(prom, CDR(args));
668
24.5k
  UNPROTECT(1);
669
24.5k
    }
670
24.5k
    PROTECT(args);
671
24.5k
    int disp = DispatchOrEval(call, op, generic, args, rho, ans, 0, 0);
672
24.5k
    if (prom) DECREMENT_LINKS(PRVALUE(prom));
673
24.5k
    UNPROTECT(1);
674
24.5k
    return disp;
675
9.64M
}
676
677
/* The "[" subset operator.
678
 * This provides the most general form of subsetting. */
679
680
attribute_hidden SEXP do_subset(SEXP call, SEXP op, SEXP args, SEXP rho)
681
885k
{
682
885k
    SEXP ans;
683
684
    /* If the first argument is an object and there is an */
685
    /* appropriate method, we dispatch to that method, */
686
    /* otherwise we evaluate the arguments and fall through */
687
    /* to the generic code below.  Note that evaluation */
688
    /* retains any missing argument indicators. */
689
690
    /* DispatchOrEval internal generic: [ */
691
885k
    if(R_DispatchOrEvalSP(call, op, "[", args, rho, &ans)) {
692
/*     if(DispatchAnyOrEval(call, op, "[", args, rho, &ans, 0, 0)) */
693
264
  if (NAMED(ans))
694
0
      ENSURE_NAMEDMAX(ans);
695
264
  return(ans);
696
264
    }
697
698
    /* Method dispatch has failed, we now */
699
    /* run the generic internal code. */
700
885k
    return do_subset_dflt(call, op, ans, rho);
701
885k
}
702
703
static R_INLINE R_xlen_t scalarIndex(SEXP s)
704
11.6M
{
705
11.6M
    if (ATTRIB(s) == R_NilValue) {
706
11.5M
  if (IS_SCALAR(s, INTSXP)) {
707
6.71M
      int ival = SCALAR_IVAL(s);
708
6.71M
      if (ival != NA_INTEGER)
709
6.71M
    return ival;
710
3
      else return -1;
711
6.71M
  }
712
4.84M
  else if (IS_SCALAR(s, REALSXP)) {
713
3.90M
      double rval = SCALAR_DVAL(s);
714
      // treat infinite indices as NA, like asInteger
715
3.90M
      if (R_FINITE(rval))
716
3.89M
    return (R_xlen_t) rval;
717
4.39k
      else return -1;
718
3.90M
  }
719
937k
  else return -1;
720
11.5M
    }
721
61.3k
    else return -1;
722
11.6M
}
723
724
// called from (R `[` => ) do_subset, but also from R .subset() :
725
attribute_hidden SEXP do_subset_dflt(SEXP call, SEXP op, SEXP args, SEXP rho)
726
14.2M
{
727
    /* By default we drop extents of length 1 */
728
729
    /* Handle cases of extracting a single element from a simple vector
730
       or matrix directly to improve speed for these simple cases. */
731
14.2M
    SEXP x = CAR(args);
732
14.2M
    SEXP cdrArgs = CDR(args);
733
14.2M
    SEXP cddrArgs = CDR(cdrArgs);
734
14.2M
    if (cdrArgs != R_NilValue && cddrArgs == R_NilValue &&
735
14.1M
  TAG(cdrArgs) == R_NilValue) {
736
  /* one index, not named */
737
14.1M
  if (ATTRIB(x) == R_NilValue) {
738
11.6M
      SEXP s = CAR(cdrArgs);
739
11.6M
      R_xlen_t i = scalarIndex(s);
740
11.6M
      switch (TYPEOF(x)) {
741
3.00M
      case REALSXP:
742
3.00M
    if (i >= 1 && i <= XLENGTH(x))
743
4.16k
        return ScalarReal( REAL_ELT(x, i-1) );
744
3.00M
    break;
745
3.00M
      case INTSXP:
746
480k
    if (i >= 1 && i <= XLENGTH(x))
747
865
        return ScalarInteger( INTEGER_ELT(x, i-1) );
748
479k
    break;
749
479k
      case LGLSXP:
750
63.1k
    if (i >= 1 && i <= XLENGTH(x))
751
263
        return ScalarLogical( LOGICAL_ELT(x, i-1) );
752
62.8k
    break;
753
//      do the more rare cases as well, since we've already prepared everything:
754
62.8k
      case CPLXSXP:
755
2.32k
    if (i >= 1 && i <= XLENGTH(x))
756
956
        return ScalarComplex( COMPLEX_ELT(x, i-1) );
757
1.36k
    break;
758
1.36k
      case RAWSXP:
759
149
    if (i >= 1 && i <= XLENGTH(x))
760
91
        return ScalarRaw( RAW_ELT(x, i-1) );
761
58
    break;
762
8.06M
      default: break;
763
11.6M
      }
764
11.6M
  }
765
14.1M
    }
766
145k
    else if (cddrArgs != R_NilValue && CDR(cddrArgs) == R_NilValue &&
767
144k
       TAG(cdrArgs) == R_NilValue && TAG(cddrArgs) == R_NilValue) {
768
  /* two indices, not named */
769
144k
  SEXP attr = ATTRIB(x);
770
144k
  if (TAG(attr) == R_DimSymbol && CDR(attr) == R_NilValue) {
771
      /* only attribute of x is 'dim' */
772
758
      SEXP dim = CAR(attr);
773
758
      if (TYPEOF(dim) == INTSXP && LENGTH(dim) == 2) {
774
    /* x is a matrix */
775
758
    SEXP si = CAR(cdrArgs);
776
758
    SEXP sj = CAR(cddrArgs);
777
758
    R_xlen_t i = scalarIndex(si);
778
758
    R_xlen_t j = scalarIndex(sj);
779
758
    int nrow = INTEGER_ELT(dim, 0);
780
758
    int ncol = INTEGER_ELT(dim, 1);
781
758
    if (i > 0 && j > 0 && i <= nrow && j <= ncol) {
782
        /* indices are legal scalars */
783
0
        R_xlen_t k = i - 1 + nrow * (j - 1);
784
0
        switch (TYPEOF(x)) {
785
0
        case REALSXP:
786
0
      if (k < XLENGTH(x))
787
0
          return ScalarReal( REAL_ELT(x, k) );
788
0
      break;
789
0
        case INTSXP:
790
0
      if (k < XLENGTH(x))
791
0
          return ScalarInteger( INTEGER_ELT(x, k) );
792
0
      break;
793
0
        case LGLSXP:
794
0
      if (k < XLENGTH(x))
795
0
          return ScalarLogical( LOGICAL_ELT(x, k) );
796
0
      break;
797
0
        case CPLXSXP:
798
0
      if (k < XLENGTH(x))
799
0
          return ScalarComplex( COMPLEX_ELT(x, k) );
800
0
      break;
801
0
        case RAWSXP:
802
0
      if (k < XLENGTH(x))
803
0
          return ScalarRaw( RAW_ELT(x, k) );
804
0
      break;
805
0
        default: break;
806
0
        }
807
0
    }
808
758
      }
809
758
  }
810
144k
    }
811
812
14.2M
    PROTECT(args);
813
814
14.2M
    int drop = 1;
815
14.2M
    ExtractDropArg(args, &drop);
816
817
    /* This was intended for compatibility with S, */
818
    /* but in fact S does not do this. */
819
    /* FIXME: replace the test by isNull ... ? */
820
821
14.2M
    if (x == R_NilValue) {
822
1.63k
  UNPROTECT(1);
823
1.63k
  return x;
824
1.63k
    }
825
826
14.2M
    SEXP subs = CDR(args);
827
14.2M
    int nsubs = length(subs); /* Will be short */
828
14.2M
    int type = TYPEOF(x);
829
830
    /* Here coerce pair-based objects into generic vectors. */
831
    /* All subsetting takes place on the generic vector form. */
832
833
14.2M
    SEXP ax = x;
834
14.2M
    if (isVector(x))
835
13.6M
  PROTECT(ax);
836
599k
    else if (type == LISTSXP || type == LANGSXP) { // *not* <DOTSXP>[]  :
837
599k
  SEXP dim = getAttrib(x, R_DimSymbol);
838
599k
  int ndim = length(dim);
839
599k
  if (ndim > 1) {
840
0
      PROTECT(ax = allocArray(VECSXP, dim));
841
0
      setAttrib(ax, R_DimNamesSymbol, getAttrib(x, R_DimNamesSymbol));
842
0
      setAttrib(ax, R_NamesSymbol, getAttrib(x, R_DimNamesSymbol));
843
0
  }
844
599k
  else {
845
599k
      PROTECT(ax = allocVector(VECSXP, length(x)));
846
599k
      setAttrib(ax, R_NamesSymbol, getAttrib(x, R_NamesSymbol));
847
599k
  }
848
599k
  SEXP px; int i;
849
2.09M
  for(px = x, i = 0 ; px != R_NilValue ; px = CDR(px))
850
1.49M
      SET_VECTOR_ELT(ax, i++, CAR(px));
851
599k
    }
852
2
    else errorcallNotSubsettable(x, call);
853
854
    /* This is the actual subsetting code. */
855
    /* The separation of arrays and matrices is purely an optimization. */
856
857
14.2M
    SEXP ans;
858
14.2M
    if(nsubs < 2) {
859
14.1M
  SEXP dim = getAttrib(x, R_DimSymbol);
860
14.1M
  int ndim = length(dim);
861
14.1M
  PROTECT(ans = VectorSubset(ax, (nsubs == 1 ? CAR(subs) : R_MissingArg),
862
14.1M
           call));
863
  /* one-dimensional arrays went through here, and they should
864
     have their dimensions dropped only if the result has
865
     length one and drop == TRUE
866
  */
867
14.1M
  if(ndim == 1) {
868
0
      int len = length(ans);
869
0
      if(!drop || len > 1) {
870
    // must grab these before the dim is set.
871
0
    SEXP nm = PROTECT(getAttrib(ans, R_NamesSymbol));
872
0
    SEXP attr = PROTECT(ScalarInteger(length(ans)));
873
0
    if(!isNull(getAttrib(dim, R_NamesSymbol)))
874
0
        setAttrib(attr, R_NamesSymbol, getAttrib(dim, R_NamesSymbol));
875
0
    setAttrib(ans, R_DimSymbol, attr);
876
0
    SEXP attrib;
877
0
    if((attrib = getAttrib(x, R_DimNamesSymbol)) != R_NilValue) {
878
        /* reinstate dimnames, include names of dimnames */
879
0
        SEXP nattrib = PROTECT(duplicate(attrib));
880
0
        SET_VECTOR_ELT(nattrib, 0, nm);
881
0
        setAttrib(ans, R_DimNamesSymbol, nattrib);
882
0
        setAttrib(ans, R_NamesSymbol, R_NilValue);
883
0
        UNPROTECT(1);
884
0
    }
885
0
    UNPROTECT(2);
886
0
      }
887
0
  }
888
14.1M
    } else {
889
145k
  if (nsubs != length(getAttrib(x, R_DimSymbol)))
890
15
      errorcall(call, _("incorrect number of dimensions"));
891
145k
  if (nsubs == 2)
892
145k
      ans = MatrixSubset(ax, subs, call, drop);
893
17
  else
894
17
      ans = ArraySubset(ax, subs, call, drop);
895
145k
  PROTECT(ans);
896
145k
    }
897
898
    /* Note: we do not coerce back to pair-based lists. */
899
    /* They are "defunct" in this version of R. */
900
901
14.2M
    if (type == LANGSXP) {
902
599k
  ax = ans;
903
599k
  PROTECT(ans = allocLang(LENGTH(ax)));
904
599k
  if ( LENGTH(ax) > 0 ) {
905
595k
      SEXP px; int i;
906
1.47M
      for(px = ans, i = 0 ; px != R_NilValue ; px = CDR(px))
907
882k
    SETCAR(px, VECTOR_ELT(ax, i++));
908
595k
      setAttrib(ans, R_DimSymbol,      getAttrib(ax, R_DimSymbol));
909
595k
      setAttrib(ans, R_DimNamesSymbol, getAttrib(ax, R_DimNamesSymbol));
910
595k
      setAttrib(ans, R_NamesSymbol,    getAttrib(ax, R_NamesSymbol));
911
595k
      RAISE_NAMED(ans, NAMED(ax)); /* PR#7924 */
912
595k
  }
913
599k
    }
914
13.6M
    else {
915
13.6M
  PROTECT(ans);
916
13.6M
    }
917
14.2M
    if (ATTRIB(ans) != R_NilValue) { /* remove probably erroneous attr's */
918
168k
  setAttrib(ans, R_TspSymbol, R_NilValue);
919
#ifdef _S4_subsettable
920
  if(!IS_S4_OBJECT(x))
921
#endif
922
168k
      setAttrib(ans, R_ClassSymbol, R_NilValue);
923
168k
    }
924
14.2M
    UNPROTECT(4);
925
14.2M
    return ans;
926
14.2M
}
927
928
929
/* The [[ subset operator.  It needs to be fast. */
930
/* The arguments to this call are evaluated on entry. */
931
932
attribute_hidden SEXP do_subset2(SEXP call, SEXP op, SEXP args, SEXP rho)
933
7.85M
{
934
7.85M
    SEXP ans;
935
936
    /* If the first argument is an object and there is */
937
    /* an appropriate method, we dispatch to that method, */
938
    /* otherwise we evaluate the arguments and fall */
939
    /* through to the generic code below.  Note that */
940
    /* evaluation retains any missing argument indicators. */
941
942
    /* DispatchOrEval internal generic: [[ */
943
7.85M
    if(R_DispatchOrEvalSP(call, op, "[[", args, rho, &ans)) {
944
0
  if (NAMED(ans))
945
0
      ENSURE_NAMEDMAX(ans);
946
0
  return(ans);
947
0
    }
948
949
    /* Method dispatch has failed. */
950
    /* We now run the generic internal code. */
951
952
7.85M
    return do_subset2_dflt(call, op, ans, rho);
953
7.85M
}
954
955
attribute_hidden SEXP do_subset2_dflt(SEXP call, SEXP op, SEXP args, SEXP rho)
956
14.1M
{
957
14.1M
    SEXP ans, dims, dimnames, indx, subs, x;
958
14.1M
    int i, ndims, nsubs;
959
14.1M
    int drop = 1;
960
14.1M
    R_xlen_t offset = 0;
961
962
14.1M
    PROTECT(args);
963
14.1M
    ExtractDropArg(args, &drop);
964
    /* Is partial matching ok?  When the exact arg is NA, a warning is
965
       issued if partial matching occurs.
966
     */
967
14.1M
    int exact = ExtractExactArg(args);
968
14.1M
    int pok = (exact == -1) ? exact : ! exact;
969
970
14.1M
    x = CAR(args);
971
972
    /* Get the subscripting and dimensioning information */
973
    /* and check that any array subscripting is compatible. */
974
975
14.1M
    subs = CDR(args);
976
14.1M
    if(0 == (nsubs = length(subs)))
977
1
  errorcall(call, _("no index specified"));
978
979
    /* This code was intended for compatibility with S, */
980
    /* but in fact S does not do this.  Will anyone notice? */
981
14.1M
    if (x == R_NilValue) {
982
51.1k
  UNPROTECT(1); /* args */
983
51.1k
  if(CAR(subs) == R_MissingArg)
984
1
      errorcallMissingSubs(x, call);
985
  // else
986
51.1k
  return x;
987
51.1k
    }
988
989
14.0M
    dims = getAttrib(x, R_DimSymbol);
990
14.0M
    ndims = length(dims);
991
14.0M
    if(nsubs > 1 && nsubs != ndims)
992
5
  errorcall(call, _("incorrect number of subscripts"));
993
994
    /* code to allow classes to extend environment */
995
14.0M
    if(TYPEOF(x) == OBJSXP) {
996
0
  SEXP xs = x;
997
0
  x = R_getS4DataSlot(x, ANYSXP);
998
0
  if(x == R_NilValue)
999
0
      errorcall(call, _("this %s class is not subsettable"),
1000
0
          IS_S4_OBJECT(xs) ? "S4" : "object");
1001
0
    }
1002
14.0M
    PROTECT(x);
1003
1004
    /* split out ENVSXP for now */
1005
14.0M
    if( TYPEOF(x) == ENVSXP ) {
1006
58.3k
  if( nsubs != 1 || !isString(CAR(subs)) || length(CAR(subs)) != 1 )
1007
0
      errorcall(call, _("wrong arguments for subsetting an environment"));
1008
58.3k
  ans = R_findVarInFrame(x, installTrChar(STRING_ELT(CAR(subs), 0)));
1009
58.3k
  if( TYPEOF(ans) == PROMSXP ) {
1010
9.22k
      PROTECT(ans);
1011
9.22k
      ans = eval(ans, R_GlobalEnv);
1012
9.22k
      UNPROTECT(1); /* ans */
1013
49.1k
  } else ENSURE_NAMEDMAX(ans);
1014
1015
58.3k
  UNPROTECT(2); /* args, x */
1016
58.3k
  if(ans == R_UnboundValue)
1017
17.8k
      return(R_NilValue);
1018
40.5k
  if (NAMED(ans))
1019
40.5k
      ENSURE_NAMEDMAX(ans);
1020
40.5k
  return ans;
1021
58.3k
    }
1022
1023
    /* back to the regular program */
1024
14.0M
    if (!(isVector(x) || isList(x) || isLanguage(x)))
1025
1
  errorcallNotSubsettable(x, call);
1026
1027
#ifndef SWITCH_TO_REFCNT
1028
    int named_x;
1029
    named_x = NAMED(x);  /* x may change below; save this now.  See PR#13411 */
1030
#endif
1031
1032
14.0M
    if(nsubs == 1) { /* vector indexing */
1033
14.0M
  SEXP thesub = CAR(subs);
1034
14.0M
  int len = length(thesub);
1035
1036
14.0M
  if (len > 1) {
1037
11
#ifdef SWITCH_TO_REFCNT
1038
11
      if (IS_GETTER_CALL(call)) {
1039
    /* This is (most likely) a getter call in a complex
1040
       assighment so we duplicate as needed. The original
1041
       x should have been duplicated if it might be
1042
       shared, but might get additional references before
1043
       it arrives here. */
1044
5
    if (MAYBE_SHARED(x)) {
1045
2
        x = shallow_duplicate(x);
1046
2
        UNPROTECT(1); /* old x */
1047
2
        PROTECT(x);
1048
2
    }
1049
5
    x = vectorIndex(x, thesub, 0, len-1, pok, call, TRUE);
1050
5
      }
1051
6
      else
1052
6
    x = vectorIndex(x, thesub, 0, len-1, pok, call, FALSE);
1053
#else
1054
      x = vectorIndex(x, thesub, 0, len-1, pok, call, FALSE);
1055
      named_x = NAMED(x);
1056
#endif
1057
11
      UNPROTECT(1); /* x */
1058
11
      PROTECT(x);
1059
11
  }
1060
1061
14.0M
  SEXP xnames = PROTECT(getAttrib(x, R_NamesSymbol));
1062
14.0M
  offset = get1index(thesub, xnames,
1063
14.0M
         xlength(x), pok, len > 1 ? len-1 : -1, call);
1064
14.0M
  UNPROTECT(1); /* xnames */
1065
14.0M
  if (offset < 0 || offset >= xlength(x)) {
1066
      /* a bold attempt to get the same behaviour for $ and [[ */
1067
50.3k
      if (offset < 0 && (isNewList(x) ||
1068
2
             isExpression(x) ||
1069
2
             isList(x) ||
1070
50.3k
             isLanguage(x))) {
1071
50.3k
    UNPROTECT(2); /* args, x */
1072
50.3k
    return R_NilValue;
1073
50.3k
      }
1074
17
      else errorcallOutOfBoundsSEXP(x, -1, thesub, call);
1075
50.3k
  }
1076
14.0M
    } else { /* nsubs == ndims >= 2 : matrix|array indexing */
1077
  /* Here we use the fact that: */
1078
  /* CAR(R_NilValue) = R_NilValue */
1079
  /* CDR(R_NilValue) = R_NilValue */
1080
1081
7
  int ndn; /* Number of dimnames. Unlikely to be anything but
1082
        0 or nsubs, but just in case... */
1083
1084
7
  PROTECT(indx = allocVector(INTSXP, nsubs));
1085
7
  int *pindx = INTEGER(indx);
1086
7
  const int *pdims = INTEGER_RO(dims);
1087
7
  dimnames = getAttrib(x, R_DimNamesSymbol);
1088
7
  ndn = length(dimnames);
1089
7
  for (i = 0; i < nsubs; i++) {
1090
0
      SEXP thesub = CAR(subs);
1091
0
      pindx[i] = (int)
1092
0
    get1index(thesub,
1093
0
        (i < ndn) ? VECTOR_ELT(dimnames, i) : R_NilValue,
1094
0
        pdims[i], pok, -1, call);
1095
0
      subs = CDR(subs);
1096
0
      if (pindx[i] < 0 || pindx[i] >= pdims[i])
1097
0
    errorcallOutOfBoundsSEXP(x, i, thesub, call);
1098
0
  }
1099
7
  offset = 0;
1100
7
  for (i = (nsubs - 1); i > 0; i--)
1101
0
      offset = (offset + pindx[i]) * pdims[i - 1];
1102
7
  offset += pindx[0];
1103
7
  UNPROTECT(1); /* indx */
1104
7
    }
1105
1106
13.9M
    if(isPairList(x)) {
1107
1.42M
#ifdef LONG_VECTOR_SUPPORT
1108
1.42M
  if (offset > R_SHORT_LEN_MAX)
1109
0
      error("invalid subscript for pairlist");
1110
1.42M
#endif
1111
1.42M
  ans = CAR(nthcdr(x, (int) offset));
1112
#ifndef SWITCH_TO_REFCNT
1113
  RAISE_NAMED(ans, named_x);
1114
#endif
1115
12.5M
    } else if(isVectorList(x)) {
1116
  /* did unconditional duplication before 2.4.0 */
1117
9.38M
  ans = VECTOR_ELT(x, offset);
1118
#ifndef SWITCH_TO_REFCNT
1119
  RAISE_NAMED(ans, named_x);
1120
#endif
1121
9.38M
    } else {
1122
3.15M
  ans = PROTECT(allocVector(TYPEOF(x), 1));
1123
3.15M
  switch (TYPEOF(x)) {
1124
0
  case LGLSXP:
1125
0
      LOGICAL0(ans)[0] = LOGICAL_ELT(x, offset);
1126
0
      break;
1127
2.96M
  case INTSXP:
1128
2.96M
      INTEGER0(ans)[0] = INTEGER_ELT(x, offset);
1129
2.96M
      break;
1130
129k
  case REALSXP:
1131
129k
      REAL0(ans)[0] = REAL_ELT(x, offset);
1132
129k
      break;
1133
3
  case CPLXSXP:
1134
3
      COMPLEX0(ans)[0] = COMPLEX_ELT(x, offset);
1135
3
      break;
1136
67.5k
  case STRSXP:
1137
67.5k
      SET_STRING_ELT(ans, 0, STRING_ELT(x, offset));
1138
67.5k
      break;
1139
0
  case RAWSXP:
1140
0
      RAW0(ans)[0] = RAW_ELT(x, offset);
1141
0
      break;
1142
0
  default:
1143
0
      UNIMPLEMENTED_TYPE("do_subset2", x);
1144
3.15M
  }
1145
3.15M
  UNPROTECT(1); /* ans */
1146
3.15M
    }
1147
13.9M
    UNPROTECT(2); /* args, x */
1148
13.9M
    return ans;
1149
13.9M
}
1150
1151
attribute_hidden SEXP dispatch_subset2(SEXP x, R_xlen_t i, SEXP call, SEXP rho)
1152
1.96M
{
1153
1.96M
    static SEXP bracket_op = NULL;
1154
1.96M
    SEXP args, x_elt;
1155
1.96M
    if (isObject(x)) {
1156
0
        if (bracket_op == NULL)
1157
0
            bracket_op = R_Primitive("[[");
1158
0
        PROTECT(args = list2(x, ScalarReal((double)i + 1)));
1159
0
        x_elt = do_subset2(call, bracket_op, args, rho);
1160
0
        UNPROTECT(1);
1161
1.96M
    } else {
1162
      // FIXME: throw error if not a list
1163
1.96M
        x_elt = VECTOR_ELT(x, i);
1164
1.96M
    }
1165
1.96M
    return(x_elt);
1166
1.96M
}
1167
1168
enum pmatch {
1169
    NO_MATCH,
1170
    EXACT_MATCH,
1171
    PARTIAL_MATCH
1172
};
1173
1174
/* A helper to partially match tags against a candidate.
1175
   Tags are always in the native charset.
1176
 */
1177
/* Returns: */
1178
static
1179
enum pmatch
1180
pstrmatch(SEXP target, SEXP input, size_t slen)
1181
37.0M
{
1182
37.0M
    const char *st = "";
1183
37.0M
    const char *si = "";
1184
37.0M
    const void *vmax = vmaxget();
1185
1186
37.0M
    if(target == R_NilValue)
1187
0
  return NO_MATCH;
1188
1189
37.0M
    switch (TYPEOF(target)) {
1190
6.09k
    case SYMSXP:
1191
6.09k
  st = CHAR(PRINTNAME(target));
1192
6.09k
  break;
1193
37.0M
    case CHARSXP:
1194
37.0M
  st = translateChar(target);
1195
37.0M
  break;
1196
37.0M
    }
1197
37.0M
    si = translateChar(input);
1198
37.0M
    if(si[0] != '\0' && strncmp(st, si, slen) == 0) {
1199
6.18M
  vmaxset(vmax);
1200
6.18M
  return (strlen(st) == slen) ?  EXACT_MATCH : PARTIAL_MATCH;
1201
30.8M
    } else {
1202
30.8M
  vmaxset(vmax);
1203
30.8M
  return NO_MATCH;
1204
30.8M
    }
1205
37.0M
}
1206
1207
attribute_hidden SEXP
1208
fixSubset3Args(SEXP call, SEXP args, SEXP env, SEXP* syminp)
1209
928k
{
1210
928k
    SEXP input, nlist;
1211
1212
    /* first translate CADR of args into a string so that we can
1213
       pass it down to DispatchorEval and have it behave correctly */
1214
1215
928k
    PROTECT(input = allocVector(STRSXP, 1));
1216
928k
    nlist = CADR(args);
1217
928k
    if (TYPEOF(nlist) == PROMSXP)
1218
38
  nlist = eval(nlist, env);
1219
928k
    if(isSymbol(nlist)) {
1220
928k
  if (syminp != NULL)
1221
24.6k
      *syminp = nlist;
1222
928k
  SET_STRING_ELT(input, 0, PRINTNAME(nlist));
1223
928k
    } else if(isString(nlist) ) {
1224
51
  if (LENGTH(nlist) != 1)
1225
0
      error(_("invalid subscript length"));
1226
51
  SET_STRING_ELT(input, 0, STRING_ELT(nlist, 0));
1227
51
    }
1228
1
    else {
1229
1
  errorcall(call,_("invalid subscript type '%s'"),
1230
1
      R_typeToChar(nlist));
1231
1
  return R_NilValue; /*-Wall*/
1232
1
    }
1233
1234
    /* replace the second argument with a string */
1235
1236
    /* Previously this was SETCADR(args, input); */
1237
    /* which could cause problems when nlist was */
1238
    /* ..., as in PR#8718 */
1239
1240
928k
    args = shallow_duplicate(args);
1241
928k
    SETCADR(args, input);
1242
928k
    UNPROTECT(1); /* input */
1243
928k
    return args;
1244
928k
}
1245
1246
/* The $ subset operator.
1247
   We need to be sure to only evaluate the first argument.
1248
   The second will be a symbol that needs to be matched, not evaluated.
1249
*/
1250
attribute_hidden SEXP do_subset3(SEXP call, SEXP op, SEXP args, SEXP env)
1251
904k
{
1252
904k
    SEXP ans;
1253
1254
904k
    checkArity(op, args);
1255
904k
    PROTECT(args = fixSubset3Args(call, args, env, NULL));
1256
1257
    /* If the first argument is an object and there is */
1258
    /* an appropriate method, we dispatch to that method, */
1259
    /* otherwise we evaluate the arguments and fall */
1260
    /* through to the generic code below.  Note that */
1261
    /* evaluation retains any missing argument indicators. */
1262
1263
    /* DispatchOrEval internal generic: $ */
1264
904k
    if(R_DispatchOrEvalSP(call, op, "$", args, env, &ans)) {
1265
0
  UNPROTECT(1); /* args */
1266
0
  if (NAMED(ans))
1267
0
      ENSURE_NAMEDMAX(ans);
1268
0
  return(ans);
1269
0
    }
1270
904k
    PROTECT(ans);
1271
904k
    ans = R_subset3_dflt(CAR(ans), STRING_ELT(CADR(args), 0), call);
1272
904k
    UNPROTECT(2); /* args, ans */
1273
904k
    return ans;
1274
904k
}
1275
1276
/* also used in eval.c */
1277
attribute_hidden SEXP R_subset3_dflt(SEXP x, SEXP input, SEXP call)
1278
7.49M
{
1279
7.49M
    SEXP y;
1280
7.49M
    PROTECT(input);
1281
7.49M
    PROTECT(x);
1282
1283
    /* Optimisation to prevent repeated recalculation */
1284
7.49M
    size_t slen = strlen(translateChar(input));
1285
    /* The mechanism to allow a class extending "environment" */
1286
7.49M
    if( IS_S4_OBJECT(x) && TYPEOF(x) == OBJSXP ){
1287
0
  x = R_getS4DataSlot(x, ANYSXP);
1288
0
  if(x == R_NilValue)
1289
0
      errorcall(call, "$ operator not defined for this S4 class");
1290
1291
0
  UNPROTECT(1); /* x */
1292
0
  PROTECT(x);
1293
0
    }
1294
1295
    // isPairList(x)  but *not* <DOTSXP> :
1296
7.49M
    if (TYPEOF(x) == LISTSXP || TYPEOF(x) == LANGSXP || TYPEOF(x) == NILSXP) {
1297
11.0k
  SEXP xmatch = R_NilValue;
1298
11.0k
  int havematch;
1299
11.0k
  havematch = 0;
1300
15.6k
  for (y = x ; y != R_NilValue ; y = CDR(y)) {
1301
6.09k
      switch(pstrmatch(TAG(y), input, slen)) {
1302
1.52k
      case EXACT_MATCH:
1303
1.52k
    y = CAR(y);
1304
1.52k
    RAISE_NAMED(y, NAMED(x));
1305
1.52k
    UNPROTECT(2); /* input, x */
1306
1.52k
    return y;
1307
0
      case PARTIAL_MATCH:
1308
0
    havematch++;
1309
0
    xmatch = y;
1310
0
#ifdef SWITCH_TO_REFCNT
1311
0
    if (IS_GETTER_CALL(call))
1312
0
        MARK_NOT_MUTABLE(y);
1313
0
#endif
1314
0
    break;
1315
4.57k
      case NO_MATCH:
1316
4.57k
    break;
1317
6.09k
      }
1318
6.09k
  }
1319
9.53k
  if (havematch == 1) { /* unique partial match */
1320
0
      if(R_warn_partial_match_dollar) {
1321
0
    SEXP target = TAG(xmatch);
1322
0
    SEXP cond =
1323
0
        R_makePartialMatchWarningCondition(call,
1324
0
                   input,
1325
0
                   target);
1326
0
    PROTECT(cond);
1327
0
    R_signalWarningCondition(cond);
1328
0
    UNPROTECT(1);
1329
0
      }
1330
0
      y = CAR(xmatch);
1331
0
      RAISE_NAMED(y, NAMED(x));
1332
0
      UNPROTECT(2); /* input, x */
1333
0
      return y;
1334
0
  }
1335
9.53k
  UNPROTECT(2); /* input, x */
1336
9.53k
  return R_NilValue;
1337
9.53k
    }
1338
7.48M
    else if (isVectorList(x)) {
1339
6.27M
  R_xlen_t i, n, imatch = -1;
1340
6.27M
  int havematch;
1341
6.27M
  SEXP nlist = getAttrib(x, R_NamesSymbol);
1342
1343
6.27M
  n = xlength(nlist);
1344
6.27M
  havematch = 0;
1345
37.0M
  for (i = 0 ; i < n ; i = i + 1) {
1346
37.0M
      switch(pstrmatch(STRING_ELT(nlist, i), input, slen)) {
1347
6.18M
      case EXACT_MATCH:
1348
6.18M
    y = VECTOR_ELT(x, i);
1349
6.18M
    RAISE_NAMED(y, NAMED(x));
1350
6.18M
    UNPROTECT(2); /* input, x */
1351
6.18M
    return y;
1352
100
      case PARTIAL_MATCH:
1353
100
    havematch++;
1354
100
    if (havematch == 1) {
1355
        /* partial matches can cause aliasing in eval.c:evalseq
1356
           This is overkill, but alternative ways to prevent
1357
           the aliasing appear to be even worse */
1358
86
        y = VECTOR_ELT(x,i);
1359
86
#ifdef SWITCH_TO_REFCNT
1360
86
        if (IS_GETTER_CALL(call))
1361
55
      MARK_NOT_MUTABLE(y);
1362
#else
1363
        ENSURE_NAMEDMAX(y);
1364
#endif
1365
86
        SET_VECTOR_ELT(x,i,y);
1366
86
    }
1367
100
    imatch = i;
1368
100
    break;
1369
30.8M
      case NO_MATCH:
1370
30.8M
    break;
1371
37.0M
      }
1372
37.0M
  }
1373
84.9k
  if(havematch == 1) { /* unique partial match */
1374
47
      if(R_warn_partial_match_dollar) {
1375
0
    SEXP target = STRING_ELT(nlist, imatch);
1376
0
    SEXP cond =
1377
0
        R_makePartialMatchWarningCondition(call,
1378
0
                   input,
1379
0
                   target);
1380
0
    PROTECT(cond);
1381
0
    R_signalWarningCondition(cond);
1382
0
    UNPROTECT(1);
1383
0
      }
1384
47
      y = VECTOR_ELT(x, imatch);
1385
47
      RAISE_NAMED(y, NAMED(x));
1386
47
      UNPROTECT(2); /* input, x */
1387
47
      return y;
1388
47
  }
1389
84.9k
  UNPROTECT(2); /* input, x */
1390
84.9k
  return R_NilValue;
1391
84.9k
    }
1392
1.21M
    else if( isEnvironment(x) ){
1393
1.21M
  y = R_findVarInFrame(x, installTrChar(input));
1394
1.21M
  if( TYPEOF(y) == PROMSXP ) {
1395
534
      PROTECT(y);
1396
534
      y = eval(y, R_GlobalEnv);
1397
534
      UNPROTECT(1); /* y */
1398
534
  }
1399
1.21M
  UNPROTECT(2); /* input, x */
1400
1.21M
  if( y != R_UnboundValue ) {
1401
1.21M
      if (NAMED(y))
1402
1.21M
    ENSURE_NAMEDMAX(y);
1403
0
      else RAISE_NAMED(y, NAMED(x));
1404
1.21M
      return(y);
1405
1.21M
  }
1406
0
  return R_NilValue;
1407
1.21M
    }
1408
95
    else if( isVectorAtomic(x) ){
1409
91
  errorcall(call, "$ operator is invalid for atomic vectors");
1410
91
    }
1411
4
    else /* e.g. a function */
1412
4
  errorcallNotSubsettable(x, call);
1413
95
    UNPROTECT(2); /* input, x */
1414
95
    return R_NilValue;
1415
7.49M
}