Ejemplo n.º 1
0
/* parse a decimal number: returns 0 if string isn't a number, 1 otherwise */
int
getn(const char *s, int *ai)
{
	int i, c, rv = 0;
	bool neg = false;

	do {
		c = *s++;
	} while (ksh_isspace(c));
	if (c == '-') {
		neg = true;
		c = *s++;
	} else if (c == '+')
		c = *s++;
	*ai = i = 0;
	do {
		if (!ksh_isdigit(c))
			goto getn_out;
		i *= 10;
		if (i < *ai)
			/* overflow */
			goto getn_out;
		i += c - '0';
		*ai = i;
	} while ((c = *s++));
	rv = 1;

 getn_out:
	if (neg)
		*ai = -*ai;
	return (rv);
}
Ejemplo n.º 2
0
/* parse a decimal number: returns 0 if string isn't a number, 1 otherwise */
int
getn(const char *s, int *ai)
{
	char c;
	mksh_ari_u num;
	bool neg = false;

	num.u = 0;

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

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

	do {
		if (!ksh_isdigit(c))
			/* not numeric */
			return (0);
		if (num.u > 214748364U)
			/* overflow on multiplication */
			return (0);
		num.u = num.u * 10U + (unsigned int)ksh_numdig(c);
		/* now: num.u <= 2147483649U */
	} while ((c = *s++));

	if (num.u > (neg ? 2147483648U : 2147483647U))
		/* overflow for signed 32-bit int */
		return (0);

	if (neg)
		num.u = -num.u;
	*ai = num.i;
	return (1);
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
static char *
formatstr(struct tbl *vp, const char *s)
{
	int olen, nlen;
	char *p, *q;
	size_t psiz;

	olen = (int)utf_mbswidth(s);

	if (vp->flag & (RJUST|LJUST)) {
		if (!vp->u2.field)
			/* default field width */
			vp->u2.field = olen;
		nlen = vp->u2.field;
	} else
		nlen = olen;

	p = alloc((psiz = nlen * /* MB_LEN_MAX */ 3 + 1), ATEMP);
	if (vp->flag & (RJUST|LJUST)) {
		int slen = olen, i = 0;

		if (vp->flag & RJUST) {
			const char *qq = s;
			int n = 0;

			while (i < slen)
				i += utf_widthadj(qq, &qq);
			/* strip trailing spaces (AT&T uses qq[-1] == ' ') */
			while (qq > s && ksh_isspace(qq[-1])) {
				--qq;
				--slen;
			}
			if (vp->flag & ZEROFIL && vp->flag & INTEGER) {
				if (!s[0] || !s[1])
					goto uhm_no;
				if (s[1] == '#')
					n = 2;
				else if (s[2] == '#')
					n = 3;
 uhm_no:
				if (vp->u2.field <= n)
					n = 0;
			}
			if (n) {
				memcpy(p, s, n);
				s += n;
			}
			while (slen > vp->u2.field)
				slen -= utf_widthadj(s, &s);
			if (vp->u2.field - slen)
				memset(p + n, (vp->flag & ZEROFIL) ? '0' : ' ',
				    vp->u2.field - slen);
			slen -= n;
			shf_snprintf(p + vp->u2.field - slen,
			    psiz - (vp->u2.field - slen),
			    "%.*s", slen, s);
		} else {
			/* strip leading spaces/zeros */
			while (ksh_isspace(*s))
				s++;
			if (vp->flag & ZEROFIL)
				while (*s == '0')
					s++;
			shf_snprintf(p, nlen + 1, "%-*.*s",
				vp->u2.field, vp->u2.field, s);
		}
	} else
		memcpy(p, s, strlen(s) + 1);

	if (vp->flag & UCASEV_AL) {
		for (q = p; *q; q++)
			*q = ksh_toupper(*q);
	} else if (vp->flag & LCASEV) {
		for (q = p; *q; q++)
			*q = ksh_tolower(*q);
	}

	return (p);
}
Ejemplo n.º 5
0
static int
getsc_uu(void)
{
	Source *s = source;
	int c;

	while ((c = *s->str++) == 0) {
		/* return 0 for EOF by default */
		s->str = NULL;
		switch (s->type) {
		case SEOF:
			s->str = null;
			return (0);

		case SSTDIN:
		case SFILE:
			getsc_line(s);
			break;

		case SWSTR:
			break;

		case SSTRING:
		case SSTRINGCMDLINE:
			break;

		case SWORDS:
			s->start = s->str = *s->u.strv++;
			s->type = SWORDSEP;
			break;

		case SWORDSEP:
			if (*s->u.strv == NULL) {
				s->start = s->str = "\n";
				s->type = SEOF;
			} else {
				s->start = s->str = " ";
				s->type = SWORDS;
			}
			break;

		case SALIAS:
			if (s->flags & SF_ALIASEND) {
				/* pass on an unused SF_ALIAS flag */
				source = s->next;
				source->flags |= s->flags & SF_ALIAS;
				s = source;
			} else if (*s->u.tblp->val.s &&
			    (c = strnul(s->u.tblp->val.s)[-1], ksh_isspace(c))) {
				/* pop source stack */
				source = s = s->next;
				/*
				 * Note that this alias ended with a
				 * space, enabling alias expansion on
				 * the following word.
				 */
				s->flags |= SF_ALIAS;
			} else {
				/*
				 * At this point, we need to keep the current
				 * alias in the source list so recursive
				 * aliases can be detected and we also need to
				 * return the next character. Do this by
				 * temporarily popping the alias to get the
				 * next character and then put it back in the
				 * source list with the SF_ALIASEND flag set.
				 */
				/* pop source stack */
				source = s->next;
				source->flags |= s->flags & SF_ALIAS;
				c = getsc_uu();
				if (c) {
					s->flags |= SF_ALIASEND;
					s->ugbuf[0] = c; s->ugbuf[1] = '\0';
					s->start = s->str = s->ugbuf;
					s->next = source;
					source = s;
				} else {
					s = source;
					/* avoid reading EOF twice */
					s->str = NULL;
					break;
				}
			}
			continue;

		case SREREAD:
			if (s->start != s->ugbuf)
				/* yuck */
				afree(s->u.freeme, ATEMP);
			source = s = s->next;
			continue;
		}
		if (s->str == NULL) {
			s->type = SEOF;
			s->start = s->str = null;
			return ('\0');
		}
		if (s->flags & SF_ECHO) {
			shf_puts(s->str, shl_out);
			shf_flush(shl_out);
		}
	}
	return (c);
}