aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-12-16 17:20:38 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-12-16 17:20:38 +0000
commit0163111325009ea10979105508bb294d4d67680c (patch)
treeaf0c356024acfde96833b0b9d0c938560139f242
parent9ad2cb3f1a3a8999df1d08422ed7cf01242158a5 (diff)
downloadbusybox-w32-0163111325009ea10979105508bb294d4d67680c.tar.gz
busybox-w32-0163111325009ea10979105508bb294d4d67680c.tar.bz2
busybox-w32-0163111325009ea10979105508bb294d4d67680c.zip
ash: reduce global data/bss usage
(add/remove: 4/29 grow/shrink: 76/21 up/down: 1007/-1713) Total: -706 bytes text data bss dec hex filename 777206 1084 8976 787266 c0342 busybox_old 778077 908 7568 786553 c0079 busybox_unstripped
-rw-r--r--shell/ash.c456
1 files changed, 277 insertions, 179 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 4c8a28911..f7604cf93 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -67,6 +67,13 @@ extern char **environ;
67#endif 67#endif
68 68
69 69
70/* ============ Hash table sizes. Configurable. */
71
72#define VTABSIZE 39
73#define ATABSIZE 39
74#define CMDTABLESIZE 31 /* should be prime */
75
76
70/* ============ Misc helpers */ 77/* ============ Misc helpers */
71 78
72#define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0) 79#define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
@@ -127,30 +134,10 @@ static char optlist[NOPTS] ALIGN1;
127 134
128/* ============ Misc data */ 135/* ============ Misc data */
129 136
130static char nullstr[1] ALIGN1; /* zero length string */
131static const char homestr[] ALIGN1 = "HOME"; 137static const char homestr[] ALIGN1 = "HOME";
132static const char snlfmt[] ALIGN1 = "%s\n"; 138static const char snlfmt[] ALIGN1 = "%s\n";
133static const char illnum[] ALIGN1 = "Illegal number: %s"; 139static const char illnum[] ALIGN1 = "Illegal number: %s";
134 140
135static char *minusc; /* argument to -c option */
136
137/* pid of main shell */
138static int rootpid;
139/* shell level: 0 for the main shell, 1 for its children, and so on */
140static int shlvl;
141#define rootshell (!shlvl)
142/* trap handler commands */
143static char *trap[NSIG];
144static smallint isloginsh;
145/* current value of signal */
146static char sigmode[NSIG - 1];
147/* indicates specified signal received */
148static char gotsig[NSIG - 1];
149static char *arg0; /* value of $0 */
150
151
152/* ============ Interrupts / exceptions */
153
154/* 141/*
155 * We enclose jmp_buf in a structure so that we can declare pointers to 142 * We enclose jmp_buf in a structure so that we can declare pointers to
156 * jump locations. The global variable handler contains the location to 143 * jump locations. The global variable handler contains the location to
@@ -163,34 +150,84 @@ static char *arg0; /* value of $0 */
163struct jmploc { 150struct jmploc {
164 jmp_buf loc; 151 jmp_buf loc;
165}; 152};
166static struct jmploc *exception_handler; 153
167static int exception; 154struct globals_misc {
168/* exceptions */ 155 /* pid of main shell */
156 int rootpid;
157 /* shell level: 0 for the main shell, 1 for its children, and so on */
158 int shlvl;
159#define rootshell (!shlvl)
160 char *minusc; /* argument to -c option */
161
162 char *curdir; // = nullstr; /* current working directory */
163 char *physdir; // = nullstr; /* physical working directory */
164
165 char *arg0; /* value of $0 */
166
167 struct jmploc *exception_handler;
168 int exception;
169 /* exceptions */
169#define EXINT 0 /* SIGINT received */ 170#define EXINT 0 /* SIGINT received */
170#define EXERROR 1 /* a generic error */ 171#define EXERROR 1 /* a generic error */
171#define EXSHELLPROC 2 /* execute a shell procedure */ 172#define EXSHELLPROC 2 /* execute a shell procedure */
172#define EXEXEC 3 /* command execution failed */ 173#define EXEXEC 3 /* command execution failed */
173#define EXEXIT 4 /* exit the shell */ 174#define EXEXIT 4 /* exit the shell */
174#define EXSIG 5 /* trapped signal in wait(1) */ 175#define EXSIG 5 /* trapped signal in wait(1) */
175static volatile int suppressint; 176 volatile int suppressint;
176static volatile sig_atomic_t intpending; 177 volatile sig_atomic_t intpending;
177/* do we generate EXSIG events */ 178 /* do we generate EXSIG events */
178static int exsig; 179 int exsig;
179/* last pending signal */ 180 /* last pending signal */
180static volatile sig_atomic_t pendingsig; 181 volatile sig_atomic_t pendingsig;
181 182
182/* 183 /* trap handler commands */
183 * Sigmode records the current value of the signal handlers for the various 184 char *trap[NSIG];
184 * modes. A value of zero means that the current handler is not known. 185 smallint isloginsh;
185 * S_HARD_IGN indicates that the signal was ignored on entry to the shell, 186 char nullstr[1]; /* zero length string */
186 */ 187 /*
187 188 * Sigmode records the current value of the signal handlers for the various
189 * modes. A value of zero means that the current handler is not known.
190 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
191 */
192 char sigmode[NSIG - 1];
188#define S_DFL 1 /* default signal handling (SIG_DFL) */ 193#define S_DFL 1 /* default signal handling (SIG_DFL) */
189#define S_CATCH 2 /* signal is caught */ 194#define S_CATCH 2 /* signal is caught */
190#define S_IGN 3 /* signal is ignored (SIG_IGN) */ 195#define S_IGN 3 /* signal is ignored (SIG_IGN) */
191#define S_HARD_IGN 4 /* signal is ignored permenantly */ 196#define S_HARD_IGN 4 /* signal is ignored permenantly */
192#define S_RESET 5 /* temporary - to reset a hard ignored sig */ 197#define S_RESET 5 /* temporary - to reset a hard ignored sig */
193 198
199 /* indicates specified signal received */
200 char gotsig[NSIG - 1];
201};
202/* Make it reside in writable memory, yet make compiler understand that it is not going to change. */
203static struct globals_misc *const ptr_to_globals_misc __attribute__ ((section (".data")));
204#define G_misc (*ptr_to_globals_misc)
205#define rootpid (G_misc.rootpid )
206#define shlvl (G_misc.shlvl )
207#define minusc (G_misc.minusc )
208#define curdir (G_misc.curdir )
209#define physdir (G_misc.physdir )
210#define arg0 (G_misc.arg0 )
211#define exception_handler (G_misc.exception_handler)
212#define exception (G_misc.exception )
213#define suppressint (G_misc.suppressint )
214#define intpending (G_misc.intpending )
215#define exsig (G_misc.exsig )
216#define pendingsig (G_misc.pendingsig )
217#define trap (G_misc.trap )
218#define isloginsh (G_misc.isloginsh)
219#define nullstr (G_misc.nullstr )
220#define sigmode (G_misc.sigmode )
221#define gotsig (G_misc.gotsig )
222#define INIT_G_misc() do { \
223 (*(struct globals_misc**)&ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
224 curdir = nullstr; \
225 physdir = nullstr; \
226} while (0)
227
228
229/* ============ Interrupts / exceptions */
230
194/* 231/*
195 * These macros allow the user to suspend the handling of interrupt signals 232 * These macros allow the user to suspend the handling of interrupt signals
196 * over a period of time. This is similar to SIGHOLD to or sigblock, but 233 * over a period of time. This is similar to SIGHOLD to or sigblock, but
@@ -1090,7 +1127,7 @@ enum {
1090 * on many machines. */ 1127 * on many machines. */
1091 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1, 1128 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1092 /* Minimum size of a block */ 1129 /* Minimum size of a block */
1093 MINSIZE = SHELL_ALIGN(504), 1130 MINSIZE = SHELL_ALIGN(504),
1094}; 1131};
1095 1132
1096struct stack_block { 1133struct stack_block {
@@ -1105,16 +1142,38 @@ struct stackmark {
1105 struct stackmark *marknext; 1142 struct stackmark *marknext;
1106}; 1143};
1107 1144
1108static struct stack_block stackbase;
1109static struct stack_block *stackp = &stackbase;
1110static struct stackmark *markp;
1111static char *stacknxt = stackbase.space;
1112static size_t stacknleft = MINSIZE;
1113static char *sstrend = stackbase.space + MINSIZE;
1114static int herefd = -1;
1115 1145
1116#define stackblock() ((void *)stacknxt) 1146struct globals_memstack {
1117#define stackblocksize() stacknleft 1147 struct stack_block *g_stackp; // = &stackbase;
1148 struct stackmark *markp;
1149 char *g_stacknxt; // = stackbase.space;
1150 char *sstrend; // = stackbase.space + MINSIZE;
1151 size_t g_stacknleft; // = MINSIZE;
1152 int herefd; // = -1;
1153 struct stack_block stackbase;
1154};
1155/* Make it reside in writable memory, yet make compiler understand that it is not going to change. */
1156static struct globals_memstack *const ptr_to_globals_memstack __attribute__ ((section (".data")));
1157#define G_memstack (*ptr_to_globals_memstack)
1158#define g_stackp (G_memstack.g_stackp )
1159#define markp (G_memstack.markp )
1160#define g_stacknxt (G_memstack.g_stacknxt )
1161#define sstrend (G_memstack.sstrend )
1162#define g_stacknleft (G_memstack.g_stacknleft)
1163#define herefd (G_memstack.herefd )
1164#define stackbase (G_memstack.stackbase )
1165#define INIT_G_memstack() do { \
1166 (*(struct globals_memstack**)&ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1167 g_stackp = &stackbase; \
1168 g_stacknxt = stackbase.space; \
1169 g_stacknleft = MINSIZE; \
1170 sstrend = stackbase.space + MINSIZE; \
1171 herefd = -1; \
1172} while (0)
1173
1174#define stackblock() ((void *)g_stacknxt)
1175#define stackblocksize() g_stacknleft
1176
1118 1177
1119static void * 1178static void *
1120ckrealloc(void * p, size_t nbytes) 1179ckrealloc(void * p, size_t nbytes)
@@ -1158,7 +1217,7 @@ stalloc(size_t nbytes)
1158 size_t aligned; 1217 size_t aligned;
1159 1218
1160 aligned = SHELL_ALIGN(nbytes); 1219 aligned = SHELL_ALIGN(nbytes);
1161 if (aligned > stacknleft) { 1220 if (aligned > g_stacknleft) {
1162 size_t len; 1221 size_t len;
1163 size_t blocksize; 1222 size_t blocksize;
1164 struct stack_block *sp; 1223 struct stack_block *sp;
@@ -1171,16 +1230,16 @@ stalloc(size_t nbytes)
1171 ash_msg_and_raise_error(bb_msg_memory_exhausted); 1230 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1172 INT_OFF; 1231 INT_OFF;
1173 sp = ckmalloc(len); 1232 sp = ckmalloc(len);
1174 sp->prev = stackp; 1233 sp->prev = g_stackp;
1175 stacknxt = sp->space; 1234 g_stacknxt = sp->space;
1176 stacknleft = blocksize; 1235 g_stacknleft = blocksize;
1177 sstrend = stacknxt + blocksize; 1236 sstrend = g_stacknxt + blocksize;
1178 stackp = sp; 1237 g_stackp = sp;
1179 INT_ON; 1238 INT_ON;
1180 } 1239 }
1181 p = stacknxt; 1240 p = g_stacknxt;
1182 stacknxt += aligned; 1241 g_stacknxt += aligned;
1183 stacknleft -= aligned; 1242 g_stacknleft -= aligned;
1184 return p; 1243 return p;
1185} 1244}
1186 1245
@@ -1188,13 +1247,13 @@ static void
1188stunalloc(void *p) 1247stunalloc(void *p)
1189{ 1248{
1190#if DEBUG 1249#if DEBUG
1191 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) { 1250 if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1192 write(2, "stunalloc\n", 10); 1251 write(2, "stunalloc\n", 10);
1193 abort(); 1252 abort();
1194 } 1253 }
1195#endif 1254#endif
1196 stacknleft += stacknxt - (char *)p; 1255 g_stacknleft += g_stacknxt - (char *)p;
1197 stacknxt = p; 1256 g_stacknxt = p;
1198} 1257}
1199 1258
1200/* 1259/*
@@ -1210,9 +1269,9 @@ ststrdup(const char *p)
1210static void 1269static void
1211setstackmark(struct stackmark *mark) 1270setstackmark(struct stackmark *mark)
1212{ 1271{
1213 mark->stackp = stackp; 1272 mark->stackp = g_stackp;
1214 mark->stacknxt = stacknxt; 1273 mark->stacknxt = g_stacknxt;
1215 mark->stacknleft = stacknleft; 1274 mark->stacknleft = g_stacknleft;
1216 mark->marknext = markp; 1275 mark->marknext = markp;
1217 markp = mark; 1276 markp = mark;
1218} 1277}
@@ -1227,13 +1286,13 @@ popstackmark(struct stackmark *mark)
1227 1286
1228 INT_OFF; 1287 INT_OFF;
1229 markp = mark->marknext; 1288 markp = mark->marknext;
1230 while (stackp != mark->stackp) { 1289 while (g_stackp != mark->stackp) {
1231 sp = stackp; 1290 sp = g_stackp;
1232 stackp = sp->prev; 1291 g_stackp = sp->prev;
1233 free(sp); 1292 free(sp);
1234 } 1293 }
1235 stacknxt = mark->stacknxt; 1294 g_stacknxt = mark->stacknxt;
1236 stacknleft = mark->stacknleft; 1295 g_stacknleft = mark->stacknleft;
1237 sstrend = mark->stacknxt + mark->stacknleft; 1296 sstrend = mark->stacknxt + mark->stacknleft;
1238 INT_ON; 1297 INT_ON;
1239} 1298}
@@ -1252,13 +1311,13 @@ growstackblock(void)
1252{ 1311{
1253 size_t newlen; 1312 size_t newlen;
1254 1313
1255 newlen = stacknleft * 2; 1314 newlen = g_stacknleft * 2;
1256 if (newlen < stacknleft) 1315 if (newlen < g_stacknleft)
1257 ash_msg_and_raise_error(bb_msg_memory_exhausted); 1316 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1258 if (newlen < 128) 1317 if (newlen < 128)
1259 newlen += 128; 1318 newlen += 128;
1260 1319
1261 if (stacknxt == stackp->space && stackp != &stackbase) { 1320 if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1262 struct stack_block *oldstackp; 1321 struct stack_block *oldstackp;
1263 struct stackmark *xmark; 1322 struct stackmark *xmark;
1264 struct stack_block *sp; 1323 struct stack_block *sp;
@@ -1266,15 +1325,15 @@ growstackblock(void)
1266 size_t grosslen; 1325 size_t grosslen;
1267 1326
1268 INT_OFF; 1327 INT_OFF;
1269 oldstackp = stackp; 1328 oldstackp = g_stackp;
1270 sp = stackp; 1329 sp = g_stackp;
1271 prevstackp = sp->prev; 1330 prevstackp = sp->prev;
1272 grosslen = newlen + sizeof(struct stack_block) - MINSIZE; 1331 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1273 sp = ckrealloc(sp, grosslen); 1332 sp = ckrealloc(sp, grosslen);
1274 sp->prev = prevstackp; 1333 sp->prev = prevstackp;
1275 stackp = sp; 1334 g_stackp = sp;
1276 stacknxt = sp->space; 1335 g_stacknxt = sp->space;
1277 stacknleft = newlen; 1336 g_stacknleft = newlen;
1278 sstrend = sp->space + newlen; 1337 sstrend = sp->space + newlen;
1279 1338
1280 /* 1339 /*
@@ -1283,20 +1342,20 @@ growstackblock(void)
1283 */ 1342 */
1284 xmark = markp; 1343 xmark = markp;
1285 while (xmark != NULL && xmark->stackp == oldstackp) { 1344 while (xmark != NULL && xmark->stackp == oldstackp) {
1286 xmark->stackp = stackp; 1345 xmark->stackp = g_stackp;
1287 xmark->stacknxt = stacknxt; 1346 xmark->stacknxt = g_stacknxt;
1288 xmark->stacknleft = stacknleft; 1347 xmark->stacknleft = g_stacknleft;
1289 xmark = xmark->marknext; 1348 xmark = xmark->marknext;
1290 } 1349 }
1291 INT_ON; 1350 INT_ON;
1292 } else { 1351 } else {
1293 char *oldspace = stacknxt; 1352 char *oldspace = g_stacknxt;
1294 int oldlen = stacknleft; 1353 int oldlen = g_stacknleft;
1295 char *p = stalloc(newlen); 1354 char *p = stalloc(newlen);
1296 1355
1297 /* free the space we just allocated */ 1356 /* free the space we just allocated */
1298 stacknxt = memcpy(p, oldspace, oldlen); 1357 g_stacknxt = memcpy(p, oldspace, oldlen);
1299 stacknleft += newlen; 1358 g_stacknleft += newlen;
1300 } 1359 }
1301} 1360}
1302 1361
@@ -1304,8 +1363,8 @@ static void
1304grabstackblock(size_t len) 1363grabstackblock(size_t len)
1305{ 1364{
1306 len = SHELL_ALIGN(len); 1365 len = SHELL_ALIGN(len);
1307 stacknxt += len; 1366 g_stacknxt += len;
1308 stacknleft -= len; 1367 g_stacknleft -= len;
1309} 1368}
1310 1369
1311/* 1370/*
@@ -1343,7 +1402,7 @@ growstackstr(void)
1343static char * 1402static char *
1344makestrspace(size_t newlen, char *p) 1403makestrspace(size_t newlen, char *p)
1345{ 1404{
1346 size_t len = p - stacknxt; 1405 size_t len = p - g_stacknxt;
1347 size_t size = stackblocksize(); 1406 size_t size = stackblocksize();
1348 1407
1349 for (;;) { 1408 for (;;) {
@@ -1568,41 +1627,26 @@ static unsigned long rseed;
1568 1627
1569/* ============ Shell variables */ 1628/* ============ Shell variables */
1570 1629
1571/* flags */ 1630/*
1572#define VEXPORT 0x01 /* variable is exported */ 1631 * The parsefile structure pointed to by the global variable parsefile
1573#define VREADONLY 0x02 /* variable cannot be modified */ 1632 * contains information about the current file being read.
1574#define VSTRFIXED 0x04 /* variable struct is statically allocated */ 1633 */
1575#define VTEXTFIXED 0x08 /* text is statically allocated */ 1634struct redirtab {
1576#define VSTACK 0x10 /* text is allocated on the stack */ 1635 struct redirtab *next;
1577#define VUNSET 0x20 /* the variable is not set */ 1636 int renamed[10];
1578#define VNOFUNC 0x40 /* don't call the callback function */ 1637 int nullredirs;
1579#define VNOSET 0x80 /* do not set variable - just readonly test */ 1638};
1580#define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1581#ifdef DYNAMIC_VAR
1582# define VDYNAMIC 0x200 /* dynamic variable */
1583#else
1584# define VDYNAMIC 0
1585#endif
1586
1587#ifdef IFS_BROKEN
1588static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1589#define defifs (defifsvar + 4)
1590#else
1591static const char defifs[] ALIGN1 = " \t\n";
1592#endif
1593 1639
1594struct shparam { 1640struct shparam {
1595 int nparam; /* # of positional parameters (without $0) */ 1641 int nparam; /* # of positional parameters (without $0) */
1596 unsigned char malloc; /* if parameter list dynamically allocated */
1597 char **p; /* parameter list */
1598#if ENABLE_ASH_GETOPTS 1642#if ENABLE_ASH_GETOPTS
1599 int optind; /* next parameter to be processed by getopts */ 1643 int optind; /* next parameter to be processed by getopts */
1600 int optoff; /* used by getopts */ 1644 int optoff; /* used by getopts */
1601#endif 1645#endif
1646 unsigned char malloced; /* if parameter list dynamically allocated */
1647 char **p; /* parameter list */
1602}; 1648};
1603 1649
1604static struct shparam shellparam; /* $@ current positional parameters */
1605
1606/* 1650/*
1607 * Free the list of positional parameters. 1651 * Free the list of positional parameters.
1608 */ 1652 */
@@ -1611,7 +1655,7 @@ freeparam(volatile struct shparam *param)
1611{ 1655{
1612 char **ap; 1656 char **ap;
1613 1657
1614 if (param->malloc) { 1658 if (param->malloced) {
1615 for (ap = param->p; *ap; ap++) 1659 for (ap = param->p; *ap; ap++)
1616 free(*ap); 1660 free(*ap);
1617 free(param->p); 1661 free(param->p);
@@ -1619,12 +1663,7 @@ freeparam(volatile struct shparam *param)
1619} 1663}
1620 1664
1621#if ENABLE_ASH_GETOPTS 1665#if ENABLE_ASH_GETOPTS
1622static void 1666static void getoptsreset(const char *value);
1623getoptsreset(const char *value)
1624{
1625 shellparam.optind = number(value);
1626 shellparam.optoff = -1;
1627}
1628#endif 1667#endif
1629 1668
1630struct var { 1669struct var {
@@ -1642,7 +1681,31 @@ struct localvar {
1642 const char *text; /* saved text */ 1681 const char *text; /* saved text */
1643}; 1682};
1644 1683
1645/* Forward decls for varinit[] */ 1684/* flags */
1685#define VEXPORT 0x01 /* variable is exported */
1686#define VREADONLY 0x02 /* variable cannot be modified */
1687#define VSTRFIXED 0x04 /* variable struct is statically allocated */
1688#define VTEXTFIXED 0x08 /* text is statically allocated */
1689#define VSTACK 0x10 /* text is allocated on the stack */
1690#define VUNSET 0x20 /* the variable is not set */
1691#define VNOFUNC 0x40 /* don't call the callback function */
1692#define VNOSET 0x80 /* do not set variable - just readonly test */
1693#define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1694#ifdef DYNAMIC_VAR
1695# define VDYNAMIC 0x200 /* dynamic variable */
1696#else
1697# define VDYNAMIC 0
1698#endif
1699
1700#ifdef IFS_BROKEN
1701static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1702#define defifs (defifsvar + 4)
1703#else
1704static const char defifs[] ALIGN1 = " \t\n";
1705#endif
1706
1707
1708/* Need to be before varinit_data[] */
1646#if ENABLE_LOCALE_SUPPORT 1709#if ENABLE_LOCALE_SUPPORT
1647static void 1710static void
1648change_lc_all(const char *value) 1711change_lc_all(const char *value)
@@ -1666,46 +1729,78 @@ static void changepath(const char *);
1666static void change_random(const char *); 1729static void change_random(const char *);
1667#endif 1730#endif
1668 1731
1669static struct var varinit[] = { 1732static const struct {
1733 int flags;
1734 const char *text;
1735 void (*func)(const char *);
1736} varinit_data[] = {
1670#ifdef IFS_BROKEN 1737#ifdef IFS_BROKEN
1671 { NULL, VSTRFIXED|VTEXTFIXED, defifsvar, NULL }, 1738 { VSTRFIXED|VTEXTFIXED , defifsvar , NULL },
1672#else 1739#else
1673 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", NULL }, 1740 { VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0" , NULL },
1674#endif 1741#endif
1675#if ENABLE_ASH_MAIL 1742#if ENABLE_ASH_MAIL
1676 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail }, 1743 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0" , changemail },
1677 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail }, 1744 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1678#endif 1745#endif
1679 { NULL, VSTRFIXED|VTEXTFIXED, bb_PATH_root_path, changepath }, 1746 { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath },
1680 { NULL, VSTRFIXED|VTEXTFIXED, "PS1=$ ", NULL }, 1747 { VSTRFIXED|VTEXTFIXED , "PS1=$ " , NULL },
1681 { NULL, VSTRFIXED|VTEXTFIXED, "PS2=> ", NULL }, 1748 { VSTRFIXED|VTEXTFIXED , "PS2=> " , NULL },
1682 { NULL, VSTRFIXED|VTEXTFIXED, "PS4=+ ", NULL }, 1749 { VSTRFIXED|VTEXTFIXED , "PS4=+ " , NULL },
1683#if ENABLE_ASH_GETOPTS 1750#if ENABLE_ASH_GETOPTS
1684 { NULL, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset }, 1751 { VSTRFIXED|VTEXTFIXED , "OPTIND=1" , getoptsreset },
1685#endif 1752#endif
1686#if ENABLE_ASH_RANDOM_SUPPORT 1753#if ENABLE_ASH_RANDOM_SUPPORT
1687 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random }, 1754 { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1688#endif 1755#endif
1689#if ENABLE_LOCALE_SUPPORT 1756#if ENABLE_LOCALE_SUPPORT
1690 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all }, 1757 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL\0" , change_lc_all },
1691 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype }, 1758 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE\0", change_lc_ctype },
1692#endif 1759#endif
1693#if ENABLE_FEATURE_EDITING_SAVEHISTORY 1760#if ENABLE_FEATURE_EDITING_SAVEHISTORY
1694 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL }, 1761 { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE\0", NULL },
1695#endif 1762#endif
1696}; 1763};
1697 1764
1698#define vifs varinit[0] 1765
1766struct globals_var {
1767 struct shparam shellparam; /* $@ current positional parameters */
1768 struct redirtab *redirlist;
1769 int g_nullredirs;
1770 int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1771 struct var *vartab[VTABSIZE];
1772 struct var varinit[ARRAY_SIZE(varinit_data)];
1773};
1774/* Make it reside in writable memory, yet make compiler understand that it is not going to change. */
1775static struct globals_var *const ptr_to_globals_var __attribute__ ((section (".data")));
1776#define G_var (*ptr_to_globals_var)
1777#define shellparam (G_var.shellparam )
1778#define redirlist (G_var.redirlist )
1779#define g_nullredirs (G_var.g_nullredirs )
1780#define preverrout_fd (G_var.preverrout_fd)
1781#define vartab (G_var.vartab )
1782#define varinit (G_var.varinit )
1783#define INIT_G_var() do { \
1784 int i; \
1785 (*(struct globals_var**)&ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1786 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1787 varinit[i].flags = varinit_data[i].flags; \
1788 varinit[i].text = varinit_data[i].text; \
1789 varinit[i].func = varinit_data[i].func; \
1790 } \
1791} while (0)
1792
1793#define vifs varinit[0]
1699#if ENABLE_ASH_MAIL 1794#if ENABLE_ASH_MAIL
1700#define vmail (&vifs)[1] 1795#define vmail (&vifs)[1]
1701#define vmpath (&vmail)[1] 1796#define vmpath (&vmail)[1]
1702#else 1797#else
1703#define vmpath vifs 1798#define vmpath vifs
1704#endif 1799#endif
1705#define vpath (&vmpath)[1] 1800#define vpath (&vmpath)[1]
1706#define vps1 (&vpath)[1] 1801#define vps1 (&vpath)[1]
1707#define vps2 (&vps1)[1] 1802#define vps2 (&vps1)[1]
1708#define vps4 (&vps2)[1] 1803#define vps4 (&vps2)[1]
1709#define voptind (&vps4)[1] 1804#define voptind (&vps4)[1]
1710#if ENABLE_ASH_GETOPTS 1805#if ENABLE_ASH_GETOPTS
1711#define vrandom (&voptind)[1] 1806#define vrandom (&voptind)[1]
@@ -1730,27 +1825,19 @@ static struct var varinit[] = {
1730 1825
1731#define mpathset() ((vmpath.flags & VUNSET) == 0) 1826#define mpathset() ((vmpath.flags & VUNSET) == 0)
1732 1827
1733/*
1734 * The parsefile structure pointed to by the global variable parsefile
1735 * contains information about the current file being read.
1736 */
1737struct redirtab {
1738 struct redirtab *next;
1739 int renamed[10];
1740 int nullredirs;
1741};
1742
1743static struct redirtab *redirlist;
1744static int nullredirs;
1745static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1746
1747#define VTABSIZE 39
1748
1749static struct var *vartab[VTABSIZE];
1750 1828
1751#define is_name(c) ((c) == '_' || isalpha((unsigned char)(c))) 1829#define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1752#define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c))) 1830#define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1753 1831
1832#if ENABLE_ASH_GETOPTS
1833static void
1834getoptsreset(const char *value)
1835{
1836 shellparam.optind = number(value);
1837 shellparam.optoff = -1;
1838}
1839#endif
1840
1754/* 1841/*
1755 * Return of a legal variable name (a letter or underscore followed by zero or 1842 * Return of a legal variable name (a letter or underscore followed by zero or
1756 * more letters, underscores, and digits). 1843 * more letters, underscores, and digits).
@@ -2221,9 +2308,6 @@ setprompt(int whichprompt)
2221 2308
2222static int docd(const char *, int); 2309static int docd(const char *, int);
2223 2310
2224static char *curdir = nullstr; /* current working directory */
2225static char *physdir = nullstr; /* physical working directory */
2226
2227static int 2311static int
2228cdopt(void) 2312cdopt(void)
2229{ 2313{
@@ -2310,7 +2394,7 @@ updatepwd(const char *dir)
2310static char * 2394static char *
2311getpwd(void) 2395getpwd(void)
2312{ 2396{
2313 char *dir = getcwd(0, 0); 2397 char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2314 return dir ? dir : nullstr; 2398 return dir ? dir : nullstr;
2315} 2399}
2316 2400
@@ -2903,8 +2987,6 @@ static const char syntax_index_table[258] = {
2903#define ALIASINUSE 1 2987#define ALIASINUSE 1
2904#define ALIASDEAD 2 2988#define ALIASDEAD 2
2905 2989
2906#define ATABSIZE 39
2907
2908struct alias { 2990struct alias {
2909 struct alias *next; 2991 struct alias *next;
2910 char *name; 2992 char *name;
@@ -2912,7 +2994,12 @@ struct alias {
2912 int flag; 2994 int flag;
2913}; 2995};
2914 2996
2915static struct alias *atab[ATABSIZE]; 2997
2998static struct alias **atab; // [ATABSIZE];
2999#define INIT_G_alias() do { \
3000 atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3001} while (0)
3002
2916 3003
2917static struct alias ** 3004static struct alias **
2918__lookupalias(const char *name) { 3005__lookupalias(const char *name) {
@@ -4797,7 +4884,7 @@ redirect(union node *redir, int flags)
4797 int fd; 4884 int fd;
4798 int newfd; 4885 int newfd;
4799 4886
4800 nullredirs++; 4887 g_nullredirs++;
4801 if (!redir) { 4888 if (!redir) {
4802 return; 4889 return;
4803 } 4890 }
@@ -4807,10 +4894,10 @@ redirect(union node *redir, int flags)
4807 sv = ckmalloc(sizeof(*sv)); 4894 sv = ckmalloc(sizeof(*sv));
4808 sv->next = redirlist; 4895 sv->next = redirlist;
4809 redirlist = sv; 4896 redirlist = sv;
4810 sv->nullredirs = nullredirs - 1; 4897 sv->nullredirs = g_nullredirs - 1;
4811 for (i = 0; i < 10; i++) 4898 for (i = 0; i < 10; i++)
4812 sv->renamed[i] = EMPTY; 4899 sv->renamed[i] = EMPTY;
4813 nullredirs = 0; 4900 g_nullredirs = 0;
4814 } 4901 }
4815 n = redir; 4902 n = redir;
4816 do { 4903 do {
@@ -4861,7 +4948,7 @@ popredir(int drop)
4861 struct redirtab *rp; 4948 struct redirtab *rp;
4862 int i; 4949 int i;
4863 4950
4864 if (--nullredirs >= 0) 4951 if (--g_nullredirs >= 0)
4865 return; 4952 return;
4866 INT_OFF; 4953 INT_OFF;
4867 rp = redirlist; 4954 rp = redirlist;
@@ -4880,7 +4967,7 @@ popredir(int drop)
4880 } 4967 }
4881 } 4968 }
4882 redirlist = rp->next; 4969 redirlist = rp->next;
4883 nullredirs = rp->nullredirs; 4970 g_nullredirs = rp->nullredirs;
4884 free(rp); 4971 free(rp);
4885 INT_ON; 4972 INT_ON;
4886} 4973}
@@ -4896,7 +4983,7 @@ static void
4896clearredir(int drop) 4983clearredir(int drop)
4897{ 4984{
4898 for (;;) { 4985 for (;;) {
4899 nullredirs = 0; 4986 g_nullredirs = 0;
4900 if (!redirlist) 4987 if (!redirlist)
4901 break; 4988 break;
4902 popredir(drop); 4989 popredir(drop);
@@ -6458,7 +6545,6 @@ static void find_command(char *, struct cmdentry *, int, const char *);
6458 * would make the command name "hash" a misnomer. 6545 * would make the command name "hash" a misnomer.
6459 */ 6546 */
6460 6547
6461#define CMDTABLESIZE 31 /* should be prime */
6462#define ARB 1 /* actual size determined at run time */ 6548#define ARB 1 /* actual size determined at run time */
6463 6549
6464struct tblentry { 6550struct tblentry {
@@ -6469,8 +6555,13 @@ struct tblentry {
6469 char cmdname[ARB]; /* name of command */ 6555 char cmdname[ARB]; /* name of command */
6470}; 6556};
6471 6557
6472static struct tblentry *cmdtable[CMDTABLESIZE]; 6558static struct tblentry **cmdtable;
6473static int builtinloc = -1; /* index in path of %builtin, or -1 */ 6559#define INIT_G_cmdtable() do { \
6560 cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
6561} while (0)
6562
6563static int builtinloc = -1; /* index in path of %builtin, or -1 */
6564
6474 6565
6475static void 6566static void
6476tryexec(char *cmd, char **argv, char **envp) 6567tryexec(char *cmd, char **argv, char **envp)
@@ -7840,7 +7931,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
7840 savehandler = exception_handler; 7931 savehandler = exception_handler;
7841 exception_handler = &jmploc; 7932 exception_handler = &jmploc;
7842 localvars = NULL; 7933 localvars = NULL;
7843 shellparam.malloc = 0; 7934 shellparam.malloced = 0;
7844 func->count++; 7935 func->count++;
7845 funcnest++; 7936 funcnest++;
7846 INT_ON; 7937 INT_ON;
@@ -7851,7 +7942,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
7851 shellparam.optoff = -1; 7942 shellparam.optoff = -1;
7852#endif 7943#endif
7853 evaltree(&func->n, flags & EV_TESTED); 7944 evaltree(&func->n, flags & EV_TESTED);
7854funcdone: 7945 funcdone:
7855 INT_OFF; 7946 INT_OFF;
7856 funcnest--; 7947 funcnest--;
7857 freefunc(func); 7948 freefunc(func);
@@ -8979,7 +9070,7 @@ setparam(char **argv)
8979 } 9070 }
8980 *ap = NULL; 9071 *ap = NULL;
8981 freeparam(&shellparam); 9072 freeparam(&shellparam);
8982 shellparam.malloc = 1; 9073 shellparam.malloced = 1;
8983 shellparam.nparam = nparam; 9074 shellparam.nparam = nparam;
8984 shellparam.p = newparam; 9075 shellparam.p = newparam;
8985#if ENABLE_ASH_GETOPTS 9076#if ENABLE_ASH_GETOPTS
@@ -9094,7 +9185,7 @@ shiftcmd(int argc, char **argv)
9094 INT_OFF; 9185 INT_OFF;
9095 shellparam.nparam -= n; 9186 shellparam.nparam -= n;
9096 for (ap1 = shellparam.p; --n >= 0; ap1++) { 9187 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9097 if (shellparam.malloc) 9188 if (shellparam.malloced)
9098 free(*ap1); 9189 free(*ap1);
9099 } 9190 }
9100 ap2 = shellparam.p; 9191 ap2 = shellparam.p;
@@ -10971,7 +11062,7 @@ dotcmd(int argc, char **argv)
10971 11062
10972 if (argc > 2) { 11063 if (argc > 2) {
10973 saveparam = shellparam; 11064 saveparam = shellparam;
10974 shellparam.malloc = 0; 11065 shellparam.malloced = 0;
10975 shellparam.nparam = argc - 2; 11066 shellparam.nparam = argc - 2;
10976 shellparam.p = argv + 2; 11067 shellparam.p = argv + 2;
10977 }; 11068 };
@@ -12741,7 +12832,7 @@ procargs(int argc, char **argv)
12741 shellparam.optind = 1; 12832 shellparam.optind = 1;
12742 shellparam.optoff = -1; 12833 shellparam.optoff = -1;
12743#endif 12834#endif
12744 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */ 12835 /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
12745 while (*xargv) { 12836 while (*xargv) {
12746 shellparam.nparam++; 12837 shellparam.nparam++;
12747 xargv++; 12838 xargv++;
@@ -12805,6 +12896,13 @@ int ash_main(int argc, char **argv)
12805 struct jmploc jmploc; 12896 struct jmploc jmploc;
12806 struct stackmark smark; 12897 struct stackmark smark;
12807 12898
12899 /* Initialize global data */
12900 INIT_G_misc();
12901 INIT_G_memstack();
12902 INIT_G_var();
12903 INIT_G_alias();
12904 INIT_G_cmdtable();
12905
12808#if PROFILE 12906#if PROFILE
12809 monitor(4, etext, profile_buf, sizeof(profile_buf), 50); 12907 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
12810#endif 12908#endif