Commit f692d832 authored by Samuel Newbold's avatar Samuel Newbold

Semicolon divides statements outside of argfunctions

Also,
 *  Separate errors for unclosed_brace and unclosed_parenthesis
 *  .source uses the – [argv ...] prototype
 *  command lines are no longer used as arguments to interpret
    themselves. This was a cute feature that got used several
    times in the test suite, and never anywhere else.
parent eebd9138
......@@ -48,8 +48,10 @@ std::string::size_type Arg_script::add_quote(const std::string& src,
split += 1;
break;
default: std::abort();}
if (split == std::string::npos)
throw Unclosed_parenthesis(src.substr(0, point+1));
if (split == std::string::npos) {
errors.add_error(Exception(Argm::Unclosed_parenthesis,
src.substr(0, point+1)));
return std::string::npos;}
else {
literal += src.substr(point+1, split-point-1);
point = src.find_first_not_of(WSPACE, split+1);
......@@ -96,21 +98,6 @@ Arg_script::Arg_script(const Rwsh_istream_p& input_i,
argfunction(0), argfunction_level(0), input(input_i), output(output_i),
error(error_i), indent(indent_i), terminator(terminator_i) {}
Arg_script::Arg_script(const std::string& src, unsigned max_soon,
Error_list& errors) :
argfunction(0), argfunction_level(0), input(default_input),
output(default_output), error(default_error), terminator('!') {
auto point = src.find_first_not_of(WSPACE, 0);
indent = src.substr(0, point);
point = constructor(src, point, max_soon, errors);
if (point < src.length())
if (src[point] == '}' || src[point] == ';') {
errors.add_error(Exception(Argm::Mismatched_brace,src.substr(0,point+1)));
while (point < src.length()) // see if anything else is wrong
point = constructor(src, ++point, max_soon, errors);}
else std::abort();
else;}
Arg_script::Arg_script(const std::string& src, std::string::size_type& point,
unsigned max_soon, Error_list& errors) :
argfunction(0), argfunction_level(0), input(default_input),
......@@ -138,7 +125,10 @@ std::string::size_type Arg_script::constructor(const std::string& src,
argfunction_level = 3;
else std::abort(); // unhandled argfunction level
else;
if (src[point] == '}') terminator = *"";
if (point >= src.length()) {
terminator = *"";
point = std::string::npos;}
else if (src[point] == '}') terminator = *"";
else terminator = src[point];
return point;}
......
......@@ -23,9 +23,8 @@ class Arg_script {
std::string::size_type parse_token(const std::string& src,
std::string::size_type token_start, unsigned max_soon,
Error_list& errors);
public:
Arg_script(const std::string& src, unsigned max_soon, Error_list& errors);
public:
Arg_script(const std::string& src, std::string::size_type& point,
unsigned max_soon, Error_list& errors);
Arg_script(const Arg_script& src);
......
......@@ -126,15 +126,17 @@ Arg_spec::Arg_spec(const std::string& src, std::string::size_type style,
parse_brace_type(src, max_soon, style, point, errors);
if (type == FIXED) {
auto split = src.find_first_of('}', point);
if (split == std::string::npos)
throw Unclosed_brace(src.substr(0, point-1));
if (src[style] == '[')
if (src[split+1] == ']') ++split;
else errors.add_error(Exception(Argm::Mismatched_bracket,
src.substr(style, split-style+1)));
else;
text = src.substr(style, split-style+1);
point = split+1;}
if (split == std::string::npos) {
errors.add_error(Exception(Argm::Unclosed_brace, src.substr(0, point+1)));
point = std::string::npos;}
else {
if (src[style] == '[')
if (src[split+1] == ']') ++split;
else errors.add_error(Exception(Argm::Mismatched_bracket,
src.substr(style, split-style+1)));
else;
text = src.substr(style, split-style+1);
point = split+1;}}
else {
substitution = new Command_block(src, point, soon_level, errors);
if (point < src.length() && !sub_term_char(src[point]))
......
......@@ -10,7 +10,7 @@ call stack .source .try_catch_recursive(body)
.function_all_flags .after_command -- args ... [.{argfunction}] {.nop $args}
.function_all_flags .prompt {.echo \$}
.function_all_flags .vars {.internal_vars}
.source /etc/rwshrc-basic
.source /etc/rwshrc-basic $argv$
.function_all_flags # -- [ignored ...] [.{argfunction}] {.nop $ignored$}
.function_all_flags fn -- prototype ... .{argfunction} {
.function_all_flags $prototype$ {.argfunction}}
......@@ -151,10 +151,14 @@ call stack .source .try_catch_recursive(body)
.function_all_flags .mismatched_bracket context [stack ...] {
echo mismatched bracket: $context
if_only .var_exists stack {echo call stack: $stack$}}
.function .mismatched_parenthesis {
.echo signal triggered: $0 \( $* \); .combine $nl
echo mismatched parenthesis: $1
echo call stack: $*2}
.function_all_flags .mismatched_parenthesis string [stack ...] {
.echo signal triggered: $0 \( $string $stack$ \); .combine $nl
echo mismatched parenthesis: $string
echo call stack: $stack$}
.function_all_flags .unclosed_parenthesis string [stack ...] {
.echo signal triggered: $0 \( $string $stack$ \); .combine $nl
echo mismatched parenthesis: $string
echo call stack: $stack$}
.function_all_flags .missing_argfunction cmd [add_stack ...] {
echo $cmd requires an argfunction
if_only .var_exists add_stack {echo stack $add_stack$}}
......@@ -184,6 +188,7 @@ call stack .source .try_catch_recursive(body)
.function_all_flags .post_dash_dash_flag -- flag stack ... {
echo flag option $flag occurs after -- in the prototype
echo call stack: $stack$}
.function_all_flags .prompt {.echo \$}
.function_all_flags .result_range -- lhs rhs op [stack ...] {
echo result of $op with arguments $lhs and $rhs is out of range
echo call stack: $op $stack$}
......@@ -232,6 +237,8 @@ call stack .source .try_catch_recursive(body)
echo call stack: $stack$}
.function_all_flags .unchecked_variable -- var [stack ...] {
echo $var was not checked with call stack $stack$}
.function_all_flags .unclosed_brace context [stack ...] {
echo unclosed brace: $context $stack$}
.function_all_flags .undeclared_variable -- name [stack ...] {
echo $name was not declared
echo call stack: $stack$}
......@@ -353,26 +360,7 @@ fn ln [-?] target {
.test_file_exists $target
&{.which_path ln /bin:/usr/bin} $-* $target}
fn test -- args ... {.try_catch_recursive .return_code {${whichp test} $args$}}
.else_if .test_string_equal $2 -c {
.for ${.list_environment}$ {
.scope $1$ (-- var val) {
.if .var_exists $var {.nop $val}
.else {
.global $var $val
.nop $$var}}}
.source /etc/rwshrc-basic
.nop $FIGNORE
.function_all_flags .shutdown -- [args ...] {.nop $args}
.function_all_flags .return_code code cmd [add_stack ...] {
echo $cmd returned $code : call stack $cmd $add_stack$
.exit $code}
.collect_errors_except .nop {
.mapped_argfunction &3 {$1$}
.exit 0}}
.else {
.echo unexpected command line: &* (
)
.source /etc/rwshrc-default}
if_only .var_exists argv {.error ignored excess arguments $argv $nl}
$.echo $nl $nl $nl $nl
......
......@@ -103,6 +103,8 @@ class Argm {
Sigunknown,
Tardy_flag,
Unchecked_variable,
Unclosed_brace,
Unclosed_parenthesis,
Undeclared_variable,
Undefined_variable,
Unfinished_if_block,
......@@ -182,14 +184,6 @@ struct Exception : public Argm {
Exception(Exception_t exception, int x, int y, int z);
Exception(Exception_t exception, const Argm& src);};
struct Unclosed_brace : public Exception {
Unclosed_brace(const std::string& prefix) :
Exception(Argm::Mismatched_brace, prefix) {}};
struct Unclosed_parenthesis : public Exception {
Unclosed_parenthesis(const std::string& prefix_i) :
Exception(Argm::Mismatched_parenthesis, prefix_i) {}};
struct Undefined_variable : public Exception {
Undefined_variable(const std::string& name_i) :
Exception(Argm::Undefined_variable, name_i) {}};
......
......@@ -525,18 +525,22 @@ void b_source(const Argm& argm, Error_list& exceptions) {
throw Exception(Argm::File_open_failure, argm[1]);
if (!(sb.st_mode & S_IXUSR)) throw Exception(Argm::Not_executable, argm[1]);
Rwsh_istream_p src(new File_istream(argm[1]), false, false);
Argm script_arg(argm.subrange(1), nullptr, argm.parent_map(),
argm.input, argm.output.child_stream(), argm.error);
Command_stream command_stream(src, false);
Arg_script script("", 0, exceptions);
while (!command_stream.fail() && !global_stack.unwind_stack())
try {
command_stream.getline(script, exceptions);
Command_block block;
Prototype prototype(Argv{"--", "[argv", "...]"});
Variable_map locals(argm.parent_map());
prototype.arg_to_param(argm.subrange(1), locals, exceptions);
Argm script_arg(argm.subrange(1), nullptr, &locals,
argm.input, argm.output.child_stream(), argm.error);
try {
while (!command_stream.fail() && !global_stack.unwind_stack()) {
command_stream.getline(block, exceptions);
if (command_stream.fail()) break;
Argm command(script.interpret(script_arg, exceptions));
if (global_stack.unwind_stack()) break;
executable_map.run(command, exceptions);}
catch (Exception exception) {exceptions.add_error(exception);}}
block.execute(script_arg, exceptions);}
prototype.unused_var_check(&locals, exceptions);}
catch (Exception error) {
prototype.unused_var_check(&locals, exceptions);
throw error;}}
// run the argument function once with each command in the specified function
// invocation
......@@ -549,7 +553,7 @@ void b_stepwise(const Argm& argm, Error_list& exceptions) {
if (!f) return; //throw Exception(Argm::Not_a_function, argm[1]);
// this must be caught and handled to use .stepwise recursively
Variable_map locals(lookup.parent_map());
f->arg_to_param(lookup, locals, exceptions);
f->arg_to_param(lookup.argv(), locals, exceptions);
if (global_stack.unwind_stack()) return;
Argm params(lookup.argv(), lookup.argfunction(), &locals,
lookup.input, lookup.output, lookup.error);
......
......@@ -32,7 +32,8 @@ Command_stream::Command_stream(Rwsh_istream_p& s, bool subprompt_i) :
src(s), subprompt(subprompt_i) {}
// write the next command to dest. run .prompt as appropriate
Command_stream& Command_stream::getline(Arg_script& dest, Error_list& errors) {
Command_stream& Command_stream::getline(Command_block& dest,
Error_list& errors) {
if (this->fail()) return *this;
std::string cmd;
for (bool cmd_is_incomplete=true; cmd_is_incomplete;) {
......@@ -46,24 +47,23 @@ Command_stream& Command_stream::getline(Arg_script& dest, Error_list& errors) {
src.getline(line);
gettimeofday(&after_input, rwsh_clock.no_timezone);
rwsh_clock.user_wait(before_input, after_input);
if (fail())
std::string::size_type point = 0;
if (fail()) {
if (cmd.size()) { // EOF without a complete command
Exception raw_command(Argm::Raw_command, cmd);
executable_map.run_handling_exceptions(raw_command, errors);
Arg_script(cmd, 0, errors);} // this will throw the right exception
else return *this;
Command_block(cmd, point, 0, errors);} // will throw the right exception
return *this;}
else cmd += line;
try {
dest = Arg_script(cmd, 0, errors);
if (global_stack.unwind_stack()) {
Exception raw_command(Argm::Raw_command, cmd);
global_stack.catch_one(raw_command, errors);
return *this;}
cmd_is_incomplete = false;}
catch (Unclosed_parenthesis exception) {
cmd += '\n';}
catch (Unclosed_brace exception) {
cmd += '\n';}}
dest = Command_block(cmd, point, 0, errors);
if (global_stack.remove_exceptions(".unclosed_brace", errors) ||
global_stack.remove_exceptions(".unclosed_parenthesis", errors))
cmd += '\n';
else if (global_stack.unwind_stack()) {
Exception raw_command(Argm::Raw_command, cmd);
global_stack.catch_one(raw_command, errors);
return *this;}
else cmd_is_incomplete = false;}
Exception raw_command(Argm::Raw_command, cmd);
executable_map.run_handling_exceptions(raw_command, errors);
return *this;}
......
......@@ -5,5 +5,5 @@ class Command_stream {
bool subprompt;
public:
Command_stream (Rwsh_istream_p& s, bool subprompt);
Command_stream& getline(Arg_script& dest, Error_list& errors);
Command_stream& getline(Command_block& dest, Error_list& errors);
bool fail () const; };
......@@ -3,7 +3,7 @@
// its key so that it can return argument functions which are part of the Argm
// object.
//
// Copyright (C) 2005-2017 Samuel Newbold
// Copyright (C) 2005-2019 Samuel Newbold
#include <list>
#include <map>
......@@ -115,9 +115,11 @@ void Executable_map::not_found(Argm& argm_i, Error_list& exceptions) {
Argm prototype_argm(argm_i.parent_map(), argm_i.input, argm_i.output,
argm_i.error);
tokenize_words("cmd [args ...]", std::back_inserter(prototype_argm));
std::string::size_type point = 0;
Command_block body("{.echo $cmd (: command not found) "
"\\( $cmd $args$ \\); .echo (\n)}",
point, 0, exceptions);
set(new Function(Argm::exception_names[Argm::Function_not_found],
prototype_argm.argv(),
"{.echo $cmd (: command not found) \\( $cmd $args$ \\);"
" .echo (\n)}", exceptions));}
prototype_argm.argv(), body));}
throw Exception(Argm::Function_not_found, argm_i);}
......@@ -36,7 +36,7 @@ Builtin::Builtin(const std::string& name_i,
// run the given builtin
void Builtin::execute(const Argm& argm, Error_list& exceptions) const {
Variable_map locals(argm.parent_map());
prototype.arg_to_param(argm, locals, exceptions);
prototype.arg_to_param(argm.argv(), locals, exceptions);
locals.bless_unused_vars();
if (prototype.non_prototype) std::abort();
else if (argm.argfunction() && prototype.exclude_argfunction)
......@@ -77,7 +77,7 @@ void Command_block::prototype_execute(const Argm& argm,
const Prototype& prototype,
Error_list& exceptions) const {
Variable_map locals(argm.parent_map());
prototype.arg_to_param(argm, locals, exceptions);
prototype.arg_to_param(argm.argv(), locals, exceptions);
if (prototype.non_prototype);
else if (argm.argfunction() && prototype.exclude_argfunction)
exceptions.add_error(Exception(Argm::Excess_argfunction));
......@@ -101,38 +101,29 @@ std::string Command_block::str() const {
for (auto i = begin(); i != end()-1; ++i) body += i->str() + "";
return "{" + body + back().str() + "}";} //+ trailing + ",";}
// if src[point] == '{' , then the block ends at the matching '}', otherwise
// it continues to the end of the string.
Command_block::Command_block(const std::string& src,
std::string::size_type& point,
unsigned max_soon, Error_list& errors) {
std::string::size_type tpoint = point;
while (tpoint != std::string::npos && src[tpoint] != '}') {
push_back(Arg_script(src, ++tpoint, max_soon, errors));
while (tpoint != std::string::npos) {
if (src[tpoint] == '}')
if (src[point] == '{') break;
else errors.add_error(Exception(Argm::Mismatched_brace,
src.substr(0, tpoint+1)));
else;
if (src[tpoint] == '{' || src[tpoint] == '}' ||
src[tpoint] == ';' || src[tpoint] =='\n') ++tpoint;
push_back(Arg_script(src, tpoint, max_soon, errors));
if (size() != 1 && back().is_argfunction())
default_output <<".argfunction cannot occur as one of several "
"commands\n";}
if (tpoint == std::string::npos)
throw Unclosed_brace(src.substr(0, point-1));
if (!size()) push_back(Arg_script("", max_soon, errors));
point = tpoint + 1;}
Function::Function(const std::string& name_i,
const Argv& parameters,
const std::string& src, Error_list& errors) :
name_v(name_i), prototype(parameters) {
std::string::size_type point = 0;
try {
body = Command_block(src, point, 0, errors);
// this error handling is not simply testable because it requires bad
// functions in rwsh_init.cc
if (point != src.length())
throw "function with text following closing brace " + name_i + "\n" +
src.substr(point) + "\n";}
catch (Unclosed_brace error) {
throw "unclosed brace on construction of function " + name_i + "\n" +
error[1] + "\n";}
catch (Unclosed_parenthesis error) {
throw "unclosed parenthesis on construction of function " + name_i + "\n" +
error[1] + "\n";}}
if (tpoint == std::string::npos) {
if (src[point] == '{') errors.add_error(Exception(Argm::Unclosed_brace,
src.substr(0, point-1)));
point = std::string::npos;}
else point = tpoint + 1;}
Function::Function(const std::string& name_i, const Argv& parameters,
const Command_block& src) :
......
......@@ -53,17 +53,15 @@ class Function : public Named_executable {
public:
Command_block body;
Function(const std::string& name, const Argv& parameters,
const std::string& src, Error_list& errors);
Function(const std::string& name_i, bool non_prototype_i,
const Command_block& src);
Function(const std::string& name_i, const Argv& parameters,
const Command_block& src);
Function(const Function& src) :
name_v(src.name_v), prototype(src.prototype), body(src.body) {}
void arg_to_param(const Argm& invoking_argm, Variable_map& locals,
void arg_to_param(const Argv& invoking_argv, Variable_map& locals,
Error_list& exceptions) const {
return prototype.arg_to_param(invoking_argm, locals, exceptions);}
return prototype.arg_to_param(invoking_argv, locals, exceptions);}
Function* copy_pointer(void) const {
if (!this) return 0;
else return new Function(*this);};
......
......@@ -160,7 +160,7 @@ Prototype::Prototype(const Argv& parameters) :
has_elipsis = true;
elipsis_var = group.names[group.elipsis];}}}
void Prototype::arg_to_param(const Argm& argm, Variable_map& locals,
void Prototype::arg_to_param(const Argv& argv, Variable_map& locals,
Error_list& exceptions) const {
if (non_prototype) return;
enum Dash_dash_type dash_dash = dash_dash_position? UNSEEN:
......@@ -169,16 +169,16 @@ void Prototype::arg_to_param(const Argm& argm, Variable_map& locals,
else if (flag_options.size()) locals.param("-*", "");
int needed = required_argc;
std::string missing;
auto f_arg = argm.begin()+1;
auto f_arg = argv.begin()+1;
auto param = positional.begin();
for (int available = argm.argc()-1; f_arg != argm.end();)
for (int available = argv.size()-1; f_arg != argv.end();)
if ((*f_arg)[0] == '-' && f_arg->length() > 1 && dash_dash != BARE) {
auto h = flag_options.find(*f_arg);
if (dash_dash == BRACKET && *f_arg != "--") {
--available;
exceptions.add_error(Exception(Argm::Tardy_flag, *f_arg++));}
else if (h != flag_options.end())
h->second.arg_to_param(available, needed, missing, f_arg, argm.end(),
h->second.arg_to_param(available, needed, missing, f_arg, argv.end(),
&h->second.names[0], elipsis_var, dash_dash,
locals, exceptions);
else {
......@@ -193,14 +193,14 @@ void Prototype::arg_to_param(const Argm& argm, Variable_map& locals,
else if (param == positional.end()) break;
else {
if (param->required || available > needed)
param->arg_to_param(available, needed, missing, f_arg, argm.end(),
param->arg_to_param(available, needed, missing, f_arg, argv.end(),
nullptr, elipsis_var, dash_dash, locals,
exceptions);
else param->add_undefined_params(locals);
if (++param - positional.begin() == dash_dash_position)
dash_dash = bare_dash_dash? BARE: BRACKET;}
if (f_arg != argm.end() || needed || missing.length())
bad_args(missing, locals, f_arg, argm.end(), param, exceptions);
if (f_arg != argv.end() || needed || missing.length())
bad_args(missing, locals, f_arg, argv.end(), param, exceptions);
if (param != positional.end()) {
if (param->elipsis == -1) {
const std::string& var((param-1)->names.back());
......
......@@ -43,7 +43,7 @@ class Prototype {
bool required_argfunction;
Prototype(bool non_prototype);
Prototype(const Argv& parameters);
void arg_to_param(const Argm& invoking_argm, Variable_map& locals,
void arg_to_param(const Argv& invoking_argm, Variable_map& locals,
Error_list& exceptions) const;
void bad_args(std::string& missing, const Variable_map& locals,
Argm::const_iterator f_arg, Argm::const_iterator end,
......
......@@ -109,6 +109,8 @@ std::string Argm::exception_names[Argm::Exception_count] = {
".sigunknown",
".tardy_flag",
".unchecked_variable",
".unclosed_brace",
".unclosed_parenthesis",
".undeclared_variable",
".undefined_variable",
".unfinished_if_block",
......@@ -143,27 +145,30 @@ int main(int argc, char *argv[]) {
Argm init_command(".init", std_argv,
nullptr, Variable_map::global_map,
default_input, default_output, default_error);
Argm interpret(".interpret", Argv(),
nullptr, Variable_map::global_map,
default_input, default_output, default_error);
executable_map.base_run(init_command, exceptions);
register_signals();
Arg_script script("", 0, exceptions);
Command_block block;
Exception prompt(Argm::Prompt);
while (!command_stream.fail()) {
executable_map.base_run(prompt, exceptions);
Argm command(Variable_map::global_map,
default_input, default_output, default_error);
try {
command_stream.getline(script, exceptions);
if (exceptions.size()) {
global_stack.exception_handler(exceptions);
continue;}
else if (command_stream.fail()) break;
else command = script.interpret(script.argm(), exceptions);}
catch (Exception exception) {command = exception;}
executable_map.run_if_exists(".before_command", command);
if (exceptions.size()) global_stack.exception_handler(exceptions);
else if (!executable_map.run_if_exists(".run_logic", command))
executable_map.base_run(command, exceptions);
executable_map.run_if_exists(".after_command", command);}
command_stream.getline(block, exceptions);
if (exceptions.size()) {
global_stack.exception_handler(exceptions);
continue;}
else if (command_stream.fail()) break;
else for (auto j: block) {
try {command = j.interpret(interpret, exceptions);}
catch (Exception exception) {command = exception;}
executable_map.run_if_exists(".before_command", command);
if (exceptions.size()) global_stack.exception_handler(exceptions);
else if (!executable_map.run_if_exists(".run_logic", command))
executable_map.base_run(command, exceptions);
executable_map.run_if_exists(".after_command", command);}}
Argm shutdown_command(Argm::exception_names[Argm::Shutdown],
std_argv, nullptr, Variable_map::global_map,
default_input, default_output, default_error);
......
......@@ -23,14 +23,20 @@
#include "function.h"
inline void bi(const std::string& name,
void bi(const std::string& name,
void (*implementation)(const Argm& argm, Error_list& exceptions),
const Argv& parameters) {
executable_map.set(new Builtin(name, implementation, parameters));}
inline void fn(const std::string& name, const Argv& parameters,
const std::string& body, Error_list& exceptions) {
executable_map.set(new Function(name, parameters, body, exceptions));}
void fn(const std::string& name, const Argv& parameters,
const std::string& src, Error_list& exceptions) {
std::string::size_type point = 0;
Command_block body(src, point, 0, exceptions);
if (point != src.length() && point != std::string::npos) std::abort();
// testing this error handling requires bad functions in internal_init()
else if (global_stack.unwind_stack())
global_stack.exception_handler(exceptions);
else executable_map.set(new Function(name, parameters, body));}
void internal_init(Error_list& exceptions) {
bi(".argc", b_argc, Argv {"--", "[list", "...]"});
......@@ -70,23 +76,24 @@ void internal_init(Error_list& exceptions) {
bi(".global", b_global, Argv {"--", "var", "value"});
bi(".if", b_if, Argv {"--", "condition", "...", ".{argfunction}"});
fn(".init", Argv {"--", "[args", "...]"},
"{.set_max_nesting 10\n"
" .function_all_flags .file_open_failure name stack ... {"
".set_max_nesting 10\n"
" .function_all_flags .file_open_failure name stack ... {.nop\n"
" .combine (init file ) $name ( does not exist\n"
"call stack ) $stack (\n)}\n"
" .function_all_flags .raw_command -- args ... {.nop $args}\n"
" .source /etc/rwshrc $args$\n"
" .for &{.internal_functions}$ {" //.echo $1; .whence_function $1}\n"
" .if .test_executable_exists $1 {.nop}\n"
" .else {.echo &&1 not defined (\n)}}\n"
" .if .test_executable_exists .help {"
" .if .test_not_empty ${.help} {.nop}\n"
" .else {.echo .help produces no output (\n)}}\n"
" .else {.echo .help not defined (\n)}}", exceptions);
" .collect_errors_except .nop {.nop\n"
" .source /etc/rwshrc $args$\n"
" .for &{.internal_functions}$ {\n"
" .if .test_executable_exists $1 {.nop}\n"
" .else {.echo &&&1 not defined (\n)}}\n"
" .if .test_executable_exists .help {.nop\n"
" .if .test_not_empty ${.help} {.nop}\n"
" .else {.echo .help produces no output (\n)}}\n"
" .else {.echo .help not defined (\n)}}", exceptions);
fn(".internal_features", Argv {},
"{.echo (.after_command .before_command .run_logic\n)}", exceptions);
".echo (.after_command .before_command .run_logic\n)", exceptions);
bi(".internal_functions", b_internal_functions, Argv {});
fn(".internal_vars", Argv {}, "{.echo (FIGNORE\n)}", exceptions);
fn(".internal_vars", Argv {}, ".echo (FIGNORE\n)", exceptions);
bi(".is_default_input", b_is_default_input, Argv {});
bi(".is_default_output", b_is_default_output, Argv {});
bi(".is_default_error", b_is_default_error, Argv {});
......@@ -112,7 +119,7 @@ void internal_init(Error_list& exceptions) {
bi(".set_max_extra_exceptions", b_set_max_extra_exceptions,
Argv {"--", "maximum"});
bi(".set_max_nesting", b_set_max_nesting, Argv {"--", "maximum"});
fn(".shutdown", Argv {"--", "[args", "...]"}, "{.nop $args; .exit 10}",
fn(".shutdown", Argv {"--", "[args", "...]"}, ".nop $args; .exit 10",
exceptions);
bi(".source", b_source, Argv {"--", "file", "[args", "...]"});
bi(".stepwise", b_stepwise, Argv {"--", "command", "...", ".{argfunction}"});
......
......@@ -3,40 +3,43 @@
.set_max_nesting 20
.function_all_flags () {.nop}
.function_all_flags #! -- ignored ... {.nop $ignored}
.function_all_flags .autofunction -- cmd [args ...] {
.nop $args$
.function_all_flags .autofunction -- cmd [args ...] [.{argfunction}] {
.if .var_exists args {.nop $args}
.else {.nop}
.nop {argfunction}
.local full_path ${.which_path $cmd $PATH}
if_only_not .test_executable_exists $full_path {.binary $full_path}
if_only_not .test_string_equal $cmd $full_path {
.function_all_flags $cmd -- [args ...] {
&&full_path $args$}}
.error added $cmd to executable map $nl}
.if .test_number_equal $# 2 {.source /etc/rwshrc-default}
.else_if .test_string_equal $2 -to {
.global SHELL /bin/rwsh
.global TESTABILITY (an=external var(iable))
.exec ./rwsh test_init.sh
.exit 0}
.else_if .test_number_equal $# 3 {
.nop .source /etc/rwshrc-default
.source &2}
.else_if .test_string_equal $2 -c {
.for ${.list_environment}$ {
.scope $1$ (-- var val) {
.if .var_exists $var {.nop $val}
.else {
.global $var $val
.nop $$var}}}
.source /etc/rwshrc-basic
.nop $FIGNORE
.function_all_flags .shutdown -- [args ...] {.nop $args}
.function_all_flags .return_code code cmd [add_stack ...] {
echo $cmd returned $code : call stack $cmd $add_stack$
.exit $code}
.collect_errors_except .nop {
.mapped_argfunction &3 {$1$}
.exit 0}}
.if .test_less ${.argc $argv$} 2 {.source /etc/rwshrc-default}
.else {
.echo unexpected command line: &* (
.if .test_string_equal $argv$1 -to {
.global SHELL /bin/rwsh
.global TESTABILITY (an=external var(iable))
.exec ./rwsh test_init.rwsh
.exit 0}
.else_if .test_number_equal ${.argc $argv$} 2 {
.nop .source /etc/rwshrc-default
.source $argv$1}
.else_if .test_string_equal $argv$1 -c {
.for ${.list_environment}$ {
.scope $1$ (-- var val) {
.if .var_exists $var {.nop $val}
.else {
.global $var $val
.nop $$var}}}
.source /etc/rwshrc-basic
.nop $FIGNORE
.function_all_flags .shutdown -- [args ...] {.nop $args}
.function_all_flags .return_code code cmd [add_stack ...] {
echo $cmd returned $code : call stack $cmd $add_stack$
.exit $code}
.collect_errors_except .nop {
.mapped_argfunction $argv$2 {$1$}
.exit 0}}
.else {
.echo unexpected command line: $argv$ (
)
.source /etc/rwshrc-default}
.source /etc/rwshrc-default}}
......@@ -138,10 +138,14 @@
.function_all_flags .mismatched_bracket context [stack ...] {
echo mismatched bracket: $context
if_only .var_exists stack {echo call stack: $stack$}}
.function .mismatched_parenthesis {
.echo signal triggered: $0 \( $* \); .combine $nl
echo mismatched parenthesis: $1
echo call stack: $*2}
.function_all_flags .mismatched_parenthesis string [stack ...] {
.echo signal triggered: $0 \( $string $stack$ \); .combine $nl
echo mismatched parenthesis: $string
echo call stack: $stack$}
.function_all_flags .unclosed_parenthesis string [stack ...] {
.echo signal triggered: $0 \( $string $stack$ \); .combine $nl
echo mismatched parenthesis: $string
echo call stack: $stack$}
.function_all_flags .missing_argfunction cmd [add_stack ...] {
echo $cmd requires an argfunction
if_only .var_exists add_stack {echo stack $add_stack$}}
......@@ -171,6 +175,7 @@
.function_all_flags .post_dash_dash_flag -- flag stack ... {
echo flag option $flag occurs after -- in the prototype
echo call stack: $stack$}
.function_all_flags .prompt {.echo \$}
.function_all_flags .result_range -- lhs rhs op [stack ...] {
echo result of $op with arguments $lhs and $rhs is out of range
echo call stack: $op $stack$}
......@@ -219,6 +224,8 @@
echo call stack: $stack$}
.function_all_flags .unchecked_variable -- var [stack ...] {
echo $var was not checked with call stack $stack$}
.function_all_flags .unclosed_brace context [stack ...] {
echo unclosed brace: $context $stack$}
.function_all_flags .undeclared_variable -- name [stack ...] {
echo $name was not declared
echo call stack: $stack$}
......@@ -340,3 +347,4 @@ fn ln [-?] target {
.test_file_exists $target
&{.which_path ln /bin:/usr/bin} $-* $target}
fn test -- args ... {.try_catch_recursive .return_code {${whichp test} $args$}}
if_only .var_exists argv {.error ignored excess arguments $argv $nl}
.nop $argv$
.for ${.list_environment}$ {
.scope $1$ (-- var val) {
.if .var_exists $var {.nop $val}
......@@ -155,7 +156,7 @@ sfn wc
fn unselect {.set s ()}
# internal functions
fn .run_logic -- cmd [args ...] {
fn .run_logic -- cmd [args ...] [.{argfunction}] {
.try_catch_recursive &{.internal_functions}$ {$cmd $args$ {.argfunction}}
# $* {.argfunction}}
fn .prompt {.echo $s; .echo \$}
......@@ -231,3 +232,4 @@ fn bless-arg {&{whichp cp} argfunction.result.last argfunction.basic-result}
.else {
.combine rwsh\ v &{.version} $nl
.global already-initialized true}
if_only .var_exists argv {.error ignored excess arguments $argv $nl}
This diff is collapsed.