int main(int argc, char *argv[]) {

  /* Some CTRL-C interrupt handling stuff... */
  gotsignal = 0;
  signal(SIGINT, breakhandler);
  
  /* When not enough arguments, print the help information */
  if ( (argc<3) ) {
    PrintHelpInformation();
    exit(1);
  }
  
  /* Initialize analysis control flags to default values,
     then read in the command line arguments. */
  controlVariables *ctrl = new controlVariables();
  ctrl->Initialize();
  Int_t good2Go = ctrl->InterpretCommandLine(argc, argv);
  if (good2Go != 1) { exit(-1); }

  cout << endl;
  cout << "********************************************************" << endl;
  cout << endl;
  
  cout << endl;
  
  good2Go = ctrl->ReportRunFlags();
  if (good2Go != 1) { exit(-2); }
  
  cout << endl;

  TStopwatch timer;

  /* Declare and then initialize GRETINA variables, i.e. geometry
     stuff, and calibration parameters, etc. */
  counterVariables *cnt = new counterVariables();

  /* Initialize the GRETINA data structures. */

  /* And data arrays... */
  /* GRETINA */
  unsigned char gBuf[32*32*1024];

  FILE *inf = NULL;

  FILE *generalOut = NULL;
  
  /* Loop over each run given at the command line. */
  if (ctrl->fileType == "f") { ctrl->startRun = 0; argc = 1; } /* For specific file name, 
								  once through loop only. */

  for (Int_t mm = ctrl->startRun; mm<argc; mm++) {
    
    timer.Reset();
    timer.Start();
    
    cnt->ResetRunCounters();

    TString runNumber = argv[mm];
    cnt->runNum = atoi(argv[mm]);
    
    /* Figure out the filename, etc. */
    if (ctrl->fileType == "g") {
      ctrl->fileName = ctrl->directory + "/Run" + runNumber + "/Global.dat";
      ctrl->outfileName = "./ROOTFiles/Run" + runNumber + "wGH.root";
    } else if (ctrl->fileType == "f") {
      ctrl->outfileName = "./ROOTFiles/test-wGH.root";
    } else {
      cerr << "WHAT???" << endl;
      return 0;
    }

    cout << "********************************************************" << endl;
    cout << endl;

    /* Open the input data file... */
    if (ctrl->compressedFile) {
      ctrl->fileName = "zcat " + ctrl->fileName;
      if (ctrl->fileName.EndsWith(".gz")) { }
      else { ctrl->fileName = ctrl->fileName + ".gz"; }
      inf = popen(ctrl->fileName.Data(), "r");
    } else if (ctrl->compressedFileB) {
      ctrl->fileName = "bzcat " + ctrl->fileName;
      if (ctrl->fileName.EndsWith(".bz2")) { }
      else { ctrl->fileName = ctrl->fileName + ".bz2"; }
      inf = popen(ctrl->fileName.Data(), "r");
    } else {
      inf = fopen(ctrl->fileName.Data(), "r");
    }

    ctrl->outputON = 1;
    
    if (ctrl->outputON) {
      if (ctrl->outputName) {
	generalOut = fopen(ctrl->outputFileName.Data(), "wb");
      } else if (!ctrl->outputName) {
	ctrl->outputFileName = ctrl->fileName;
	if (ctrl->fileName.EndsWith(".bz2")) { 
	  ctrl->outputFileName.ReplaceAll(".dat.bz2","GH.dat");
	} else if (ctrl->fileName.EndsWith(".gz")) {
	  ctrl->outputFileName.ReplaceAll(".dat.gz","GH.dat");
	} else {
	  ctrl->outputFileName.ReplaceAll(".dat","GH.dat");
	}
	ctrl->outputFileName.ReplaceAll("zcat ", "");
	generalOut = fopen(ctrl->outputFileName.Data(), "wb");
      }
      if (!generalOut) {
	cout << "Could not open output file " << ctrl->outputFileName.Data() << endl;
	exit(2); 
      } else {
	cout << "Opened output file " << ctrl->outputFileName.Data() << endl;
      } 
    } else {
      generalOut = NULL;
    }
    
    /* Reset variables needed for unpacking, histogramming, etc. */
    cnt->ResetRunCounters();
    
    Int_t TSerrors = 0;
    long long int currTS = 0;  long long int lastTS = 0;
    
    Int_t remaining = 0;
    
    /********************************************************/
    /*  THE MAIN EVENT -- SORTING LOOP                      */
    /********************************************************/

    /* Loop over file, reading data, and building events... */
    while (!gotsignal) {

      if (ctrl->pgh == 2) {
	
	gHeader.type = DECOMP;
	remaining = GetGRETINA(inf, generalOut, gBuf, sizeof(gBuf), gHeader.type, 0, ctrl, cnt);
	gHeader.timestamp = gMode2.timestamp;

      } else if (ctrl->pgh == 3) {

	gHeader.type = RAW;
	remaining = GetGRETINA(inf, generalOut, gBuf, sizeof(gBuf), gHeader.type, 0, ctrl, cnt);
	gHeader.timestamp = gMode3.led_timestamp;

      }

      /* Check against timestamps in file being out of order... */
      if (gHeader.timestamp < lastTS) {
	if (!ctrl->suppressTS)
	  cout << "TS out of order : lastTS " << lastTS << " current " 
	       << gHeader.timestamp << endl;
	TSerrors++;
      }
      lastTS = gHeader.timestamp;
	
      if ( (gHeader.timestamp != 0) && (currTS == 0) ) {
	currTS = gHeader.timestamp;
      }
      
      if (cnt->bytes_read_since_last_time > 2*1024*1024) {    
	cerr << "Processing " << cnt->bytes_read/(1024*1024) << " MB" <<"\r";
	cnt->MBread+=2;
	cnt->bytes_read_since_last_time = 0;
      }
      
      /**********************************************************/
      /* More GRETINA information before another global header. */
      /**********************************************************/
      while (remaining && !gotsignal) { 

	remaining = GetGRETINA(inf, generalOut, gBuf, sizeof(gBuf), gHeader.type, 
			       remaining, ctrl, cnt);
	if (ctrl->pgh == 2) { gHeader.timestamp = gMode2.timestamp; }
	else if (ctrl->pgh == 3) { gHeader.timestamp = gMode3.led_timestamp; }

	if (cnt->bytes_read_since_last_time > 2*1024*1024) {    
	  cerr << "Processing " << cnt->bytes_read/(1024*1024) << " MB" << "\r";
	  cnt->MBread+=2;
	  cnt->bytes_read_since_last_time = 0;
	}
      } /* end of ' while (remaining) ' */

    } /* End of "while we still have data and no interrupt signal" */
    
    timer.Stop();
    
    cout << "\n CPU time: " << timer.CpuTime() << "\tReal time: " << timer.RealTime() << endl;
    cout << " Average processing speed: " << (cnt->bytes_read/(1024*1024))/timer.RealTime() 
	 << "MB/s -- File size was " << cnt->bytes_read/(1024*1024) << " MB \n" << endl;
    
    cnt->PrintRunStatistics(ctrl->pgh, ctrl->withWAVE, ctrl->superPulse, ctrl->analyze2AND3);
    cnt->ResetRunCounters();

  } /* End of iterating over different run # */

  if (ctrl->outputON) {
    cout << endl;
    cout << "Closing output file...";
    fclose(generalOut);
    cout << "Done. " << endl;    
  }
  
  /* Declare victory!!! */
  
  cout << endl;
  timer.Delete();
  cout << "We finished without crashing!! Yay us! :)" << endl;
  cout << endl;

  return 1;
}