From owner-freebsd-hackers@FreeBSD.ORG Fri Oct 31 01:43:35 2003 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id A92D616A4CE; Fri, 31 Oct 2003 01:43:35 -0800 (PST) Received: from xorpc.icir.org (xorpc.icir.org [192.150.187.68]) by mx1.FreeBSD.org (Postfix) with ESMTP id E45D843FE0; Fri, 31 Oct 2003 01:43:34 -0800 (PST) (envelope-from rizzo@xorpc.icir.org) Received: from xorpc.icir.org (localhost [127.0.0.1]) by xorpc.icir.org (8.12.9p1/8.12.3) with ESMTP id h9V9hVsd081299; Fri, 31 Oct 2003 01:43:31 -0800 (PST) (envelope-from rizzo@xorpc.icir.org) Received: (from rizzo@localhost) by xorpc.icir.org (8.12.9p1/8.12.3/Submit) id h9V9hVIv081298; Fri, 31 Oct 2003 01:43:31 -0800 (PST) (envelope-from rizzo) Date: Fri, 31 Oct 2003 01:43:31 -0800 From: Luigi Rizzo To: hackers@freebsd.org Message-ID: <20031031014331.A71967@xorpc.icir.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5.1i Subject: RFC: proposed new builtin for /bin/sh (associative arrays) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 31 Oct 2003 09:43:35 -0000 [Not sure what is the appropriate forum to discuss this, so please redirect the discussion if you know where. I have Bcc-ed a few /bin/sh committers] I am trying to implement, in the most unintrusive way, something resembliung associative arrays in /bin/sh. I am not interested in syntactic sugar, so i am happy to use something like _ as a separator between the array basename and the "index", i.e. foo_red foo_green foo_blue would be part of the same array. And, as a first step, I am also happy to be limited to [0-9A-Za-z_]+ as "index" values. So all it was necessary was a command to enumerate the indexes of an array, which is implemented by the attached patch, and can be used as follows: for i in `indexes foo_` do eval x=\$foo_$i echo "variable foo_$i has value $x" done (basically, "indexes xyz" lists the remaining part of all variable names that start with xyz. As a possibly useful side effect, indexes "" lists all variable names, which i believe is not an available sh function -- and i find it strange since we can list the names of readonly and export-ed variables with the "readonly" and "export" builtins). Any comments ? Is this interesting enough to be committed (with a proper manpage description) ? I could provide a flag to "indexes" to return the values instead of the names, but i believe this form is more useful. The next step would be to allow arbitrary strings as indexes, but that would be trickier because it would change the syntax for variable names (e.g. allowing \[.*\] as the last part of a variable name) cheers luigi Index: builtins.def =================================================================== RCS file: /home/ncvs/src/bin/sh/builtins.def,v retrieving revision 1.7.2.2 diff -u -r1.7.2.2 builtins.def --- builtins.def 27 Aug 2002 01:36:28 -0000 1.7.2.2 +++ builtins.def 30 Oct 2003 09:02:37 -0000 @@ -69,6 +69,7 @@ fgcmd -j fg getoptscmd getopts hashcmd hash +indexes indexes jobidcmd jobid jobscmd jobs #linecmd line Index: var.c =================================================================== RCS file: /home/ncvs/src/bin/sh/var.c,v retrieving revision 1.15.2.2 diff -u -r1.15.2.2 var.c --- var.c 27 Aug 2002 01:36:28 -0000 1.15.2.2 +++ var.c 31 Oct 2003 09:06:27 -0000 @@ -602,6 +602,28 @@ return 0; } +int +indexes(int argc, char **argv) +{ + struct var **vpp; + struct var *vp; + char *p, *q; + + if (argc != 2) + error("indexes require one argument"); + for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { + for (vp = *vpp ; vp ; vp = vp->next) { + for (p = vp->text, q = argv[1]; + *p != '=' && *p == *q; p++, q++) + ; + if (*q != '\0') + continue; /* not found */ + while (*p != '=') + out1c(*p++); + out1c('\n'); + } + } +} /* * The "local" command.