Index: /trunk/FACT++/src/fixfits.cc
===================================================================
--- /trunk/FACT++/src/fixfits.cc	(revision 20035)
+++ /trunk/FACT++/src/fixfits.cc	(revision 20036)
@@ -36,5 +36,4 @@
 {
     ostringstream str;
-    str << setfill(' ');
     str << value;
 
@@ -42,13 +41,14 @@
     str.str("");
 
-    str << setw(8-keyword.size()) << keyword;
+    str << setfill(' ') << left;
+    str << setw(8) << keyword;
 
     str << "= ";
 
-    str << setw(20-num_length) << value << " / " << comment;
+    str << setw(20) << value << " / " << comment;
 
     str << setw(80-str.str().size()) << ' ';
 
-    cout << '\n' << str.str() << '\n';
+    cout << keyword.size() << ":" << num_length << ":" << str.str().size() << ":" << str.str() << '\n';
 
     if (str.str().size() != 80)
@@ -68,5 +68,7 @@
     control.add_options()
         ("file",  var<string>()->required(),  "Input file name. Fits file to be repaired.")
-        ("out,o", var<string>(),              "Output file name (+'.repaired' if empty)")
+        ("out,o", var<string>(),              "Output file name (+'.repaired' if empty), dry-run if not provided")
+        ("no-progress", po_switch(),          "Suppress progress output")
+        ("dry-run", po_switch(),              "Do not write any output")
         ;
 
@@ -105,11 +107,19 @@
     const string input_name  = conf.Get<string>("file");
     const string output_name = conf.Has("out") ? conf.Get<string>("out") :
-        (fs::path(input_name)/".repaired").string();
-
-    cout << "Reading: " << input_name << endl;
+        (input_name+".repaired");
+
+    const bool no_progress = conf.Get<bool>("no-progress");
+    const bool dry_run = conf.Get<bool>("dry-run");
+
+    cout << "\nReading: " << input_name << endl;
 
     ifstream input(input_name.c_str(), ios_base::binary);
-
-    cout << "Looking for beginning of data table." << endl;
+    if (!input)
+    {
+        cerr << "Error opening file: " << strerror(errno) << endl;
+        return 6;
+    }
+
+    cout << "Seeking beginning of data table." << endl;
 
     // ------------------------------------------------------------
@@ -137,6 +147,9 @@
         num_bytes+=80;
 
-        cout << "\rByte " << num_bytes << "      ";
-    }
+        if (!no_progress)
+            cout << "\rByte " << num_bytes << "      ";
+    }
+    if (no_progress)
+        cout << "Reached " << num_bytes << '\n';
     cout << "\nFound beginning of data table." << endl;
 
@@ -155,6 +168,9 @@
         num_bytes+=80;
 
-        cout << "\rByte " << num_bytes << "       ";
-    }
+        if (!no_progress)
+            cout << "\rByte " << num_bytes << "       ";
+    }
+    if (no_progress)
+        cout << "Reached " << num_bytes << '\n';
 
     cout << "\nReached end of data table header" << endl;
@@ -168,6 +184,9 @@
         num_bytes+=80;
 
-        cout << "\rByte " << num_bytes << "       ";
-    }
+        if (!no_progress)
+            cout << "\rByte " << num_bytes << "       ";
+    }
+    if (no_progress)
+        cout << "Reached " << num_bytes << '\n';
 
 
@@ -180,9 +199,13 @@
         input.read(buffer, 4);
         num_bytes += 4;
-        cout << "\rByte " << num_bytes << "      ";
-    }
+
+        if (!no_progress)
+            cout << "\rByte " << num_bytes << "      ";
+    }
+    if (no_progress)
+        cout << "Reached " << num_bytes << '\n';
 
     input.seekg(num_bytes-4);
-    cout << "\nFound start of very first compressed tile" << endl;
+    cout << "\nFound start of first compressed tile," << endl;
 
     // ------------------------------------------------------------
@@ -196,7 +219,7 @@
     BlockHeader block_head;
 
-    input.read((char*)(&tile_head), sizeof(TileHeader));
-
-    cout << "First tile is " << tile_head.size << " bytes long" << endl;
+    input.read(reinterpret_cast<char*>(&tile_head), sizeof(TileHeader));
+
+    cout << "First tile is " << tile_head.size << " bytes long." << endl;
 
     // ------------------------------------------------------------
@@ -205,7 +228,7 @@
     size_t num_blocks = 0;
 
-    while (input.tellg() < byte_where_tile_start+tile_head.size)
-    {
-        input.read((char*)(&block_head), sizeof(BlockHeader));
+    while (size_t(input.tellg()) < byte_where_tile_start+tile_head.size)
+    {
+        input.read(reinterpret_cast<char*>(&block_head), sizeof(BlockHeader));
         block_bytes += block_head.size;
 
@@ -220,5 +243,5 @@
     }
 
-    if (input.tellg() != byte_where_tile_start+tile_head.size)
+    if (size_t(input.tellg()) != byte_where_tile_start+tile_head.size)
     {
         cout << "Discrepancy between tile size and sum of blocks size." << endl;
@@ -226,5 +249,5 @@
     }
 
-    cout << "There are " << num_blocks << " blocks in each tile. Now looping over all tiles" << endl;
+    cout << "There are " << num_blocks << " blocks in each tile.\nLooping over all tiles" << endl;
 
     // ------------------------------------------------------------
@@ -253,5 +276,5 @@
         }
 
-        input.read((char*)(&tile_head), sizeof(TileHeader));
+        input.read(reinterpret_cast<char*>(&tile_head), sizeof(TileHeader));
         if (memcmp(tile_head.id, "TILE", 4) || input.eof())
         {
@@ -263,5 +286,5 @@
         catalog.emplace_back();
 
-        for (int i=0;i<num_blocks;i++)
+        for (size_t i=0; i<num_blocks; i++)
         {
             input.read((char*)(&block_head), sizeof(BlockHeader));
@@ -285,5 +308,6 @@
         catalog.back().emplace_back(0,0);
 
-        cout << "\rByte " << input.tellg() << "      ";
+        if (!no_progress)
+            cout << "\rByte " << input.tellg() << "      ";
         num_tiles++;
     }
@@ -304,113 +328,130 @@
 
     //Now we have everything that we need. Go again through the input file and write the output, fixed file
-    cout << "Data recovered.\n Writing output file: " << output_name << endl;
+    cout << "Recovery finished!\n\nWriting: " << output_name << endl;
 
     // ============================================================
 
-    ofstream output(output_name.c_str(), ios_base::binary);
-    input.seekg(0);
-
-    //copy everything until the catalog start and update header values on our way
-    counter = 0;
-    for (uint64_t i=0; i<output_catalog_start; i+=80)
-    {
-        input.read(buffer, 80);
-
-        if (!strcmp(buffer, "XTENSION= 'BINTABLE'           / binary table extension                         "))
-            counter++;
-
-        if (counter == 2)
-        {
-            bool rc = true;
-            if (!memcmp(buffer, "NAXIS2", 6))
-                rc &= update_header_key(buffer, "NAXIS2", num_tiles, "number of rows in table");
-            if (!memcmp(buffer, "ZNAXIS2", 7))
-                rc &= update_header_key(buffer, "ZNAXIS2", num_tiles, "Number of uncompressed rows");
-            if (!memcmp(buffer, "PCOUNT", 6))
-                rc &= update_header_key(buffer, "PCOUNT", output_heap_end - output_catalog_end, "size of special data area");
-            if (!memcmp(buffer, "THEAP", 5))
-                rc &= update_header_key(buffer, "THEAP", theap, "Pointer to heap");
-            if (!memcmp(buffer, "ZHEAPPTR", 8))
-                rc &= update_header_key(buffer, "ZHEAPPTR", zheapptr, "Pointer to data");
-
-            if (!rc)
-                return 5;
-        }
-
-        output.write(buffer, 80);
-
-        cout << "\rByte " << input.tellg() << "       ";
-    }
-
-    // ------------------------------------------------------------
-
-    // now write the updated catalog
-    const uint64_t reserved_num_tiles   = zheapptr / (num_cols*16);
-    const uint32_t one_catalog_row_size = num_cols*16;
-    const uint32_t total_catalog_size   = reserved_num_tiles*one_catalog_row_size;
-
-    vector<char> swapped_catalog(total_catalog_size);
-
-    uint32_t shift = 0;
-    for (auto it=catalog.cbegin(); it!=catalog.cend(); it++)
-    {
-        revcpy<sizeof(int64_t)>(swapped_catalog.data() + shift, (char*)(it->data()), num_cols*2);
-        shift += one_catalog_row_size;
-    }
-
-    if (num_tiles < reserved_num_tiles)
-        memset(swapped_catalog.data()+shift, 0, total_catalog_size - shift);
-
-    output.write(swapped_catalog.data(), total_catalog_size);
-
-    // ------------------------------------------------------------
-
-    // we are now at the beginning of the heap in the output file. Move there in the input file
-    input.seekg(output_heap_start);
-
-    uint64_t num_heap_bytes_written = 0;
-    uint64_t total_heap_bytes_to_write = output_heap_end - output_heap_start;
-
-    cout << endl << "Catalog updated. Copying " << total_heap_bytes_to_write << " of data now." << endl;
-
-    while (num_heap_bytes_written != total_heap_bytes_to_write)
-    {
-        uint64_t bytes_to_write = 2048;
-        if (total_heap_bytes_to_write - num_heap_bytes_written < 2048)
-            bytes_to_write = total_heap_bytes_to_write - num_heap_bytes_written;
-
-        input.read(buffer, bytes_to_write);
-        output.write(buffer, bytes_to_write);
-        num_heap_bytes_written += bytes_to_write;
-        cout << "\rByte " << input.tellg() << "           ";
-    }
-
-    cout << "\nData written. Adding FITS padding. " << endl;
-
-    // ------------------------------------------------------------
-
-    //now add the FITS padding at the end
-    while (output.tellp() % 2880 != 0)
-    {
-        output.write("\0", 1);
-    }
+    if (!dry_run)
+    {
+        ofstream output(output_name.c_str(), ios_base::binary);
+        input.seekg(0);
+
+        //copy everything until the catalog start and update header values on our way
+        counter = 0;
+        for (uint64_t i=0; i<output_catalog_start; i+=80)
+        {
+            input.read(buffer, 80);
+
+            if (!strcmp(buffer, "XTENSION= 'BINTABLE'           / binary table extension                         "))
+                counter++;
+
+            if (counter == 2)
+            {
+                bool rc = true;
+
+                if (!memcmp(buffer, "NAXIS2", 6))
+                    rc &= update_header_key(buffer, "NAXIS2", num_tiles, "number of rows in table");
+                if (!memcmp(buffer, "ZNAXIS2", 7))
+                    rc &= update_header_key(buffer, "ZNAXIS2", num_tiles, "Number of uncompressed rows");
+                if (!memcmp(buffer, "PCOUNT", 6))
+                    rc &= update_header_key(buffer, "PCOUNT", output_heap_end - output_catalog_end, "size of special data area");
+                if (!memcmp(buffer, "THEAP", 5))
+                    rc &= update_header_key(buffer, "THEAP", theap, "Pointer to heap");
+                if (!memcmp(buffer, "ZHEAPPTR", 8))
+                    rc &= update_header_key(buffer, "ZHEAPPTR", zheapptr, "Pointer to data");
+
+                if (!rc)
+                    return 5;
+            }
+
+            output.write(buffer, 80);
+
+            if (!no_progress)
+                cout << "\rByte " << input.tellg() << "       ";
+        }
+
+        if (no_progress)
+            cout << "Reached " << input.tellg() << '\n';
+
+        // ------------------------------------------------------------
+
+        // now write the updated catalog
+        const uint64_t reserved_num_tiles   = zheapptr / (num_cols*16);
+        const uint32_t one_catalog_row_size = num_cols*16;
+        const uint32_t total_catalog_size   = reserved_num_tiles*one_catalog_row_size;
+
+        vector<char> swapped_catalog(total_catalog_size);
+
+        uint32_t shift = 0;
+        for (auto it=catalog.cbegin(); it!=catalog.cend(); it++)
+        {
+            revcpy<sizeof(int64_t)>(swapped_catalog.data() + shift, (char*)(it->data()), num_cols*2);
+            shift += one_catalog_row_size;
+        }
+
+        if (num_tiles < reserved_num_tiles)
+            memset(swapped_catalog.data()+shift, 0, total_catalog_size - shift);
+
+        output.write(swapped_catalog.data(), total_catalog_size);
+
+        // ------------------------------------------------------------
+
+        // we are now at the beginning of the heap in the output file. Move there in the input file
+        input.seekg(output_heap_start);
+
+        uint64_t num_heap_bytes_written = 0;
+        uint64_t total_heap_bytes_to_write = output_heap_end - output_heap_start;
+
+        cout << "\nCatalog updated.\nCopying " << total_heap_bytes_to_write << " of data now." << endl;
+
+        while (num_heap_bytes_written != total_heap_bytes_to_write)
+        {
+            uint64_t bytes_to_write = 2048;
+            if (total_heap_bytes_to_write - num_heap_bytes_written < 2048)
+                bytes_to_write = total_heap_bytes_to_write - num_heap_bytes_written;
+
+            input.read(buffer, bytes_to_write);
+            output.write(buffer, bytes_to_write);
+            num_heap_bytes_written += bytes_to_write;
+
+            if (!no_progress)
+                cout << "\rByte " << input.tellg() << "           ";
+        }
+        if (no_progress)
+            cout << "Reached " << input.tellg() << '\n';
+
+        cout << "\nData written. Adding FITS padding. " << endl;
+
+        // ------------------------------------------------------------
+
+        //now add the FITS padding at the end
+        while (output.tellp() % 2880 != 0)
+            output.write("\0", 1);
+    }
+    else
+        cout << " ... skipped ...\n";
+
     cout << "File recovered!\n";
 
-    input.close();
-    output.close();
-
-    // ------------------------------------------------------------
-
-    cout << "\nValid num tiles: " << num_tiles;
-    cout << "\nCatalog start  : " << output_catalog_start;
-    cout << "\nCatalog end    : " << output_catalog_end;
-    cout << "\nHeap start     : " << output_heap_start;
-    cout << "\nHeap end       : " << output_heap_end;
-    cout << "\nZHEAPPTR       : " << zheapptr;
-    cout << "\nTHEAP          : " << theap;
-    cout << "\nPCOUNT         : " << output_heap_end - output_catalog_end;
-    cout << "\nNAXIS2         : " << num_tiles;
-    cout << "\nZNAXIS2        : " << num_tiles;
-
+    // ------------------------------------------------------------
+
+    cout << "\nValid num tiles  : " << setw(12) << num_tiles;
+    cout << "\nNAXIS2           : " << setw(12) << num_tiles;
+    cout << "\nZNAXIS2          : " << setw(12) << num_tiles;
+    cout << "\nCatalog start    : " << setw(12) << output_catalog_start;
+    cout << "\nCatalog end      : " << setw(12) << output_catalog_end;
+    cout << "\nZHEAPPTR         : " << setw(12) << zheapptr;
+    cout << "\nTHEAP            : " << setw(12) << theap;
+    cout << "\nHeap start       : " << setw(12) << output_heap_start;
+    cout << "\nHeap end         : " << setw(12) << output_heap_end;
+    cout << "\nPCOUNT           : " << setw(12) << output_heap_end - output_catalog_end;
+    cout << '\n';
+    cout << "\nInput  file size : " << setw(12) << fs::file_size(input_name);
+    if (!dry_run)
+    {
+        cout << "\nOutput file size : " << setw(12) << fs::file_size(output_name);
+        cout << "\nLost bytes       : " << setw(12) << fs::file_size(input_name)-fs::file_size(output_name);
+        cout << "\nLost fraction    : " << setw(12) <<  1.-fs::file_size(output_name)/fs::file_size(input_name);
+    }
     cout << "\n\nYou should now:\n";
     cout << "- update TSTOPI and TSTOPF using \"fitsdump -c UnixTimeUTC --minmax --nozero\" and then fv\n";
