-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexecutable_map.cc
More file actions
125 lines (109 loc) · 4.64 KB
/
executable_map.cc
File metadata and controls
125 lines (109 loc) · 4.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// The definition of the Executable_map class, which defines the mapping
// between executable names and Executable objects. It takes an Argm as
// its key so that it can return argument functions which are part of the Argm
// object.
//
// Copyright (C) 2005-2023 Samuel Newbold
#include <list>
#include <map>
#include <set>
#include <string>
#include <sys/time.h>
#include <vector>
#include "rwsh_stream.h"
#include "variable_map.h"
#include "argm.h"
#include "arg_script.h"
#include "call_stack.h"
#include "executable.h"
#include "executable_map.h"
#include "prototype.h"
#include "tokenize.cc"
#include "function.h"
Executable_map::Executable_map(void) : in_autofunction(false) {}
// insert target into map, with key target->name(), replacing old value if key
// is already in the map
void Executable_map::set(Named_executable* target) {
std::pair<iterator, bool> ret;
ret = insert(std::make_pair(target->name(), target));
if (!ret.second) { // replace if key already exists
if (!ret.first->second->is_running()) delete ret.first->second;
else ret.first->second->del_on_term = true;
Base::erase(ret.first);
insert(std::make_pair(target->name(), target));}}
Executable_map::size_type Executable_map::erase (const std::string& key) {
iterator pos = Base::find(key);
if (pos == end()) return 0;
else {
if (!pos->second->is_running()) delete pos->second;
else pos->second->del_on_term = true;
Base::erase(pos);
return 1;}}
Base_executable* Executable_map::find_second(const Argm& key) {
iterator i = Base::find(key[0]);
if (i != end()) return i->second;
else if (key[0] == ".mapped_argfunction") return key.argfunction();
else return nullptr;}
bool Executable_map::run_if_exists(const std::string& key, Argm& argm_i) {
Argm temp_argm(key, argm_i.argv(), argm_i.argfunction(),
argm_i.parent_map(), argm_i.input,argm_i.output, argm_i.error);
Base_executable* i = find_second(temp_argm);
if (i) {
Error_list exceptions;
(*i)(temp_argm, exceptions);
if (global_stack.unwind_stack())
global_stack.exception_handler(exceptions);
return true;}
else {
return false;}}
void Executable_map::base_run(Argm& argm, Error_list& exceptions) {
run(argm, exceptions);
if (gc_state.in_if_block && !gc_state.exception_thrown) {
gc_state.in_if_block = false;
exceptions.add_error(Exception(Argm::Unfinished_if_block));}
if (global_stack.unwind_stack())
global_stack.exception_handler(exceptions);}
void Executable_map::run_handling_exceptions(Argm& argm,
Error_list& exceptions) {
run(argm, exceptions);
if (global_stack.unwind_stack())
global_stack.exception_handler(exceptions);}
void Executable_map::unused_var_check_at_exit(void) {
Error_list exceptions;
Prototype shell_invocation;
shell_invocation.unused_var_check(Variable_map::global_map, exceptions);
if (exceptions.size()) global_stack.exception_handler(exceptions);}
void Executable_map::run(Argm& argm, Error_list& exceptions) {
try {
Base_executable* i = find_second(argm); // first check for key
if (i) (*i)(argm, exceptions);
else if (in_autofunction) // nested autofunction
not_found(argm, exceptions);
else {
in_autofunction = true;
Argm auto_argm(Argm::exception_names[Argm::Autofunction], argm.argv(),
argm.argfunction(), argm.parent_map(),
argm.input, argm.output, argm.error);
run(auto_argm, exceptions);
in_autofunction = false;
i = find_second(argm); // second check for key
if (i) (*i)(argm, exceptions);
else not_found(argm, exceptions);}}
catch (Exception error) {
exceptions.add_error(error);}}
bool Executable_map::run_condition(Argm& argm, Error_list& exceptions) {
run(argm, exceptions);
return !global_stack.remove_exceptions(".false", exceptions) &&
!exceptions.size();} // optional
void Executable_map::not_found(Argm& argm_i, Error_list& exceptions) {
if (Base::find(Argm::exception_names[Argm::Function_not_found]) == end()) {
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(), body));}
throw Exception(Argm::Function_not_found, argm_i);}