[Python-checkins] CVS: python/dist/src/Python compile.c,2.221,2.222

Tim Peters tim_one@users.sourceforge.net
Fri, 07 Sep 2001 01:45:57 -0700


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

Modified Files:
	compile.c 
Log Message:
SF bug [#458941] Looks like a unary minus bug.
com_factor():  when a unary minus is attached to a float or imaginary zero,
don't optimize the UNARY_MINUS opcode away:  the const dict can't
distinguish between +0.0 and -0.0, so ended up treating both like the
first one added to it.  Optimizing UNARY_PLUS away isn't a problem.

(BTW, I already uploaded the 2.2a3 Windows installer, and this isn't
important enough to delay the release.)


Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.221
retrieving revision 2.222
diff -C2 -d -r2.221 -r2.222
*** compile.c	2001/08/30 18:53:25	2.221
--- compile.c	2001/09/07 08:45:55	2.222
***************
*** 1880,1910 ****
  }
  
  static void
  com_factor(struct compiling *c, node *n)
  {
  	int childtype = TYPE(CHILD(n, 0));
  	REQ(n, factor);
  	/* If the unary +, -, or ~ operator is applied to a constant,
! 	   don't generate a UNARY_xxx opcode. Just store the
  	   approriate value as a constant.  If the value is negative,
  	   extend the string containing the constant and insert a
! 	   negative in the 0th position. 
  	 */
  	if ((childtype == PLUS || childtype == MINUS || childtype == TILDE)
  	    && NCH(n) == 2
! 	    && TYPE(CHILD(n, 1)) == factor
!  	    && NCH(CHILD(n, 1)) == 1
! 	    && TYPE(CHILD(CHILD(n, 1), 0)) == power
!  	    && NCH(CHILD(CHILD(n, 1), 0)) == 1
! 	    && TYPE(CHILD(CHILD(CHILD(n, 1), 0), 0)) == atom
! 	    && TYPE(CHILD(CHILD(CHILD(CHILD(n, 1), 0), 0), 0)) == NUMBER) {
! 		node *constant = CHILD(CHILD(CHILD(n, 1), 0), 0);
  		if (childtype == TILDE) {
! 			com_invert_constant(c, CHILD(constant, 0));
  			return;
  		}
  		if (childtype == MINUS) {
! 			node *numnode = CHILD(constant, 0);
! 			char *s = malloc(strlen(STR(numnode)) + 2);
  			if (s == NULL) {
  				com_error(c, PyExc_MemoryError, "");
--- 1880,1943 ----
  }
  
+ static int
+ is_float_zero(const char *p)
+ {
+ 	int found_radix_point = 0;
+ 	int ch;
+ 	while ((ch = Py_CHARMASK(*p++)) != '\0') {
+ 		switch (ch) {
+ 		case '0':
+ 			/* no reason to believe it's not 0 -- continue */
+ 			break;
+ 
+ 		case 'e': case 'E': case 'j': case 'J':
+ 			/* If this was a hex constant, we already would have
+ 			   returned 0 due to the 'x' or 'X', so 'e' or 'E'
+ 			   must be an exponent marker, and we haven't yet
+ 			   seen a non-zero digit, and it doesn't matter what
+ 			   the exponent is then.  For 'j' or 'J' similarly,
+ 			   except that this is an imaginary 0 then. */
+ 			return 1;
+ 
+ 		case '.':
+ 			found_radix_point = 1;
+ 			break;
+ 
+ 		default:
+ 			return 0;
+ 		}
+ 	}
+ 	return found_radix_point;
+ }
+ 
  static void
  com_factor(struct compiling *c, node *n)
  {
  	int childtype = TYPE(CHILD(n, 0));
+ 	node *pfactor, *ppower, *patom, *pnum;
  	REQ(n, factor);
  	/* If the unary +, -, or ~ operator is applied to a constant,
! 	   don't generate a UNARY_xxx opcode.  Just store the
  	   approriate value as a constant.  If the value is negative,
  	   extend the string containing the constant and insert a
! 	   negative in the 0th position -- unless we're doing unary minus
! 	   of a floating zero!  In that case the sign is significant, but
! 	   the const dict can't distinguish +0.0 from -0.0.
  	 */
  	if ((childtype == PLUS || childtype == MINUS || childtype == TILDE)
  	    && NCH(n) == 2
! 	    && TYPE((pfactor = CHILD(n, 1))) == factor
!  	    && NCH(pfactor) == 1
! 	    && TYPE((ppower = CHILD(pfactor, 0))) == power
!  	    && NCH(ppower) == 1
! 	    && TYPE((patom = CHILD(ppower, 0))) == atom
! 	    && TYPE((pnum = CHILD(patom, 0))) == NUMBER
! 	    && !(childtype == MINUS && is_float_zero(STR(pnum)))) {
  		if (childtype == TILDE) {
! 			com_invert_constant(c, pnum);
  			return;
  		}
  		if (childtype == MINUS) {
! 			char *s = malloc(strlen(STR(pnum)) + 2);
  			if (s == NULL) {
  				com_error(c, PyExc_MemoryError, "");
***************
*** 1913,1921 ****
  			}
  			s[0] = '-';
! 			strcpy(s + 1, STR(numnode));
! 			free(STR(numnode));
! 			STR(numnode) = s;
  		}
! 		com_atom(c, constant);
  	}
  	else if (childtype == PLUS) {
--- 1946,1954 ----
  			}
  			s[0] = '-';
! 			strcpy(s + 1, STR(pnum));
! 			free(STR(pnum));
! 			STR(pnum) = s;
  		}
! 		com_atom(c, patom);
  	}
  	else if (childtype == PLUS) {