updated for version 7.3.377
Problem:    No support for bitwise AND, OR, XOR and invert.
Solution:   Add add(), or(), invert() and xor() functions.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 46ecaee..9844072 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -801,11 +801,12 @@
 For |Lists| only "+" is possible and then both expr6 must be a list.  The
 result is a new list with the two lists Concatenated.
 
-expr7 *	 expr7 ..	number multiplication			*expr-star*
-expr7 /	 expr7 ..	number division				*expr-/*
-expr7 %	 expr7 ..	number modulo				*expr-%*
+expr7 *	 expr7 ..	Number multiplication			*expr-star*
+expr7 /	 expr7 ..	Number division				*expr-/*
+expr7 %	 expr7 ..	Number modulo				*expr-%*
 
 For all, except ".", Strings are converted to Numbers.
+For bitwise operators see |and()|, |or()| and |xor()|.
 
 Note the difference between "+" and ".":
 	"123" + "456" = 579
@@ -1687,6 +1688,7 @@
 abs( {expr})			Float or Number  absolute value of {expr}
 acos( {expr})			Float	arc cosine of {expr}
 add( {list}, {item})		List	append {item} to |List| {list}
+and( {expr}, {expr})		Number  bitwise AND
 append( {lnum}, {string})	Number	append {string} below line {lnum}
 append( {lnum}, {list})		Number	append lines {list} below line {lnum}
 argc()				Number	number of files in the argument list
@@ -1825,6 +1827,7 @@
 inputsave()			Number	save and clear typeahead
 inputsecret( {prompt} [, {text}]) String  like input() but hiding the text
 insert( {list}, {item} [, {idx}]) List	insert {item} in {list} [before {idx}]
+invert( {expr})			Number  bitwise invert
 isdirectory( {directory})	Number	TRUE if {directory} is a directory
 islocked( {expr})		Number	TRUE if {expr} is locked
 items( {dict})			List	key-value pairs in {dict}
@@ -1864,6 +1867,7 @@
 mzeval( {expr})			any	evaluate |MzScheme| expression
 nextnonblank( {lnum})		Number	line nr of non-blank line >= {lnum}
 nr2char( {expr})		String	single char with ASCII value {expr}
+or( {expr}, {expr})		Number  bitwise OR
 pathshorten( {expr})		String	shorten directory names in a path
 pow( {x}, {y})			Float	{x} to the power of {y}
 prevnonblank( {lnum})		Number	line nr of non-blank line <= {lnum}
@@ -1987,6 +1991,7 @@
 winwidth( {nr})			Number	width of window {nr}
 writefile( {list}, {fname} [, {binary}])
 				Number	write list of lines to file {fname}
+xor( {expr}, {expr})		Number  bitwise XOR
 
 abs({expr})							*abs()*
 		Return the absolute value of {expr}.  When {expr} evaluates to
@@ -2026,6 +2031,13 @@
 		Use |insert()| to add an item at another position.
 
 
+and({expr}, {expr})					*and()*
+		Bitwise AND on the two arguments.  The arguments are converted
+		to a number.  A List, Dict or Float argument causes an error.
+		Example: >
+			:let flag = and(bits, 0x80)
+
+
 append({lnum}, {expr})					*append()*
 		When {expr} is a |List|: Append each item of the |List| as a
 		text line below line {lnum} in the current buffer.
@@ -3782,6 +3794,11 @@
 		Note that when {item} is a |List| it is inserted as a single
 		item.  Use |extend()| to concatenate |Lists|.
 
+invert({expr})						*invert()*
+		Bitwise invert.  The argument is converted to a number.  A
+		List, Dict or Float argument causes an error.  Example: >
+			:let bits = invert(bits)
+
 isdirectory({directory})				*isdirectory()*
 		The result is a Number, which is non-zero when a directory
 		with the name {directory} exists.  If {directory} doesn't
@@ -4347,6 +4364,13 @@
 			call setpos('.', save_cursor)
 <		Also see |setpos()|.
 
+or({expr}, {expr})					*or()*
+		Bitwise OR on the two arguments.  The arguments are converted
+		to a number.  A List, Dict or Float argument causes an error.
+		Example: >
+			:let bits = or(bits, 0x80)
+
+
 pathshorten({expr})					*pathshorten()*
 		Shorten directory names in the path {expr} and return the
 		result.  The tail, the file name, is kept as-is.  The other
@@ -6121,7 +6145,15 @@
 		To copy a file byte for byte: >
 			:let fl = readfile("foo", "b")
 			:call writefile(fl, "foocopy", "b")
-<
+
+
+xor({expr}, {expr})					*xor()*
+		Bitwise XOR on the two arguments.  The arguments are converted
+		to a number.  A List, Dict or Float argument causes an error.
+		Example: >
+			:let bits = xor(bits, 0x80)
+
+
 
 							*feature-list*
 There are three types of features:
diff --git a/src/eval.c b/src/eval.c
index d93836a..8bf243e 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -474,6 +474,7 @@
 static void f_acos __ARGS((typval_T *argvars, typval_T *rettv));
 #endif
 static void f_add __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_and __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_append __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_argc __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv));
@@ -602,6 +603,7 @@
 static void f_inputsave __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_inputsecret __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_insert __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_invert __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_isdirectory __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_islocked __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_items __ARGS((typval_T *argvars, typval_T *rettv));
@@ -640,6 +642,7 @@
 #endif
 static void f_nextnonblank __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_nr2char __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_or __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_pathshorten __ARGS((typval_T *argvars, typval_T *rettv));
 #ifdef FEAT_FLOAT
 static void f_pow __ARGS((typval_T *argvars, typval_T *rettv));
@@ -751,6 +754,7 @@
 static void f_winsaveview __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_winwidth __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_writefile __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_xor __ARGS((typval_T *argvars, typval_T *rettv));
 
 static int list2fpos __ARGS((typval_T *arg, pos_T *posp, int *fnump));
 static pos_T *var2fpos __ARGS((typval_T *varp, int dollar_lnum, int *fnum));
@@ -7715,6 +7719,7 @@
     {"acos",		1, 1, f_acos},	/* WJMc */
 #endif
     {"add",		2, 2, f_add},
+    {"and",		2, 2, f_and},
     {"append",		2, 2, f_append},
     {"argc",		0, 0, f_argc},
     {"argidx",		0, 0, f_argidx},
@@ -7850,6 +7855,7 @@
     {"inputsave",	0, 0, f_inputsave},
     {"inputsecret",	1, 2, f_inputsecret},
     {"insert",		2, 3, f_insert},
+    {"invert",		1, 1, f_invert},
     {"isdirectory",	1, 1, f_isdirectory},
     {"islocked",	1, 1, f_islocked},
     {"items",		1, 1, f_items},
@@ -7888,6 +7894,7 @@
 #endif
     {"nextnonblank",	1, 1, f_nextnonblank},
     {"nr2char",		1, 1, f_nr2char},
+    {"or",		2, 2, f_or},
     {"pathshorten",	1, 1, f_pathshorten},
 #ifdef FEAT_FLOAT
     {"pow",		2, 2, f_pow},
@@ -7999,6 +8006,7 @@
     {"winsaveview",	0, 0, f_winsaveview},
     {"winwidth",	1, 1, f_winwidth},
     {"writefile",	2, 3, f_writefile},
+    {"xor",		2, 2, f_xor},
 };
 
 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
@@ -8572,6 +8580,18 @@
 }
 
 /*
+ * "and(expr, expr)" function
+ */
+    static void
+f_and(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL)
+					& get_tv_number_chk(&argvars[1], NULL);
+}
+
+/*
  * "append(lnum, string/list)" function
  */
     static void
@@ -12958,6 +12978,17 @@
 }
 
 /*
+ * "invert(expr)" function
+ */
+    static void
+f_invert(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    rettv->vval.v_number = ~get_tv_number_chk(&argvars[0], NULL);
+}
+
+/*
  * "isdirectory()" function
  */
     static void
@@ -14108,6 +14139,18 @@
 }
 
 /*
+ * "or(expr, expr)" function
+ */
+    static void
+f_or(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL)
+					| get_tv_number_chk(&argvars[1], NULL);
+}
+
+/*
  * "pathshorten()" function
  */
     static void
@@ -18394,6 +18437,19 @@
 }
 
 /*
+ * "xor(expr, expr)" function
+ */
+    static void
+f_xor(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL)
+					^ get_tv_number_chk(&argvars[1], NULL);
+}
+
+
+/*
  * Translate a String variable into a position.
  * Returns NULL when there is an error.
  */
diff --git a/src/testdir/test65.in b/src/testdir/test65.in
index 896e9ed..ca53f27 100644
--- a/src/testdir/test65.in
+++ b/src/testdir/test65.in
@@ -1,4 +1,4 @@
-Test for floating point.
+Test for floating point and logical operators.
 
 STARTTEST
 :so small.vim
@@ -72,6 +72,23 @@
 :$put ='float2nr'
 :$put =float2nr(123.456)
 :$put =float2nr(-123.456)
+:$put ='AND'
+:$put =and(127, 127)
+:$put =and(127, 16)
+:$put =and(127, 128)
+:$put ='OR'
+:$put =or(16, 7)
+:$put =or(8, 7)
+:$put =or(0, 123)
+:$put ='XOR'
+:$put =xor(127, 127)
+:$put =xor(127, 16)
+:$put =xor(127, 128)
+:$put ='invert'
+:$put =and(invert(127), 65535)
+:$put =and(invert(16), 65535)
+:$put =and(invert(128), 65535)
+:$put =invert(1.0)
 :/^Results/,$wq! test.out
 ENDTEST
 
diff --git a/src/testdir/test65.ok b/src/testdir/test65.ok
index 26c7312..7aac326 100644
--- a/src/testdir/test65.ok
+++ b/src/testdir/test65.ok
@@ -54,3 +54,20 @@
 float2nr
 123
 -123
+AND
+127
+16
+0
+OR
+23
+15
+123
+XOR
+0
+111
+255
+invert
+65408
+65519
+65407
+0
diff --git a/src/version.c b/src/version.c
index 258a29f..6fa74b4 100644
--- a/src/version.c
+++ b/src/version.c
@@ -715,6 +715,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    377,
+/**/
     376,
 /**/
     375,