From 5db40a2aa6488c422f1de51bdc55cff18bc4a736 Mon Sep 17 00:00:00 2001
From: Andriy Palamarchuk <apa3a@yahoo.com>
Date: Thu, 28 Feb 2002 21:46:43 +0000
Subject: [PATCH] Made regapi scripts able to process .reg files in regedit
 format. Implemented unit tests for reg diff functionality.

---
 programs/regapi/Makefile.in      |  3 ++
 programs/regapi/README           | 12 +----
 programs/regapi/regFixer.pl      | 19 ++-----
 programs/regapi/regRestorer.pl   | 24 ++++-----
 programs/regapi/regSet.sh        | 12 ++---
 programs/regapi/regapi.c         | 14 +++--
 programs/regapi/tests/.cvsignore |  1 +
 programs/regapi/tests/README     |  5 ++
 programs/regapi/tests/after.reg  | 92 ++++++++++++++++++++++++++++++++
 programs/regapi/tests/before.reg | 42 +++++++++++++++
 programs/regapi/tests/orig.reg   | 49 +++++++++++++++++
 programs/regapi/tests/regapi.pl  | 47 ++++++++++++++++
 12 files changed, 268 insertions(+), 52 deletions(-)
 create mode 100644 programs/regapi/tests/.cvsignore
 create mode 100644 programs/regapi/tests/README
 create mode 100644 programs/regapi/tests/after.reg
 create mode 100644 programs/regapi/tests/before.reg
 create mode 100644 programs/regapi/tests/orig.reg
 create mode 100644 programs/regapi/tests/regapi.pl

diff --git a/programs/regapi/Makefile.in b/programs/regapi/Makefile.in
index 0eb1b24dadb..7b122672e1f 100644
--- a/programs/regapi/Makefile.in
+++ b/programs/regapi/Makefile.in
@@ -7,6 +7,9 @@ MODULE    = regapi
 C_SRCS = \
 	regapi.c
 
+PLTESTS = \
+	tests/regapi.pl
+
 @MAKE_PROG_RULES@
 
 ### Dependencies:
diff --git a/programs/regapi/README b/programs/regapi/README
index 3500fd140e8..13b122f6bbd 100644
--- a/programs/regapi/README
+++ b/programs/regapi/README
@@ -38,16 +38,8 @@ Registry Command Line API Tool
   ( let's say we keep the added values only ).
 
   At this point we know which registry entry to add to the wine registry.  It 
-  only remains to take the format we have and reset it into a format similar
-  to the one we get from regedit.
-
-  I say "similar" because there is a tiny difference between Windows regedit 
-  export format and the format actually required by the tool.
-
-  The problem with this (and it is not a big one) is that regedit exports long 
-  data streams onto many lines, and since I don't have tons of time I setup 
-  another Perl script (regRestorer.pl) that fixes this (this could easily 
-  be done in C obviously) (left as exercise ;-) ).  
+  only remains to take the format we have and reset it into a format  we get from
+  regedit.
     
   So, once you parsed app.added into regRestorer.pl you get an app.reg ready to 
   process by regapi.
diff --git a/programs/regapi/regFixer.pl b/programs/regapi/regFixer.pl
index 11a98a03f18..c20735e6c7b 100755
--- a/programs/regapi/regFixer.pl
+++ b/programs/regapi/regFixer.pl
@@ -8,10 +8,10 @@
 # 
 
 ${prefix} = "";
-${line}   = "";   
 
 LINE: while(<>) {
-  chomp;                    # Get rid of 0x0a
+  chomp;
+  s/\r$//;                  # Get rid of 0x0a
 
   next LINE if(/^$/);       # This is an empty line
 
@@ -21,20 +21,7 @@ LINE: while(<>) {
   }
   s/\\\\/\\/g;              # Still some more substitutions... To fix paths...
 
-  s/^  //;                  # Get rid of the stupid two spaces at the begining
-                            # they are there in the case of a multi-line thing
-
-  if (/\\$/) {              # The line ends with '\', it means it is a multi
-    s/\\$//;                # line thing, remove it.
-    
-    ${line} = "${line}${_}";# Add the current line to the line to output
-    next LINE;              # process the next line
-  }
-
-  ${line} = "${line}${_}";  # Set line to the multi line thing+the current line
-
-  print "${prefix}${line}\n";  
-  ${line} = "";             # start over...
+  print "${prefix}$_\n";  
 }
 
 
diff --git a/programs/regapi/regRestorer.pl b/programs/regapi/regRestorer.pl
index 02525e43761..f8491cefa65 100755
--- a/programs/regapi/regRestorer.pl
+++ b/programs/regapi/regRestorer.pl
@@ -2,11 +2,7 @@
 
 # This script takes as STDIN an output from the regFixer.pl
 # and reformat the file as if it would have been exported from the registry
-#
-# Note: the output file is not exactly the one we get when exporting from
-#       regedit, the tiny difference is that multilines (which were 
-#       single-linized by regFixer.pl) values are not re-multi-linized by 
-#       this script.
+# in the "REGEDIT4" format.
 #
 # Copyright 1999 Sylvain St-Germain
 # 
@@ -19,6 +15,8 @@ ${data}   = "";
 # the input file comes from the output of regFixer.pl, therefore things 
 # should be ok, if they are not, investigate and send me an email...
 
+print "REGEDIT4\n";
+
 LINE: while(<>) {
   chomp;                             # get rid of new line
 
@@ -39,13 +37,15 @@ LINE: while(<>) {
   }
   else
   {
-    ${newkey} = ${key};             # assign it
-
     print "\n";
-    print "${key}\n";
-    print "${data}\n";
+    print "$key\n";
+    my $s = $data;
+    $s =~ s/^\s+//;
+    $s =~ s/\s+$//;  
+    if ($s ne "")
+    {
+        $newkey = $key;              # assign it
+        print "$data\n";
+    }
   }
 }
-
-
-
diff --git a/programs/regapi/regSet.sh b/programs/regapi/regSet.sh
index a4e26ae98b3..3b56b1f95f6 100755
--- a/programs/regapi/regSet.sh
+++ b/programs/regapi/regSet.sh
@@ -39,23 +39,23 @@ if [ $1 != "/dev/null" ]; then
 else
   diff /dev/null $2.fix > $2.diff
 fi
+
 #
 # Keep only added lines
 # 
 echo "Grepping keys to add and generating cleaned fixed registry file."
-cat $2.diff | grep '^> ' | sed -e 's/^> //' > $2.toAdd
+cat $2.diff | grep '^> ' | sed -e 's/^> //' > $2.toAdd.clean
 
 # 
 # Restore the file format to the regedit export 'like' format
 #
 echo "Restoring key's in the regedit export format..."
-cat $2.toAdd | ./regRestorer.pl > $2.toAdd.final
+cat $2.toAdd.clean | ./regRestorer.pl > $2.toAdd
 
 echo "Cleaning..."
-rm $1.fix $2.fix >/dev/null 2>&1
-rm $2.diff       >/dev/null 2>&1
-rm $2.toAdd      >/dev/null 2>&1
-mv $2.toAdd.final $2.toAdd 
+rm $1.fix $2.fix    >/dev/null 2>&1
+rm $2.diff          >/dev/null 2>&1
+rm $2.toAdd.clean   >/dev/null 2>&1
 
 echo "Operation completed, result file is $2.toAdd"
 
diff --git a/programs/regapi/regapi.c b/programs/regapi/regapi.c
index 619964879b6..8479e67c55e 100644
--- a/programs/regapi/regapi.c
+++ b/programs/regapi/regapi.c
@@ -21,8 +21,8 @@
 #define IDENTICAL             0 
 #define COMMAND_COUNT         7
 
-#define KEY_MAX_LEN           1024 
-#define STDIN_MAX_LEN         2048
+#define KEY_MAX_LEN             1024 
+#define STDIN_MAX_LEN         102400
 
 /* Return values */
 #define COMMAND_NOT_FOUND     -1
@@ -163,10 +163,7 @@ static char helpText[] =
 "INPUT FILE FORMAT\n"
 "\n"
 "          setValue\n"
-"              The input file format required by the setValue command is similar\n"
-"              to the one obtained from regedit.exe export option.  The only\n"
-"              difference is that multi line values are not supported, the\n"
-"              value data must be on a single line.\n"
+"              The input file is in format, obtained from regedit.exe export.\n"
 "\n"
 "              [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
 "              \"Value1\"=\"Data1\"\n"
@@ -994,7 +991,7 @@ static void doUnregisterDLL(LPSTR stdInput) {
  *        It then reads the STDIN line by line forwarding their processing
  *        to the appropriate method.
  */
-int PASCAL WinMain (HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
+int PASCAL WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 {
   LPSTR  token          = NULL;  /* current token analized */
   LPSTR  stdInput       = NULL;  /* line read from stdin */
@@ -1075,10 +1072,11 @@ int PASCAL WinMain (HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
               stdInput=HeapReAlloc(GetProcessHeap(),0,stdInput,strlen(stdInput)+STDIN_MAX_LEN);
 
               currentSize+=STDIN_MAX_LEN;
-    }
+          }
 
           strcat(stdInput,nextLine+2);
       }
+
     }
 
     /* 
diff --git a/programs/regapi/tests/.cvsignore b/programs/regapi/tests/.cvsignore
new file mode 100644
index 00000000000..48dcef97e6d
--- /dev/null
+++ b/programs/regapi/tests/.cvsignore
@@ -0,0 +1 @@
+regapi.ok
diff --git a/programs/regapi/tests/README b/programs/regapi/tests/README
new file mode 100644
index 00000000000..2e841734bab
--- /dev/null
+++ b/programs/regapi/tests/README
@@ -0,0 +1,5 @@
+Test data:
+
+after.reg       - registry file with the change, exported from regedit
+before.reg      - registry file without the change, exported from regedit
+orig.reg        - registry file ot the test change, exported from regedit
diff --git a/programs/regapi/tests/after.reg b/programs/regapi/tests/after.reg
new file mode 100644
index 00000000000..61e49523764
--- /dev/null
+++ b/programs/regapi/tests/after.reg
@@ -0,0 +1,92 @@
+REGEDIT4
+
+[HKEY_CURRENT_USER]
+
+[HKEY_CURRENT_USER\Software\WinCvs\wincvs\FileDetailView]
+"Column Widths"="150 50 50 100 150 150 150 "
+"Column Order"="0 1 2 3 4 5 6 "
+
+[HKEY_CURRENT_USER\Software\WinCvs\wincvs\Settings]
+"Window Pos"="2,3,-1,-1,-1,-1,198,198,1062,828"
+
+[HKEY_CURRENT_USER\Software\WinCvs\wincvs\Tip]
+"TimeStamp"="Mon Feb 11 13:20:51 2002"
+"StartUp"=dword:00000001
+"FilePos"=dword:00000247
+
+[HKEY_CURRENT_USER\Test Regapi]
+
+[HKEY_CURRENT_USER\Test Regapi\New Key #1]
+@="Sample default value data, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, end"
+"New String Value #1"="One more long string value 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 sss 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0  sssssss 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 end"
+"New Binary Value #1"=hex:30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,55
+"New DWORD Value #1"=dword:00000200
+"New DWORD Value #2"=dword:000000c9
+"New Binary Value #2"=hex:
+"New DWORD Value #3"=dword:00000000
+"New String Value #2"=""
+
+[HKEY_CURRENT_USER\UNICODE Program Groups]
+
+[HKEY_CURRENT_USER\Windows 3.1 Migration Status]
+
+[HKEY_CURRENT_USER\Windows 3.1 Migration Status\Groups]
+
+[HKEY_CURRENT_USER\Windows 3.1 Migration Status\IniFiles]
+
+[HKEY_CURRENT_USER\Volatile Environment]
+"NWUSERNAME"="APalamar"
+"LOGONSERVER"="\\\\CE08N270"
+"NWLANGUAGE"="English"
+"=M:"="M:\\"
+"=O:"="O:\\"
+"=P:"="P:\\"
+"=U:"="U:\\"
+"=Z:"="Z:\\"
+"PATH"="Z:."
+"USERNAME"="APalamar"
+"=N:"="N:\\"
+"=Q:"="Q:\\"
+"=S:"="S:\\"
+"=X:"="X:\\"
+"=T:"="T:\\"
+"WINDOWS_LOGIN"="0"
+
diff --git a/programs/regapi/tests/before.reg b/programs/regapi/tests/before.reg
new file mode 100644
index 00000000000..f9855b6563e
--- /dev/null
+++ b/programs/regapi/tests/before.reg
@@ -0,0 +1,42 @@
+REGEDIT4
+
+[HKEY_CURRENT_USER]
+
+[HKEY_CURRENT_USER\Software\WinCvs\wincvs\FileDetailView]
+"Column Widths"="150 50 50 100 150 150 150 "
+"Column Order"="0 1 2 3 4 5 6 "
+
+[HKEY_CURRENT_USER\Software\WinCvs\wincvs\Settings]
+"Window Pos"="2,3,-1,-1,-1,-1,198,198,1062,828"
+
+[HKEY_CURRENT_USER\Software\WinCvs\wincvs\Tip]
+"TimeStamp"="Mon Feb 11 13:20:51 2002"
+"StartUp"=dword:00000001
+"FilePos"=dword:00000247
+
+[HKEY_CURRENT_USER\UNICODE Program Groups]
+
+[HKEY_CURRENT_USER\Windows 3.1 Migration Status]
+
+[HKEY_CURRENT_USER\Windows 3.1 Migration Status\Groups]
+
+[HKEY_CURRENT_USER\Windows 3.1 Migration Status\IniFiles]
+
+[HKEY_CURRENT_USER\Volatile Environment]
+"NWUSERNAME"="APalamar"
+"LOGONSERVER"="\\\\CE08N270"
+"NWLANGUAGE"="English"
+"=M:"="M:\\"
+"=O:"="O:\\"
+"=P:"="P:\\"
+"=U:"="U:\\"
+"=Z:"="Z:\\"
+"PATH"="Z:."
+"USERNAME"="APalamar"
+"=N:"="N:\\"
+"=Q:"="Q:\\"
+"=S:"="S:\\"
+"=X:"="X:\\"
+"=T:"="T:\\"
+"WINDOWS_LOGIN"="0"
+
diff --git a/programs/regapi/tests/orig.reg b/programs/regapi/tests/orig.reg
new file mode 100644
index 00000000000..b4a3d7f66a7
--- /dev/null
+++ b/programs/regapi/tests/orig.reg
@@ -0,0 +1,49 @@
+REGEDIT4
+
+[HKEY_CURRENT_USER\Test Regapi\New Key #1]
+@="Sample default value data, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, very long, end"
+"New String Value #1"="One more long string value 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 sss 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0  sssssss 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 1,2,3,4,5,6,7,8,9,0 end"
+"New Binary Value #1"=hex:30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,\
+  37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,\
+  32,33,34,35,36,37,38,55
+"New DWORD Value #1"=dword:00000200
+"New DWORD Value #2"=dword:000000c9
+"New Binary Value #2"=hex:
+"New DWORD Value #3"=dword:00000000
+"New String Value #2"=""
diff --git a/programs/regapi/tests/regapi.pl b/programs/regapi/tests/regapi.pl
new file mode 100644
index 00000000000..ec0255b2771
--- /dev/null
+++ b/programs/regapi/tests/regapi.pl
@@ -0,0 +1,47 @@
+#!/usr/bin/perl -w
+#This script tests regapi functionality
+
+use strict;
+use diagnostics;
+
+test_diff();
+#TODO!!!
+#test_regedit();
+
+#removes all test output files
+sub clear_output
+{
+    unlink './tests/after.reg.toAdd';
+}
+
+#tests scripts which implement "diff" functionality for registry
+sub test_diff
+{
+    my $generated = './tests/after.reg.toAdd';
+    my $orig =  './tests/orig.reg';
+    my $s;
+
+    $s = './regSet.sh ./tests/before.reg ./tests/after.reg > /dev/null';
+    qx/$s/;
+
+    #files must be the same
+    if (-z($generated) || (-s($generated) != -s($orig))) {
+        die "Original and generated registry files ($orig and $generated) " .
+            "are different";
+    }
+    clear_output();
+}
+
+#tests compatibility with regedit
+sub test_regedit
+{
+    my $orig = './tests/orig.reg';
+    my $regedit = 'regapi';
+    my $delete_cmd;
+    my $insert_cmd = "$regedit setValue < $orig";
+    my $export_cmd;
+
+    qx/$insert_cmd/;
+    print "Insert: $insert_cmd\n";
+    clear_output();
+}
-- 
GitLab