Commit 41af4942 authored by Samuel Newbold's avatar Samuel Newbold

List env with parens, don't mangle internal parens

parent 16ccd3e4
......@@ -2,7 +2,7 @@
// won't export templates, so it must be included directly in each file where
// it is used.
//
// Copyright (C) 2006-2016 Samuel Newbold
// Copyright (C) 2006-2018 Samuel Newbold
// constructor of Argm from a pair of iterators
template <class String_it>
......@@ -43,23 +43,30 @@ inline Out Argm::star_var(const std::string& key, unsigned reference_level,
*res++ = next;}
return res;}
namespace {
std::string substr_word(const std::string& in, unsigned start, unsigned end) {
if (in[start] == '(' && in[end-1] == ')')
return in.substr(start+1, end-start-2);
else return in.substr(start, end-start);}
} // end unnamed namespace
template<class Out>
Out tokenize_words(const std::string& in, Out res) {
unsigned token_start=0, i=0, nesting=0;
while (i<in.length() && isspace(in[i])) ++i;
token_start = i; // drop leading space
for (; i<in.length(); ++i)
if (in[i] == '(') {if (!nesting++) ++token_start;}
else if (in[i] == ')') {if (!nesting--)
throw Exception(Argm::Mismatched_parenthesis, in.substr(0, i+1));}
else if (!nesting && isspace(in[i])) {
unsigned end = i;
while (i<in.length() && isspace(in[i])) ++i; // drop leading space
if (in[end-1] == ')') *res++ = in.substr(token_start, end-token_start-1);
else *res++ = in.substr(token_start, end-token_start);
token_start = i--;}
unsigned j=0, nesting=0;
while (j < in.length() && isspace(in[j])) ++j;
unsigned token_start = j; // drop leading space
for (; j<in.length(); ++j)
if (isspace(in[j])) {
*res++ = substr_word(in, token_start, j);
while (j < in.length() && isspace(in[j])) ++j;
token_start = j--;} // drop leading space
else if (in[j] == ')')
throw Exception(Argm::Mismatched_parenthesis, in.substr(0, j+1));
else if (in[j] == '(') for (nesting++; nesting && ++j<in.length();)
if (in[j] == '(') nesting++;
else if (in[j] == ')') nesting--;
else; // step through nested non-parentheses
else; // step through non-nested printing non-parentheses
if (nesting) throw Exception(Argm::Mismatched_parenthesis, in);
if (token_start != i)
if (in[i-1] == ')') *res = in.substr(token_start, i-token_start-1);
else *res = in.substr(token_start, i-token_start);
if (token_start != j) *res++ = substr_word(in, token_start, j);
return res;}
......@@ -404,7 +404,6 @@ int b_list_environment(const Argm& argm, Error_list& exceptions) {
if (argm.argfunction()) throw Exception(Argm::Excess_argfunction);
for (char** i=environ; *i; ++i) {
std::string src(*i);
if (src.find_first_of("()") != std::string::npos) continue;
std::string::size_type div = src.find("=");
if (div != std::string::npos) {
if (i != environ) argm.output <<" ";
......
......@@ -68,11 +68,11 @@ int Base_executable::operator() (const Argm& argm,
executable_map.run(focus, children);}
if (children.size()) {
last_exception_v = "";
for (Error_list::iterator i = children.begin(); i != children.end();) {
last_exception_v += i->str() + " " + argm.str();
i->push_back(argm[0]);
parent_exceptions.push_back(*i);
if (++i != children.end()) last_exception_v += "; ";}}
for (auto j = children.begin(); j != children.end();) {
last_exception_v += j->str() + " " + argm.str();
j->push_back(argm[0]);
parent_exceptions.push_back(*j);
if (++j != children.end()) last_exception_v += "; ";}}
--executable_nesting;
if (del_on_term && !executable_nesting) delete this;
return ret;}
......@@ -122,7 +122,7 @@ void Base_executable::exception_handler(Error_list& exceptions) {
// code to call exception handlers when requested within a function
void Base_executable::catch_blocks(const Argm& argm,
Error_list& exceptions) {
for (Error_list::iterator focus = exceptions.begin();
for (auto focus = exceptions.begin();
focus != exceptions.end();)
if (find(argm.begin() + 1, argm.end(), (*focus)[0]) != argm.end()) {
if (dropped_catches >= max_extra) {
......
......@@ -2,7 +2,7 @@
// arguments passed to an executable and/or tie several other executables into
// a single executable.
//
// Copyright (C) 2006-2017 Samuel Newbold
// Copyright (C) 2006-2018 Samuel Newbold
#include <algorithm>
#include <iterator>
......@@ -39,16 +39,16 @@ Command_block* Command_block::apply(const Argm& argm, unsigned nesting,
else {
Command_block* result = new Command_block();
std::back_insert_iterator<std::vector<Arg_script> > ins(*result);
for (Command_block::const_iterator i = begin(); i != end(); ++i) {
i->apply(argm, nesting, ins, exceptions);}
for (auto i: *this) i.apply(argm, nesting, ins, exceptions);
result->trailing = trailing;
return result;}}
#include <iostream>
int Command_block::collect_errors_core(const Argm& src_argm,
const std::vector<std::string>& exceptional,
bool logic, Error_list& parent_exceptions) {
int ret;
for (const_iterator i = begin(); i != end() && !unwind_stack_v; ++i) {
for (auto j: *this) {
if (current_exception_count > max_collect) {
if (!collect_excess_thrown)
parent_exceptions.add_error(
......@@ -56,24 +56,23 @@ int Command_block::collect_errors_core(const Argm& src_argm,
unwind_stack_v = collect_excess_thrown = true;
return ret;}
Error_list children;
Argm statement_argm = i->interpret(src_argm, children);
Argm statement_argm = j.interpret(src_argm, children);
ret = executable_map.run(statement_argm, children);
if (children.size()) {
unwind_stack_v = false;
for (Error_list::iterator i = children.begin();
i != children.end();) {
for (auto k: children) {
parent_exceptions.push_back(k);
if (logic == (find(exceptional.begin(), exceptional.end(),
(*i)[0]) != exceptional.end()))
unwind_stack_v = true;
parent_exceptions.push_back(*i++);}}}
(k)[0]) != exceptional.end()))
unwind_stack_v = true;}}} // will cause subsequent j to not run
if (parent_exceptions.size()) unwind_stack_v = true;
return ret;}
int Command_block::execute(const Argm& src_argm,
Error_list& exceptions) const {
int ret;
for (const_iterator i = begin(); i != end(); ++i) {
Argm statement_argm = i->interpret(src_argm, exceptions);
for (auto j: *this) {
Argm statement_argm = j.interpret(src_argm, exceptions);
ret = executable_map.run(statement_argm, exceptions);
if (unwind_stack()) break;}
return ret;}
......@@ -93,12 +92,11 @@ int Command_block::prototype_execute(const Argm& argm,
throw error;}}
void Command_block::promote_soons(unsigned nesting) {
if (this)
for (iterator i = begin(); i != end(); ++i) i->promote_soons(nesting);}
if (this) for (auto j = begin(); j != end(); ++j) j->promote_soons(nesting);}
std::string Command_block::str() const {
std::string body;
for (const_iterator i = begin(); i != end()-1; ++i) body += i->str() + "";
for (auto i = begin(); i != end()-1; ++i) body += i->str() + "";
return "{" + body + back().str() + "}";} //+ trailing + ",";}
Command_block::Command_block(const std::string& src,
......
......@@ -6,17 +6,16 @@ objects = argm.o arg_script.o arg_spec.o builtin.o clock.o command_stream.o \
prototype.o selection.o substitution_stream.o variable_map.o
local_objects = rwsh_init.o
#CC = g++-7
#CXX = g++-7
CC = g++
CXX = g++
CXXFLAGS += -g -std=c++11
#CXXFLAGS += -g -std=c++17
CXX = g++-7
#CXX = g++
#CXXFLAGS += -g -std=c++11
CXXFLAGS += -g -std=c++17
LDLIBS = -lreadline
rwsh: $(objects) $(local_objects)
$(CXX) $^ $(CXXFLAGS) $(LDLIBS) -o $@
librwsh.a: $(objects)
ar -ruv librwsh.a $(objects)
ar -rv $@ $(objects)
arg_script.o: arg_spec.h rwsh_stream.h argm.h arg_script.h executable.h \
file_stream.h function.h prototype.h variable_map.h
......
// the registering of builtins
// Copyright Samuel Newbold 2005-2017
// Copyright Samuel Newbold 2005-2018
#include <list>
#include <map>
......
......@@ -4,9 +4,9 @@
)
.if .test_number_equal $# 2 {.source /etc/rwshrc-default}
.else_if .test_string_equal $2 -to {
.for ${.list_environment}$ {
.scope $1$ (var val) {
.global $var $val}}
.global EMPTY ()
.global SHELL /bin/rwsh
.global TESTABILITY (an=external var(iable))
.exec ./rwsh test_init.sh
.exit}
.else_if .test_number_equal $# 3 {
......
......@@ -329,7 +329,6 @@ fn ret {.return $*}
.if .return 1 {.nop}; .stepwise $* {.else_if_not $* {.nop}}; .else {.nop}}
.function or {
.if .return 1 {.nop}; .stepwise $* {.else_if $* {.nop}}; .else {.nop}}
.global TESTABILITY (an external variable)
fn st {
.collect_errors_except .nop {
/bin/rwsh -to <test_main.sh >last.test.result
......
......@@ -62,8 +62,7 @@ bool Simple_pattern::match(const std::string& s) const {
// convert to a string. inverse of constructor.
std::string Simple_pattern::str(void) const {
std::string result = initial;
for (auto i=terms.begin(); i != terms.end(); ++i)
result += '*' + *i;
for (auto j: terms) result += '*' + j;
if (unterminated) result += '*';
return result;}
......@@ -71,13 +70,11 @@ Entry_pattern::Entry_pattern(const std::string& src) {
std::vector<std::string> temp;
tokenize_strict(src, std::back_inserter(temp),
std::bind2nd(std::equal_to<char>(), ' '));
for (auto i = temp.begin(); i != temp.end(); ++i)
options.push_back(Simple_pattern(*i));
for (auto j: temp) options.push_back(Simple_pattern(j));
only_text = options.size() == 1 && options[0].is_only_text();}
bool Entry_pattern::match(const std::string& s) const {
for (auto i = options.begin(); i != options.end(); ++i)
if (i->match(s)) return true;
for (auto j: options) if (j.match(s)) return true;
return false;}
std::string Entry_pattern::str(void) const {
......
// The templates for selection read.
//
// Copyright (C) 2006-2016 Samuel Newbold
// Copyright (C) 2006-2018 Samuel Newbold
// modify partial by treating each element as a directory, and then replacing
// that element with the entries in that directory that match entry_pattern,
......@@ -8,16 +8,15 @@
template<class In>
void partial_match_children(In& partial, const Entry_pattern& entry_pattern,
const Entry_pattern& ignore_pattern, bool more) {
typename In::iterator first = partial.begin();
auto first = partial.begin();
while (first != partial.end()) {
std::vector<std::string> temp;
if (first->empty()) read_dir(".", std::back_inserter(temp));
else read_dir(*first, std::back_inserter(temp));
for (std::vector<std::string>::iterator k=temp.begin(); k!=temp.end();
++k) { // each element of directory
if (ignore_pattern.match(*k)) continue;
if (entry_pattern.match(*k)) {
first = partial.insert(first, *first + *k + (more? "/": ""));
for (auto k: temp) { // each element of directory
if (ignore_pattern.match(k)) continue;
if (entry_pattern.match(k)) {
first = partial.insert(first, *first + k + (more? "/": ""));
++first;}} // point back at dir we are reading
first = partial.erase(first);}}
......@@ -28,20 +27,19 @@ void selection_read(const std::string& src, Out res) {
str_to_entry_pattern_list(src, focus);
Entry_pattern ignore(Variable_map::global_map->get("FIGNORE"));
std::list<std::string> partial(1);
for (std::list<Entry_pattern>::const_iterator i=focus.begin();
i!=focus.end() && partial.size(); ++i){// each path step in the selection
std::list<Entry_pattern>::const_iterator k = i;
for (auto q=focus.begin();
q!=focus.end() && partial.size(); ++q){// each path step in the selection
auto k = q;
bool more = ++k != focus.end();
if (i->is_only_text())
for (std::list<std::string>::iterator j=partial.begin();
j!=partial.end(); ++j) {
*j += i->str();
if (q->is_only_text())
for (auto j = partial.begin(); j != partial.end(); ++j) {
*j += q->str();
if (more) *j += '/';
struct stat sb;
if (stat(j->c_str(), &sb)) {j = partial.erase(j); --j;}}
else partial_match_children(partial, *i, ignore, more);
else partial_match_children(partial, *q, ignore, more);
if (!partial.size())
throw Exception(Argm::Selection_not_found,
entry_pattern_list_to_str(focus.begin(), ++i), src);}
entry_pattern_list_to_str(focus.begin(), ++q), src);}
copy(partial.begin(), partial.end(), res);}
......@@ -524,7 +524,13 @@ $# Arg_spec::REFERENCE, interpret(), evaluate_expansion(), evaluate_var()
$.set A /bin
0
$.global B ((zero zero) ((one one) one) two three)
$.global B ( (zero zero) ((one one ) one ) two three)
0
$.global C ((external) () ( ) internal(parenthesis))
0
$.global broken (extra_close\) \(extra_open)
0
$e $A $0 @$A
......@@ -553,13 +559,13 @@ signal triggered: rwsh.invalid_word_selection ( $$1$ )
-1
$m $B {e $# $*}
2 (zero zero) ((one one) one) two three
2 (zero zero) ((one one ) one ) two three
0
$m $B$ {e $# $*}
5 zero zero (one one) one two three
5 zero zero (one one ) one two three
0
$m $B$$ {e $# $*}
7 zero zero one one one two three
7 zero zero one one one two three
0
$m $B$$$$ {e $# $*}
8 zero zero one one one two three
......@@ -572,11 +578,31 @@ signal triggered: rwsh.undefined_variable ( $B$10 )
-1
$m $B$1 {e $# $*}
2 (one one) one
2 (one one ) one
0
$m $B$$1 {e $# $*}
2 zero
0
$m $broken {e $# $*}
2 extra_close) (extra_open
0
$m $broken$ {e $# $*}
signal triggered: rwsh.mismatched_parenthesis ( extra_close) )
-1
$m $broken$$ {e $# $*}
signal triggered: rwsh.mismatched_parenthesis ( extra_close) )
-1
$m $C {e $# $*}
2 (external) () ( ) internal(parenthesis)
0
$m $C$ {e $# $*}
5 external internal(parenthesis)
0
$m $C$$ {e $# $*}
3 external internal(parenthesis)
0
$
0
......@@ -617,7 +643,7 @@ $m {m &B$$$$ {e $# $*}}
8 zero zero one one one two three
0
$m {m &B$1 {e $# $*}}
2 (one one) one
2 (one one ) one
0
$m {m &B$$1 {e $# $*}}
2 zero
......@@ -734,34 +760,34 @@ signal triggered: rwsh.invalid_word_selection ( @ )
-1
$m ${e $B} {e $# $*}
2 (zero zero) ((one one) one) two three
2 (zero zero) ((one one ) one ) two three
0
$m &{e $B} {e $# $*}
2 (zero zero) ((one one) one) two three
2 (zero zero) ((one one ) one ) two three
0
$m ${e $B}$ {e $# $*}
5 zero zero (one one) one two three
5 zero zero (one one ) one two three
0
$m &{e $B}$ {e $# $*}
5 zero zero (one one) one two three
5 zero zero (one one ) one two three
0
$e $# &{e $B}$
3 zero zero (one one) one two three
3 zero zero (one one ) one two three
0
$m {e $# &{e $B}$}
1 zero zero (one one) one two three
1 zero zero (one one ) one two three
0
$m &{e $B}$$ {e $# $*}
7 zero zero one one one two three
7 zero zero one one one two three
0
$m ${e $B}$$ {e $# $*}
7 zero zero one one one two three
7 zero zero one one one two three
0
$m {m ${e $B}$1 {e $# $*}}
2 (one one) one
2 (one one ) one
0
$m {m &{e $B}$1 {e $# $*}}
2 (one one) one
2 (one one ) one
0
$m {m ${e $B}$$$1 {e $# $*}}
2 zero
......@@ -5224,9 +5250,11 @@ $/usr/bin/printenv
.var_exists=must be requested to be checked
?=0
A=-7.29496e+09
C=(external) () ( ) internal(parenthesis)
FIGNORE=*de*
LC_ALL=C
N=4
broken=extra_close) (extra_open
last_command_return=0
nl=
......@@ -5242,21 +5270,6 @@ $# .list_environment
0
$.global SHELL unmodified
0
$/usr/bin/printenv
.var_exists=must be requested to be checked
?=0
A=-7.29496e+09
FIGNORE=*de*
LC_ALL=C
N=4
SHELL=unmodified
last_command_return=0
nl=
original_message=Exception for failed handler. Original exception with call stack:
0
$.list_environment x
signal triggered: rwsh.bad_argc ( 1 0 0 .list_environment )
......@@ -5272,7 +5285,7 @@ $for ${.list_environment}$ {
0
$e $TESTABILITY
an external variable
an=external var(iable)
0
$e $SHELL
unmodified
......@@ -5285,10 +5298,29 @@ $for ${.list_environment}$ {
0
$e $TESTABILITY
an external variable
an=external var(iable)
0
$e $SHELL
/bin/rwsh
0
$/usr/bin/printenv
.var_exists=must be requested to be checked
?=0
A=-7.29496e+09
C=(external) () ( ) internal(parenthesis)
EMPTY=
FIGNORE=
LC_ALL=C
N=4
SHELL=/bin/rwsh
TESTABILITY=an=external var(iable)
broken=extra_close) (extra_open
last_command_return=0
nl=
original_message=Exception for failed handler. Original exception with call stack:
0
$.set_max_collectible_exceptions 7
......
......@@ -112,7 +112,9 @@ sort test_files/tmp
# Arg_spec::REFERENCE, interpret(), evaluate_expansion(), evaluate_var()
.set A /bin
.global B ((zero zero) ((one one) one) two three)
.global B ( (zero zero) ((one one ) one ) two three)
.global C ((external) () ( ) internal(parenthesis))
.global broken (extra_close\) \(extra_open)
e $A $0 @$A
e A $1 1 $$3 $$$3
e A 1 2 3 4 5 6 7 $$$$$$$$$8
......@@ -128,6 +130,12 @@ m {m $B$$$$ {e $# $*}}
m $B$10 {e $# $*}
m $B$1 {e $# $*}
m $B$$1 {e $# $*}
m $broken {e $# $*}
m $broken$ {e $# $*}
m $broken$$ {e $# $*}
m $C {e $# $*}
m $C$ {e $# $*}
m $C$$ {e $# $*}
# Arg_spec::SOON, apply()
e A &1 1 &$3 &$$3
......@@ -1427,7 +1435,6 @@ rwsh.vars
# .list_environment
.global SHELL unmodified
/usr/bin/printenv
.list_environment x
.list_environment {excess argfunc}
for ${.list_environment}$ {
......@@ -1440,6 +1447,7 @@ for ${.list_environment}$ {
.scope $1$ (var val) {setf $var $val; .nop $$var}}
e $TESTABILITY
e $SHELL
/usr/bin/printenv
.set_max_collectible_exceptions 7
.collect_errors_except .nop {${.throw echo exception from inside substitution}}
.collect_errors_only .nop {${.throw echo exception from inside substitution}}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment