فهرست منبع

Shell: Implement the `return` POSIX builtin

This is also available in the regular shell mode, as it's a generally
useful builtin to have.
Ali Mohammad Pur 1 سال پیش
والد
کامیت
a8c7448ccb
4فایلهای تغییر یافته به همراه25 افزوده شده و 1 حذف شده
  1. 1 1
      Userland/Shell/AST.cpp
  2. 17 0
      Userland/Shell/Builtin.cpp
  3. 4 0
      Userland/Shell/Shell.cpp
  4. 3 0
      Userland/Shell/Shell.h

+ 1 - 1
Userland/Shell/AST.cpp

@@ -1230,7 +1230,7 @@ ErrorOr<RefPtr<Value>> ForLoop::run(RefPtr<Shell> shell)
 
     size_t consecutive_interruptions = 0;
     auto run = [&](auto& block_value) {
-        if (shell->has_error(Shell::ShellError::InternalControlFlowBreak)) {
+        if (shell->has_error(Shell::ShellError::InternalControlFlowBreak) || shell->has_error(Shell::ShellError::InternalControlFlowReturn)) {
             shell->take_error();
             return IterationDecision::Break;
         }

+ 17 - 0
Userland/Shell/Builtin.cpp

@@ -268,6 +268,23 @@ ErrorOr<int> Shell::builtin_continue(Main::Arguments arguments)
     return 0;
 }
 
+ErrorOr<int> Shell::builtin_return(Main::Arguments arguments)
+{
+    int return_code = last_return_code.value_or(0);
+
+    Core::ArgsParser parser;
+    parser.add_positional_argument(return_code, "Return code to return to the parent shell", "return-code", Core::ArgsParser::Required::No);
+    parser.set_general_help("Return from a function or source file");
+
+    if (!parser.parse(arguments, Core::ArgsParser::FailureBehavior::PrintUsage))
+        return 1;
+
+    last_return_code = return_code & 0xff;
+    raise_error(ShellError::InternalControlFlowReturn, "POSIX return");
+
+    return 0;
+}
+
 ErrorOr<int> Shell::builtin_bg(Main::Arguments arguments)
 {
     int job_id = -1;

+ 4 - 0
Userland/Shell/Shell.cpp

@@ -487,6 +487,9 @@ bool Shell::invoke_function(const AST::Command& command, int& retval)
 
     (void)function.body->run(*this);
 
+    if (has_error(ShellError::InternalControlFlowReturn))
+        take_error();
+
     retval = last_return_code.value_or(0);
     return true;
 }
@@ -2435,6 +2438,7 @@ void Shell::possibly_print_error() const
         break;
     case ShellError::InternalControlFlowBreak:
     case ShellError::InternalControlFlowContinue:
+    case ShellError::InternalControlFlowReturn:
     case ShellError::InternalControlFlowInterrupted:
     case ShellError::InternalControlFlowKilled:
         return;

+ 3 - 0
Userland/Shell/Shell.h

@@ -60,6 +60,7 @@
     __ENUMERATE_SHELL_BUILTIN(noop, InAllModes)              \
     __ENUMERATE_SHELL_BUILTIN(break, OnlyInPOSIXMode)        \
     __ENUMERATE_SHELL_BUILTIN(continue, OnlyInPOSIXMode)     \
+    __ENUMERATE_SHELL_BUILTIN(return, InAllModes)            \
     __ENUMERATE_SHELL_BUILTIN(read, OnlyInPOSIXMode)         \
     __ENUMERATE_SHELL_BUILTIN(run_with_env, OnlyInPOSIXMode) \
     __ENUMERATE_SHELL_BUILTIN(argsparser_parse, InAllModes)  \
@@ -360,6 +361,7 @@ public:
         None,
         InternalControlFlowBreak,
         InternalControlFlowContinue,
+        InternalControlFlowReturn,
         InternalControlFlowInterrupted,
         InternalControlFlowKilled,
         EvaluatedSyntaxError,
@@ -396,6 +398,7 @@ public:
         switch (error) {
         case ShellError::InternalControlFlowBreak:
         case ShellError::InternalControlFlowContinue:
+        case ShellError::InternalControlFlowReturn:
         case ShellError::InternalControlFlowInterrupted:
         case ShellError::InternalControlFlowKilled:
             return true;