/* FLDSEL.C - command line utility to select fields from a stream of tabular records.
 * Copyright 1998-2001 Stephen C. Grubb  (www.sgpr.net) .
 * This code is covered under the GNU General Public License (GPL);
 * see the file ./Copyright for details. */

#include "tdhkit.h"
#ifdef SHSQL
#include "shsql.h"
#else
  /* this allows us to work with wide data sets, but field names may be specified by number only */
  #undef MAXITEMS
  #define MAXITEMS 300
#endif

extern int TDH_setfmdelim(), GL_ranger();

int
main( argc, argv )
int argc; 
char **argv;
{
int i, j, col, fld;
char buf[ MAXRECORDLEN ];
char f[ MAXITEMS ][ DATAMAXLEN+1 ];
char tok[ DATAMAXLEN+1 ];
char recordid[80];
char rangespec[DATAMAXLEN+1];
int fieldlist[ MAXITEMS ];
int omitmode, nfl, topt, headermode, prec, headerout, nfields, padopt, len, stat, nrec;
char addfld[DATAMAXLEN];
char addfldname[80];
char delim;

TDH_errprog( "fldsel" );

if( argc < 2 ) {
	err( 2200, "invalid usage", "" );
	fprintf( stderr, "usage: fldsel [-r recid] [-d outdelim] [-s range] [-h -o] f1 .. fn\n" );
	fprintf( stderr, "       where f1 .. fn are either int field #s or field names.\n" );
	exit( 1 );
	}

/* process config file if any.. */
#ifdef SHSQL
  stat = SHSQL_allconfig();
  delim = SHSQL_delim;
#else
  stat = TDH_readconfig( "TDHKIT_CONFIG" );
  delim = ' ';
#endif
/* if( stat != 0 ) exit( 1 ); */ /* scg 8/28/03 */
strcpy( recordid, "" );


/* set some defaults.. */
omitmode = 0;
headermode = 0;
topt = 0;
nfl = 0;
headerout = 0;
padopt = 0;
strcpy( addfld, "" );

/* process command line args.. */
for( i = 1; i < argc; i++ ) {

	/* handle -r option.. */
	if( strcmp( argv[i], "-r" )==0 ) {
		strcpy( recordid, argv[i+1] );
		i ++;
		continue;
		}

	/* handle -d option.. */
	else if( strcmp( argv[i], "-d" )==0 ) {
		if( i < argc-1) {
			strcpy( tok, argv[i+1] );
			if( strcmp( tok, "space" )==0 ) delim = ' ';
			else if( strcmp( tok, "tab" )==0 ) delim = '\t';
			else delim = tok[0];
			i ++;
			}
		continue;
		}

	else if( strcmp( argv[i], "-o" )==0 ) {
		omitmode = 1;
		continue;
		}

	else if( strcmp( argv[i], "-h" )==0 || strcmp( argv[i], "-H" )==0 ) {
		headermode = 1;
		/* get 1st line of input now.. */
		while( fgets( buf, MAXRECORDLEN-1, stdin ) != NULL ) {
			if( sscanf( buf, "%s", tok ) < 1 ) continue; 
			if( strncmp( tok, "//", 2 ) ==0 ) continue;
			break;
			}
#ifdef SHSQL
		TDH_setfmdelim( SHSQL_delim );
		stat = TDH_loadfieldmap( "shsql_header", buf );         /* tagvalue */
		TDH_setfmdelim( BLANK );
		strcpy( recordid, "shsql_header" );
#else
		TDH_loadfieldmap( "header", buf );
		strcpy( recordid, "header" );
#endif
		if( strcmp( argv[i], "-H" )==0 ) headerout = 1;
		continue;
		}

	else if( strcmp( argv[i], "-t" )==0 ) {
		delim = '\t';
		topt = 1;
		continue;
		}

	else if( strcmp( argv[i], "-s" )==0 ) {   /* range notation */
		if( i < argc-1 ) {
			strcpy( rangespec, argv[i+1] ); /* rangespec will be modified.. */
			nfl = MAXITEMS - 5;
			GL_ranger( rangespec, fieldlist, &nfl );
			i++;
			}
		continue;
		}

	else if( strcmp( argv[i], "-p" )==0 ) { 	/* pad  - added 8/8/02 */
		padopt = 1;  
		continue;
		}

	else if( strcmp( argv[i], "-a" )==0 ) {		/* add new field at end of record (used by shsql ALTER) - added 8/8/02 */
				/* usage:   -a newname newcontents */
		omitmode = 1;	/* implies -o, but no fields should be specified on command line */
		if( i < argc-1 ) {
			i++;
			strcpy( addfldname, argv[i] );
			i++;
			strcpy( addfld, argv[i] );
			}
		continue;
		}
		

	/* otherwise, assume we have a field specifier.. add it to fieldlist.. */
	if( argv[i][0] == '@' ) strcpy( tok, &argv[i][1] );
	else strcpy( tok, argv[i] );
	if( GL_goodnum( tok, &prec )) fieldlist[ nfl++ ] = atoi( tok );
	else 	{
		fld = TDH_fieldmap( recordid, tok );
		if( fld < 0 ) fieldlist[ nfl++ ] = -1;
		else fieldlist[ nfl++ ] = fld + 1;
		}
	}

if( nfl < 1 && !omitmode ) {
	err( 2201, "no items specified", "" );
	exit(1);
	}

/* process incoming records.. */
nrec = 0;
while( 1 ) {
	if( headermode ) {
		headermode = 0;
		if( !headerout ) continue;

		/* header fields will be written just like ordinary fields, below */
		}
	else if( fgets( buf, MAXRECORDLEN-1, stdin ) == NULL ) break;

#ifdef SHSQL
	j = 0;
	SHSQL_getfld( tok, buf, &j );
	if( tok[0] == '\0' || strncmp( tok, "//", 2 )==0 ) continue;
#else
	if( sscanf( buf, "%s", tok ) < 1 ) continue; /* blank line */		/* datadelim */
	if( strncmp( tok, "//", 2 )==0 ) continue; /* comment line */
#endif

	/* split up into fields.. */
	i = 0; col = 0;
	while( 1 ) {
#ifdef SHSQL
		SHSQL_getfld( f[i], buf, &col );
#else
		if( topt ) GL_getseg( f[i], buf, &col, "\t\n" );
		else strcpy( f[i], GL_getok( buf, &col ) );
#endif
		if( f[i][0] == '\0' ) break;
		i++;
		}
	nfields = i;

	/* for each field specified on command line.. */
	len = 0;
	if( !omitmode ) {
		for( i = 0; i < nfl; i++ ) {
			if( fieldlist[i] < 0 ) printf( "BAD-FIELD" );			/* datadelim */
			else 	{
				printf( "%s", f[ fieldlist[i] - 1 ] );
				if( padopt ) len += (strlen( f[ fieldlist[i] - 1 ] ) + 1 );
				}
			if( i < (nfl-1) ) printf( "%c", delim );			/* datadelim */
			}
		}
	else	{ /* omitmode */
		for( i = 0; i < nfields; i++ ) {
			for( j = 0; j < nfl; j++ ) if( i == fieldlist[j] - 1 ) goto BOTTOM;
			printf( "%s%c", f[ i ], delim );				/* datadelim */
			if( padopt ) len += (strlen( f[ i ] ) + 1);
			BOTTOM: ;
			}
		}
	if( addfld[0] ) {
		if( headerout && nrec == 0 ) printf( "%s%c", addfldname, delim );
		else printf( "%s%c", addfld, delim );					/* datadelim */
		}
	if( padopt ) {
		len *= 0.2;
		if( len < 12 ) len = 12;
		for( i = 0; i < len; i++ ) printf( "%c", delim );			/* datadelim */
		}
	printf( "\n" );
	nrec++;
	}
exit( 0 );
}
