/src/r-source/src/main/list.c
Line | Count | Source |
1 | | /* |
2 | | * R : A Computer Language for Statistical Data Analysis |
3 | | * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka |
4 | | * Copyright (C) 2001, 2006 The R Core Team |
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 | | * |
22 | | * Basic List Handling Features |
23 | | * |
24 | | * These remain here to show that R is truly descended from Lisp :-). |
25 | | * There is one real function "allnames" shich should probably be |
26 | | * elsewhere. |
27 | | */ |
28 | | |
29 | | #ifdef HAVE_CONFIG_H |
30 | | #include <config.h> |
31 | | #endif |
32 | | |
33 | | #include <Defn.h> |
34 | | #include <Internal.h> |
35 | | |
36 | | /* Utility functions moved to Rinlinedfuns.h */ |
37 | | |
38 | | /* The following code is used to recursive traverse a block */ |
39 | | /* of code and extract all the symbols present in that code. */ |
40 | | |
41 | | typedef struct { |
42 | | SEXP ans; |
43 | | int UniqueNames; |
44 | | int IncludeFunctions; |
45 | | int StoreValues; |
46 | | int ItemCounts; |
47 | | int MaxCount; |
48 | | } NameWalkData; |
49 | | |
50 | | static void namewalk(SEXP s, NameWalkData *d) |
51 | 0 | { |
52 | 0 | SEXP name; |
53 | |
|
54 | 0 | switch(TYPEOF(s)) { |
55 | 0 | case SYMSXP: |
56 | 0 | name = PRINTNAME(s); |
57 | | /* skip blank symbols */ |
58 | 0 | if(CHAR(name)[0] == '\0') goto ignore; |
59 | 0 | if(d->ItemCounts < d->MaxCount) { |
60 | 0 | if(d->StoreValues) { |
61 | 0 | if(d->UniqueNames) { |
62 | 0 | for(int j = 0 ; j < d->ItemCounts ; j++) { |
63 | 0 | if(STRING_ELT(d->ans, j) == name) |
64 | 0 | goto ignore; |
65 | 0 | } |
66 | 0 | } |
67 | 0 | SET_STRING_ELT(d->ans, d->ItemCounts, name); |
68 | 0 | } |
69 | 0 | d->ItemCounts++; |
70 | 0 | } |
71 | 0 | ignore: |
72 | 0 | break; |
73 | 0 | case LANGSXP: |
74 | 0 | if(!d->IncludeFunctions) s = CDR(s); |
75 | 0 | while(s != R_NilValue) { |
76 | 0 | namewalk(CAR(s), d); |
77 | 0 | s = CDR(s); |
78 | 0 | } |
79 | 0 | break; |
80 | 0 | case EXPRSXP: |
81 | 0 | for(R_xlen_t i = 0 ; i < XLENGTH(s) ; i++) |
82 | 0 | namewalk(VECTOR_ELT(s, i), d); |
83 | 0 | break; |
84 | 0 | default: |
85 | | /* it seems the intention is to do nothing here! */ |
86 | 0 | break; |
87 | 0 | } |
88 | 0 | } |
89 | | |
90 | | /* Also does all.vars with functions=FALSE |
91 | | .Internal(all.names(expr, functions, max.names, unique)) */ |
92 | | attribute_hidden SEXP do_allnames(SEXP call, SEXP op, SEXP args, SEXP env) |
93 | 0 | { |
94 | 0 | SEXP expr; |
95 | 0 | int i, savecount; |
96 | 0 | NameWalkData data = {NULL, 0, 0, 0, 0, 0}; |
97 | |
|
98 | 0 | checkArity(op, args); |
99 | |
|
100 | 0 | expr = CAR(args); |
101 | 0 | args = CDR(args); |
102 | |
|
103 | 0 | data.IncludeFunctions = asLogical(CAR(args)); |
104 | 0 | if(data.IncludeFunctions == NA_LOGICAL) |
105 | 0 | data.IncludeFunctions = 0; |
106 | 0 | args = CDR(args); |
107 | |
|
108 | 0 | data.MaxCount = asInteger(CAR(args)); |
109 | 0 | if(data.MaxCount == -1) data.MaxCount = INT_MAX; |
110 | 0 | if(data.MaxCount < 0 || data.MaxCount == NA_INTEGER) |
111 | 0 | data.MaxCount = 0; |
112 | 0 | args = CDR(args); |
113 | |
|
114 | 0 | data.UniqueNames = asLogical(CAR(args)); |
115 | 0 | if(data.UniqueNames == NA_LOGICAL) |
116 | 0 | data.UniqueNames = 1; |
117 | |
|
118 | 0 | namewalk(expr, &data); |
119 | 0 | savecount = data.ItemCounts; |
120 | |
|
121 | 0 | data.ans = allocVector(STRSXP, data.ItemCounts); |
122 | |
|
123 | 0 | data.StoreValues = 1; |
124 | 0 | data.ItemCounts = 0; |
125 | 0 | namewalk(expr, &data); |
126 | |
|
127 | 0 | if(data.ItemCounts != savecount) { |
128 | 0 | PROTECT(expr = data.ans); |
129 | 0 | data.ans = allocVector(STRSXP, data.ItemCounts); |
130 | 0 | for(i = 0 ; i < data.ItemCounts ; i++) |
131 | 0 | SET_STRING_ELT(data.ans, i, STRING_ELT(expr, i)); |
132 | 0 | UNPROTECT(1); |
133 | 0 | } |
134 | |
|
135 | 0 | return data.ans; |
136 | 0 | } |