From 8c87404928e86741a9c409c04e276f73a3e3b00a Mon Sep 17 00:00:00 2001 From: "[GPL]Ed" Date: Mon, 29 May 2023 14:50:23 +0000 Subject: [PATCH] Change substitution rules for arrays (better security+optimization), add array lexical scoping --- doc/man1/let.1 | 9 ++++++--- examples/unique.zrc | 29 +++++++++++++++++++++++++++++ src/config.hpp | 2 +- src/dispatch.hpp | 24 ++++++++++++++++++------ src/subst.hpp | 4 ++-- 5 files changed, 56 insertions(+), 12 deletions(-) create mode 100755 examples/unique.zrc diff --git a/doc/man1/let.1 b/doc/man1/let.1 index debff14..f2f4153 100644 --- a/doc/man1/let.1 +++ b/doc/man1/let.1 @@ -6,15 +6,18 @@ let \- Use a lexical scoping block .SH DESCRIPTION The first argument of .I let -must be a list representing the variables that will return to their original value after executing the second argument, which is a "code block". +must be a list representing the variables that will return to their original value after executing the second argument, which is a "code block". If a variable's name begins with `A,...`, then the utility stores a backup of the associative array of the same name. .SH EXAMPLE .EX set var1 = value set var2 = value - let {var1 var2} { + set arr(1) = x + set arr(2) = y + let {var1 var2 A,arr} { + array delete arr set var1 = a set var2 = b } #The original values were preserved! - echo $var1 $var2 + echo $var1 $var2 $arr(1) .EE diff --git a/examples/unique.zrc b/examples/unique.zrc new file mode 100755 index 0000000..ea3108d --- /dev/null +++ b/examples/unique.zrc @@ -0,0 +1,29 @@ +#!/usr/lib/zrc/bin/zrc +alias str string + +fn unique { + let {count line A,map} { + set count = 0 + until {[read line]} { + switch $map($line) { + case '' { + inc count + set map($line) = 1 + } + case 1 { + inc count -1 + set map($line) = 2 + } + } + } + echo $count + } +} + +if {$argc == 2} { + unique +} else { + for {set i = 2} {$i < $argc} {inc i} { + unique < $argv($i) + } +} diff --git a/src/config.hpp b/src/config.hpp index f496d9d..3db2acc 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -3,4 +3,4 @@ static std::string errmsg = "syntax error: "; static std::string default_prompt = "zrc% "; -static std::string ver = "zrc v0.2"; +static std::string ver = "zrc v0.3"; diff --git a/src/dispatch.hpp b/src/dispatch.hpp index 63da58f..530ad71 100644 --- a/src/dispatch.hpp +++ b/src/dispatch.hpp @@ -493,18 +493,30 @@ Command(let) { syntax_error(" "); WordList vars; - std::map hm; + std::map a_hm_bak; + std::map s_hm_bak; /* empty */ { NullFin; vars = tokenize(argv[1], fin); } - for (std::string const& str : vars.wl) - hm[str] = getvar(str); + for (std::string str : vars.wl) { + if (str[0] == 'A' && str[1] == ',') { + str.erase(0, 2); + a_hm_bak[str] = a_hm[str]; + } else { + s_hm_bak[str] = getvar(str); + } + } eval(argv[2]); - for (std::string const& str : vars.wl) - setvar(str, hm[str]); + for (std::string& str : vars.wl) { + if (str[0] == 'A' && str[1] == ',') { + str.erase(0, 2); + a_hm[str] = a_hm_bak[str]; + } else { + setvar(str, s_hm_bak[str]); + } + } NoReturn; - } /** Sourcing scripts into current session **/ diff --git a/src/subst.hpp b/src/subst.hpp index 9ba9b00..906c41f 100644 --- a/src/subst.hpp +++ b/src/subst.hpp @@ -117,13 +117,13 @@ str_subst(std::string& str) tmp1 += str[i]; if (str[i] == '(') { ITERATE_PAREN('(',')'); - str_subst(tmp2); tmp1 += tmp2+")"; arr_ok = true; break; } } - str_subst(tmp1); + if (!arr_ok) + str_subst(tmp1); res += get_var(tmp1); if (!arr_ok) --i;