• R/O
  • SSH
  • HTTPS

yash: Commit


Commit MetaInfo

Revision3823 (tree)
Time2018-03-04 12:02:32
Authormagicant

Log Message

Add errreturn option

Change Summary

Incremental Difference

--- yash/trunk/exec.c (revision 3822)
+++ yash/trunk/exec.c (revision 3823)
@@ -1,6 +1,6 @@
11 /* Yash: yet another shell */
22 /* exec.c: command execution */
3-/* (C) 2007-2016 magicant */
3+/* (C) 2007-2018 magicant */
44
55 /* This program is free software: you can redistribute it and/or modify
66 * it under the terms of the GNU General Public License as published by
@@ -144,8 +144,11 @@
144144 static void exec_commands(command_T *c, exec_T type);
145145 static bool is_errexit_condition(void)
146146 __attribute__((pure));
147-static inline bool is_errexit_condition_for(const command_T *c)
148- __attribute__((nonnull,pure));
147+static bool is_errreturn_condition(void)
148+ __attribute__((pure));
149+static void apply_errexit_errreturn(const command_T *c);
150+static bool is_err_condition_for(const command_T *c)
151+ __attribute__((pure));
149152 static inline void next_pipe(pipeinfo_T *pi, bool next)
150153 __attribute__((nonnull));
151154 static pid_t exec_process(
@@ -194,9 +197,9 @@
194197 pid_t lastasyncpid;
195198
196199 /* This flag is set to true while the shell is executing the condition of an if-
197- * statement, an and-or list, etc. to suppress the effect of the "errexit"
198- * option. */
199-static bool suppresserrexit = false;
200+ * statement, an and-or list, etc. to suppress the effect of the "errexit" and
201+ * "errreturn" options. */
202+static bool suppresserrexit = false, suppresserrreturn = false;
200203
201204 /* state of currently executed loop */
202205 static execstate_T execstate;
@@ -297,8 +300,10 @@
297300 if (!first && p->pl_cond == (laststatus != Exit_SUCCESS))
298301 continue;
299302
300- bool savesee = suppresserrexit;
301- suppresserrexit |= p->pl_neg || p->next != NULL;
303+ bool savesee = suppresserrexit, saveser = suppresserrreturn;
304+ bool suppress = p->pl_neg || p->next != NULL;
305+ suppresserrexit |= suppress;
306+ suppresserrreturn |= suppress;
302307
303308 bool self = finally_exit && !doing_job_control_now
304309 && !p->next && !p->pl_neg && !any_trap_set && !shopt_pipefail;
@@ -310,7 +315,7 @@
310315 laststatus = Exit_SUCCESS;
311316 }
312317
313- suppresserrexit = savesee;
318+ suppresserrexit = savesee, suppresserrreturn = saveser;
314319 }
315320 if (finally_exit)
316321 exit_shell();
@@ -386,10 +391,10 @@
386391 if (c == NULL)
387392 return true;
388393
389- bool savesee = suppresserrexit;
390- suppresserrexit = true;
394+ bool savesee = suppresserrexit, saveser = suppresserrreturn;
395+ suppresserrexit = suppresserrreturn = true;
391396 exec_and_or_lists(c, false);
392- suppresserrexit = savesee;
397+ suppresserrexit = savesee, suppresserrreturn = saveser;
393398 return laststatus == Exit_SUCCESS;
394399 }
395400
@@ -407,8 +412,7 @@
407412 /* expand the words between "in" and "do" of the for command. */
408413 if (!expand_line(c->c_forwords, &count, &words)) {
409414 laststatus = Exit_EXPERROR;
410- if (is_errexit_condition())
411- exit_shell_with_status(laststatus);
415+ apply_errexit_errreturn(NULL);
412416 goto finish;
413417 }
414418 } else {
@@ -540,8 +544,7 @@
540544
541545 fail:
542546 laststatus = Exit_EXPERROR;
543- if (is_errexit_condition())
544- exit_shell_with_status(laststatus);
547+ apply_errexit_errreturn(NULL);
545548 goto done;
546549 }
547550
@@ -651,9 +654,7 @@
651654
652655 handle_signals();
653656
654- if (is_errexit_condition_for(c)) {
655- exit_shell_with_status(laststatus);
656- }
657+ apply_errexit_errreturn(c);
657658
658659 comsfree(c);
659660 }
@@ -674,12 +675,31 @@
674675 return true;
675676 }
676677
677-/* Returns true if the shell should exit because of the `errexit' option. */
678-bool is_errexit_condition_for(const command_T *c)
678+/* Returns true if the shell should return because of the `errreturn' option. */
679+bool is_errreturn_condition(void)
679680 {
680- if (!is_errexit_condition())
681+ if (!shopt_errreturn || suppresserrreturn || execstate.noreturn)
681682 return false;
683+ return laststatus != Exit_SUCCESS;
684+}
682685
686+/* Tests the current condition for "errexit" and "errreturn" and then performs
687+ * exit or return if applicable. */
688+void apply_errexit_errreturn(const command_T *c)
689+{
690+ if (is_errexit_condition() && is_err_condition_for(c))
691+ exit_shell_with_status(laststatus);
692+ if (is_errreturn_condition() && is_err_condition_for(c))
693+ exception = E_RETURN;
694+}
695+
696+/* Returns true if "errexit" and "errreturn" should be applied to the given
697+ * command. */
698+bool is_err_condition_for(const command_T *c)
699+{
700+ if (c == NULL)
701+ return true;
702+
683703 /* If this is a multi-command pipeline, the commands are executed in
684704 * subshells. Otherwise, we need to check the type of the command. */
685705 if (c->next != NULL)
@@ -814,8 +834,7 @@
814834 if (!open_redirections(c->c_redirs, &savefd)) {
815835 /* On redirection error, the command is not executed. */
816836 laststatus = Exit_REDIRERR;
817- if (is_errexit_condition())
818- exit_shell_with_status(laststatus);
837+ apply_errexit_errreturn(NULL);
819838 if (posixly_correct && !is_interactive_now && c->c_type == CT_SIMPLE &&
820839 argc > 0 && is_special_builtin(argv0))
821840 finally_exit = true;
@@ -1014,6 +1033,7 @@
10141033 restore_signals(sigtype & t_leave); /* signal mask is restored here */
10151034 clear_shellfds(sigtype & t_leave);
10161035 is_interactive_now = false;
1036+ suppresserrreturn = false;
10171037 }
10181038 return cpid;
10191039 }
@@ -1358,6 +1378,9 @@
13581378 execstate_T *saveexecstate = save_execstate();
13591379 reset_execstate(false);
13601380
1381+ bool saveser = suppresserrreturn;
1382+ suppresserrreturn = false;
1383+
13611384 open_new_environment(false);
13621385 set_positional_parameters(args);
13631386 #if YASH_ENABLE_LINEEDIT
@@ -1370,6 +1393,7 @@
13701393 close_current_environment();
13711394
13721395 cancel_return();
1396+ suppresserrreturn = saveser;
13731397 restore_execstate(saveexecstate);
13741398 }
13751399
@@ -1949,8 +1973,14 @@
19491973
19501974 execstate_T *saveexecstate = save_execstate();
19511975 reset_execstate(false);
1976+
1977+ bool saveser = suppresserrreturn;
1978+ suppresserrreturn = false;
1979+
19521980 exec_input(fd, mbsfilename, enable_alias ? XIO_SUBST_ALIAS : 0);
1981+
19531982 cancel_return();
1983+ suppresserrreturn = saveser;
19541984 restore_execstate(saveexecstate);
19551985 remove_shellfd(fd);
19561986 xclose(fd);
--- yash/trunk/NEWS (revision 3822)
+++ yash/trunk/NEWS (revision 3823)
@@ -10,6 +10,7 @@
1010 ----------------------------------------------------------------------
1111 Yash 2.47
1212
13+ + '--errreturn' option.
1314 = Expansion results printed by the -x option is now quoted to
1415 disambiguate presence of special characters.
1516 = When the shell prints aliases, variables, key bindings, etc. they
--- yash/trunk/option.c (revision 3822)
+++ yash/trunk/option.c (revision 3823)
@@ -1,6 +1,6 @@
11 /* Yash: yet another shell */
22 /* option.c: option settings */
3-/* (C) 2007-2016 magicant */
3+/* (C) 2007-2018 magicant */
44
55 /* This program is free software: you can redistribute it and/or modify
66 * it under the terms of the GNU General Public License as published by
@@ -93,6 +93,9 @@
9393 /* If set, when a command returns a non-zero status, the shell exits.
9494 * Corresponds to the -e/--errexit option. */
9595 bool shopt_errexit = false;
96+/* Like `shopt_errexit', but instead of exiting the shell, the "return"
97+ * built-in is executed on a non-zero status. */
98+bool shopt_errreturn = false;
9699 /* If set, the last non-zero exit status in a pipeline becomes the exit status
97100 * of the whole pipeline. Otherwise, the last command in the pipeline always
98101 * defines the exit status of the whole pipeline. Corresponds to the --pipefail
@@ -215,6 +218,7 @@
215218 #endif
216219 { 0, 0, L"emptylastfield", &shopt_emptylastfield, true, },
217220 { L'e', 0, L"errexit", &shopt_errexit, true, },
221+ { 0, 0, L"errreturn", &shopt_errreturn, true, },
218222 { 0, L'n', L"exec", &shopt_exec, true, },
219223 { 0, 0, L"extendedglob", &shopt_extendedglob, true, },
220224 { 0, L'f', L"glob", &shopt_glob, true, },
--- yash/trunk/option.h (revision 3822)
+++ yash/trunk/option.h (revision 3823)
@@ -1,6 +1,6 @@
11 /* Yash: yet another shell */
22 /* option.h: option settings */
3-/* (C) 2007-2016 magicant */
3+/* (C) 2007-2018 magicant */
44
55 /* This program is free software: you can redistribute it and/or modify
66 * it under the terms of the GNU General Public License as published by
@@ -42,8 +42,8 @@
4242 extern _Bool do_job_control, shopt_notify, shopt_notifyle,
4343 shopt_curasync, shopt_curbg, shopt_curstop;
4444 extern _Bool shopt_allexport, shopt_hashondef;
45-extern _Bool shopt_errexit, shopt_pipefail, shopt_unset, shopt_exec,
46- shopt_ignoreeof, shopt_verbose, shopt_xtrace;
45+extern _Bool shopt_errexit, shopt_errreturn, shopt_pipefail, shopt_unset,
46+ shopt_exec, shopt_ignoreeof, shopt_verbose, shopt_xtrace;
4747 extern _Bool shopt_traceall;
4848 #if YASH_ENABLE_HISTORY
4949 extern _Bool shopt_histspace;
--- yash/trunk/tests/Makefile.in (revision 3822)
+++ yash/trunk/tests/Makefile.in (revision 3823)
@@ -28,7 +28,7 @@
2828 LDLIBS = @LDLIBS@
2929 SOURCES = checkfg.c resetsig.c
3030 POSIX_TEST_SOURCES = alias-p.tst andor-p.tst arith-p.tst async-p.tst bg-p.tst break-p.tst builtins-p.tst case-p.tst cd-p.tst cmdsub-p.tst command-p.tst comment-p.tst continue-p.tst dot-p.tst errexit-p.tst error-p.tst eval-p.tst exec-p.tst exit-p.tst export-p.tst fg-p.tst fnmatch-p.tst for-p.tst fsplit-p.tst function-p.tst getopts-p.tst grouping-p.tst if-p.tst input-p.tst job-p.tst kill-p.tst lineno-p.tst nop-p.tst option-p.tst param-p.tst path-p.tst pipeline-p.tst ppid-p.tst quote-p.tst read-p.tst readonly-p.tst redir-p.tst return-p.tst set-p.tst shift-p.tst signal-p.tst simple-p.tst test-p.tst testtty-p.tst tilde-p.tst trap-p.tst umask-p.tst unset-p.tst until-p.tst wait-p.tst while-p.tst
31-YASH_TEST_SOURCES = alias-y.tst andor-y.tst arith-y.tst array-y.tst async-y.tst bg-y.tst bindkey-y.tst brace-y.tst break-y.tst builtins-y.tst case-y.tst cd-y.tst cmdsub-y.tst command-y.tst complete-y.tst continue-y.tst dirstack-y.tst disown-y.tst dot-y.tst echo-y.tst errexit-y.tst error-y.tst eval-y.tst exec-y.tst exit-y.tst export-y.tst fc-y.tst fg-y.tst for-y.tst fsplit-y.tst function-y.tst getopts-y.tst grouping-y.tst hash-y.tst help-y.tst history-y.tst historyx-y.tst if-y.tst job-y.tst jobs-y.tst kill-y.tst lineno-y.tst option-y.tst param-y.tst pipeline-y.tst printf-y.tst prompt-y.tst pwd-y.tst quote-y.tst random-y.tst read-y.tst readonly-y.tst redir-y.tst return-y.tst set-y.tst settty-y.tst shift-y.tst signal-y.tst simple-y.tst startup-y.tst suspend-y.tst test-y.tst tilde-y.tst times-y.tst trap-y.tst typeset-y.tst ulimit-y.tst umask-y.tst unset-y.tst until-y.tst wait-y.tst while-y.tst
31+YASH_TEST_SOURCES = alias-y.tst andor-y.tst arith-y.tst array-y.tst async-y.tst bg-y.tst bindkey-y.tst brace-y.tst break-y.tst builtins-y.tst case-y.tst cd-y.tst cmdsub-y.tst command-y.tst complete-y.tst continue-y.tst dirstack-y.tst disown-y.tst dot-y.tst echo-y.tst errexit-y.tst error-y.tst errretur-y.tst eval-y.tst exec-y.tst exit-y.tst export-y.tst fc-y.tst fg-y.tst for-y.tst fsplit-y.tst function-y.tst getopts-y.tst grouping-y.tst hash-y.tst help-y.tst history-y.tst historyx-y.tst if-y.tst job-y.tst jobs-y.tst kill-y.tst lineno-y.tst option-y.tst param-y.tst pipeline-y.tst printf-y.tst prompt-y.tst pwd-y.tst quote-y.tst random-y.tst read-y.tst readonly-y.tst redir-y.tst return-y.tst set-y.tst settty-y.tst shift-y.tst signal-y.tst simple-y.tst startup-y.tst suspend-y.tst test-y.tst tilde-y.tst times-y.tst trap-y.tst typeset-y.tst ulimit-y.tst umask-y.tst unset-y.tst until-y.tst wait-y.tst while-y.tst
3232 TEST_SOURCES = $(POSIX_TEST_SOURCES) $(YASH_TEST_SOURCES)
3333 TEST_RESULTS = $(TEST_SOURCES:.tst=.trs)
3434 RECHECK_LOGS = $(TEST_RESULTS)
--- yash/trunk/doc/ja/_set.txt (revision 3822)
+++ yash/trunk/doc/ja/_set.txt (revision 3823)
@@ -67,7 +67,7 @@
6767 このオプションが有効な時、link:expand.html#split[単語分割]で最後の単語が空になっても削除しません。
6868
6969 [[so-errexit]]err-exit (+-e+)::
70-このオプションが有効な時、実行したlink:syntax.html#pipelines[パイプライン]の終了ステータスが 0 でなければ、シェルは直ちに終了します。ただし、以下の場合を除きます。
70+このオプションが有効な時、実行したlink:syntax.html#pipelines[パイプライン]の終了ステータスが 0 でなければ、シェルは直ちに終了します。ただし、以下の抑止条件に当てはまる場合を除きます。
7171
7272 - そのコマンドが link:syntax.html#if[if 文]の分岐や
7373 link:syntax.html#while-until[while/until 文]のループ条件の判定に使われる場合
@@ -74,6 +74,10 @@
7474 - パイプラインの先頭に +!+ が付いている場合
7575 - パイプラインがサブシェルlink:syntax.html#grouping[グルーピング]以外の単独のlink:syntax.html#compound[複合コマンド]から構成される場合
7676
77+[[so-errreturn]]err-return::
78+このオプションは err-exit オプションと同様ですが、終了ステータスが 0 でないときにシェルが終了する代わりに link:_return.html[return 組込みコマンド]が発動します。
79+Err-exit オプションと異なり、抑止条件はlink:exec.html#function[関数]・サブシェルlink:syntax.html#grouping[グルーピング]・link:_dot.html[スクリプトファイル]の中では無視されます。
80+
7781 [[so-exec]]exec (`+n`)::
7882 このオプションが無効な時、シェルはコマンドの解釈だけを行い、実際にはコマンドを実行しません。このオプションはシェルスクリプトの文法チェックをするのに便利です。このオプションはシェルの起動時に最初から有効になっています。link:interact.html[対話モード]では、このオプションに関わらずコマンドは常に実行されます。
7983
--- yash/trunk/doc/_set.txt (revision 3822)
+++ yash/trunk/doc/_set.txt (revision 3823)
@@ -98,7 +98,8 @@
9898
9999 [[so-errexit]]err-exit (+-e+)::
100100 When enabled, if a link:syntax.html#pipelines[pipeline] ends with a non-zero
101-exit status, the shell immediately exits unless:
101+exit status, the shell immediately exits unless the following suppress
102+condition is met:
102103
103104 - the pipeline is a condition of an link:syntax.html#if[if command] or
104105 link:syntax.html#while-until[while or until loop];
@@ -106,6 +107,13 @@
106107 - the pipeline is a single link:syntax.html#compound[compound command] other
107108 than a subshell link:syntax.html#grouping[grouping].
108109
110+[[so-errreturn]]err-return::
111+This option is like the err-exit option, but the link:_return.html[return
112+built-in] is executed instead of the shell exiting on a non-zero exit status.
113+Unlike err-exit, the suppress condition does not apply inside a
114+link:exec.html#function[function],
115+subshell link:syntax.html#grouping[grouping], or link:_dot.html[script file].
116+
109117 [[so-exec]]exec (`+n`)::
110118 (Enabled by default)
111119 Commands are actually executed only when this option is enabled.
Show on old repository browser