about summary refs log tree commit diff
path: root/Src/math.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2004-08-16 09:52:56 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2004-08-16 09:52:56 +0000
commit7d3220f2981c81dbd3cbde873c1bb4d540c92574 (patch)
tree42dc0190ace60c7558619a8a208612c5c4d03376 /Src/math.c
parentb8e6c82fab9d36e463fe32ed5b1a905c795919d5 (diff)
downloadzsh-7d3220f2981c81dbd3cbde873c1bb4d540c92574.tar.gz
zsh-7d3220f2981c81dbd3cbde873c1bb4d540c92574.tar.xz
zsh-7d3220f2981c81dbd3cbde873c1bb4d540c92574.zip
20251: integer conversion truncation
20258: save command status in prompt substitution
update FAQ
rename version to 4.2.1-dev-1
Diffstat (limited to 'Src/math.c')
-rw-r--r--Src/math.c120
1 files changed, 72 insertions, 48 deletions
diff --git a/Src/math.c b/Src/math.c
index eb3a768ec..ce316414e 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -186,6 +186,68 @@ static int type[TOKCOUNT] =
 /* 50 */  LR|OP_OPF, RL|OP_E2, LR|OP_OPF
 };
 
+static int
+lexconstant(void)
+{
+#ifdef USE_LOCALE
+    char *prev_locale;
+#endif
+    char *nptr;
+
+    nptr = ptr;
+    if (*nptr == '-')
+	nptr++;
+
+    if (*nptr == '0')
+    {
+	nptr++;
+	if (*nptr == 'x' || *nptr == 'X') {
+	    /* Let zstrtol parse number with base */
+	    yyval.u.l = zstrtol(ptr, &ptr, 0);
+	    /* Should we set lastbase here? */
+	    lastbase = 16;
+	    return NUM;
+	}
+	else if (isset(OCTALZEROES) &&
+		 (memchr(nptr, '.', strlen(nptr)) == NULL) &&
+		 idigit(*nptr)) {
+	    yyval.u.l = zstrtol(ptr, &ptr, 0);
+	    lastbase = 8;
+	    return NUM;
+	}
+    }
+
+    while (idigit(*nptr))
+	nptr++;
+
+    if (*nptr == '.' || *nptr == 'e' || *nptr == 'E') {
+	/* it's a float */
+	yyval.type = MN_FLOAT;
+#ifdef USE_LOCALE
+	prev_locale = dupstring(setlocale(LC_NUMERIC, NULL));
+	setlocale(LC_NUMERIC, "POSIX");
+#endif
+	yyval.u.d = strtod(ptr, &nptr);
+#ifdef USE_LOCALE
+	if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
+#endif
+	if (ptr == nptr || *nptr == '.') {
+	    zerr("bad floating point constant", NULL, 0);
+	    return EOI;
+	}
+	ptr = nptr;
+    } else {
+	/* it's an integer */
+	yyval.u.l = zstrtol(ptr, &ptr, 10);
+
+	if (*ptr == '#') {
+	    ptr++;
+	    yyval.u.l = zstrtol(ptr, &ptr, lastbase = yyval.u.l);
+	}
+    }
+    return NUM;
+}
+
 /**/
 int outputradix;
 
@@ -193,9 +255,6 @@ int outputradix;
 static int
 zzlex(void)
 {
-#ifdef USE_LOCALE
-    char *prev_locale;
-#endif
     int cct = 0;
     yyval.type = MN_INTEGER;
 
@@ -220,7 +279,14 @@ zzlex(void)
 		ptr++;
 		return MINUSEQ;
 	    }
-	    return (unary) ? UMINUS : MINUS;
+	    if (unary) {
+		if (idigit(*ptr) || *ptr == '.') {
+		    ptr--;
+		    return lexconstant();
+		} else
+		    return UMINUS;
+	    } else
+		return MINUS;
 	case '(':
 	    return M_INPAR;
 	case ')':
@@ -376,52 +442,10 @@ zzlex(void)
 	case '\t':
 	case '\n':
 	    break;
-	case '0':
-	    if (*ptr == 'x' || *ptr == 'X') {
-		ptr++;
-		/* Should we set lastbase here? */
-		yyval.u.l = zstrtol(ptr, &ptr, lastbase = 16);
-		return NUM;
-	    }
-	    else if (isset(OCTALZEROES) &&
-		    (memchr(ptr, '.', strlen(ptr)) == NULL) &&
-		     idigit(*ptr)) {
-	        yyval.u.l = zstrtol(ptr, &ptr, lastbase = 8);
-		return NUM;
-	    }
 	/* Fall through! */
 	default:
-	    if (idigit(*--ptr) || *ptr == '.') {
-		char *nptr;
-		for (nptr = ptr; idigit(*nptr); nptr++);
-
-		if (*nptr == '.' || *nptr == 'e' || *nptr == 'E') {
-		    /* it's a float */
-		    yyval.type = MN_FLOAT;
-#ifdef USE_LOCALE
-		    prev_locale = dupstring(setlocale(LC_NUMERIC, NULL));
-		    setlocale(LC_NUMERIC, "POSIX");
-#endif
-		    yyval.u.d = strtod(ptr, &nptr);
-#ifdef USE_LOCALE
-		    if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
-#endif
-		    if (ptr == nptr || *nptr == '.') {
-			zerr("bad floating point constant", NULL, 0);
-			return EOI;
-		    }
-		    ptr = nptr;
-		} else {
-		    /* it's an integer */
-		    yyval.u.l = zstrtol(ptr, &ptr, 10);
-
-		    if (*ptr == '#') {
-			ptr++;
-			yyval.u.l = zstrtol(ptr, &ptr, lastbase = yyval.u.l);
-		    }
-		}
-		return NUM;
-	    }
+	    if (idigit(*--ptr) || *ptr == '.')
+		return lexconstant();
 	    if (*ptr == '#') {
 		if (*++ptr == '\\' || *ptr == '#') {
 		    int v;