[BusyBox] Arith in ash

Aaron Lehmann aaronl at vitelus.com
Thu Jun 28 04:09:54 UTC 2001


I noticed this in the new ash.c:


	/* The generated file arith.c has been snipped. 

	....

Arithmetic support is needed for POSIX shell compliance, in
expressions such as $((...)). The other day I rewrote arith_lex.l, the
arith lexer, in C. This saved about 5 kilobytes on i386, since lex
doesn't generate good code. To keep arith support in busybox's ash,
you could use this lexer and port the small yacc grammar to C. This
wouldn't be to hard - it just takes a stack. I may voulenteer to do
it.

Also, command line editing and history is a great feature. Take a look
at hetio.c in a recent Debian version of ash. This code allegedly adds
less than 3k to an i386 binary. Actually, wait a few days before
looking because I have an important patch to hetio.c pending ;-).

Here's the yylex that I ported to C, improved on by Herbert Xu:


int
yylex()
{
	int value;

	for (;; arith_buf++) {
		switch (*arith_buf) {
		case ' ':
		case '\t':
		case '\n':
			continue;
		case 0:
			return 0;
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			yylval = strtol(arith_buf, (char **) &arith_buf, 10);
			return ARITH_NUM;
		case '(':
			value = ARITH_LPAREN;
			break;
		case ')':
			value = ARITH_RPAREN;
			break;
		case '|':
			if (*++arith_buf != '|') {
				return ARITH_BOR;
			}
			value = ARITH_OR;
			break;
		case '&':
			if (*++arith_buf != '&') {
				return ARITH_BAND;
			}
			value = ARITH_AND;
			break;
		case '=':
			if (*++arith_buf != '=') {
				goto err;
			}
			value = ARITH_EQ;
			break;
		case '!':
			if (*++arith_buf != '=') {
				return ARITH_NOT;
			}
			value = ARITH_NE;
			break;
		case '>':
			switch (*++arith_buf) {
			case '=':
				value = ARITH_GE;
				break;
			case '>':
				value = ARITH_RSHIFT;
				break;
			default:
				return ARITH_GT;
			}
			break;
		case '<':
			switch (*++arith_buf) {
			case '=':
				value = ARITH_LE;
				break;
			case '<':
				value = ARITH_LSHIFT;
				break;
			default:
				return ARITH_LT;
			}
			break;
		case '*':
			value = ARITH_MUL;
			break;
		case '/':
			value = ARITH_DIV;
			break;
		case '%':
			value = ARITH_REM;
			break;
		case '+':
			value = ARITH_ADD;
			break;
		case '-':
			value = ARITH_SUB;
			break;
		case '~':
			value = ARITH_BNOT;
			break;
		default:
err:
			error("arith: syntax error: \"%s\"\n", arith_startbuf);
			/* NOTREACHED */
		}
		break;
	}

	arith_buf++;
	return value;
}





More information about the busybox mailing list