示例#1
0
文件: var.c 项目: rovaughn/distro
static int
getint(struct tbl *vp, mksh_ari_u *nump, bool arith)
{
	mksh_uari_t c, num = 0, base = 10;
	const char *s;
	bool have_base = false, neg = false;

	if (vp->flag & SPECIAL)
		getspec(vp);
	/* XXX is it possible for ISSET to be set and val.s to be NULL? */
	if (!(vp->flag & ISSET) || (!(vp->flag & INTEGER) && vp->val.s == NULL))
		return (-1);
	if (vp->flag & INTEGER) {
		nump->i = vp->val.i;
		return (vp->type);
	}
	s = vp->val.s + vp->type;

	do {
		c = (unsigned char)*s++;
	} while (ksh_isspace(c));

	switch (c) {
	case '-':
		neg = true;
		/* FALLTHROUGH */
	case '+':
		c = (unsigned char)*s++;
		break;
	}

	if (c == '0' && arith) {
		if (ksh_eq(s[0], 'X', 'x')) {
			/* interpret as hexadecimal */
			base = 16;
			++s;
			goto getint_c_style_base;
		} else if (Flag(FPOSIX) && ksh_isdigit(s[0]) &&
		    !(vp->flag & ZEROFIL)) {
			/* interpret as octal (deprecated) */
			base = 8;
 getint_c_style_base:
			have_base = true;
			c = (unsigned char)*s++;
		}
	}

	do {
		if (c == '#') {
			/* ksh-style base determination */
			if (have_base || num < 1)
				return (-1);
			if ((base = num) == 1) {
				/* mksh-specific extension */
				unsigned int wc;

				if (!UTFMODE)
					wc = *(const unsigned char *)s;
				else if (utf_mbtowc(&wc, s) == (size_t)-1)
					/* OPTU-8 -> OPTU-16 */
					/*
					 * (with a twist: 1#\uEF80 converts
					 * the same as 1#\x80 does, thus is
					 * not round-tripping correctly XXX)
					 */
					wc = 0xEF00 + *(const unsigned char *)s;
				nump->u = (mksh_uari_t)wc;
				return (1);
			} else if (base > 36)
				base = 10;
			num = 0;
			have_base = true;
			continue;
		}
		if (ksh_isdigit(c))
			c = ksh_numdig(c);
		else if (ksh_isupper(c))
			c = ksh_numuc(c) + 10;
		else if (ksh_islower(c))
			c = ksh_numlc(c) + 10;
		else
			return (-1);
		if (c >= base)
			return (-1);
		/* handle overflow as truncation */
		num = num * base + c;
	} while ((c = (unsigned char)*s++));

	if (neg)
		num = -num;
	nump->u = num;
	return (base);
}
示例#2
0
static int
getint(struct tbl *vp, mksh_ari_t *nump, bool arith)
{
	int c, base, neg;
	mksh_uari_t num;
	const char *s;
	bool have_base = false;

	if (vp->flag&SPECIAL)
		getspec(vp);
	/* XXX is it possible for ISSET to be set and val.s to be 0? */
	if (!(vp->flag&ISSET) || (!(vp->flag&INTEGER) && vp->val.s == NULL))
		return (-1);
	if (vp->flag&INTEGER) {
		*nump = vp->val.i;
		return (vp->type);
	}
	s = vp->val.s + vp->type;
	base = 10;
	num = 0;
	neg = 0;
	if (arith && s[0] == '0' && (s[1] | 0x20) == 'x') {
		s += 2;
		base = 16;
		have_base = true;
	}
#ifdef MKSH_LEGACY_MODE
	if (arith && s[0] == '0' && ksh_isdigit(s[1]) &&
	    !(vp->flag & ZEROFIL)) {
		/* interpret as octal (deprecated) */
		base = 8;
		have_base = true;
	}
#endif
	while ((c = *s++)) {
		if (c == '-') {
			neg++;
			continue;
		} else if (c == '#') {
			if (have_base || num < 1 || num > 36)
				return (-1);
			base = (int)num;
			if (base == 1) {
				unsigned int wc;

				if (!UTFMODE)
					wc = *(const unsigned char *)s;
				else if (utf_mbtowc(&wc, s) == (size_t)-1)
					/* OPTU-8 -> OPTU-16 */
					/*
					 * (with a twist: 1#\uEF80 converts
					 * the same as 1#\x80 does, thus is
					 * not round-tripping correctly XXX)
					 */
					wc = 0xEF00 + *(const unsigned char *)s;
				*nump = (mksh_ari_t)wc;
				return (1);
			}
			num = 0;
			have_base = true;
			continue;
		} else if (ksh_isdigit(c))
			c -= '0';
		else if (ksh_islower(c))
			c -= 'a' - 10;
		else if (ksh_isupper(c))
			c -= 'A' - 10;
		else
			return (-1);
		if (c < 0 || c >= base)
			return (-1);
		num = num * base + c;
	}
	*nump = neg ? -((mksh_ari_t)num) : (mksh_ari_t)num;
	return (base);
}