/* llsortlt.cpp   using classes and overloading <
 *
 * usage: llsortlt infilename outfilename [/+number]
 *
 * sort infilename by column 'number' and send records to outfilename
 */
#include 
#include 
#include 
#include "tcslll_.cpp"
#define   bool int

#define N 1000
ifstream inData;
ofstream outData;
long int sort_column;

/* a user defined node */
struct MyNode
  {
    int   length;
    char *mystring;

    bool operator < (const MyNode item);
  };

bool MyNode::operator < (const MyNode item)
  { char  *a, * b;
    MyNode *p, *q;

    p = this;
    q =(MyNode *) &item;
    a = this->mystring;
    b = item.mystring;

    a += sort_column-1;
    b += sort_column-1;

    if (p->length >= sort_column)
      if (q->length >= sort_column)
        return strcmp(a,b) < 0;
      else
        return strcmp(a," ") < 0;
    else
      if (q->length >= sort_column)
        return strcmp(" ",b) < 0;
      else
        return 0;
  }


ostream & operator << (ostream & os, const MyNode & rv)
  { os;
    return outData << rv.mystring << endl;
  }


typedef
  ListNode MyListNode;

int main (int argc, char *argv[])
{
  long int i;
  char *q,st[N];
  MyNode mn;
  MyListNode *p, *tail;
  List MyList;
  long int fs;
  long ints;
  char infn[256], outfn[256];
  char params[4][14] =
    { "program ","input   ","output  ","sort pos " };

/* display the command line arguments */
   cout << "ll_sorlt:\nargc = " << argc << endl;
   for (i=0; i < argc; i++)
     cout << "argv [" << i << "] " << params[i] << " " << argv[i] << endl;
   if (argc < 3) {
     cout << "Usage: llsort infile outfile number" << endl;
     exit(1);
   }

/* pick off the file names */
   strcpy( infn, argv[1]);
   strcpy(outfn, argv[2]);

// pick off the starting sort column (if it exists)
   sort_column = argc > 3 ? atol(argv[3]+2) : 1;
   if(sort_column<=0) sort_column=1;
   cout << "sort_column " << sort_column << endl;

  /* open the files */
  inData.open(infn);
  outData.open(outfn);

  /* read the input file and build the linked list */
  tail = NULL;
  cout << "Reading in the file:" << endl;
  while (inData.getline(st,100,'\n'))  /* get 1 line */
    {
      /* allocate space for the next string */
      q = (char *) malloc(strlen(st)+1);
      if (!q) { cout << "Not enough memory" << endl; exit(0); }
      strcpy(q,st);

      // gcount() of a blank line is 1
      if (inData.gcount()==1) *q = 0;

      /* save the length and address of the string,
       * then fetch and initialize a node */ 
      mn.length = strlen(q);
      mn.mystring = q;
      p = new MyListNode(mn);

      /* insert the node onto the tail end of the list */
      MyList.Insert_Right(tail,p);
    }
  inData.close();

/* sort the list using the overloaded <  */
   cout << "Sorting the file: " << endl;
   MyList.Sort(tail);

/* send the sorted records to the 'output' file */
   cout << "Writing the new file:" << endl;
   MyList.Traverse(tail);
   outData.close();
}