diff -pru dash-0.5.3/ChangeLog dash-0.5.3-raf/ChangeLog --- dash-0.5.3/ChangeLog 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/ChangeLog 2006-08-16 19:31:46.000000000 +0200 @@ -1,3 +1,25 @@ +2006-08-16 Roberto A. Foglietta + + * Add support for option -e in echo builtin command + * Add support for exp and readline from bsd/fox version + * Fix a bug introduced in supporting negative value return + +2006-08-15 Roberto A. Foglietta + + * Add support for function as functions definition keyword + * Add support for $[ ] equivalent to $(( )) syntax + +2006-08-11 Roberto A. Foglietta + + * Add support for return a negative value, fixed is_number() + * Add support for test == operator as string comparing + +2006-08-05 Roberto A. Foglietta + + * Add support for local -i, defining integer variables + * Add support for typedef and declare as shell keywords + * Group in to one typedef, declare, local, export, readonly + 2005-11-26 Herbert Xu * Release 0.5.3. diff -pru dash-0.5.3/src/arith.y dash-0.5.3-raf/src/arith.y --- dash-0.5.3/src/arith.y 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/arith.y 2006-08-16 18:31:04.000000000 +0200 @@ -124,6 +124,46 @@ arith(s) } +/* + * The exp(1) builtin. + */ +int +expcmd(argc, argv) + int argc; + char **argv; +{ + const char *p; + char *concat; + char **ap; + long i; + + if (argc > 1) { + p = argv[1]; + if (argc > 2) { + /* + * concatenate arguments + */ + STARTSTACKSTR(concat); + ap = argv + 2; + for (;;) { + while (*p) + STPUTC(*p++, concat); + if ((p = *ap++) == NULL) + break; + STPUTC(' ', concat); + } + STPUTC('\0', concat); + p = grabstackstr(concat); + } + } else + p = nullstr; + + i = arith(p); + + out1fmt("%ld\n", i); + return (! i); +} + /*************************/ #ifdef TEST_ARITH #include diff -pru dash-0.5.3/src/bltin/printf.c dash-0.5.3-raf/src/bltin/printf.c --- dash-0.5.3/src/bltin/printf.c 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/bltin/printf.c 2006-08-16 15:46:14.000000000 +0200 @@ -434,13 +434,17 @@ echocmd(int argc, char **argv) int nonl = 0; struct output *outs = out1; - if (!*++argv) - goto end; - if (equal(*argv, "-n")) { - nonl = ~nonl; + do { if (!*++argv) goto end; - } + if (!equal(*argv,"-en") + && !equal(*argv,"-ne") + && !equal(*argv,"-e") + && !equal(*argv,"-n")) + break; + if (strchr(*argv,'n')) + nonl = 1; + } while(1); do { char c; diff -pru dash-0.5.3/src/bltin/test.c dash-0.5.3-raf/src/bltin/test.c --- dash-0.5.3/src/bltin/test.c 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/bltin/test.c 2006-08-11 11:22:12.000000000 +0200 @@ -62,6 +62,7 @@ enum token { STREZ, STRNZ, STREQ, + STREQN, STRNE, STRLT, STRGT, @@ -113,6 +114,7 @@ static struct t_op { {"-L", FILSYM, UNOP}, {"-S", FILSOCK,UNOP}, {"=", STREQ, BINOP}, + {"==", STREQN, BINOP}, //RAF, 2006-08-11 {"!=", STRNE, BINOP}, {"<", STRLT, BINOP}, {">", STRGT, BINOP}, @@ -275,6 +277,7 @@ binop(void) /* NOTREACHED */ #endif case STREQ: + case STREQN: return strcmp(opnd1, opnd2) == 0; case STRNE: return strcmp(opnd1, opnd2) != 0; diff -pru dash-0.5.3/src/builtins.def.in dash-0.5.3-raf/src/builtins.def.in --- dash-0.5.3/src/builtins.def.in 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/builtins.def.in 2006-08-16 19:13:06.000000000 +0200 @@ -34,6 +34,11 @@ * @(#)builtins.def 8.4 (Berkeley) 5/4/95 */ +/* + * 2006-08-05, Roberto A. Foglietta + * Modified in order to have typeset -i for integer variables + */ + /* * This file lists all the builtin commands. The first column is the name * of a C routine. @@ -65,12 +70,11 @@ echocmd echo evalcmd -s eval execcmd -s exec exitcmd -s exit -exportcmd -as export -as readonly +expcmd exp falsecmd -u false getoptscmd -u getopts hashcmd hash jobscmd -u jobs -localcmd -a local printfcmd printf pwdcmd pwd readcmd -u read @@ -81,6 +85,7 @@ timescmd -s times trapcmd -s trap truecmd -s : -u true typecmd type +typesetcmd -a typeset -as export -as readonly -a declare -a local umaskcmd -u umask unaliascmd -u unalias unsetcmd -s unset diff -pru dash-0.5.3/src/error.h dash-0.5.3-raf/src/error.h --- dash-0.5.3/src/error.h 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/error.h 2006-08-16 18:34:30.000000000 +0200 @@ -62,6 +62,7 @@ struct jmploc { extern struct jmploc *handler; extern int exception; +extern int exerrno; /* error for EXEXEC */ /* exceptions */ #define EXINT 0 /* SIGINT received */ @@ -138,3 +139,14 @@ void exerror(int, const char *, ...) __a const char *errmsg(int, int); void sh_warnx(const char *, ...); + + +/* + * BSD setjmp saves the signal mask, which violates ANSI C and takes time, + * so we use _setjmp instead. + */ + +#if defined(BSD) && !defined(__SVR4) && !defined(__GLIBC__) +#define setjmp(jmploc) _setjmp(jmploc) +#define longjmp(jmploc, val) _longjmp(jmploc, val) +#endif diff -pru dash-0.5.3/src/eval.c dash-0.5.3-raf/src/eval.c --- dash-0.5.3/src/eval.c 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/eval.c 2006-08-16 19:39:30.000000000 +0200 @@ -32,6 +32,11 @@ * SUCH DAMAGE. */ +/* + * 2006-08-16, Roberto A. Foglietta + * Modified in order to support return -n (negative integers) + */ + #include #include #include @@ -1052,8 +1057,11 @@ returncmd(int argc, char **argv) * If called outside a function, do what ksh does; * skip the rest of the file. */ + char *p = argv[1]; + int n = exitstatus; evalskip = funcnest ? SKIPFUNC : SKIPFILE; - return argv[1] ? number(argv[1]) : exitstatus; + if(p) n = (*p == '-') ? -number(++p) : number(p); + return n; } @@ -1098,3 +1106,4 @@ eprintlist(struct output *out, struct st return sep; } + diff -pru dash-0.5.3/src/exec.c dash-0.5.3-raf/src/exec.c --- dash-0.5.3/src/exec.c 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/exec.c 2006-08-16 18:36:41.000000000 +0200 @@ -37,6 +37,7 @@ #include #include #include +#include #include /* @@ -58,6 +59,7 @@ #include "builtins.h" #include "var.h" #include "options.h" +#include "input.h" #include "output.h" #include "syntax.h" #include "memalloc.h" diff -pru dash-0.5.3/src/input.c dash-0.5.3-raf/src/input.c --- dash-0.5.3/src/input.c 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/input.c 2006-08-16 18:43:26.000000000 +0200 @@ -123,6 +123,15 @@ RESET { } #endif +#ifdef USE_READLINE +#include +#include +static int readline_interactive = 0; +void readline_init(void) +{ + readline_interactive = 1; +} +#endif /* * Read a line from the script. @@ -214,6 +223,27 @@ retry: nr = hetio_read_input(parsefile->fd); if (nr == -255) #endif +#ifdef USE_READLINE + if (!parsefile->fd && readline_interactive) { + char *line; + + line = readline(getprompt(NULL)); + if (line) { + add_history(line); + strncpy(buf, line, BUFSIZ - 1); + if (strlen(line) < (BUFSIZ - 1)) { + strcpy(buf + strlen(buf), "\n"); + } else { + strcpy(buf + BUFSIZ - 2, "\n"); + } + free(line); + nr = strlen(buf); + } else { + /* EOF (Ctrl-D) */ + nr = 0; + } + } else +#endif nr = read(parsefile->fd, buf, IBUFSIZ - 1); diff -pru dash-0.5.3/src/jobs.c dash-0.5.3-raf/src/jobs.c --- dash-0.5.3/src/jobs.c 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/jobs.c 2006-08-15 17:07:17.000000000 +0200 @@ -1181,8 +1181,7 @@ commandtext(union node *n) STARTSTACKSTR(cmdnextc); cmdtxt(n); name = stackblock(); - TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n", - name, cmdnextc, ps->cmd)); + TRACE(("commandtext: name %p, end %p\n", name, cmdnextc)); return savestr(name); } diff -pru dash-0.5.3/src/main.c dash-0.5.3-raf/src/main.c --- dash-0.5.3/src/main.c 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/main.c 2006-08-16 18:49:40.000000000 +0200 @@ -209,6 +209,12 @@ cmdloop(int top) if(iflag && top) hetio_init(); #endif +#ifdef USE_READLINE + if(iflag && top) { + extern void readline_init(void); + readline_init(); + } +#endif for (;;) { int skip; diff -pru dash-0.5.3/src/mksyntax.c dash-0.5.3-raf/src/mksyntax.c --- dash-0.5.3/src/mksyntax.c 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/mksyntax.c 2006-08-15 18:57:23.000000000 +0200 @@ -32,6 +32,11 @@ * SUCH DAMAGE. */ +/* + * 2006-08-15, Roberto A. Foglietta + * Modified in order to support $[ ] syntax for arithmetic + */ + /* * This program creates syntax.h and syntax.c. */ @@ -55,6 +60,7 @@ struct synclass synclass[] = { { "CBACK", "a backslash character" }, { "CSQUOTE", "single quote" }, { "CDQUOTE", "double quote" }, + { "CSQUARE", "a right square paren closing arith" }, { "CENDQUOTE", "a terminating quote" }, { "CBQUOTE", "backwards single quote" }, { "CVAR", "a dollar sign" }, @@ -239,6 +245,7 @@ main(int argc, char **argv) add("}", "CENDVAR"); add("(", "CLP"); add(")", "CRP"); + add("]", "CSQUARE"); print("arisyntax"); filltable("0"); fputs("\n/* character classification table */\n", cfile); diff -pru dash-0.5.3/src/mktokens dash-0.5.3-raf/src/mktokens --- dash-0.5.3/src/mktokens 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/mktokens 2006-08-16 14:29:57.000000000 +0200 @@ -33,6 +33,11 @@ # # @(#)mktokens 8.1 (Berkeley) 5/31/93 +# +# 2006-08-15, Roberto A. Foglietta +# Modified in order to support function keyword in function definition +# + # The following is a list of tokens. The second column is nonzero if the # token marks the end of a list. The third column is the name to print in # error messages. @@ -60,6 +65,7 @@ TELSE 1 "else" TESAC 1 "esac" TFI 1 "fi" TFOR 0 "for" +TFUNC 0 "function" TIF 0 "if" TIN 0 "in" TTHEN 1 "then" diff -pru dash-0.5.3/src/parser.c dash-0.5.3-raf/src/parser.c --- dash-0.5.3/src/parser.c 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/parser.c 2006-08-16 19:07:07.000000000 +0200 @@ -32,6 +32,12 @@ * SUCH DAMAGE. */ +/* + * 2006-08-15, Roberto A. Foglietta + * Modified in order to support $[ ] syntax and function keyword + */ + +#include #include #include "shell.h" @@ -299,9 +305,6 @@ command(void) rpp2 = &redir; switch (readtoken()) { - default: - synexpect(-1); - /* NOTREACHED */ case TIF: n1 = (union node *)stalloc(sizeof (struct nif)); n1->type = NIF; @@ -445,10 +448,14 @@ next_case: n1 = list(0); t = TEND; break; + case TFUNC: case TWORD: case TREDIR: tokpushback++; return simplecmd(); + default: + synexpect(-1); + /* NOTREACHED */ } if (readtoken() != t) @@ -496,8 +503,22 @@ simplecmd(void) { savecheckkwd = CHKALIAS; for (;;) { + int t; checkkwd = savecheckkwd; - switch (readtoken()) { + t = readtoken(); + switch (t) { + case TREDIR: + *rpp = n = redirnode; + rpp = &n->nfile.next; + parsefname(); /* read name of redirection file */ + break; + case TFUNC: + t = readtoken(); + if(t != TWORD) + synexpect(TWORD); + t = peektoken(); + if(t != TLP) + synexpect(TLP); case TWORD: n = (union node *)stalloc(sizeof (struct narg)); n->type = NARG; @@ -511,12 +532,8 @@ simplecmd(void) { app = &n->narg.next; savecheckkwd = 0; } - break; - case TREDIR: - *rpp = n = redirnode; - rpp = &n->nfile.next; - parsefname(); /* read name of redirection file */ - break; + if(t != TFUNC) + break; case TLP: if ( args && app == &args->narg.next && @@ -811,7 +828,6 @@ breakloop: } - /* * If eofmark is NULL, read a word or a redirection symbol. If eofmark * is not NULL, read a here document. In the latter case, eofmark is the @@ -843,6 +859,7 @@ readtoken1(int firstc, char const *synta int dblquote; int varnest; /* levels of variables expansion */ int arinest; /* levels of arithmetic expansion */ + int arichar; /* type of paren which start arithmetic */ int parenlevel; /* levels of parens in arithmetic */ int dqvarnest; /* levels of variables expansion within double quotes */ int oldstyle; @@ -854,6 +871,7 @@ readtoken1(int firstc, char const *synta (void) &dblquote; (void) &varnest; (void) &arinest; + (void) &arichar; (void) &parenlevel; (void) &dqvarnest; (void) &oldstyle; @@ -869,6 +887,7 @@ readtoken1(int firstc, char const *synta bqlist = NULL; varnest = 0; arinest = 0; + arichar = 0; parenlevel = 0; dqvarnest = 0; @@ -980,7 +999,8 @@ quotemark: --parenlevel; } else { if (pgetc() == ')') { - if (--arinest == 0) { +arith_square_close: + if (arichar == c && --arinest == 0) { USTPUTC(CTLENDARI, out); syntax = prevsyntax; if (syntax == DQSYNTAX) @@ -988,7 +1008,7 @@ quotemark: else dblquote = 0; } else - USTPUTC(')', out); + USTPUTC(c, out); } else { /* * unbalanced parens @@ -999,6 +1019,11 @@ quotemark: } } break; + case CSQUARE: + if(syntax == ARISYNTAX) + goto arith_square_close; + USTPUTC(']', out); + break; case CBQUOTE: /* '`' */ PARSEBACKQOLD(); break; @@ -1164,12 +1189,12 @@ parsesub: { c = pgetc(); if ( c <= PEOA || - (c != '(' && c != '{' && !is_name(c) && !is_special(c)) + (c != '(' && c != '{' && c != '[' && !is_name(c) && !is_special(c)) ) { USTPUTC('$', out); pungetc(); - } else if (c == '(') { /* $(command) or $((arith)) */ - if (pgetc() == '(') { + } else if (c == '[' || c =='(') { /* $(command), $[arith] or $((arith)) */ + if (c =='[' || pgetc() == '(') { PARSEARITH(); } else { pungetc(); @@ -1412,10 +1437,10 @@ done: * Parse an arithmetic expansion (indicate start of one and set state) */ parsearith: { - if (++arinest == 1) { prevsyntax = syntax; syntax = ARISYNTAX; + arichar = (c=='(')?')':']'; USTPUTC(CTLARI, out); if (dblquote) USTPUTC('"',out); @@ -1526,6 +1551,7 @@ setprompt(int which) needprompt = 0; whichprompt = which; +#ifndef USE_READLINE #ifdef SMALL show = 1; #else @@ -1537,6 +1563,7 @@ setprompt(int which) out2str(getprompt(NULL)); popstackmark(&smark); } +#endif } const char * diff -pru dash-0.5.3/src/shell.h dash-0.5.3-raf/src/shell.h --- dash-0.5.3/src/shell.h 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/shell.h 2006-08-16 19:08:57.000000000 +0200 @@ -71,6 +71,8 @@ typedef void *pointer; #define STATIC static #define MKINIT /* empty */ +#include + extern char nullstr[1]; /* null string */ diff -pru dash-0.5.3/src/show.c dash-0.5.3-raf/src/show.c --- dash-0.5.3/src/show.c 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/show.c 2006-08-15 17:07:17.000000000 +0200 @@ -35,6 +35,10 @@ #include #include +#ifdef DEBUG +#include +#endif + #include "shell.h" #include "parser.h" #include "nodes.h" diff -pru dash-0.5.3/src/var.c dash-0.5.3-raf/src/var.c --- dash-0.5.3/src/var.c 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/var.c 2006-08-15 19:03:16.000000000 +0200 @@ -32,6 +32,11 @@ * SUCH DAMAGE. */ +/* + * 2006-08-05, Roberto A. Foglietta + * Modified in order to have typeset -i for integer variables + */ + #include #include #include @@ -98,7 +103,7 @@ struct var varinit[] = { STATIC struct var *vartab[VTABSIZE]; -STATIC void mklocal(char *); +STATIC void mklocal(char *, int); //RAF, 04-08-2006: modified STATIC struct var **hashvar(const char *); STATIC int vpcmp(const void *, const void *); STATIC struct var **findvar(struct var **, const char *); @@ -237,23 +242,30 @@ setvar(const char *name, const char *val * Called with interrupts off. */ +//#include + void setvareq(char *s, int flags) { struct var *vp, **vpp; vpp = hashvar(s); - flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1)); + //RAF, orig:flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1)); + flags |= aflag ? VEXPORT : 0; vp = *findvar(vpp, s); if (vp) { - if (vp->flags & VREADONLY) { + //RAF, 04-08-2006: this line allow one set only but differ from bash + // if you want declare a readonly variable without + // have to set it and allow to set it later (only once + // time and no more) use this line below instead orig.if + //if ((vp->flags & VREADONLY) && !(vp->flags & VUNSET)) { + if (vp->flags & VREADONLY){ const char *n; if (flags & VNOSAVE) free(s); n = vp->text; - sh_error("%.*s: is read only", strchrnul(n, '=') - n, - n); + sh_error("%.*s: is read only", strchrnul(n,'=')-n, n); } if (flags & VNOSET) @@ -277,6 +289,21 @@ setvareq(char *s, int flags) } if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE))) s = savestr(s); + +//RAF, 04-08-2006: declare -i varname = value ... + if(flags & VINTEGER) { + char *p = strchrnul(s, '='); + //printf("setvareq '%s' 0x%02x 0x%02x 0x%02x", s, + // s[strlen(s)], s[strlen(s)+1], s[strlen(s)+2]); + if(*p && !atol(++p)) { + *p='0'; + *++p=0; + // printf(" --> '%s'", s); + } + //printf("\n"); + } +//... RAF + vp->text = s; vp->flags = flags; } @@ -405,12 +432,12 @@ showvars(const char *prefix, int on, int return 0; } - - /* * The export and readonly commands. */ +//RAF, 04-08-2006: export and local gone into typesetcmd +#if 0 int exportcmd(int argc, char **argv) { @@ -439,21 +466,70 @@ exportcmd(int argc, char **argv) } return 0; } +#endif /* - * The "local" command. + * The "export", "local", "readonly" and "typeset" commands. */ +//RAF, 04-08-2006: modified in order to have local -i name=value int -localcmd(int argc, char **argv) +typesetcmd(int argc, char **argv) { - char *name; + int opt, flags = 0; + char *name, *optstr = {""}; + + switch(argv[0][0]) { + case 'e': // export command + flags |= VEXPORT; + optstr = "p"; + break; + case 'r': // readonly command + flags |= VREADONLY; + optstr = "p"; + break; + case 't': // typeset command + case 'd': // declare command + optstr = "rix"; + break; + case 'l': // local command + optstr = "ri"; + break; + } + + while((opt = nextopt(optstr))) { + switch(opt) { + case 'i': + flags |= VINTEGER; + break; + case 'r': + flags |= VREADONLY; + break; + case 'x': + flags |= VEXPORT; + break; + case 'p': + return showvars(argv[0], flags&(VEXPORT|VREADONLY), 0); + } + } argv = argptr; while ((name = *argv++) != NULL) { - mklocal(name); + //static int i = 0; + //printf("typeset %d: '%s' (0x%04x)\n", ++i, name, flags); + if(flags & VEXPORT) { + char *p; + struct var *vp; + if ((p = strchr(name, '='))) + setvar(name, p+1, flags); + else if((vp = *findvar(hashvar(name), name))) + vp->flags |= flags; + } else { + mklocal(name, flags); + } } + return 0; } @@ -465,8 +541,9 @@ localcmd(int argc, char **argv) * "-" as a special case. */ +//RAF 04-08-2006, modified in order to have local -i name=value STATIC void -mklocal(char *name) +mklocal(char *name, int flags) { struct localvar *lvp; struct var **vpp; @@ -487,17 +564,18 @@ mklocal(char *name) eq = strchr(name, '='); if (vp == NULL) { if (eq) - setvareq(name, VSTRFIXED); + setvareq(name, flags|VSTRFIXED); else - setvar(name, NULL, VSTRFIXED); + setvar(name, NULL, flags|VSTRFIXED); vp = *vpp; /* the new variable */ lvp->flags = VUNSET; } else { lvp->text = vp->text; lvp->flags = vp->flags; - vp->flags |= VSTRFIXED|VTEXTFIXED; + //RAF: why |= and not simple =? + vp->flags |= VSTRFIXED|VTEXTFIXED|flags; if (eq) - setvareq(name, 0); + setvareq(name, flags); } } lvp->vp = vp; diff -pru dash-0.5.3/src/var.h dash-0.5.3-raf/src/var.h --- dash-0.5.3/src/var.h 2005-11-26 04:17:55.000000000 +0100 +++ dash-0.5.3-raf/src/var.h 2006-08-15 19:03:40.000000000 +0200 @@ -38,6 +38,11 @@ * Shell variables. */ +/* + * 2006-08-05, Roberto A. Foglietta + * Modified in order to have typeset -i for integer variables + */ + /* flags */ #define VEXPORT 0x01 /* variable is exported */ #define VREADONLY 0x02 /* variable cannot be modified */ @@ -48,6 +53,9 @@ #define VNOFUNC 0x40 /* don't call the callback function */ #define VNOSET 0x80 /* do not set variable - just readonly test */ #define VNOSAVE 0x100 /* when text is on the heap before setvareq */ +//RAF, 04-08-2006: declare -i varname = value ... +#define VINTEGER 0x200 /* variable is a integer value one */ +//... RAF struct var {