//     Author: Maurizio Loreti, aka MLO or (HAM) I3NOO
//     Work:   University of Padova - Department of Physics
//             Via F. Marzolo, 8 - 35131 PADOVA - Italy
//     Phone:  +39 (049) 827-7216   FAX: +39 (049) 827-7102
//     EMail:  [email protected]
//     WWW:    http://www.pd.infn.it/~loreti/mlo.html
//
// -------------------------------------------------------------------
//
//     C++ version of the program "lintex", born as an exercise
//     in programming.
//
//     $Id: ltx.cxx,v 1.9 2006/09/11 12:25:41 loreti Exp $
//
// -------------------------------------------------------------------

#include <algorithm>
#include <list>
#include <cstring>
#include "ltx.hh"               // Includes: functional, iostream, string
#include "cleandir.hh"          // Includes: string

extern "C" {
 #include <getopt.h>
 #include <unistd.h>
}

using std::cout;
using std::endl;
using std::string;

// Global variables (definition)

namespace ltx {
 string            progname;
 string            trailEd("~");
 string::size_type lTrailEd;
 bool              confirm(false);
 bool              recurse(false);
}

using namespace ltx;

// Local procedures

namespace {
 char *basename(char *);
 void  syntax();
}

int main(
 int   argc,
 char *argv[]
) {
 std::list<string> targets;

 // Gets the executable name

 progname = argv[0] = basename(argv[0]);

 // Decodes the command line options and arguments

 char          shortOpts[] = "irb::";
 struct option longOpts[]  = {
   {"interactive", no_argument,       0, 'i'},
   {"recursive",   no_argument,       0, 'r'},
   {"backup",      optional_argument, 0, 'b'},
   { 0,            0,                 0,  0}
 };

 int c;
 while ((c = getopt_long(argc, argv, shortOpts, longOpts, 0)) != -1) {
   switch (c) {
     case 'i':
       confirm = true;
       break;

     case 'r':
       recurse = true;
       break;

     case 'b':
       trailEd = optarg ? optarg : "";
       break;

     case 'h':
     case '?':
       syntax();
       return 0;

     default:
       std::cerr << "Can't happen: " << __FILE__ << ' '
                 << __LINE__ << endl;
       return 0;
   }
 }

 while (optind < argc) targets.push_back( argv[optind++] );

 // Computes the length of the extension identifying the backup
 // files, and, if no target directories were explicitly given,
 // scans the current one.

 lTrailEd = trailEd.size();

 if (targets.empty()) targets.push_back(".");

#if defined(DEBUG)
 cout << "--------------------Argument analysis\n";
 cout << "Confirm = " << confirm << endl;
 cout << "Recurse = " << recurse << endl;
 cout << "Trailing editor extension = \"" << trailEd
      << "\" (length " << lTrailEd << ")\n";
 cout << "Target directories:\n";

 for_each(targets.begin(), targets.end(), printBefore("  "));
#endif // DEBUG

 // Scans in turn all the wanted directories

 for_each(targets.begin(), targets.end(), std::ptr_fun(scan_dir));

 return 0;
}

namespace {
 char *basename(
   char *pc
 ) {
   // Strips the (eventual) path name from the full file name pointed
   // to by "pc"; if no file name is given, returns an empty string.

   char *p = std::strrchr(pc, '/');
   if (p == 0) return pc;
   return ++p;
 }

 void syntax()
 {
   cout <<
     "\nUsage:\t " << progname << " [options] [dir [dir ... ]]\n";
   cout <<
     "Purpose: removes TeX auxiliary files and editor backup files from "
     "the\n";
   cout
     << "\t given directories (default: from the current directory).  TeX\n";
   cout <<
     "\t auxiliary files are actually removed only if their modification\n";
   cout <<
     "\t time is more recent than the one of the related TeX source file.\n";
   cout <<
     "Options: -i     | --interactive : asks before removing files;\n";
   cout <<
     "\t -r     | --recursive   : scans recursively the given directories;\n";
   cout <<
     "\t -b=ext | --backup=ext  : \"ext\" is the trailing string "
     "identifying\n";
   cout <<
     "\t\t\t\t  editor backup files.\n";
   cout <<
     "Notes:\t \"ext\" defaults to \"~\"; -b \"\" avoids the unconditional "
     "cleanup of\n";
   cout <<
     "\t any special file.\n" << endl;
 }
}