#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#undef __GNUC__

#include <iostream.h>

const char *const szZONE = "Zone";
const int sizeofZONE = strlen(szZONE);

const char *const szREGION = "Region";
const int sizeofREGION = strlen(szREGION);

const int TRUE = !NULL;
const int FALSE = NULL;

const int SUCCESS = 0;
const int FAILURE = !SUCCESS;

char *progname;

void usage(void);
int main(int argc, char **argv);

void usage(void) {
  fprintf(stderr, "Usage: %s -z <zone to cut> | -r <region to cut> < <nodelist>\n"
                  "Example:\n"
                  "  $ %s -r 29 < ~fnet/nl/nodelist.153 > region29.153\n",
          progname, progname);
  return;
}

#if 1

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

  int argoff, c;

  char *zone_to_cut, *region_to_cut;
  int sizeof_zone_to_cut = 0, sizeof_region_to_cut = 0;
  int listallmatched;

  int done, matched;
  char S[BUFSIZ];
  char *p;

  progname = argv[0];
  if ((p = strrchr(argv[0], '/')))
    progname = ++p;

  zone_to_cut = region_to_cut = NULL;
  listallmatched = FALSE;

  const char *const szOPTIONS = "z:r:ah";
  argoff = 0;
  while ((c = getopt(argc - argoff, argv + argoff, szOPTIONS)) != EOF) {
    switch (c) {
      case 'z':
        zone_to_cut = strdup(optarg);
        region_to_cut = NULL;
        break;
      case 'r':
        zone_to_cut = NULL;
        region_to_cut = strdup(optarg);
        break;
      case 'a':
        listallmatched = TRUE;
      case 'h':
      default:
        usage();
        return 1;
    }
  }
  if (!zone_to_cut && !region_to_cut) {
    usage();
    fprintf(stderr, "Either zone or region must be specified.\n");
    return 2;
  }

  if (zone_to_cut)
    sizeof_zone_to_cut = strlen(zone_to_cut);

  if (region_to_cut)
    sizeof_region_to_cut = strlen(region_to_cut);
  
  done = FALSE;
  matched = FALSE;

  while (gets(S) && !done) {
    if (zone_to_cut) {
      if (!strncasecmp(S, szZONE, sizeofZONE)) {
        if (!strncmp(S + sizeofZONE + 1, zone_to_cut, sizeof_zone_to_cut)
            && *(S + sizeofZONE + 1 + sizeof_zone_to_cut) == ',')
          matched = TRUE;
        else {
          done = (listallmatched ? FALSE : (matched ? TRUE : FALSE));
          matched = FALSE;
        }
      }
    }
    else if (region_to_cut) {
      if (!strncasecmp(S, szREGION, sizeofREGION)) {
        if (!strncmp(S + sizeofREGION + 1, region_to_cut, sizeof_region_to_cut)
            && *(S + sizeofREGION + 1 + sizeof_region_to_cut) == ',')
          matched = TRUE;
        else {
          done = (listallmatched ? FALSE : (matched ? TRUE : FALSE));
          matched = FALSE;
        }
      }
      if (!strncasecmp(S, szZONE, sizeofZONE)) {
        done = (listallmatched ? FALSE : (matched ? TRUE : FALSE));
        matched = FALSE;
      }
    }

    if (matched)
      puts(S);
  }

  return 0;
}

#else

class node_entry {
    char *entry;
    char *attrib;
    int number;
    char *system_name;
    char *location;
    char *sysop_name;
    char *system_phone;
    int speed;
    char *flags;
    char **flags_array;
    int nflags;
  public:
    node_entry(char *An_entry);
    ~node_entry();
    char *get_entry(void) { return entry; };
    char *get_attrib(void) { return attrib; };
    int get_number(void) { return number; };
    char *get_system_name(void) { return system_name; };
    char *get_location(void) { return location; };
    char *get_sysop_name(void) { return sysop_name; };
    char *get_system_phone(void) { return system_phone; };
    int get_speed(void) { return speed; };
    char *get_flags(void) { return flags; };
    int get_nflags(void) { return nflags; };
    int flags_coincide_with(const char *flag);
};

node_entry::node_entry(char *An_entry) {
  char *S = strdup(An_entry);
  char *p;
  int i;
  
  entry = new char[strlen(An_entry) + 1];
  strcpy(entry, An_entry);

  p = strtok(S, ",\n\r\t");
  attrib = new char[strlen(p) + 1];
  strcpy(attrib, p);

  number = atoi(strtok(NULL, ",\n\r\t"));

  p = strtok(NULL, ",\n\r\t");
  system_name = new char[strlen(p) + 1];
  strcpy(system_name, p);

  p = strtok(NULL, ",\n\r\t");
  location = new char[strlen(p) + 1];
  strcpy(location, p);

  p = strtok(NULL, ",\n\r\t");
  sysop_name = new char[strlen(p) + 1];
  strcpy(sysop_name, p);

  p = strtok(NULL, ",\n\r\t");
  system_phone = new char[strlen(p) + 1];
  strcpy(system_phone, p);

  speed = atoi(strtok(NULL, ",\n\r\t"));
  
  p = strtok(NULL, "\n\r\t");
  flags = new char[strlen(p) + 1];
  strcpy(flags, p);

  nflags = 0;
  if (strlen(flags)) {
    p = flags;
    ++nflags;
    while ((p = strchr(p + 1, ',')))
      ++nflags;
  }
  flags_array = new char*[nflags + 1];
  p = strtok(strdup(flags), ",\n\r\t");
  for (i = 0; i < nflags; i++) {
    flags_array[i] = new char[strlen(p) + 1];
    strcpy(flags_array[i], p);
    p = strtok(NULL, ",\n\r\t");
  }
  flags_array[nflags] = NULL;
}

node_entry::~node_entry() {
  int i;

  delete entry;
  delete attrib;
  delete system_name;
  delete location;
  delete sysop_name;
  delete system_phone;
  delete flags;
  for (i = 0; i < nflags; i++)
    delete flags_array[i];
  delete flags_array;
}

int node_entry::flags_coincide_with(const char *flag) {
  int i;
  for (i = 0; i < nflags; i++)
    if (!strcasecmp(flags_array[i], flag))
      return TRUE;
  return FALSE;
}

class nodelist {
  node_entry ent;
  char *network_id;
  char *nodelist_filename;
  char *nodelist_filename_ext;
  char *nodelist_dir;
  char *nodelist_fullpath;
  int juliandate;
  FILE *fp;
  nodelist();
  ~nodelist();
  int open();
  int nodelist(char *A_nodelist_dir, char *A_nodelist_filename_ext);
  int nodelist(char *A_nodelist_dir, char *A_nodelist_filename,
               int A_juliandate = -1); // find latest if juliandate=-1
  int nodelist(char *A_nodelist_fullpath);
  char *find_latest_nodelist(char *A_nodelist_id);
  int close();
};

int nodelist::nodelist(char *A_nodelist_fullpath) {
  nodelist_fullpath = new char[strlen(A_nodelist_fullpath)];
  splitpath
  strcpy(nodelist_fullpath, A_nodelist_fullpath);
  if ((fp = fopen(nodelist_fullpath)) == NULL) {
    fprintf(strerr, "%s\n", strerror(errno));
    return SUCCESS;
  }
  return FAILURE;
}

int main(void) {
  node_entry node_ent("Hub,500,Military_Net,Yokota_Japan,Keith_Wagner,81-3117-57-2917,9600,CM,VFC,V32B,V42B\r");
  cout << "attrib=\"" << node_ent.get_attrib() << "\"" << endl;
  cout << "number=" << node_ent.get_number() << endl;
  cout << "system_name=\"" << node_ent.get_system_name() << "\"" << endl;
  cout << "location=\"" << node_ent.get_location() << "\"" << endl;
  cout << "sysop_name=\"" << node_ent.get_sysop_name() << "\"" << endl;
  cout << "system_phone=\"" << node_ent.get_system_phone() << "\"" << endl;
  cout << "speed=" << node_ent.get_speed() << endl;
  cout << "flags=\"" << node_ent.get_flags() << "\"" << endl;
  cout << "nflags=" << node_ent.get_nflags() << endl;
//  cout << "flags_array=\"" << node_ent.get_flags_array() << "\"" << endl;
  return 0;
}

#endif
