• R/O
  • SSH
  • HTTPS

yash: Commit


Commit MetaInfo

Revision3923 (tree)
Time2018-11-25 14:25:45
Authormagicant

Log Message

Evaluate double-bracket command

Change Summary

Incremental Difference

--- yash/branches/double_bracket/builtins/test.c (revision 3922)
+++ yash/branches/double_bracket/builtins/test.c (revision 3923)
@@ -27,7 +27,13 @@
2727 #include <unistd.h>
2828 #include <wchar.h>
2929 #include <wctype.h>
30+#if YASH_ENABLE_DOUBLE_BRACKET
31+# include "../expand.h"
32+#endif
3033 #include "../option.h"
34+#if YASH_ENABLE_DOUBLE_BRACKET
35+# include "../parser.h"
36+#endif
3137 #include "../path.h"
3238 #include "../plist.h"
3339 #include "../strbuf.h"
@@ -68,7 +74,22 @@
6874 static enum filecmp compare_files(const wchar_t *left, const wchar_t *right)
6975 __attribute__((nonnull));
7076
77+#if YASH_ENABLE_DOUBLE_BRACKET
78+static int eval_dbexp(const dbexp_T *e)
79+ __attribute__((nonnull));
80+static inline wchar_t *expand_double_bracket_operand(const wordunit_T *w)
81+ __attribute__((nonnull,malloc,warn_unused_result));
82+static wchar_t *expand_and_unescape_double_bracket_operand(const wordunit_T *w)
83+ __attribute__((nonnull,malloc,warn_unused_result));
84+static bool test_triple_db(
85+ const wchar_t *lhs, const wchar_t *op, const wchar_t *rhs_escaped)
86+ __attribute__((nonnull));
87+static bool test_triple_args(
88+ const wchar_t *left, const wchar_t *op, const wchar_t *right)
89+ __attribute__((nonnull));
90+#endif
7191
92+
7293 /* The "test" ("[") built-in. */
7394 int test_builtin(int argc, void **argv)
7495 {
@@ -683,5 +704,134 @@
683704 );
684705 #endif
685706
707+#if YASH_ENABLE_DOUBLE_BRACKET
686708
709+/* Executes the double-bracket command, evaluating the conditional expression.
710+ * Returns the exit status. Prints an error message on error. */
711+int exec_double_bracket(const command_T *c)
712+{
713+ assert(c->c_type == CT_BRACKET);
714+
715+ yash_error_message_count = 0;
716+ return eval_dbexp(c->c_dbexp);
717+}
718+
719+/* Evaluates the expression of a double-bracket command.
720+ * You must reset `yash_error_message_count' before calling this function.
721+ * Returns the exit status. Prints an error message on error. */
722+int eval_dbexp(const dbexp_T *e)
723+{
724+ int lhs_result;
725+ bool result;
726+ wchar_t *lhs = NULL, *rhs = NULL;
727+
728+ switch (e->type) {
729+ case DBE_OR:
730+ lhs_result = eval_dbexp(e->lhs.subexp);
731+ if (lhs_result != Exit_FALSE)
732+ return lhs_result;
733+ return eval_dbexp(e->rhs.subexp);
734+ case DBE_AND:
735+ lhs_result = eval_dbexp(e->lhs.subexp);
736+ if (lhs_result != Exit_TRUE)
737+ return lhs_result;
738+ return eval_dbexp(e->rhs.subexp);
739+ case DBE_NOT:
740+ switch (eval_dbexp(e->rhs.subexp)) {
741+ case Exit_TRUE: return Exit_FALSE;
742+ case Exit_FALSE: return Exit_TRUE;
743+ default: return Exit_TESTERROR;
744+ }
745+
746+ case DBE_UNARY:
747+ rhs = expand_and_unescape_double_bracket_operand(e->rhs.word);
748+ if (rhs == NULL)
749+ return Exit_TESTERROR;
750+ result = test_double((void *[]) { e->operator, rhs });
751+ break;
752+ case DBE_BINARY:
753+ lhs = expand_and_unescape_double_bracket_operand(e->lhs.word);
754+ if (lhs == NULL)
755+ return Exit_TESTERROR;
756+ rhs = expand_double_bracket_operand(e->rhs.word);
757+ if (rhs == NULL)
758+ return Exit_TESTERROR;
759+ result = test_triple_db(lhs, e->operator, rhs);
760+ break;
761+ case DBE_STRING:
762+ rhs = expand_and_unescape_double_bracket_operand(e->rhs.word);
763+ if (rhs == NULL)
764+ return Exit_TESTERROR;
765+ result = test_single((void *[]) { rhs });
766+ break;
767+
768+ default:
769+ assert(false);
770+ }
771+
772+ free(lhs);
773+ free(rhs);
774+ if (yash_error_message_count > 0)
775+ return Exit_TESTERROR;
776+ return result ? Exit_TRUE : Exit_FALSE;
777+}
778+
779+/* Expands the operand of a primary.
780+ * The result may contain backslash escapes. */
781+wchar_t *expand_double_bracket_operand(const wordunit_T *w)
782+{
783+ return expand_single(w, TT_SINGLE, true, false);
784+}
785+
786+/* Expands the operand of a primary.
787+ * The result is literal (does not contain backslash escapes). */
788+wchar_t *expand_and_unescape_double_bracket_operand(const wordunit_T *w)
789+{
790+ wchar_t *e = expand_double_bracket_operand(w);
791+ if (e == NULL)
792+ return NULL;
793+ return unescapefree(e);
794+}
795+
796+/* Tests the specified three-token (binary) primary in the double-bracket
797+ * command. The left-hand-side must be given literal while the right-hand-side
798+ * backslash-escaped. */
799+bool test_triple_db(
800+ const wchar_t *lhs, const wchar_t *op, const wchar_t *rhs_escaped)
801+{
802+ /* Some string comparison primaries in the double-bracket command are
803+ * different from those in the test built-in. */
804+ switch (op[0]) {
805+ case L'=':
806+ if (op[1] == L'~') {
807+ assert(op[2] == L'\0');
808+ return test_triple_args(lhs, op, rhs_escaped);
809+ }
810+ if (op[1] == L'\0' || (op[1] == L'=' && op[2] == L'\0'))
811+ return match_pattern(lhs, rhs_escaped);
812+ break;
813+ case L'!':
814+ assert(op[1] == L'=');
815+ if (op[2] == L'\0')
816+ return !match_pattern(lhs, rhs_escaped);
817+ break;
818+ }
819+
820+ wchar_t *rhs = unescape(rhs_escaped);
821+ bool result = test_triple_args(lhs, op, rhs);
822+ free(rhs);
823+ return result;
824+}
825+
826+/* Tests the specified three-token expression. */
827+bool test_triple_args(
828+ const wchar_t *left, const wchar_t *op, const wchar_t *right)
829+{
830+ void *args[] = { (void *) left, (void *) op, (void *) right, };
831+ return test_triple(args);
832+}
833+
834+#endif /* YASH_ENABLE_DOUBLE_BRACKET */
835+
836+
687837 /* vim: set ts=8 sts=4 sw=4 noet tw=80: */
--- yash/branches/double_bracket/builtins/test.h (revision 3922)
+++ yash/branches/double_bracket/builtins/test.h (revision 3923)
@@ -33,7 +33,13 @@
3333 extern _Bool is_binary_primary(const wchar_t *word)
3434 __attribute__((nonnull,pure));
3535
36+#if YASH_ENABLE_DOUBLE_BRACKET
37+struct command_T;
38+extern int exec_double_bracket(const struct command_T *c)
39+ __attribute__((nonnull));
40+#endif
3641
42+
3743 #endif /* YASH_TEST_H */
3844
3945
--- yash/branches/double_bracket/exec.c (revision 3922)
+++ yash/branches/double_bracket/exec.c (revision 3923)
@@ -57,6 +57,9 @@
5757 #include "variable.h"
5858 #include "xfnmatch.h"
5959 #include "yash.h"
60+#if YASH_ENABLE_DOUBLE_BRACKET
61+# include "builtins/test.h"
62+#endif
6063 #if YASH_ENABLE_LINEEDIT
6164 # include "lineedit/complete.h"
6265 # include "lineedit/lineedit.h"
@@ -1188,7 +1191,9 @@
11881191 break;
11891192 #if YASH_ENABLE_DOUBLE_BRACKET
11901193 case CT_BRACKET:
1191- laststatus = Exit_SUCCESS; // TODO
1194+ laststatus = exec_double_bracket(c);
1195+ if (finally_exit)
1196+ exit_shell();
11921197 break;
11931198 #endif /* YASH_ENABLE_DOUBLE_BRACKET */
11941199 case CT_FUNCDEF:
Show on old repository browser