/************************************************************************
* retroLP solves linear programs using the simplex method.             *
* Copyright (C) 2001, 2003, 2005 Gavriel Yarmish & Richard Van Slyke.  *
* For further information, and gpl licensing, see the end of this file.*
************************************************************************/


//  8/12/04 Comment lines counted twice; fixed.
// 11/25/00: Fixed bug caused by too many terminating blanks in input
//  lines. Now they are truncated in "readline."
#define BUFFSIZE 80
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>       //for exit()
#include <string>
#include <algorithm>
#include "mps.h"

using namespace std;

// Functions defined in this file
short lparse(FILE *, string &, string &, string &, string &,
  double &, double &, string &, long&);
int upper(int , string &);
string trim(string );
int readline(FILE *, string &);

//================= PARSELINE ====================
short lparse(FILE *ifile, string &key, string \
 &n0, string  &n1, string &n2, double &val1, double &val2,\
 string & bfr, long & ln )
{
  char * ptr[1];// Convenience for srtod
  string v1, v2;
  short bytes, nchars;
comment:  bytes=readline(ifile, bfr);
// Check for error or EOF
  if(bytes<0)
  {
    printf("error in input at line %ld \n", ln);
    exit(201);
  }
  if(bytes==0)return bytes;
  ln++;
// Check for comments
  if(bfr.at(0)=='*')
  {
  printf("%s \n", bfr.c_str());
  goto comment;
  }
// Check for "Key Word"
  if(bfr.at(0)!=' ')
  {
    upper(7, bfr);
    if(bfr.find("NAME")!=std::string::npos)
    {
      return NAME;
    }
    if(bfr.find("ROWS")!=std::string::npos)
    {
      return ROWS;    }
    if(bfr.find("COLUMNS")!=std::string::npos)
    {
      return COLUMNS;
    }
    if(bfr.find("RHS")!=std::string::npos)
    {
      return RHS;
    }
    if(bfr.find("RANGES")!=std::string::npos)
    {
      return RANGES;
    }
    if(bfr.find("BOUNDS")!=std::string::npos)
    {
      return BOUNDS;
    }
    if(bfr.find("ENDATA")!=std::string::npos)
    {
      return ENDATA;
    }
    bytes = -1;
    printf("Unknown keyword in input: %s\n",bfr.c_str());
    return -1;
  }
// Break into fields
    nchars = bytes;
    if (nchars > 1)
    {key=trim(bfr.substr(1,2));bytes = 8;}
    if (nchars > 4)
    {n0=trim(bfr.substr(4,8));bytes = 9;}
    if (nchars > 14)
    {n1=trim(bfr.substr(14,8));bytes = 10;}
    if (nchars > 24)
    {
      v1=bfr.substr(24,12);
      val1=strtod(v1.c_str(),ptr);
      bytes = 11;
    }
    if (nchars > 39)
    {n2=trim(bfr.substr(39,8));bytes = 12;}
    if (nchars > 49)
    {
      v2=bfr.substr(49,12);
      val2=strtod(v2.c_str(),ptr);
      bytes = 13;
    }
    return bytes;
}
//========================== UPPER ==========================
// This converts a string to upper case. (Josuttis p. 499)
// using an iterator.
int upper(int nchars, string & s)
{
  transform(s.begin(), s.end(), s.begin(), toupper);
  return 0;
}

//========================== TRIM ==============================
string trim(string s)
{
// Boundary cases are empty string, all spaces, no spaces
  string::size_type i;
// Look for empty string
  if(s.length()==0)return s;
// Look for all blanks; if so return empty string
  if((i=s.find_first_not_of(" "))==string::npos)return s.erase();
// Otherwise take substring excluding initial and terminal spaces
  s =  s.substr(i,s.find_last_not_of(" ")-i+1);
  return s;
}

//========================== READLINE ==========================
int readline(FILE *ifile, string &bfr)
{     int bytes;
      char buffer[BUFFSIZE+3];
      if(fgets(buffer, BUFFSIZE+3, ifile)==NULL)
      {
      //If hit EOF return 0; if error return -1
         if(feof(ifile))bytes=0; else bytes=-1;
         return(bytes);
      }
      else bytes=strlen(buffer);
      if(bytes > BUFFSIZE+1)
      {
        printf(" Input line too long:\n"),
        bytes=-bytes;
        return(bytes);
      }
// Casts from character array to string         
      bfr=buffer;
// Get rid of eol if it exists
      string::size_type idx = bfr.rfind('\n');
      if(idx!=string::npos)
      {
        bfr.erase(idx,1);
        bytes--;
      }
// Get rid of terminal blanks
        bfr = bfr.erase(bfr.find_last_not_of(" ") + 1);
        bytes = bfr.size();
      return(bytes);
}

/************************************************************************
* retroLP solves linear programs using the simplex method.             *
* Copyright (C) 2001, 2003, 2005 Gavriel Yarmish & Richard Van Slyke.  *
*                                                                      *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or    *
* (at your option) any later version.                                  *
*                                                                      *
* This program is distributed in the hope that it will be useful,      *
* but WITHOUT ANY WARRANTY; without even the implied warranty of       *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
* GNU General Public License for more details.                         *
*                                                                      *
* You should have received a copy of the GNU General Public License    *  
* along with this program; if not, write to the Free Software          *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,           *
*                                                                      *
************************************************************************/
