implement bash-style array initialisation, as requested by many
still experimental
This commit is contained in:
parent
4fef868b6d
commit
3a94b076a0
24
check.t
24
check.t
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.115 2007/06/21 16:04:45 tg Exp $
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.116 2007/06/22 23:34:40 tg Exp $
|
||||
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
||||
@ -7,7 +7,7 @@
|
||||
# http://www.research.att.com/~gsf/public/ifs.sh
|
||||
|
||||
expected-stdout:
|
||||
@(#)MIRBSD KSH R29 2007/06/21
|
||||
@(#)MIRBSD KSH R29 2007/06/22
|
||||
description:
|
||||
Check version of shell.
|
||||
category: pdksh
|
||||
@ -4009,3 +4009,23 @@ expected-stdout:
|
||||
integer='typeset -i'
|
||||
local=typeset
|
||||
---
|
||||
name: arrays-1
|
||||
description:
|
||||
Check if Korn Shell arrays work as expected
|
||||
stdin:
|
||||
v="c d"
|
||||
set -A foo -- a \$v "$v" '$v' b
|
||||
echo "${#foo[*]}|${foo[0]}|${foo[1]}|${foo[2]}|${foo[3]}|${foo[4]}|"
|
||||
expected-stdout:
|
||||
5|a|$v|c d|$v|b|
|
||||
---
|
||||
name: arrays-2
|
||||
description:
|
||||
Check if bash-style arrays work as expected
|
||||
stdin:
|
||||
v="c d"
|
||||
foo=(a \$v "$v" '$v' b)
|
||||
echo "${#foo[*]}|${foo[0]}|${foo[1]}|${foo[2]}|${foo[3]}|${foo[4]}|"
|
||||
expected-stdout:
|
||||
5|a|$v|c d|$v|b|
|
||||
---
|
||||
|
28
lex.c
28
lex.c
@ -2,7 +2,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.35 2007/06/16 15:02:56 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.36 2007/06/22 23:34:40 tg Exp $");
|
||||
|
||||
/* Structure to keep track of the lexing state and the various pieces of info
|
||||
* needed for each particular state. */
|
||||
@ -37,6 +37,12 @@ struct lex_state {
|
||||
} u_sbquote;
|
||||
|
||||
Lex_state *base; /* used to point to next state block */
|
||||
|
||||
/* =(...) */
|
||||
struct sletarray_info {
|
||||
int nparen; /* count open parentheses */
|
||||
#define ls_sletarray ls_info.u_sletarray
|
||||
} u_sletarray;
|
||||
} ls_info;
|
||||
};
|
||||
|
||||
@ -121,6 +127,9 @@ yylex(int cf)
|
||||
*wp++ = OQUOTE; /* enclose arguments in (double) quotes */
|
||||
state = SLETPAREN;
|
||||
statep->ls_sletparen.nparen = 0;
|
||||
} else if (cf&LETARRAY) {
|
||||
state = SLETARRAY;
|
||||
statep->ls_sletarray.nparen = 0;
|
||||
} else { /* normal lexing */
|
||||
state = (cf & HEREDELIM) ? SHEREDELIM : SBASE;
|
||||
while ((c = getsc()) == ' ' || c == '\t')
|
||||
@ -535,6 +544,17 @@ yylex(int cf)
|
||||
++statep->ls_sletparen.nparen;
|
||||
goto Sbase2;
|
||||
|
||||
case SLETARRAY: /* LETARRAY: =( ... ) */
|
||||
if (c == '('/*)*/)
|
||||
++statep->ls_sletarray.nparen;
|
||||
else if (c == /*(*/')')
|
||||
if (statep->ls_sletarray.nparen-- == 0) {
|
||||
c = 0;
|
||||
goto Done;
|
||||
}
|
||||
*wp++ = CHAR, *wp++ = c;
|
||||
break;
|
||||
|
||||
case SHEREDELIM: /* <<,<<- delimiter */
|
||||
/* XXX chuck this state (and the next) - use
|
||||
* the existing states ($ and \`..` should be
|
||||
@ -607,6 +627,9 @@ yylex(int cf)
|
||||
/* XXX figure out what is missing */
|
||||
yyerror("no closing quote\n");
|
||||
|
||||
if (state == SLETARRAY && statep->ls_sletarray.nparen != -1)
|
||||
yyerror("syntax error: ')' missing\n");
|
||||
|
||||
/* This done to avoid tests for SHEREDELIM wherever SBASE tested */
|
||||
if (state == SHEREDELIM)
|
||||
state = SBASE;
|
||||
@ -680,7 +703,8 @@ yylex(int cf)
|
||||
|
||||
*wp++ = EOS; /* terminate word */
|
||||
yylval.cp = Xclose(ws, wp);
|
||||
if (state == SWORD || state == SLETPAREN) /* ONEWORD? */
|
||||
if (state == SWORD || state == SLETPAREN ||
|
||||
state == SLETARRAY) /* ONEWORD? */
|
||||
return LWORD;
|
||||
ungetsc(c); /* unget terminator */
|
||||
|
||||
|
15
mksh.1
15
mksh.1
@ -1,7 +1,7 @@
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.87 2007/06/17 00:50:08 tg Exp $
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.88 2007/06/22 23:34:41 tg Exp $
|
||||
.\" $OpenBSD: ksh.1,v 1.120 2007/05/31 20:47:44 otto Exp $
|
||||
.\"
|
||||
.Dd June 17, 2007
|
||||
.Dd June 22, 2007
|
||||
.Dt MKSH 1
|
||||
.Os MirBSD
|
||||
.Sh NAME
|
||||
@ -3208,6 +3208,17 @@ is used, the array is reset (i.e. emptied) first; if
|
||||
.Ic +A
|
||||
is used, the first N elements are set (where N is the number of arguments);
|
||||
the rest are left untouched.
|
||||
.Pp
|
||||
An alternative syntax for the command
|
||||
.Ic set -A foo -- a b c
|
||||
which is compatible to
|
||||
.Tn GNU
|
||||
.Nm bash
|
||||
and also supported by
|
||||
.At
|
||||
.Nm ksh93
|
||||
is:
|
||||
.Ic foo=(a b c)
|
||||
.It Fl a \*(Ba Ic allexport
|
||||
All new parameters are created with the export attribute.
|
||||
.It Fl b \*(Ba Ic notify
|
||||
|
6
sh.h
6
sh.h
@ -8,8 +8,8 @@
|
||||
/* $OpenBSD: c_test.h,v 1.4 2004/12/20 11:34:26 otto Exp $ */
|
||||
/* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto Exp $ */
|
||||
|
||||
#define MKSH_SH_H_ID "$MirOS: src/bin/mksh/sh.h,v 1.149 2007/06/21 16:04:46 tg Exp $"
|
||||
#define MKSH_VERSION "R29 2007/06/21"
|
||||
#define MKSH_SH_H_ID "$MirOS: src/bin/mksh/sh.h,v 1.150 2007/06/22 23:34:41 tg Exp $"
|
||||
#define MKSH_VERSION "R29 2007/06/22"
|
||||
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
@ -1112,6 +1112,7 @@ struct source {
|
||||
#define SHEREDQUOTE 10 /* parsing " in <<,<<- delimiter */
|
||||
#define SPATTERN 11 /* parsing *(...|...) pattern (*+?@!) */
|
||||
#define STBRACE 12 /* parsing ${..[#%]..} */
|
||||
#define SLETARRAY 13 /* inside =( ), just copy */
|
||||
|
||||
typedef union {
|
||||
int i;
|
||||
@ -1162,6 +1163,7 @@ typedef union {
|
||||
#define HEREDELIM BIT(9) /* parsing <<,<<- delimiter */
|
||||
#define LQCHAR BIT(10) /* source string contains QCHAR */
|
||||
#define HEREDOC BIT(11) /* parsing a here document */
|
||||
#define LETARRAY BIT(12) /* copy expression inside =( ) */
|
||||
|
||||
#define HERES 10 /* max << in line */
|
||||
|
||||
|
40
syn.c
40
syn.c
@ -2,7 +2,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.14 2007/06/06 23:28:17 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.15 2007/06/22 23:34:42 tg Exp $");
|
||||
|
||||
struct nesting_state {
|
||||
int start_token; /* token than began nesting (eg, FOR) */
|
||||
@ -248,6 +248,9 @@ get_command(int cf)
|
||||
ACCEPT;
|
||||
goto Subshell;
|
||||
}
|
||||
if ((XPsize(args) == 0 || Flag(FKEYWORD)) &&
|
||||
XPsize(vars) == 1 && is_wdvarassign(yylval.cp))
|
||||
goto is_wdarrassign;
|
||||
/* Must be a function */
|
||||
if (iopn != 0 || XPsize(args) != 1 ||
|
||||
XPsize(vars) != 0)
|
||||
@ -257,6 +260,41 @@ get_command(int cf)
|
||||
musthave(')', 0);
|
||||
t = function_body(XPptrv(args)[0], false);
|
||||
goto Leave;
|
||||
is_wdarrassign:
|
||||
{
|
||||
static const char set_cmd0[] = {
|
||||
CHAR, 'e', CHAR, 'v',
|
||||
CHAR, 'a', CHAR, 'l', EOS
|
||||
};
|
||||
static const char set_cmd1[] = {
|
||||
CHAR, 's', CHAR, 'e',
|
||||
CHAR, 't', CHAR, ' ',
|
||||
CHAR, '-', CHAR, 'A', EOS
|
||||
};
|
||||
static const char set_cmd2[] = {
|
||||
CHAR, '-', CHAR, '-', EOS
|
||||
};
|
||||
char *tcp;
|
||||
XPfree(vars);
|
||||
XPinit(vars, 16);
|
||||
/*
|
||||
* we know (or rather hope) that yylval.cp
|
||||
* contains a string "varname="
|
||||
*/
|
||||
tcp = wdcopy(yylval.cp, ATEMP);
|
||||
tcp[wdscan(tcp, EOS) - tcp - 3] = EOS;
|
||||
/* now make an array assignment command */
|
||||
t = newtp(TCOM);
|
||||
t->lineno = source->line;
|
||||
ACCEPT;
|
||||
XPput(args, wdcopy(set_cmd0, ATEMP));
|
||||
XPput(args, wdcopy(set_cmd1, ATEMP));
|
||||
XPput(args, tcp);
|
||||
XPput(args, wdcopy(set_cmd2, ATEMP));
|
||||
musthave(LWORD,LETARRAY);
|
||||
XPput(args, yylval.cp);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
goto Leave;
|
||||
|
Loading…
x
Reference in New Issue
Block a user