From 47910edf8b613d2626716d6ae3f88b23aa40cf90 Mon Sep 17 00:00:00 2001
From: Greg Price <price@mit.edu>
Date: Wed, 22 Aug 2012 18:14:11 -0400
Subject: [PATCH 1/4] Clarify and explain loaded_feature_path and rb_feature_p

In loaded_feature_path, the earlier, single "type" and "name[plen]"
checks have the same behavior as the old later, repeated checks
because a previous check had guaranteed n == plen.

The early check against vlen == len has no effect on behavior
because we already returned zero in all cases when vlen == len.
(Which is good, because then plen is negative.)
---
 ChangeLog | 10 ++++++++++
 load.c    | 55 ++++++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 52 insertions(+), 13 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 88edf06..4feebfc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Tue Sep  4 14:13:51 2012  Greg Price  <price@mit.edu>
+
+	* load.c (loaded_feature_path): clarify and briefly comment
+	  function.  These clarifications have no effect on the behavior
+	  of the function.
+
+	* load.c (rb_feature_p): explain the search loop.  Especially
+	  useful because the logic is complicated as described in the
+	  second paragraph.
+
 Fri Sep  7 01:21:51 2012  Nobuyoshi Nakada  <nobu@ruby-lang.org>
 
 	* ext/extmk.rb (extmake), lib/mkmf.rb (have_framework): fix splitting
diff --git a/load.c b/load.c
index b0e6f16..4c98dbb 100644
--- a/load.c
+++ b/load.c
@@ -69,6 +69,17 @@ get_loading_table(void)
     return GET_VM()->loading_table;
 }
 
+/* This searches `load_path` for a value such that
+     name == "#{load_path[i]}/#{feature}"
+   if `feature` is a suffix of `name`, or otherwise
+     name == "#{load_path[i]}/#{feature}#{ext}"
+   for an acceptable string `ext`.  It returns
+   `load_path[i].to_str` if found, else 0.
+
+   If type is 's', then `ext` is acceptable only if IS_DLEXT(ext);
+   if 'r', then only if IS_RBEXT(ext); otherwise `ext` may be absent
+   or have any value matching `%r{^\.[^./]*$}`.
+*/
 static VALUE
 loaded_feature_path(const char *name, long vlen, const char *feature, long len,
 		    int type, VALUE load_path)
@@ -77,7 +88,7 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len,
     long plen;
     const char *e;
 
-    if(vlen < len) return 0;
+    if(vlen < len+1) return 0;
     if (!strncmp(name+(vlen-len),feature,len)){
 	plen = vlen - len - 1;
     } else {
@@ -88,23 +99,22 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len,
 	    return 0;
 	plen = e - name - len - 1;
     }
+    if (type == 's' && !IS_DLEXT(&name[plen+len+1])
+     || type == 'r' && !IS_RBEXT(&name[plen+len+1])
+     || name[plen] != '/') {
+	return 0;
+    }
+    /* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable
+       (possibly empty) and prefix is some string of length plen. */
+
     for (i = 0; i < RARRAY_LEN(load_path); ++i) {
 	VALUE p = RARRAY_PTR(load_path)[i];
 	const char *s = StringValuePtr(p);
 	long n = RSTRING_LEN(p);
 
-	if (n != plen ) continue;
-	if (n && (strncmp(name, s, n) || name[n] != '/')) continue;
-	switch (type) {
-	  case 's':
-	    if (IS_DLEXT(&name[n+len+1])) return p;
-	    break;
-	  case 'r':
-	    if (IS_RBEXT(&name[n+len+1])) return p;
-	    break;
-	  default:
-	    return p;
-	}
+	if (n != plen) continue;
+	if (n && strncmp(name, s, n)) continue;
+	return p;
     }
     return 0;
 }
@@ -152,6 +162,25 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c
     }
     features = get_loaded_features();
     for (i = 0; i < RARRAY_LEN(features); ++i) {
+	/* This loop searches `features` for an entry such that either
+	     "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}"
+	   for some j, or
+	     "#{features[i]}" == "#{feature}#{e}"
+	   Here `e` is an "allowed" extension -- either empty or one
+	   of the extensions accepted by IS_RBEXT, IS_SOEXT, or
+	   IS_DLEXT.  Further, if `ext && rb` then `IS_RBEXT(e)`,
+	   and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`.
+
+	   If `expanded`, then only the latter form (without
+	   load_path[j]) is accepted.  Otherwise either form is
+	   accepted, *unless* `ext` is false and an otherwise-matching
+	   entry of the first form is preceded by an entry of the form
+	     "#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}"
+	   where `e2` matches /^\.[^./]*$/ but is not an allowed extension.
+	   After a "distractor" entry of this form, only entries of the
+	   form "#{feature}#{e}" are accepted.
+	*/
+
 	v = RARRAY_PTR(features)[i];
 	f = StringValuePtr(v);
 	if ((n = RSTRING_LEN(v)) < len) continue;
-- 
1.7.11.3

