[Python-checkins] CVS: python/dist/src/Python import.c,2.162,2.163

Tim Peters tim_one@users.sourceforge.net
Tue, 27 Feb 2001 21:34:29 -0800


Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv27896/python/dist/src/Python

Modified Files:
	import.c 
Log Message:
Implement PEP 235:  Import on Case-Insensitive Platforms.
    http://python.sourceforge.net/peps/pep-0235.html

Renamed check_case to case_ok.  Substantial code rearrangement to get
this stuff in one place in the file.  Innermost loop of find_module()
now much simpler and #ifdef-free, and I want to keep it that way (it's
bad enough that the innermost loop is itself still in an #ifdef!).

Windows semantics tested and are fine.

Jason, Cygwin *should* be fine if and only if what you did before "worked"
for case_ok.

Jack, the semantics on your flavor of Mac have definitely changed (see
the PEP), and need to be tested.  The intent is that your flavor of Mac
now work the same as everything else in the "lower left" box, including
respecting PYTHONCASEOK.

Steven, sorry, you did the most work here so far but you got screwed the
worst.  Happy to work with you on repairing it, but I don't understand
anything about all your Mac variants.  We need to add another branch (or
two, three, ...?) inside case_ok.  But we should not need to change
anything else.


Index: import.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/import.c,v
retrieving revision 2.162
retrieving revision 2.163
diff -C2 -r2.162 -r2.163
*** import.c	2001/02/20 21:43:24	2.162
--- import.c	2001/02/28 05:34:27	2.163
***************
*** 634,638 ****
  				|O_BINARY   /* necessary for Windows */
  #endif
! 		
  			, 0666);
  	if (fd < 0)
--- 634,638 ----
  				|O_BINARY   /* necessary for Windows */
  #endif
! 
  			, 0666);
  	if (fd < 0)
***************
*** 830,841 ****
  					char *, int);
  #endif
- 
- #ifdef CHECK_IMPORT_CASE
- static int check_case(char *, int, int, char *);
- #endif
  
  static int find_init_module(char *); /* Forward */
  
! #ifdef HAVE_DIRENT_H
  
  static int MatchFilename(char *pathname, char *filename);
--- 830,838 ----
  					char *, int);
  #endif
  
+ static int case_ok(char *, int, int, char *);
  static int find_init_module(char *); /* Forward */
  
! #if 0 /* XXX was #ifdef HAVE_DIRENT_H; resolve whether we really need this */
  
  static int MatchFilename(char *pathname, char *filename);
***************
*** 945,953 ****
  #ifdef macintosh
  #ifdef INTERN_STRINGS
! 		/* 
  		** Speedup: each sys.path item is interned, and
  		** FindResourceModule remembers which items refer to
  		** folders (so we don't have to bother trying to look
! 		** into them for resources). 
  		*/
  		PyString_InternInPlace(&PyList_GET_ITEM(path, i));
--- 942,950 ----
  #ifdef macintosh
  #ifdef INTERN_STRINGS
! 		/*
  		** Speedup: each sys.path item is interned, and
  		** FindResourceModule remembers which items refer to
  		** folders (so we don't have to bother trying to look
! 		** into them for resources).
  		*/
  		PyString_InternInPlace(&PyList_GET_ITEM(path, i));
***************
*** 957,961 ****
  			static struct filedescr resfiledescr =
  				{"", "", PY_RESOURCE};
! 			
  			return &resfiledescr;
  		}
--- 954,958 ----
  			static struct filedescr resfiledescr =
  				{"", "", PY_RESOURCE};
! 
  			return &resfiledescr;
  		}
***************
*** 963,967 ****
  			static struct filedescr resfiledescr =
  				{"", "", PY_CODERESOURCE};
! 			
  			return &resfiledescr;
  		}
--- 960,964 ----
  			static struct filedescr resfiledescr =
  				{"", "", PY_CODERESOURCE};
! 
  			return &resfiledescr;
  		}
***************
*** 975,990 ****
  		strcpy(buf+len, name);
  		len += namelen;
  #ifdef HAVE_STAT
! 		if (stat(buf, &statbuf) == 0) {
! 			if (S_ISDIR(statbuf.st_mode)) {
! 				if (find_init_module(buf)) {
! #ifdef CHECK_IMPORT_CASE
! 					if (!check_case(buf, len, namelen,
! 							name))
! 						return NULL;
! #endif
! 					return &fd_package;
! 				}
! 			}
  		}
  #else
--- 972,986 ----
  		strcpy(buf+len, name);
  		len += namelen;
+ 
+ 		/* Check for package import (buf holds a directory name,
+ 		   and there's an __init__ module in that directory */
  #ifdef HAVE_STAT
! 		if (stat(buf, &statbuf) == 0 &&
! 		    S_ISDIR(statbuf.st_mode) &&
! 		    find_init_module(buf)) {
! 			if (case_ok(buf, len, namelen, name))
! 				return &fd_package;
! 			else
! 				return NULL;
  		}
  #else
***************
*** 1001,1025 ****
  				PySys_WriteStderr("# trying %s\n", buf);
  			fp = fopen(buf, fdp->mode);
! #ifdef HAVE_DIRENT_H
! 
! 		        if (fp != NULL) {  /* check case */
! 				char *curpath = PyString_AsString(v);
! 				char *nstart = buf + strlen(curpath);
! 				if (*nstart == SEP)
! 					nstart++; 
! 				if (MatchFilename(curpath, nstart)) {
! 					break;      /* Found */
  				}
- 				fclose(fp); /* No. Close & continue search */
- 				fp = NULL;
- 				if (Py_VerboseFlag > 1)
- 					PySys_WriteStderr(
- 					      "# case mismatch for %s:  %s\n", 
- 					      name, buf);
  			}
- #else  /* !HAVE_DIRENT_H */
- 			if (fp != NULL)
- 				break;
- #endif /* HAVE_DIRENT_H */
  		}
  #endif /* !macintosh */
--- 997,1008 ----
  				PySys_WriteStderr("# trying %s\n", buf);
  			fp = fopen(buf, fdp->mode);
! 			if (fp != NULL) {
! 				if (case_ok(buf, len, namelen, name))
! 					break;
! 				else {	 /* continue search */
! 					fclose(fp);
! 					fp = NULL;
  				}
  			}
  		}
  #endif /* !macintosh */
***************
*** 1032,1084 ****
  		return NULL;
  	}
- #ifdef CHECK_IMPORT_CASE
- 	if (!check_case(buf, len, namelen, name)) {
- 		fclose(fp);
- 		return NULL;
- 	}
- #endif
- 
  	*p_fp = fp;
  	return fdp;
  }
  
! #ifdef CHECK_IMPORT_CASE
! 
  #if defined(MS_WIN32) || defined(__CYGWIN__)
  #include <windows.h>
  #include <ctype.h>
- 
- static int
- allcaps8x3(char *s)
- {
- 	/* Return 1 if s is an 8.3 filename in ALLCAPS */
- 	char c;
- 	char *dot = strchr(s, '.');
- 	char *end = strchr(s, '\0');
- 	if (dot != NULL) {
- 		if (dot-s > 8)
- 			return 0; /* More than 8 before '.' */
- 		if (end-dot > 4)
- 			return 0; /* More than 3 after '.' */
- 		end = strchr(dot+1, '.');
- 		if (end != NULL)
- 			return 0; /* More than one dot  */
- 	}
- 	else if (end-s > 8)
- 		return 0; /* More than 8 and no dot */
- 	while ((c = *s++)) {
- 		if (islower(c))
- 			return 0;
- 	}
- 	return 1;
- }
- 
  #ifdef __CYGWIN__
  #include <sys/cygwin.h>
  #endif
  
  static int
! check_case(char *buf, int len, int namelen, char *name)
  {
  	WIN32_FIND_DATA data;
  	HANDLE h;
--- 1015,1065 ----
  		return NULL;
  	}
  	*p_fp = fp;
  	return fdp;
  }
  
! /* case_ok(buf, len, namelen, name)
!  * We've already done a successful stat() or fopen() on buf (a path of length
!  * len; can not assume there's a trailing null).  name is the last component
!  * of then path (a string of length namelen, exclusive of trailing null).
!  * case_ok() is to return 1 if there's a case-sensitive match for
!  * name, else 0.  case_ok() is also to return 1 if envar PYTHONCASEOK
!  * exists.
!  * case_ok() is used to implement case-sensitive import semantics even
!  * on platforms with case-insensitive filesystems.  It's trivial to implement
!  * for case-sensitive filesystems.  It's pretty much a cross-platform
!  * nightmare for systems with case-insensitive filesystems.
!  */
! 
! /* First we may need a pile of platform-specific header files; the sequence
!  * of #if's here should match the sequence in the body of case_ok().
!  */
  #if defined(MS_WIN32) || defined(__CYGWIN__)
  #include <windows.h>
  #include <ctype.h>
  #ifdef __CYGWIN__
  #include <sys/cygwin.h>
  #endif
  
+ #elif defined(DJGPP)
+ #include <dir.h>
+ 
+ #elif defined(macintosh)
+ #include <TextUtils.h>
+ #ifdef USE_GUSI1
+ #include "TFileSpec.h"		/* for Path2FSSpec() */
+ #endif
+ 
+ #endif
+ 
  static int
! case_ok(char *buf, int len, int namelen, char *name)
  {
+ /* Pick a platform-specific implementation; the sequence of #if's here should
+  * match the sequence just above.
+  */
+ 
+ /* MS_WIN32 || __CYGWIN__ */
+ #if defined(MS_WIN32) || defined(__CYGWIN__)
  	WIN32_FIND_DATA data;
  	HANDLE h;
***************
*** 1086,1091 ****
--- 1067,1074 ----
  	char tempbuf[MAX_PATH];
  #endif
+ 
  	if (getenv("PYTHONCASEOK") != NULL)
  		return 1;
+ 
  #ifdef __CYGWIN__
  	cygwin32_conv_to_win32_path(buf, tempbuf);
***************
*** 1101,1133 ****
  	}
  	FindClose(h);
! 	if (allcaps8x3(data.cFileName)) {
! 		/* Skip the test if the filename is ALL.CAPS.  This can
! 		   happen in certain circumstances beyond our control,
! 		   e.g. when software is installed under NT on a FAT
! 		   filesystem and then the same FAT filesystem is used
! 		   under Windows 95. */
  		return 1;
! 	}
! 	if (strncmp(data.cFileName, name, namelen) != 0) {
! 		strcpy(buf+len-namelen, data.cFileName);
  		PyErr_Format(PyExc_NameError,
! 		  "Case mismatch for module name %.100s\n(filename %.300s)",
  		  name, buf);
  		return 0;
  	}
! 	return 1;
! }
! #endif /* MS_WIN32 */
  
! #ifdef macintosh
! #include <TextUtils.h>
! #ifdef USE_GUSI1
! #include "TFileSpec.h"		/* for Path2FSSpec() */
! #endif
! static int
! check_case(char *buf, int len, int namelen, char *name)
! {
  	FSSpec fss;
  	OSErr err;
  #ifndef USE_GUSI1
  	err = FSMakeFSSpec(0, 0, Pstring(buf), &fss);
--- 1084,1114 ----
  	}
  	FindClose(h);
! 	return strncmp(data.cFileName, name, namelen) == 0;
! 
! /* DJGPP */
! #elif defined(DJGPP)
! 	struct ffblk ffblk;
! 	int done;
! 
! 	if (getenv("PYTHONCASEOK") != NULL)
  		return 1;
! 
! 	done = findfirst(buf, &ffblk, FA_ARCH|FA_RDONLY|FA_HIDDEN|FA_DIREC);
! 	if (done) {
  		PyErr_Format(PyExc_NameError,
! 		  "Can't find file for module %.100s\n(filename %.300s)",
  		  name, buf);
  		return 0;
  	}
! 	return strncmp(ffblk.ff_name, name, namelen) == 0;
  
! /* macintosh */
! #elif defined(macintosh)
  	FSSpec fss;
  	OSErr err;
+ 
+ 	if (getenv("PYTHONCASEOK") != NULL)
+ 		return 1;
+ 
  #ifndef USE_GUSI1
  	err = FSMakeFSSpec(0, 0, Pstring(buf), &fss);
***************
*** 1154,1200 ****
  		     name, buf);
  		return 0;
- 	}
- 	if (namelen > fss.name[0] ||
- 	    strncmp(name, (char *)fss.name+1, namelen) != 0) {
- 		PyErr_Format(PyExc_NameError,
- 		     "Case mismatch for module name %.100s\n(filename %.300s)",
- 		     name, fss.name);
- 		return 0;
  	}
! 	return 1;
! }
! #endif /* macintosh */
! 
! #ifdef DJGPP
! #include <dir.h>
  
! static int
! check_case(char *buf, int len, int namelen, char *name)
! {
! 	struct ffblk ffblk;
! 	int done;
! 
! 	if (getenv("PYTHONCASEOK") != NULL)
! 		return 1;
! 	done = findfirst(buf, &ffblk, FA_ARCH|FA_RDONLY|FA_HIDDEN|FA_DIREC);
! 	if (done) {
! 		PyErr_Format(PyExc_NameError,
! 		  "Can't find file for module %.100s\n(filename %.300s)",
! 		  name, buf);
! 		return 0;
! 	}
! 
! 	if (strncmp(ffblk.ff_name, name, namelen) != 0) {
! 		strcpy(buf+len-namelen, ffblk.ff_name);
! 		PyErr_Format(PyExc_NameError,
! 		  "Case mismatch for module name %.100s\n(filename %.300s)",
! 		  name, buf);
! 		return 0;
! 	}
  	return 1;
! }
  #endif
  
- #endif /* CHECK_IMPORT_CASE */
  
  #ifdef HAVE_STAT
--- 1135,1149 ----
  		     name, buf);
  		return 0;
  	}
! 	return fss.name[0] >= namelen &&
! 	       strncmp(name, (char *)fss.name+1, namelen) == 0;
  
! /* assuming it's a case-sensitive filesystem, so there's nothing to do! */
! #else
  	return 1;
! 
  #endif
+ }
  
  
  #ifdef HAVE_STAT
***************
*** 1755,1759 ****
  	*/
  
! 	if ((m = PyDict_GetItemString(modules, fullname)) != NULL) { 
  		Py_INCREF(m);
  	}
--- 1704,1708 ----
  	*/
  
! 	if ((m = PyDict_GetItemString(modules, fullname)) != NULL) {
  		Py_INCREF(m);
  	}
***************
*** 1930,1934 ****
  	Py_XDECREF(builtins);
  	Py_XDECREF(import);
!  
  	return r;
  }
--- 1879,1883 ----
  	Py_XDECREF(builtins);
  	Py_XDECREF(import);
! 
  	return r;
  }
***************
*** 2007,2011 ****
  		fob = Py_None;
  		Py_INCREF(fob);
! 	}		
  	ret = Py_BuildValue("Os(ssi)",
  		      fob, pathname, fdp->suffix, fdp->mode, fdp->type);
--- 1956,1960 ----
  		fob = Py_None;
  		Py_INCREF(fob);
! 	}
  	ret = Py_BuildValue("Os(ssi)",
  		      fob, pathname, fdp->suffix, fdp->mode, fdp->type);