// Time-stamp: </wrf/c/union/header, Wed, 4 Dec 2002, 14:58:36 EST,
// wrf@benvolio.ecse.rpi.edu>

#include <iostream>
#include <fstream>
#include <strstream>
#include <string>
#include <stdlib.h>
#include <iomanip>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <stdio.h>
#include <errno.h>

using namespace std;

// Print an expression's name then its value, possible followed by a comma or endl.
// Ex: cout << PRINTC(x) << PRINTN(y);

#define PRINT(arg)  #arg "=" << arg
#define PRINTC(arg)  #arg "=" << arg << ", "
#define PRINTN(arg)  #arg "=" << arg << endl


// Read 1, 3, 4, or 8 vars from cin.  Check for errors.

#define CINE(arg)  { cin >> arg; if (!cin) { cerr << "CINE failed reading var >" #arg "< in file >" __FILE__ "< at line >" << __LINE__ << "<."  << endl; exit(2);}}

#define CINE3(a,b,c) CINE(a);CINE(b);CINE(c)
#define CINE4(a,b,c,d) CINE(a);CINE(b);CINE(c);CINE(d)
#define CINE8(a,b,c,d,e,f,g,h) CINE(a);CINE(b);CINE(c);CINE(d);CINE(e);CINE(f);CINE(g);CINE(h)


// Read a string from cin, checking for errors.

#define GETLINE(string)  { getline(cin,string); if (!cin) { cerr << "GETLINE failed reading string " #string  << " in file " __FILE__ " at line " << __LINE__  << endl; exit(1);}}


// Do a NEW, checking for errors.

#define NEWA(var,type,size) { try  { if(!(var=new type [(size)])) throw;} catch (...)  { cerr << "NEWA failed on " #var "=new " #type "[" #size "=" << (size) << "]" << endl; exit(1); }}


// MAX (There must be a lib with this!)

template < class C, class D > inline C max (const C a, const D b)
{
    return (a > b) ? a : b;
}


// MIN

template < class C, class D > inline C min (const C a, const D b)
{
    return (a < b) ? a : b;
}


// Do a READ with error checking.

int
read2 (char *const buffer, const int len)
{
    cin.read (buffer, len);
    if (!cin)
      {
	  cerr << "READ failed reading cin at position " << cin.tellg ()
	      << " into buffer with len=" << len;
	  return 0;
      }
    if (cin.gcount () != len)
      {
	  cerr << "READ returned only " << cin.gcount ()
	      << " chars when reading cin at position " << cin.tellg ()
	      << " into buffer with len=" << len;
	  return 0;
      }
    return 1;
}


// print an int with embedded commas (e.g., -1,234,567,890) to cout

void
printioc (const int i)
{
    if (i == 0)
      {
	  cout << '0';
	  return;
      }
    int     j = abs (i);
    if (i < 0)
	cout << '-';
    if (j >= 1000000000)
      {
	  cout << j / 1000000000 << ',' << setfill ('0') << setw (3) << j %
	      1000000000 / 1000000 << ',' << setfill ('0') << setw (3) << j %
	      1000000 / 1000 << ',' << setfill ('0') << setw (3) << j % 1000;
      }
    else if (j >= 1000000)
      {
	  cout << j / 1000000 << ',' << setfill ('0') << setw (3) << j % 1000000 /
	      1000 << ',' << setfill ('0') << setw (3) << j % 1000;
      }
    else if (j >= 1000)
      {
	  cout << j / 1000 << ',' << setfill ('0') << setw (3) << j % 1000;
      }
    else
	cout << j;
}


// Print to cout an expression, then its value with embedded commas,
// possible followed by a comma.

#define PRINTIOC(arg) cout << #arg "="; printioc(arg)
#define PRINTIOCC(arg) cout << #arg "="; printioc(arg); cout << ", "


void
die (const char *msg)
{
    std::cerr << "ERROR: " << msg << endl;
    exit (1);
}


// Print the current time, source file name, when compiled, and
// compiler version.

int
print_env (ostream & out)
{
    char   *now;
    time_t  secs;

    secs = time (NULL);
    now = ctime (&secs);
    out <<
	"\n\n****************************************************************\n***** UNION starting at "
	<< now << "*****" << endl;

    out << "File: " << __FILE__ << ", compiled: " << __DATE__ << ' '
	<< __TIME__ << ", GNU compiler " << __GNUC__ << '.' << __GNUC_MINOR__;

#ifdef __GNUC_PATCHLEVEL__
    out << '.' << __GNUC_PATCHLEVEL__;
#endif
    out << ", version " << __VERSION__ << ", ";
#ifndef __OPTIMIZE__
    out << "NOT ";
#endif
    out << " optimized." << endl;
}
