ash: move ash_main() and helpers to end of ash.c, more fuctions renamed,
authorDenis Vlasenko <vda.linux@googlemail.com>
Mon, 19 Feb 2007 22:45:43 +0000 (22:45 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Mon, 19 Feb 2007 22:45:43 +0000 (22:45 -0000)
superfluous casts from memory allocators removed

shell/ash.c

index 532dad15a5c8d80617361764eff33a2574e8f6d6..e262c0e13abe9bfb4ddc6dcb25fdcd62a38bdb7b 100644 (file)
@@ -141,6 +141,7 @@ static char optlist[NOPTS];
 
 /* ============ 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 @@ static char *endofname(const char *);
 
 /*      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 const char syntax_index_table[258] = {
 
 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 @@ static void initvar(void)
        } 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 showjobs(FILE *, int);
 
 
 static void readcmdfile(char *);
-static int cmdloop(int);
-
 /*      memalloc.h        */
 
 
@@ -2018,11 +1977,11 @@ static char *sstrend = stackbase.space + MINSIZE;
 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 *optptr;                   /* used by nextopt */
 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 @@ static void
 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 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
        } 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 @@ recordregion(int start, int end, int nulonly)
                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 @@ ifsbreakup(char *string, struct arglist *arglist)
                                                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 @@ ifsbreakup(char *string, struct arglist *arglist)
                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 @@ addfname(const char *name)
 {
        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 @@ pushfile(void)
        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 @@ changemail(const char *val)
 
 #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.
@@ -8005,25 +7809,6 @@ cmdloop(int top)
 }
 
 
-/*
- * 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.
  */
@@ -8134,8 +7919,8 @@ testcmd(int argc, char **argv)
 /*
  * 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 @@ ckrealloc(pointer p, size_t nbytes)
        return p;
 }
 
-static pointer
+static void *
 ckmalloc(size_t nbytes)
 {
        return ckrealloc(NULL, nbytes);
@@ -8170,7 +7955,7 @@ savestr(const char *s)
  * 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 @@ stalloc(size_t nbytes)
 
 
 static void
-stunalloc(pointer p)
+stunalloc(void *p)
 {
 #if DEBUG
        if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
@@ -8280,7 +8065,7 @@ growstackblock(void)
                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,99 +8495,37 @@ freefunc(struct funcnode *f)
 }
 
 
-static void options(int);
 static void setoption(int, int);
 
 
-/*
- * Process the shell command line arguments.
- */
 static void
-procargs(int argc, char **argv)
+optschanged(void)
+{
+#if DEBUG
+       opentrace();
+#endif
+       setinteractive(iflag);
+       setjobctl(mflag);
+       setvimode(viflag);
+}
+
+static void minus_o(char *name, int val)
 {
        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 (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);
        }
-       if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
-               iflag = 1;
-       if (mflag == 2)
-               mflag = iflag;
+       out1str("Current option settings\n");
        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)
-{
-#if DEBUG
-       opentrace();
-#endif
-       setinteractive(iflag);
-       setjobctl(mflag);
-       setvimode(viflag);
-}
-
-static void minus_o(char *name, int val)
-{
-       int i;
-
-       if (name == NULL) {
-               out1str("Current option settings\n");
-               for (i = 0; i < NOPTS; i++)
-                       out1fmt("%-16s%s\n", optnames(i),
+               out1fmt("%-16s%s\n", optnames(i),
                                optlist[i] ? "on" : "off");
-       } else {
-               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);
-       }
 }
 
 
@@ -8865,11 +8588,12 @@ setoption(int flag, int val)
 {
        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 @@ getoptsreset(const char *value)
 #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 @@ nextopt(const char *optstring)
 
 #define EOFMARKLEN 79
 
-
 struct heredoc {
        struct heredoc *next;   /* next here document in list */
        union node *here;               /* redirection node */
@@ -9196,11 +8919,8 @@ struct heredoc {
        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 readtoken(void);
 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 @@ list(int nlflag)
                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 @@ list(int nlflag)
                        return n1;
                default:
                        if (nlflag == 1)
-                               synexpect(-1);
+                               raise_error_unexpected_syntax(-1);
                        tokpushback++;
                        return n1;
                }
@@ -9330,7 +9074,7 @@ andor(void)
                }
                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 @@ pipeline(void)
                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 @@ pipeline(void)
        }
        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 @@ command(void)
 
        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 @@ command(void)
        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 @@ command(void)
        }
        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 @@ command(void)
                        *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 @@ command(void)
                }
                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 @@ command(void)
                        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 @@ command(void)
                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 @@ command(void)
                        }
                        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 @@ command(void)
                        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 @@ command(void)
        }
 
        if (readtoken() != t)
-               synexpect(t);
+               raise_error_unexpected_syntax(t);
 
  redir:
        /* Now check for redirection which may follow command */
@@ -9566,7 +9309,7 @@ command(void)
        *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 @@ simplecmd(void)
                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 @@ simplecmd(void)
                        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 @@ simplecmd(void)
        *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 @@ makename(void)
 {
        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 @@ static void fixredir(union node *n, const char *text, int err)
        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 @@ parsefname(void)
        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 @@ parsefname(void)
                        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 @@ parseheredoc(void)
                }
                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 @@ readtoken(void)
  *  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 @@ static int xxreadtoken(void)
 
                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 @@ static int xxreadtoken(void)
 
                                        p = strchr(xxreadtoken_chars, c);
                                        if (p == NULL) {
                                        READTOKEN1:
+ READTOKEN1:
                                                return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
                                        }
 
@@ -9924,11 +9660,8 @@ static int xxreadtoken(void)
                }
        } /* for */
 }
-
-
 #else
 #define RETURN(token)   return lasttoken = token
-
 static int
 xxreadtoken(void)
 {
@@ -10199,14 +9932,14 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
  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 @@ parseredir: {
        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 @@ parseredir: {
                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 @@ parsesub: {
 #if ENABLE_ASH_MATH_SUPPORT
                        PARSEARITH();
 #else
-                       synerror("We unsupport $((arith))");
+                       raise_error_syntax("We unsupport $((arith))");
 #endif
                } else {
                        pungetc();
@@ -10392,7 +10125,7 @@ parsesub: {
                        USTPUTC(c, out);
                        c = pgetc();
                } else
- badsub:               synerror("Bad substitution");
+ badsub:               raise_error_syntax("Bad substitution");
 
                STPUTC('=', out);
                flags = 0;
@@ -10523,7 +10256,7 @@ parsebackq: {
                        case PEOA:
 #endif
                                startlinno = plinno;
-                               synerror("EOF in backquote substitution");
+                               raise_error_syntax("EOF in backquote substitution");
 
                        case '\n':
                                plinno++;
@@ -10546,7 +10279,7 @@ parsebackq: {
        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 @@ parsebackq: {
                doprompt = saveprompt;
        else {
                if (readtoken() != TRP)
-                       synexpect(TRP);
+                       raise_error_unexpected_syntax(TRP);
        }
 
        (*nlpp)->n = n;
@@ -10592,8 +10325,7 @@ parsebackq: {
                USTPUTC(CTLBACKQ, out);
        if (oldstyle)
                goto parsebackq_oldreturn;
-       else
-               goto parsebackq_newreturn;
+       goto parsebackq_newreturn;
 }
 
 #if ENABLE_ASH_MATH_SUPPORT
@@ -10606,9 +10338,9 @@ parsearith: {
                syntax = ARISYNTAX;
                USTPUTC(CTLARI, out);
                if (dblquote)
-                       USTPUTC('"',out);
+                       USTPUTC('"', out);
                else
-                       USTPUTC(' ',out);
+                       USTPUTC(' ', out);
        } else {
                /*
                 * we collapse embedded arithmetic expansion to
@@ -10666,31 +10398,6 @@ endofname(const char *name)
 }
 
 
-/*
- * 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 @@ dash_arith(const char *s)
                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 @@ static arith_t arith(const char *expr, int *perrcode)
 #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 @@ int main(int argc, char **argv)
 }
 #endif
 
+
 /*-
  * Copyright (c) 1989, 1991, 1993, 1994
  *      The Regents of the University of California.  All rights reserved.