69 |
69 |
return GET_VM()->loading_table;
|
70 |
70 |
}
|
71 |
71 |
|
|
72 |
/* This searches `load_path` for a value such that
|
|
73 |
name == "#{load_path[i]}/#{feature}"
|
|
74 |
if `feature` is a suffix of `name`, or otherwise
|
|
75 |
name == "#{load_path[i]}/#{feature}#{ext}"
|
|
76 |
for an acceptable string `ext`. It returns
|
|
77 |
`load_path[i].to_str` if found, else 0.
|
|
78 |
|
|
79 |
If type is 's', then `ext` is acceptable only if IS_DLEXT(ext);
|
|
80 |
if 'r', then only if IS_RBEXT(ext); otherwise `ext` may be absent
|
|
81 |
or have any value matching `%r{^\.[^./]*$}`.
|
|
82 |
*/
|
72 |
83 |
static VALUE
|
73 |
84 |
loaded_feature_path(const char *name, long vlen, const char *feature, long len,
|
74 |
85 |
int type, VALUE load_path)
|
... | ... | |
77 |
88 |
long plen;
|
78 |
89 |
const char *e;
|
79 |
90 |
|
80 |
|
if(vlen < len) return 0;
|
|
91 |
if(vlen < len+1) return 0;
|
81 |
92 |
if (!strncmp(name+(vlen-len),feature,len)){
|
82 |
93 |
plen = vlen - len - 1;
|
83 |
94 |
} else {
|
... | ... | |
88 |
99 |
return 0;
|
89 |
100 |
plen = e - name - len - 1;
|
90 |
101 |
}
|
|
102 |
if (type == 's' && !IS_DLEXT(&name[plen+len+1])
|
|
103 |
|| type == 'r' && !IS_RBEXT(&name[plen+len+1])
|
|
104 |
|| name[plen] != '/') {
|
|
105 |
return 0;
|
|
106 |
}
|
|
107 |
/* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable
|
|
108 |
(possibly empty) and prefix is some string of length plen. */
|
|
109 |
|
91 |
110 |
for (i = 0; i < RARRAY_LEN(load_path); ++i) {
|
92 |
111 |
VALUE p = RARRAY_PTR(load_path)[i];
|
93 |
112 |
const char *s = StringValuePtr(p);
|
94 |
113 |
long n = RSTRING_LEN(p);
|
95 |
114 |
|
96 |
|
if (n != plen ) continue;
|
97 |
|
if (n && (strncmp(name, s, n) || name[n] != '/')) continue;
|
98 |
|
switch (type) {
|
99 |
|
case 's':
|
100 |
|
if (IS_DLEXT(&name[n+len+1])) return p;
|
101 |
|
break;
|
102 |
|
case 'r':
|
103 |
|
if (IS_RBEXT(&name[n+len+1])) return p;
|
104 |
|
break;
|
105 |
|
default:
|
106 |
|
return p;
|
107 |
|
}
|
|
115 |
if (n != plen) continue;
|
|
116 |
if (n && strncmp(name, s, n)) continue;
|
|
117 |
return p;
|
108 |
118 |
}
|
109 |
119 |
return 0;
|
110 |
120 |
}
|
... | ... | |
152 |
162 |
}
|
153 |
163 |
features = get_loaded_features();
|
154 |
164 |
for (i = 0; i < RARRAY_LEN(features); ++i) {
|
|
165 |
/* This loop searches `features` for an entry such that either
|
|
166 |
"#{features[i]}" == "#{load_path[j]}/#{feature}#{e}"
|
|
167 |
for some j, or
|
|
168 |
"#{features[i]}" == "#{feature}#{e}"
|
|
169 |
Here `e` is an "allowed" extension -- either empty or one
|
|
170 |
of the extensions accepted by IS_RBEXT, IS_SOEXT, or
|
|
171 |
IS_DLEXT. Further, if `ext && rb` then `IS_RBEXT(e)`,
|
|
172 |
and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`.
|
|
173 |
|
|
174 |
If `expanded`, then only the latter form (without
|
|
175 |
load_path[j]) is accepted. Otherwise either form is
|
|
176 |
accepted, *unless* `ext` is false and an otherwise-matching
|
|
177 |
entry of the first form is preceded by an entry of the form
|
|
178 |
"#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}"
|
|
179 |
where `e2` matches /^\.[^./]*$/ but is not an allowed extension.
|
|
180 |
After a "distractor" entry of this form, only entries of the
|
|
181 |
form "#{feature}#{e}" are accepted.
|
|
182 |
*/
|
|
183 |
|
155 |
184 |
v = RARRAY_PTR(features)[i];
|
156 |
185 |
f = StringValuePtr(v);
|
157 |
186 |
if ((n = RSTRING_LEN(v)) < len) continue;
|
158 |
|
-
|