ash: move ash_main() and helpers to end of ash.c, more fuctions renamed,
superfluous casts from memory allocators removed
diff --git a/shell/ash.c b/shell/ash.c
index 532dad1..e262c0e 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -141,6 +141,7 @@
 
 /* ============ Misc data */
 
+static int isloginsh;
 /* pid of main shell */
 static int rootpid;
 /* shell level: 0 for the main shell, 1 for its children, and so on */
@@ -779,8 +780,6 @@
 
 /*      shell.h   */
 
-typedef void *pointer;
-
 static char nullstr[1];                /* zero length string */
 static const char spcstr[] = " ";
 static const char snlfmt[] = "%s\n";
@@ -1356,7 +1355,7 @@
 
 static int     funcblocksize;          /* size of structures in function */
 static int     funcstringsize;         /* size of strings in node */
-static pointer funcblock;              /* block to allocate function from */
+static void   *funcblock;              /* block to allocate function from */
 static char   *funcstring;             /* block to allocate strings from */
 
 static const short nodesize[26] = {
@@ -1853,45 +1852,6 @@
 	} while (++vp < end);
 }
 
-static void init(void)
-{
-
-	/* from input.c: */
-	{
-		basepf.nextc = basepf.buf = basebuf;
-	}
-
-	/* from trap.c: */
-	{
-		signal(SIGCHLD, SIG_DFL);
-	}
-
-	/* from var.c: */
-	{
-		char **envp;
-		char ppid[32];
-		const char *p;
-		struct stat st1, st2;
-
-		initvar();
-		for (envp = environ; envp && *envp; envp++) {
-			if (strchr(*envp, '=')) {
-				setvareq(*envp, VEXPORT|VTEXTFIXED);
-			}
-		}
-
-		snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
-		setvar("PPID", ppid, 0);
-
-		p = lookupvar("PWD");
-		if (p)
-			if (*p != '/' || stat(p, &st1) || stat(".", &st2)
-			 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
-				p = 0;
-		setpwd(p, 0);
-	}
-}
-
 /* PEOF (the end of file marker) */
 
 enum {
@@ -1989,8 +1949,7 @@
 
 
 static void readcmdfile(char *);
-static int cmdloop(int);
-
+ 
 /*      memalloc.h        */
 
 
@@ -2018,11 +1977,11 @@
 static int herefd = -1;
 
 
-static pointer ckmalloc(size_t);
-static pointer ckrealloc(pointer, size_t);
+static void *ckmalloc(size_t);
+static void *ckrealloc(void *, size_t);
 static char *savestr(const char *);
-static pointer stalloc(size_t);
-static void stunalloc(pointer);
+static void *stalloc(size_t);
+static void stunalloc(void *);
 static void setstackmark(struct stackmark *);
 static void popstackmark(struct stackmark *);
 static void growstackblock(void);
@@ -2098,7 +2057,6 @@
 static char *minusc;                   /* argument to -c option */
 
 
-static void procargs(int, char **);
 static void optschanged(void);
 static void setparam(char **);
 static void freeparam(volatile struct shparam *);
@@ -2187,27 +2145,19 @@
 reset(void)
 {
 	/* from eval.c: */
-	{
-		evalskip = 0;
-		loopnest = 0;
-	}
+	evalskip = 0;
+	loopnest = 0;
 
 	/* from input.c: */
-	{
-		parselleft = parsenleft = 0;      /* clear input buffer */
-		popallfiles();
-	}
+	parselleft = parsenleft = 0;      /* clear input buffer */
+	popallfiles();
 
 	/* from parser.c: */
-	{
-		tokpushback = 0;
-		checkkwd = 0;
-	}
+	tokpushback = 0;
+	checkkwd = 0;
 
 	/* from redir.c: */
-	{
-		clearredir(0);
-	}
+	clearredir(0);
 }
 
 #if ENABLE_ASH_ALIAS
@@ -4578,7 +4528,7 @@
 	} else {
 		if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
 			rmescapes(p);
-		sp = (struct strlist *)stalloc(sizeof(struct strlist));
+		sp = stalloc(sizeof(*sp));
 		sp->text = p;
 		*exparg.lastp = sp;
 		exparg.lastp = &sp->next;
@@ -5386,7 +5336,7 @@
 		ifsp = &ifsfirst;
 	} else {
 		INT_OFF;
-		ifsp = (struct ifsregion *)ckmalloc(sizeof(struct ifsregion));
+		ifsp = ckmalloc(sizeof(*ifsp));
 		ifsp->next = NULL;
 		ifslastp->next = ifsp;
 		INT_ON;
@@ -5440,7 +5390,7 @@
 						continue;
 					}
 					*q = '\0';
-					sp = (struct strlist *)stalloc(sizeof(*sp));
+					sp = stalloc(sizeof(*sp));
 					sp->text = start;
 					*arglist->lastp = sp;
 					arglist->lastp = &sp->next;
@@ -5481,7 +5431,7 @@
 		return;
 
  add:
-	sp = (struct strlist *)stalloc(sizeof(*sp));
+	sp = stalloc(sizeof(*sp));
 	sp->text = start;
 	*arglist->lastp = sp;
 	arglist->lastp = &sp->next;
@@ -5571,7 +5521,7 @@
 {
 	struct strlist *sp;
 
-	sp = (struct strlist *)stalloc(sizeof(*sp));
+	sp = stalloc(sizeof(*sp));
 	sp->text = sstrdup(name);
 	*exparg.lastp = sp;
 	exparg.lastp = &sp->next;
@@ -6288,7 +6238,7 @@
 	parsefile->lleft = parselleft;
 	parsefile->nextc = parsenextc;
 	parsefile->linno = plinno;
-	pf = (struct parsefile *)ckmalloc(sizeof(struct parsefile));
+	pf = ckmalloc(sizeof(*pf));
 	pf->prev = parsefile;
 	pf->fd = -1;
 	pf->strpush = NULL;
@@ -7802,152 +7752,6 @@
 
 #endif /* ASH_MAIL */
 
-/*      main.c       */
-
-
-#if PROFILE
-static short profile_buf[16384];
-extern int etext();
-#endif
-
-static int isloginsh;
-
-static void read_profile(const char *);
-
-/*
- * Main routine.  We initialize things, parse the arguments, execute
- * profiles if we're a login shell, and then call cmdloop to execute
- * commands.  The setjmp call sets up the location to jump to when an
- * exception occurs.  When an exception occurs the variable "state"
- * is used to figure out how far we had gotten.
- */
-int ash_main(int argc, char **argv);
-int ash_main(int argc, char **argv)
-{
-	char *shinit;
-	volatile int state;
-	struct jmploc jmploc;
-	struct stackmark smark;
-
-#ifdef __GLIBC__
-	dash_errno = __errno_location();
-#endif
-
-#if PROFILE
-	monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
-#endif
-
-#if ENABLE_FEATURE_EDITING
-	line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
-#endif
-	state = 0;
-	if (setjmp(jmploc.loc)) {
-		int e;
-		int s;
-
-		reset();
-
-		e = exception;
-		if (e == EXERROR)
-			exitstatus = 2;
-		s = state;
-		if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
-			exitshell();
-
-		if (e == EXINT) {
-			outcslow('\n', stderr);
-		}
-		popstackmark(&smark);
-		FORCE_INT_ON; /* enable interrupts */
-		if (s == 1)
-			goto state1;
-		else if (s == 2)
-			goto state2;
-		else if (s == 3)
-			goto state3;
-		else
-			goto state4;
-	}
-	exception_handler = &jmploc;
-#if DEBUG
-	opentrace();
-	trputs("Shell args:  ");  trargs(argv);
-#endif
-	rootpid = getpid();
-
-#if ENABLE_ASH_RANDOM_SUPPORT
-	rseed = rootpid + ((time_t)time((time_t *)0));
-#endif
-	init();
-	setstackmark(&smark);
-	procargs(argc, argv);
-#if ENABLE_FEATURE_EDITING_SAVEHISTORY
-	if (iflag) {
-		const char *hp = lookupvar("HISTFILE");
-
-		if (hp == NULL) {
-			hp = lookupvar("HOME");
-			if (hp != NULL) {
-				char *defhp = concat_path_file(hp, ".ash_history");
-				setvar("HISTFILE", defhp, 0);
-				free(defhp);
-			}
-		}
-	}
-#endif
-	if (argv[0] && argv[0][0] == '-')
-		isloginsh = 1;
-	if (isloginsh) {
-		state = 1;
-		read_profile("/etc/profile");
- state1:
-		state = 2;
-		read_profile(".profile");
-	}
- state2:
-	state = 3;
-	if (
-#ifndef linux
-		getuid() == geteuid() && getgid() == getegid() &&
-#endif
-		iflag
-	) {
-		shinit = lookupvar("ENV");
-		if (shinit != NULL && *shinit != '\0') {
-			read_profile(shinit);
-		}
-	}
- state3:
-	state = 4;
-	if (minusc)
-		evalstring(minusc, 0);
-
-	if (sflag || minusc == NULL) {
-#if ENABLE_FEATURE_EDITING_SAVEHISTORY
-		if ( iflag ) {
-			const char *hp = lookupvar("HISTFILE");
-
-			if (hp != NULL)
-				line_input_state->hist_file = hp;
-		}
-#endif
- state4: /* XXX ??? - why isn't this before the "if" statement */
-		cmdloop(1);
-	}
-#if PROFILE
-	monitor(0);
-#endif
-#ifdef GPROF
-	{
-		extern void _mcleanup(void);
-		_mcleanup();
-	}
-#endif
-	exitshell();
-	/* NOTREACHED */
-}
-
-
 /*
  * Read and execute commands.  "Top" is nonzero for the top level command
  * loop; it turns on prompting if the shell is interactive.
@@ -8006,25 +7810,6 @@
 
 
 /*
- * Read /etc/profile or .profile.  Return on error.
- */
-static void
-read_profile(const char *name)
-{
-	int skip;
-
-	if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
-		return;
-
-	skip = cmdloop(0);
-	popfile();
-
-	if (skip)
-		exitshell();
-}
-
-
-/*
  * Read a file containing shell functions.
  */
 static void
@@ -8134,8 +7919,8 @@
 /*
  * Same for malloc, realloc, but returns an error when out of space.
  */
-static pointer
-ckrealloc(pointer p, size_t nbytes)
+static void *
+ckrealloc(void * p, size_t nbytes)
 {
 	p = realloc(p, nbytes);
 	if (p == NULL)
@@ -8143,7 +7928,7 @@
 	return p;
 }
 
-static pointer
+static void *
 ckmalloc(size_t nbytes)
 {
 	return ckrealloc(NULL, nbytes);
@@ -8170,7 +7955,7 @@
  * The size 504 was chosen because the Ultrix malloc handles that size
  * well.
  */
-static pointer
+static void *
 stalloc(size_t nbytes)
 {
 	char *p;
@@ -8205,7 +7990,7 @@
 
 
 static void
-stunalloc(pointer p)
+stunalloc(void *p)
 {
 #if DEBUG
 	if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
@@ -8280,7 +8065,7 @@
 		sp = stackp;
 		prevstackp = sp->prev;
 		grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
-		sp = ckrealloc((pointer)sp, grosslen);
+		sp = ckrealloc(sp, grosslen);
 		sp->prev = prevstackp;
 		stackp = sp;
 		stacknxt = sp->space;
@@ -8710,71 +8495,9 @@
 }
 
 
-static void options(int);
 static void setoption(int, int);
 
 
-/*
- * Process the shell command line arguments.
- */
-static void
-procargs(int argc, char **argv)
-{
-	int i;
-	const char *xminusc;
-	char **xargv;
-
-	xargv = argv;
-	arg0 = xargv[0];
-	if (argc > 0)
-		xargv++;
-	for (i = 0; i < NOPTS; i++)
-		optlist[i] = 2;
-	argptr = xargv;
-	options(1);
-	xargv = argptr;
-	xminusc = minusc;
-	if (*xargv == NULL) {
-		if (xminusc)
-			ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
-		sflag = 1;
-	}
-	if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
-		iflag = 1;
-	if (mflag == 2)
-		mflag = iflag;
-	for (i = 0; i < NOPTS; i++)
-		if (optlist[i] == 2)
-			optlist[i] = 0;
-#if DEBUG == 2
-	debug = 1;
-#endif
-	/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
-	if (xminusc) {
-		minusc = *xargv++;
-		if (*xargv)
-			goto setarg0;
-	} else if (!sflag) {
-		setinputfile(*xargv, 0);
- setarg0:
-		arg0 = *xargv++;
-		commandname = arg0;
-	}
-
-	shellparam.p = xargv;
-#if ENABLE_ASH_GETOPTS
-	shellparam.optind = 1;
-	shellparam.optoff = -1;
-#endif
-	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
-	while (*xargv) {
-		shellparam.nparam++;
-		xargv++;
-	}
-	optschanged();
-}
-
-
 static void
 optschanged(void)
 {
@@ -8790,19 +8513,19 @@
 {
 	int i;
 
-	if (name == NULL) {
-		out1str("Current option settings\n");
-		for (i = 0; i < NOPTS; i++)
-			out1fmt("%-16s%s\n", optnames(i),
-				optlist[i] ? "on" : "off");
-	} else {
-		for (i = 0; i < NOPTS; i++)
+	if (name) {
+		for (i = 0; i < NOPTS; i++) {
 			if (equal(name, optnames(i))) {
 				optlist[i] = val;
 				return;
 			}
+		}
 		ash_msg_and_raise_error("Illegal option -o %s", name);
 	}
+	out1str("Current option settings\n");
+	for (i = 0; i < NOPTS; i++)
+		out1fmt("%-16s%s\n", optnames(i),
+				optlist[i] ? "on" : "off");
 }
 
 
@@ -8865,11 +8588,12 @@
 {
 	int i;
 
-	for (i = 0; i < NOPTS; i++)
+	for (i = 0; i < NOPTS; i++) {
 		if (optletters(i) == flag) {
 			optlist[i] = val;
 			return;
 		}
+	}
 	ash_msg_and_raise_error("Illegal option -%c", flag);
 	/* NOTREACHED */
 }
@@ -8980,13 +8704,13 @@
 #if ENABLE_LOCALE_SUPPORT
 static void change_lc_all(const char *value)
 {
-	if (value != 0 && *value != 0)
+	if (value && *value != '\0')
 		setlocale(LC_ALL, value);
 }
 
 static void change_lc_ctype(const char *value)
 {
-	if (value != 0 && *value != 0)
+	if (value && *value != '\0')
 		setlocale(LC_CTYPE, value);
 }
 
@@ -9188,7 +8912,6 @@
 
 #define EOFMARKLEN 79
 
-
 struct heredoc {
 	struct heredoc *next;   /* next here document in list */
 	union node *here;               /* redirection node */
@@ -9196,11 +8919,8 @@
 	int striptabs;          /* if set, strip leading tabs */
 };
 
-
-
 static struct heredoc *heredoclist;    /* list of here documents to read */
 
-
 static union node *list(int);
 static union node *andor(void);
 static union node *pipeline(void);
@@ -9214,16 +8934,40 @@
 static int xxreadtoken(void);
 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
 static int noexpand(char *);
-static void synexpect(int) ATTRIBUTE_NORETURN;
-static void synerror(const char *) ATTRIBUTE_NORETURN;
 static void setprompt(int);
 
+static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN;
+static void
+raise_error_syntax(const char *msg)
+{
+	ash_msg_and_raise_error("Syntax error: %s", msg);
+	/* NOTREACHED */
+}
+
+/*
+ * Called when an unexpected token is read during the parse.  The argument
+ * is the token that is expected, or -1 if more than one type of token can
+ * occur at this point.
+ */
+static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN;
+static void
+raise_error_unexpected_syntax(int token)
+{
+	char msg[64];
+	int l;
+
+	l = sprintf(msg, "%s unexpected", tokname(lasttoken));
+	if (token >= 0)
+		sprintf(msg + l, " (expecting %s)", tokname(token));
+	raise_error_syntax(msg);
+	/* NOTREACHED */
+}
 
 /*
  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
  * valid parse tree indicating a blank line.)
  */
-union node *
+static union node *
 parsecmd(int interact)
 {
 	int t;
@@ -9272,7 +9016,7 @@
 		if (n1 == NULL) {
 			n1 = n2;
 		} else {
-			n3 = (union node *)stalloc(sizeof(struct nbinary));
+			n3 = stalloc(sizeof(struct nbinary));
 			n3->type = NSEMI;
 			n3->nbinary.ch1 = n1;
 			n3->nbinary.ch2 = n2;
@@ -9303,7 +9047,7 @@
 			return n1;
 		default:
 			if (nlflag == 1)
-				synexpect(-1);
+				raise_error_unexpected_syntax(-1);
 			tokpushback++;
 			return n1;
 		}
@@ -9330,7 +9074,7 @@
 		}
 		checkkwd = CHKNL | CHKKWD | CHKALIAS;
 		n2 = pipeline();
-		n3 = (union node *)stalloc(sizeof(struct nbinary));
+		n3 = stalloc(sizeof(struct nbinary));
 		n3->type = t;
 		n3->nbinary.ch1 = n1;
 		n3->nbinary.ch2 = n2;
@@ -9355,15 +9099,15 @@
 		tokpushback++;
 	n1 = command();
 	if (readtoken() == TPIPE) {
-		pipenode = (union node *)stalloc(sizeof(struct npipe));
+		pipenode = stalloc(sizeof(struct npipe));
 		pipenode->type = NPIPE;
 		pipenode->npipe.backgnd = 0;
-		lp = (struct nodelist *)stalloc(sizeof(struct nodelist));
+		lp = stalloc(sizeof(struct nodelist));
 		pipenode->npipe.cmdlist = lp;
 		lp->n = n1;
 		do {
 			prev = lp;
-			lp = (struct nodelist *)stalloc(sizeof(struct nodelist));
+			lp = stalloc(sizeof(struct nodelist));
 			checkkwd = CHKNL | CHKKWD | CHKALIAS;
 			lp->n = command();
 			prev->next = lp;
@@ -9373,7 +9117,7 @@
 	}
 	tokpushback++;
 	if (negate) {
-		n2 = (union node *)stalloc(sizeof(struct nnot));
+		n2 = stalloc(sizeof(struct nnot));
 		n2->type = NNOT;
 		n2->nnot.com = n1;
 		return n2;
@@ -9397,23 +9141,23 @@
 
 	switch (readtoken()) {
 	default:
-		synexpect(-1);
+		raise_error_unexpected_syntax(-1);
 		/* NOTREACHED */
 	case TIF:
-		n1 = (union node *)stalloc(sizeof(struct nif));
+		n1 = stalloc(sizeof(struct nif));
 		n1->type = NIF;
 		n1->nif.test = list(0);
 		if (readtoken() != TTHEN)
-			synexpect(TTHEN);
+			raise_error_unexpected_syntax(TTHEN);
 		n1->nif.ifpart = list(0);
 		n2 = n1;
 		while (readtoken() == TELIF) {
-			n2->nif.elsepart = (union node *)stalloc(sizeof(struct nif));
+			n2->nif.elsepart = stalloc(sizeof(struct nif));
 			n2 = n2->nif.elsepart;
 			n2->type = NIF;
 			n2->nif.test = list(0);
 			if (readtoken() != TTHEN)
-				synexpect(TTHEN);
+				raise_error_unexpected_syntax(TTHEN);
 			n2->nif.ifpart = list(0);
 		}
 		if (lasttoken == TELSE)
@@ -9427,13 +9171,13 @@
 	case TWHILE:
 	case TUNTIL: {
 		int got;
-		n1 = (union node *)stalloc(sizeof(struct nbinary));
+		n1 = stalloc(sizeof(struct nbinary));
 		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 : ""));
-			synexpect(TDO);
+			raise_error_unexpected_syntax(TDO);
 		}
 		n1->nbinary.ch2 = list(0);
 		t = TDONE;
@@ -9441,15 +9185,15 @@
 	}
 	case TFOR:
 		if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
-			synerror("Bad for loop variable");
-		n1 = (union node *)stalloc(sizeof(struct nfor));
+			raise_error_syntax("Bad for loop variable");
+		n1 = stalloc(sizeof(struct nfor));
 		n1->type = NFOR;
 		n1->nfor.var = wordtext;
 		checkkwd = CHKKWD | CHKALIAS;
 		if (readtoken() == TIN) {
 			app = &ap;
 			while (readtoken() == TWORD) {
-				n2 = (union node *)stalloc(sizeof(struct narg));
+				n2 = stalloc(sizeof(struct narg));
 				n2->type = NARG;
 				n2->narg.text = wordtext;
 				n2->narg.backquote = backquotelist;
@@ -9459,9 +9203,9 @@
 			*app = NULL;
 			n1->nfor.args = ap;
 			if (lasttoken != TNL && lasttoken != TSEMI)
-				synexpect(-1);
+				raise_error_unexpected_syntax(-1);
 		} else {
-			n2 = (union node *)stalloc(sizeof(struct narg));
+			n2 = stalloc(sizeof(struct narg));
 			n2->type = NARG;
 			n2->narg.text = (char *)dolatstr;
 			n2->narg.backquote = NULL;
@@ -9476,16 +9220,16 @@
 		}
 		checkkwd = CHKNL | CHKKWD | CHKALIAS;
 		if (readtoken() != TDO)
-			synexpect(TDO);
+			raise_error_unexpected_syntax(TDO);
 		n1->nfor.body = list(0);
 		t = TDONE;
 		break;
 	case TCASE:
-		n1 = (union node *)stalloc(sizeof(struct ncase));
+		n1 = stalloc(sizeof(struct ncase));
 		n1->type = NCASE;
 		if (readtoken() != TWORD)
-			synexpect(TWORD);
-		n1->ncase.expr = n2 = (union node *)stalloc(sizeof(struct narg));
+			raise_error_unexpected_syntax(TWORD);
+		n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
 		n2->type = NARG;
 		n2->narg.text = wordtext;
 		n2->narg.backquote = backquotelist;
@@ -9494,7 +9238,7 @@
 			checkkwd = CHKKWD | CHKALIAS;
 		} while (readtoken() == TNL);
 		if (lasttoken != TIN)
-			synexpect(TIN);
+			raise_error_unexpected_syntax(TIN);
 		cpp = &n1->ncase.cases;
  next_case:
 		checkkwd = CHKNL | CHKKWD;
@@ -9502,11 +9246,11 @@
 		while (t != TESAC) {
 			if (lasttoken == TLP)
 				readtoken();
-			*cpp = cp = (union node *)stalloc(sizeof(struct nclist));
+			*cpp = cp = stalloc(sizeof(struct nclist));
 			cp->type = NCLIST;
 			app = &cp->nclist.pattern;
 			for (;;) {
-				*app = ap = (union node *)stalloc(sizeof(struct narg));
+				*app = ap = stalloc(sizeof(struct narg));
 				ap->type = NARG;
 				ap->narg.text = wordtext;
 				ap->narg.backquote = backquotelist;
@@ -9517,7 +9261,7 @@
 			}
 			ap->narg.next = NULL;
 			if (lasttoken != TRP)
-				synexpect(TRP);
+				raise_error_unexpected_syntax(TRP);
 			cp->nclist.body = list(2);
 
 			cpp = &cp->nclist.next;
@@ -9526,15 +9270,14 @@
 			t = readtoken();
 			if (t != TESAC) {
 				if (t != TENDCASE)
-					synexpect(TENDCASE);
-				else
-					goto next_case;
+					raise_error_unexpected_syntax(TENDCASE);
+				goto next_case;
 			}
 		}
 		*cpp = NULL;
 		goto redir;
 	case TLP:
-		n1 = (union node *)stalloc(sizeof(struct nredir));
+		n1 = stalloc(sizeof(struct nredir));
 		n1->type = NSUBSHELL;
 		n1->nredir.n = list(0);
 		n1->nredir.redirect = NULL;
@@ -9551,7 +9294,7 @@
 	}
 
 	if (readtoken() != t)
-		synexpect(t);
+		raise_error_unexpected_syntax(t);
 
  redir:
 	/* Now check for redirection which may follow command */
@@ -9566,7 +9309,7 @@
 	*rpp = NULL;
 	if (redir) {
 		if (n1->type != NSUBSHELL) {
-			n2 = (union node *)stalloc(sizeof(struct nredir));
+			n2 = stalloc(sizeof(struct nredir));
 			n2->type = NREDIR;
 			n2->nredir.n = n1;
 			n1 = n2;
@@ -9598,7 +9341,7 @@
 		checkkwd = savecheckkwd;
 		switch (readtoken()) {
 		case TWORD:
-			n = (union node *)stalloc(sizeof(struct narg));
+			n = stalloc(sizeof(struct narg));
 			n->type = NARG;
 			n->narg.text = wordtext;
 			n->narg.backquote = backquotelist;
@@ -9617,24 +9360,21 @@
 			parsefname();   /* read name of redirection file */
 			break;
 		case TLP:
-			if (
-				args && app == &args->narg.next &&
-				!vars && !redir
+			if (args && app == &args->narg.next
+			 && !vars && !redir
 			) {
 				struct builtincmd *bcmd;
 				const char *name;
 
 				/* We have a function */
 				if (readtoken() != TRP)
-					synexpect(TRP);
+					raise_error_unexpected_syntax(TRP);
 				name = n->narg.text;
-				if (
-					!goodname(name) || (
-						(bcmd = find_builtin(name)) &&
-						IS_BUILTIN_SPECIAL(bcmd)
-					)
-				)
-					synerror("Bad function name");
+				if (!goodname(name)
+				 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
+				) {
+					raise_error_syntax("Bad function name");
+				}
 				n->type = NDEFUN;
 				checkkwd = CHKNL | CHKKWD | CHKALIAS;
 				n->narg.next = command();
@@ -9650,7 +9390,7 @@
 	*app = NULL;
 	*vpp = NULL;
 	*rpp = NULL;
-	n = (union node *)stalloc(sizeof(struct ncmd));
+	n = stalloc(sizeof(struct ncmd));
 	n->type = NCMD;
 	n->ncmd.args = args;
 	n->ncmd.assign = vars;
@@ -9663,7 +9403,7 @@
 {
 	union node *n;
 
-	n = (union node *)stalloc(sizeof(struct narg));
+	n = stalloc(sizeof(struct narg));
 	n->type = NARG;
 	n->narg.next = NULL;
 	n->narg.text = wordtext;
@@ -9682,11 +9422,9 @@
 	else if (LONE_DASH(text))
 		n->ndup.dupfd = -1;
 	else {
-
 		if (err)
-			synerror("Bad fd number");
-		else
-			n->ndup.vname = makename();
+			raise_error_syntax("Bad fd number");
+		n->ndup.vname = makename();
 	}
 }
 
@@ -9697,7 +9435,7 @@
 	union node *n = redirnode;
 
 	if (readtoken() != TWORD)
-		synexpect(-1);
+		raise_error_unexpected_syntax(-1);
 	if (n->type == NHERE) {
 		struct heredoc *here = heredoc;
 		struct heredoc *p;
@@ -9707,7 +9445,7 @@
 			n->type = NXHERE;
 		TRACE(("Here document %d\n", n->type));
 		if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
-			synerror("Illegal eof marker for << redirection");
+			raise_error_syntax("Illegal eof marker for << redirection");
 		rmescapes(wordtext);
 		here->eofmark = wordtext;
 		here->next = NULL;
@@ -9743,7 +9481,7 @@
 		}
 		readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
 				here->eofmark, here->striptabs);
-		n = (union node *)stalloc(sizeof(struct narg));
+		n = stalloc(sizeof(struct narg));
 		n->narg.type = NARG;
 		n->narg.next = NULL;
 		n->narg.text = wordtext;
@@ -9845,10 +9583,8 @@
  *  We could also make parseoperator in essence the main routine, and
  *  have parseword (readtoken1?) handle both words and redirection.]
  */
-
 #define NEW_xxreadtoken
 #ifdef NEW_xxreadtoken
-
 /* singles must be first! */
 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
 
@@ -9881,9 +9617,9 @@
 
 		if ((c != ' ') && (c != '\t')
 #if ENABLE_ASH_ALIAS
-			&& (c != PEOA)
+		 && (c != PEOA)
 #endif
-			) {
+		) {
 			if (c == '#') {
 				while ((c = pgetc()) != '\n' && c != PEOF);
 				pungetc();
@@ -9907,7 +9643,7 @@
 
 					p = strchr(xxreadtoken_chars, c);
 					if (p == NULL) {
-					  READTOKEN1:
+ READTOKEN1:
 						return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
 					}
 
@@ -9924,11 +9660,8 @@
 		}
 	} /* for */
 }
-
-
 #else
 #define RETURN(token)   return lasttoken = token
-
 static int
 xxreadtoken(void)
 {
@@ -10199,14 +9932,14 @@
  endword:
 #if ENABLE_ASH_MATH_SUPPORT
 	if (syntax == ARISYNTAX)
-		synerror("Missing '))'");
+		raise_error_syntax("Missing '))'");
 #endif
 	if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
-		synerror("Unterminated quoted string");
+		raise_error_syntax("Unterminated quoted string");
 	if (varnest != 0) {
 		startlinno = plinno;
 		/* { */
-		synerror("Missing '}'");
+		raise_error_syntax("Missing '}'");
 	}
 	USTPUTC('\0', out);
 	len = out - (char *)stackblock();
@@ -10277,7 +10010,7 @@
 	char fd = *out;
 	union node *np;
 
-	np = (union node *)stalloc(sizeof(struct nfile));
+	np = stalloc(sizeof(struct nfile));
 	if (c == '>') {
 		np->nfile.fd = 1;
 		c = pgetc();
@@ -10297,11 +10030,11 @@
 		switch (c) {
 		case '<':
 			if (sizeof(struct nfile) != sizeof(struct nhere)) {
-				np = (union node *)stalloc(sizeof(struct nhere));
+				np = stalloc(sizeof(struct nhere));
 				np->nfile.fd = 0;
 			}
 			np->type = NHERE;
-			heredoc = (struct heredoc *)stalloc(sizeof(struct heredoc));
+			heredoc = stalloc(sizeof(struct heredoc));
 			heredoc->here = np;
 			c = pgetc();
 			if (c == '-') {
@@ -10356,7 +10089,7 @@
 #if ENABLE_ASH_MATH_SUPPORT
 			PARSEARITH();
 #else
-			synerror("We unsupport $((arith))");
+			raise_error_syntax("We unsupport $((arith))");
 #endif
 		} else {
 			pungetc();
@@ -10392,7 +10125,7 @@
 			USTPUTC(c, out);
 			c = pgetc();
 		} else
- badsub:		synerror("Bad substitution");
+ badsub:		raise_error_syntax("Bad substitution");
 
 		STPUTC('=', out);
 		flags = 0;
@@ -10523,7 +10256,7 @@
 			case PEOA:
 #endif
 				startlinno = plinno;
-				synerror("EOF in backquote substitution");
+				raise_error_syntax("EOF in backquote substitution");
 
 			case '\n':
 				plinno++;
@@ -10546,7 +10279,7 @@
 	nlpp = &bqlist;
 	while (*nlpp)
 		nlpp = &(*nlpp)->next;
-	*nlpp = (struct nodelist *)stalloc(sizeof(struct nodelist));
+	*nlpp = stalloc(sizeof(**nlpp));
 	(*nlpp)->next = NULL;
 	parsebackquote = oldstyle;
 
@@ -10561,7 +10294,7 @@
 		doprompt = saveprompt;
 	else {
 		if (readtoken() != TRP)
-			synexpect(TRP);
+			raise_error_unexpected_syntax(TRP);
 	}
 
 	(*nlpp)->n = n;
@@ -10592,8 +10325,7 @@
 		USTPUTC(CTLBACKQ, out);
 	if (oldstyle)
 		goto parsebackq_oldreturn;
-	else
-		goto parsebackq_newreturn;
+	goto parsebackq_newreturn;
 }
 
 #if ENABLE_ASH_MATH_SUPPORT
@@ -10606,9 +10338,9 @@
 		syntax = ARISYNTAX;
 		USTPUTC(CTLARI, out);
 		if (dblquote)
-			USTPUTC('"',out);
+			USTPUTC('"', out);
 		else
-			USTPUTC(' ',out);
+			USTPUTC(' ', out);
 	} else {
 		/*
 		 * we collapse embedded arithmetic expansion to
@@ -10667,31 +10399,6 @@
 
 
 /*
- * Called when an unexpected token is read during the parse.  The argument
- * is the token that is expected, or -1 if more than one type of token can
- * occur at this point.
- */
-static void synexpect(int token)
-{
-	char msg[64];
-	int l;
-
-	l = sprintf(msg, "%s unexpected", tokname(lasttoken));
-	if (token >= 0)
-		sprintf(msg + l, " (expecting %s)", tokname(token));
-	synerror(msg);
-	/* NOTREACHED */
-}
-
-static void
-synerror(const char *msg)
-{
-	ash_msg_and_raise_error("Syntax error: %s", msg);
-	/* NOTREACHED */
-}
-
-
-/*
  * called by editline -- any expansions to the prompt
  *    should be added here.
  */
@@ -12353,7 +12060,7 @@
 		else if (errcode == -5)
 			ash_msg_and_raise_error("expression recursion loop detected");
 		else
-			synerror(s);
+			raise_error_syntax(s);
 	}
 	INT_ON;
 
@@ -13485,6 +13192,257 @@
 #endif /* ASH_MATH_SUPPORT */
 
 
+/* ============ main() and helpers
+ *
+ * Main routine.  We initialize things, parse the arguments, execute
+ * profiles if we're a login shell, and then call cmdloop to execute
+ * commands.  The setjmp call sets up the location to jump to when an
+ * exception occurs.  When an exception occurs the variable "state"
+ * is used to figure out how far we had gotten.
+ */
+
+static void init(void)
+{
+	/* from input.c: */
+	basepf.nextc = basepf.buf = basebuf;
+
+	/* from trap.c: */
+	signal(SIGCHLD, SIG_DFL);
+
+	/* from var.c: */
+	{
+		char **envp;
+		char ppid[32];
+		const char *p;
+		struct stat st1, st2;
+
+		initvar();
+		for (envp = environ; envp && *envp; envp++) {
+			if (strchr(*envp, '=')) {
+				setvareq(*envp, VEXPORT|VTEXTFIXED);
+			}
+		}
+
+		snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
+		setvar("PPID", ppid, 0);
+
+		p = lookupvar("PWD");
+		if (p)
+			if (*p != '/' || stat(p, &st1) || stat(".", &st2)
+			 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
+				p = '\0';
+		setpwd(p, 0);
+	}
+}
+
+/*
+ * Process the shell command line arguments.
+ */
+static void
+procargs(int argc, char **argv)
+{
+	int i;
+	const char *xminusc;
+	char **xargv;
+
+	xargv = argv;
+	arg0 = xargv[0];
+	if (argc > 0)
+		xargv++;
+	for (i = 0; i < NOPTS; i++)
+		optlist[i] = 2;
+	argptr = xargv;
+	options(1);
+	xargv = argptr;
+	xminusc = minusc;
+	if (*xargv == NULL) {
+		if (xminusc)
+			ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
+		sflag = 1;
+	}
+	if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
+		iflag = 1;
+	if (mflag == 2)
+		mflag = iflag;
+	for (i = 0; i < NOPTS; i++)
+		if (optlist[i] == 2)
+			optlist[i] = 0;
+#if DEBUG == 2
+	debug = 1;
+#endif
+	/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
+	if (xminusc) {
+		minusc = *xargv++;
+		if (*xargv)
+			goto setarg0;
+	} else if (!sflag) {
+		setinputfile(*xargv, 0);
+ setarg0:
+		arg0 = *xargv++;
+		commandname = arg0;
+	}
+
+	shellparam.p = xargv;
+#if ENABLE_ASH_GETOPTS
+	shellparam.optind = 1;
+	shellparam.optoff = -1;
+#endif
+	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
+	while (*xargv) {
+		shellparam.nparam++;
+		xargv++;
+	}
+	optschanged();
+}
+
+/*
+ * Read /etc/profile or .profile.
+ */
+static void
+read_profile(const char *name)
+{
+	int skip;
+
+	if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
+		return;
+	skip = cmdloop(0);
+	popfile();
+	if (skip)
+		exitshell();
+}
+
+#if PROFILE
+static short profile_buf[16384];
+extern int etext();
+#endif
+
+int ash_main(int argc, char **argv);
+int ash_main(int argc, char **argv)
+{
+	char *shinit;
+	volatile int state;
+	struct jmploc jmploc;
+	struct stackmark smark;
+
+#ifdef __GLIBC__
+	dash_errno = __errno_location();
+#endif
+
+#if PROFILE
+	monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
+#endif
+
+#if ENABLE_FEATURE_EDITING
+	line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
+#endif
+	state = 0;
+	if (setjmp(jmploc.loc)) {
+		int e;
+		int s;
+
+		reset();
+
+		e = exception;
+		if (e == EXERROR)
+			exitstatus = 2;
+		s = state;
+		if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
+			exitshell();
+
+		if (e == EXINT) {
+			outcslow('\n', stderr);
+		}
+		popstackmark(&smark);
+		FORCE_INT_ON; /* enable interrupts */
+		if (s == 1)
+			goto state1;
+		else if (s == 2)
+			goto state2;
+		else if (s == 3)
+			goto state3;
+		else
+			goto state4;
+	}
+	exception_handler = &jmploc;
+#if DEBUG
+	opentrace();
+	trputs("Shell args: ");
+	trargs(argv);
+#endif
+	rootpid = getpid();
+
+#if ENABLE_ASH_RANDOM_SUPPORT
+	rseed = rootpid + time(NULL);
+#endif
+	init();
+	setstackmark(&smark);
+	procargs(argc, argv);
+#if ENABLE_FEATURE_EDITING_SAVEHISTORY
+	if (iflag) {
+		const char *hp = lookupvar("HISTFILE");
+
+		if (hp == NULL) {
+			hp = lookupvar("HOME");
+			if (hp != NULL) {
+				char *defhp = concat_path_file(hp, ".ash_history");
+				setvar("HISTFILE", defhp, 0);
+				free(defhp);
+			}
+		}
+	}
+#endif
+	if (argv[0] && argv[0][0] == '-')
+		isloginsh = 1;
+	if (isloginsh) {
+		state = 1;
+		read_profile("/etc/profile");
+ state1:
+		state = 2;
+		read_profile(".profile");
+	}
+ state2:
+	state = 3;
+	if (
+#ifndef linux
+		getuid() == geteuid() && getgid() == getegid() &&
+#endif
+		iflag
+	) {
+		shinit = lookupvar("ENV");
+		if (shinit != NULL && *shinit != '\0') {
+			read_profile(shinit);
+		}
+	}
+ state3:
+	state = 4;
+	if (minusc)
+		evalstring(minusc, 0);
+
+	if (sflag || minusc == NULL) {
+#if ENABLE_FEATURE_EDITING_SAVEHISTORY
+		if ( iflag ) {
+			const char *hp = lookupvar("HISTFILE");
+
+			if (hp != NULL)
+				line_input_state->hist_file = hp;
+		}
+#endif
+ state4: /* XXX ??? - why isn't this before the "if" statement */
+		cmdloop(1);
+	}
+#if PROFILE
+	monitor(0);
+#endif
+#ifdef GPROF
+	{
+		extern void _mcleanup(void);
+		_mcleanup();
+	}
+#endif
+	exitshell();
+	/* NOTREACHED */
+}
+
 #if DEBUG
 const char *applet_name = "debug stuff usage";
 int main(int argc, char **argv)
@@ -13493,6 +13451,7 @@
 }
 #endif
 
+
 /*-
  * Copyright (c) 1989, 1991, 1993, 1994
  *      The Regents of the University of California.  All rights reserved.