[BusyBox] Today's ash improvements

Vladimir N. Oleynik dzo at simtreas.ru
Sat Aug 4 10:41:03 MDT 2001


Aaron,
 
> This patch contains three distinct size optimizations:
> 
> 1) is_digit() uses only one comparison now. ((c)>='0' && (c)<='9') was
> replaced with ((unsigned)(c) - '0' <= 9). Neat trick, eh?

Such optimization certainly works, under condition of certainly, that we use
one-byte char.
But I do not like such approach.
 
> 2) The 257 byte is_type table was replaced by a few simple tests.
> is_special was changed from ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
> to (is_digit(c)||c=='!'||c=='#'||c=='$'||c=='*'||c=='-').

You have missed two more symbols: '?' and '@'.
But idea your excellent.

> 3) tokendlist was changed from a 30 byte array of booleans (chars) to
> a 30 bit bitmask.

This optimization takes into account, that position and quantity tokens will not
change.
Look my variant. In the sum we receive a prize in 300 bytes without loss of an
opportunity
to correct the tokens table.


--w
vodz
-------------- next part --------------
diff -rbu busybox.orig/ash.c busybox/ash.c
--- busybox.orig/ash.c	Sat Aug  4 19:17:44 2001
+++ busybox/ash.c	Sat Aug  4 19:28:51 2001
@@ -156,18 +156,18 @@
 
 #define TEOF 0
 #define TNL 1
-#define TSEMI 2
-#define TBACKGND 3
-#define TAND 4
-#define TOR 5
-#define TPIPE 6
-#define TLP 7
-#define TRP 8
-#define TENDCASE 9
-#define TENDBQUOTE 10
-#define TREDIR 11
-#define TWORD 12
-#define TASSIGN 13
+#define TREDIR 2
+#define TWORD 3
+#define TASSIGN 4
+#define TSEMI 5
+#define TBACKGND 6
+#define TAND 7
+#define TOR 8
+#define TPIPE 9
+#define TLP 10
+#define TRP 11
+#define TENDCASE 12
+#define TENDBQUOTE 13
 #define TNOT 14
 #define TCASE 15
 #define TDO 16
@@ -206,7 +206,7 @@
 #define is_alpha(c)     (((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))
 #define is_name(c)      (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
 #define is_in_name(c)   (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
-#define is_special(c)   ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
+#define is_special(c)   (is_digit(c)||c=='!'||c=='#'||c=='$'||c=='*'||c=='-'||c=='?'||c=='@')
 #define digit_val(c)    ((c) - '0')
 
 
@@ -973,140 +973,39 @@
       CWORD
 };
 
-/* character classification table */
-static const char is_type[257] = {
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       0,
-      0,       0,       0,       ISSPECL,
-      0,       ISSPECL, ISSPECL, 0,
-      0,       0,       0,       0,
-      ISSPECL, 0,       0,       ISSPECL,
-      0,       0,       ISDIGIT, ISDIGIT,
-      ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
-      ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
-      0,       0,       0,       0,
-      0,       ISSPECL, ISSPECL, ISUPPER,
-      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
-      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
-      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
-      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
-      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
-      ISUPPER, ISUPPER, ISUPPER, ISUPPER,
-      ISUPPER, 0,       0,       0,
-      0,       ISUNDER, 0,       ISLOWER,
-      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
-      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
-      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
-      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
-      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
-      ISLOWER, ISLOWER, ISLOWER, ISLOWER,
-      ISLOWER, 0,       0,       0,
-      0
-};
-
-/* Array indicating which tokens mark the end of a list */
-static const char tokendlist[] = {
-	1,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	1,
-	1,
-	1,
-	0,
-	0,
-	0,
-	0,
-	0,
-	1,
-	1,
-	1,
-	1,
-	1,
-	1,
-	0,
-	0,
-	0,
-	1,
-	0,
-	0,
-	0,
-	1,
-};
-
-static const char *const tokname[] = {
-	"end of file",
-	"newline",
-	"\";\"",
-	"\"&\"",
-	"\"&&\"",
-	"\"||\"",
-	"\"|\"",
-	"\"(\"",
-	"\")\"",
-	"\";;\"",
-	"\"`\"",
-	"redirection",
-	"word",
-	"assignment",
-	"\"!\"",
-	"\"case\"",
-	"\"do\"",
-	"\"done\"",
-	"\"elif\"",
-	"\"else\"",
-	"\"esac\"",
-	"\"fi\"",
-	"\"for\"",
-	"\"if\"",
-	"\"in\"",
-	"\"then\"",
-	"\"until\"",
-	"\"while\"",
-	"\"{\"",
-	"\"}\"",
+/* first char is indicating which tokens mark the end of a list */
+static const char *const tokname_array[] = {
+	"\1end of file",
+	"\0newline",
+	"\0redirection",
+	"\0word",
+	"\0assignment",
+	"\0;",
+	"\0&",
+	"\0&&",
+	"\0||",
+	"\0|",
+	"\0(",
+	"\1)",
+	"\1;;",
+	"\1`",
+	/* next token word see in parsekwd[] */
+	"",
+	"",
+	"\1",
+	"\1",
+	"\1",
+	"\1",
+	"\1",
+	"\1",
+	"",
+	"",
+	"",
+	"\1",
+	"",
+	"",
+	"",
+	"\1",
 };
 
 #define KWDOFFSET 14
@@ -1130,6 +1029,17 @@
 	"}"
 };
 
+static const char *tokname(int tok)
+{
+	static char buf[16];
+
+	if(tok>=TSEMI)
+		buf[0] = '"';
+	sprintf(buf+(tok>=TSEMI), "%s%c",
+		(tok<KWDOFFSET ? tokname_array[tok]+1 : parsekwd[tok-KWDOFFSET]),
+		(tok>=TSEMI ? '"' : 0));
+	return buf;
+}
 
 static int plinno = 1;          /* input line number */
 
@@ -1744,7 +1654,7 @@
 };
 #define NUMBUILTINS  (sizeof (builtincmds) / sizeof (struct builtincmd) )
 
-static const struct builtincmd *DOTCMD = &builtincmds[0];
+#define DOTCMD &builtincmds[0]
 static struct builtincmd *BLTINCMD;
 static struct builtincmd *EXECCMD;
 static struct builtincmd *EVALCMD;
@@ -9346,7 +9256,7 @@
 static union node *simplecmd (void);
 static void parsefname (void);
 static void parseheredoc (void);
-static int peektoken (void);
+static char peektoken (void);
 static int readtoken (void);
 static int xxreadtoken (void);
 static int readtoken1 (int, char const *, char *, int);
@@ -9391,7 +9301,7 @@
 	int tok;
 
 	checkkwd = 2;
-	if (nlflag == 0 && tokendlist[peektoken()])
+	if (nlflag == 0 && peektoken())
 		return NULL;
 	n1 = NULL;
 	for (;;) {
@@ -9434,7 +9344,7 @@
 				tokpushback++;
 			}
 			checkkwd = 2;
-			if (tokendlist[peektoken()])
+			if (peektoken())
 				return n1;
 			break;
 		case TEOF:
@@ -9572,7 +9482,7 @@
 		n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
 		n1->nbinary.ch1 = list(0);
 		if ((got=readtoken()) != TDO) {
-TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
+TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
 			synexpect(TDO);
 		}
 		n1->nbinary.ch2 = list(0);
@@ -9901,13 +9811,13 @@
 	}
 }
 
-static int
+static char
 peektoken() {
 	int t;
 
 	t = readtoken();
 	tokpushback++;
-	return (t);
+	return tokname_array[t][0];
 }
 
 static int
@@ -9955,7 +9865,7 @@
 
 			if ((pp = findkwd(wordtext))) {
 				lasttoken = t = pp - parsekwd + KWDOFFSET;
-				TRACE(("keyword %s recognized\n", tokname[t]));
+				TRACE(("keyword %s recognized\n", tokname(t)));
 				goto out;
 			}
 		}
@@ -9983,9 +9893,9 @@
 out:
 #ifdef DEBUG
 	if (!alreadyseen)
-	    TRACE(("token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
+	    TRACE(("token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
 	else
-	    TRACE(("reread token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
+	    TRACE(("reread token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
 #endif
 	return (t);
 }
@@ -10767,13 +10677,11 @@
 	int token;
 {
 	char msg[64];
+	int l;
 
-	if (token >= 0) {
-		snprintf(msg, 64, "%s unexpected (expecting %s)",
-			tokname[lasttoken], tokname[token]);
-	} else {
-		snprintf(msg, 64, "%s unexpected", tokname[lasttoken]);
-	}
+	l = sprintf(msg, "%s unexpected", tokname(lasttoken));
+	if (token >= 0)
+		sprintf(msg+l, " (expecting %s)", tokname(token));
 	synerror(msg);
 	/* NOTREACHED */
 }


More information about the busybox mailing list