/*
   <p>Test harness for the CSV library with standard i/o.</p>

               Written by M.C.Gregorie.

               Version history
               
               1.0   28/12/02   Initial release

   <kbd>
   <b>environ - C programming support functions</b><br>
   Copyright (C) 2005  Martin C Gregorie
   
   This program is free software; you can redistribute it and/or
   modify it under the terms of the Lesser GNU General Public License.
   
   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 Lesser GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   </kbd>
  
   <p>Contact Martin Gregorie at <i>martin@gregorie.org</i></p>
*/

#define VERSION         "1.0"
#define COPYRIGHT       "(c) M.C.Gregorie, 2002"

#ifndef TRUE
#define TRUE       1
#endif

#ifndef FALSE
#define FALSE      0
#endif

#define FLAGCNT    5

#define HELP       0      /* -? help */
#define DEBUG      1      /* -d debug mode */
#define QUOTEMODE  2      /* -m quote mode */
#define INSEP      3      /* -i input separator char */
#define OUTSEP     4      /* -o input separator char */

#define MAYBEMARK  '%'
#define BADMARK    '!'
#define OK         ' '
#define OPTLIST    "?dm:i:o:"

#define MAXCSV     4

#include <environ.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "csv.h"

int readargs(int argc, char *argv[], int flags[]);
void showhelp();

/*
   Function to handle escaped separator characters
*/
char inchar(char *s)
{
   char c;

   if (strcmp(s, "TAB") == 0)
      c = 0x09;
   else
      c = s[0];

   return c;
}

/*
   This function scans the command line for options and does
   all the associated setup.
*/
int readargs(int argc, char *argv[], int flags[])
{
   int i; 
   int opt;

   /* initialise flags */

   for (i=0 ; i<FLAGCNT ; i++) flags[i] = FALSE;
   flags[QUOTEMODE] = NORMAL;
   flags[INSEP]     = ',';
   flags[OUTSEP]    = ',';

   /* set up options from the command line */

   optmaybe = MAYBEMARK;
   optbad = BADMARK;
   optind = 1;
   
   while ((opt=getopt(argc,argv,OPTLIST)) != EOF)   
   {
      switch (opt) {
         case 0:         continue;
         case BADMARK:   return(opt);
         case '?':       flags[HELP] = TRUE;       
                         break;
         case 'd':       flags[DEBUG]++;
                         break;
         case 'm':       if (strcmp("NORMAL", optarg) == 0)
      	                    flags[QUOTEMODE] = NORMAL;
               	         else if (strcmp("ALWAYS", optarg) == 0)
      	                    flags[QUOTEMODE] = ALWAYS;
      	                 else if (strcmp("NEVER", optarg) == 0)
      	                    flags[QUOTEMODE] = NEVER;
      	                 else if (strcmp("MINIMAL", optarg) == 0)
      	                    flags[QUOTEMODE] = MINIMAL;
                         else
                            flags[QUOTEMODE] = -1;
                         break;
         case 'i':       flags[INSEP] = inchar(optarg);
                         break;
         case 'o':       flags[OUTSEP] = inchar(optarg);
                         break;
         default :       error(argv[0],
                               "impossible happened parsing options",
                               "");
      }
   }
   return(OK);
}

/*
   Show the punter what the options are
*/
void showhelp()
{
   printf("\ntestcsv v%s %s\n\n",VERSION,COPYRIGHT);
   printf("Syntax  : testcsv2 [<opts>]\n");
   printf("Function: CSV library test harness runs the csv library\n");
   printf("          to filter standard input to standard output.\n");
   printf("          Use -i=TAB or -o=TAB for tab separated files.\n");
   printf("Options :\n");
   printf("     -d           debug mode\n");
   printf("     -m=mode      quote mode, default is NORMAL\n");
   printf("     -i=c         input separator character. Default is comma\n");
   printf("     -o=c         output separator character. Default is comma\n");
   printf("if given\n");
}

/*
   The main program starts here
   ----------------------------
*/
int main(int argc, char *argv[])
{
   int   flags[FLAGCNT],
         argtype,
         reply;
   CSV    *in = NULL;
   CSV    *out = NULL;
   char   *line;
   char   *fld;
   int    i;
   int    n;

   /*
      Parse and set up command options
   */
   setprog(argv[0]);
   if (readargs(argc,argv,flags) == BADMARK)
   {
      return(1);
   }

   /*
      If help was asked for, give it and quit
   */
   if (flags[HELP]) 
   {
      showhelp();
      return(0);
   }

   csvsetdebug(flags[DEBUG]);
   out = csvopen(NULL, "w");
   if (csvgeterr())
   {
      printf("Opening output returned %d,%s\n", n, csvgeterrtext());
      return(1);
   }

   csvsetquote(out, flags[QUOTEMODE]);
   if (csvgeterr() == 0)
      csvsetsep(out, flags[OUTSEP]);

   if (csvgeterr())
   {
      printf("Output setup returned %d,%s\n", n, csvgeterrtext());
      return(1);
   }
   
   in = csvopen(NULL, "r");
   if (csvgeterr() == 0)
   {
      csvsetsep(in, flags[INSEP]);
   }
   
   if (csvgeterr() == 0)
   {
      while (line = csvgetline(in))
      {
      	 if (flags[DEBUG])
      	    printf("Read [%s]\n", line);
      	    
         n = csvgetn(in);
         if (csvgeterr() == 0)
         {
            for (i = 0; i < n; i++)
            {
               fld = csvgetfield(in, i);
               if (csvgeterr())
                  break;

               csvputstr(out, fld);
               if (csvgeterr())
                  break;
            }

            csvputline(out);
            if (csvgeterr())
               break;
         }
      }
   }   
   if (!csvgeterr())
   {
      csvclose(in);
      csvclose(out);
   }

   n = csvgeterr();
   if (n)
      printf("Run ended with error %d,%s\n", n, csvgeterrtext());
   else
      printf("Run ended at EOF\n");

   return(0);
}

