//-----------------------------------------------------------------------------
// Copyright © 2006 - Philip Howard - All rights reserved
//
// 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//-----------------------------------------------------------------------------
// package	libh/helloworld
// homepage	http://phil.ipal.org/freeware/libh/
//-----------------------------------------------------------------------------
// author	Philip Howard
// email	libh at ipal dot org
// homepage	http://phil.ipal.org/
//-----------------------------------------------------------------------------
// This file is best viewed using a fixed spaced font such as Courier
// and in a display at least 120 columns wide.
//-----------------------------------------------------------------------------

#define _GNU_SOURCE

#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <libh/ftr.h>
#include <libh/io.h>

//-----------------------------------------------------------------------------
// function	ftr_name_dump
//
// purpose	Dump out name field info for the specified FTR object.
//
// arguments	1 (FTR) reference to which file tree recursion.
//		2 (FILE *) which file to output to
//
// returns	(int) 0
//-----------------------------------------------------------------------------
static
int
ftr_name_dump (
    FTR			arg_ftr
    ,
    FILE *		arg_file
    )
{
    char *		ptr	;

    fprintf( arg_file, "ROOT %08lx: \"", (unsigned long) arg_ftr->name_root );
    if ( arg_ftr->name_root ) {
	ptr = arg_ftr->name_root;
	while ( * ptr ) { fput_byte( * ptr, arg_file ); ++ ptr; };
	fputs( "\"\n", arg_file );
    } else {
	fputs( "NULL\n", arg_file );
    }

    fprintf( arg_file, "FULL %08lx: ", (unsigned long) arg_ftr->name_full );
    if ( arg_ftr->name_full ) {
	if ( arg_ftr->name_full < arg_ftr->name_root ||
	     arg_ftr->name_full > arg_ftr->name_end ) {
	    fputs( "\".", arg_file );
	} else {
	    ptr = arg_ftr->name_root;
	    while ( ptr < arg_ftr->name_full ) { fputc( ' ', arg_file ); ++ ptr; };
	    fputc( '"', arg_file );
	    while ( * ptr ) { fput_byte( * ptr, arg_file ); ++ ptr; };
	}
	fprintf( arg_file, "\" [%3d] ( ", arg_ftr->rdir_full );
	fput_dirfd( arg_ftr->rdir_full, arg_file );
	fputs( " )\n", arg_file );
    } else {
	fprintf( arg_file, "NULL (%d)\n", arg_ftr->rdir_full );
    }

    fprintf( arg_file, "PART %08lx: ", (unsigned long) arg_ftr->name_part );
    if ( arg_ftr->name_part ) {
	if ( arg_ftr->name_part < arg_ftr->name_root ||
	     arg_ftr->name_part > arg_ftr->name_end ) {
	    fputs( "\".", arg_file );
	} else {
	    ptr = arg_ftr->name_root;
	    while ( ptr < arg_ftr->name_part ) { fputc( ' ', arg_file ); ++ ptr; };
	    fputc( '"', arg_file );
	    while ( * ptr ) { fput_byte( * ptr, arg_file ); ++ ptr; };
	}
	fprintf( arg_file, "\" [%3d] ( ", arg_ftr->rdir_part );
	fput_dirfd( arg_ftr->rdir_part, arg_file );
	fputs( " )\n", arg_file );
    } else {
	fprintf( arg_file, "NULL (%d)\n", arg_ftr->rdir_part );
    }

    fprintf( arg_file, "LAST %08lx: ", (unsigned long) arg_ftr->name_last );
    if ( arg_ftr->name_last ) {
	if ( arg_ftr->name_last < arg_ftr->name_root ||
	     arg_ftr->name_last > arg_ftr->name_end ) {
	    fputs( "\".", arg_file );
	} else {
	    ptr = arg_ftr->name_root;
	    while ( ptr < arg_ftr->name_last ) { fputc( ' ', arg_file ); ++ ptr; };
	    fputc( '"', arg_file );
	    while ( * ptr ) { fput_byte( * ptr, arg_file ); ++ ptr; };
	}
	fprintf( arg_file, "\" [%3d] ( ", arg_ftr->rdir_last );
	fput_dirfd( arg_ftr->rdir_last, arg_file );
	fputs( " )\n", arg_file );
    } else {
	fprintf( arg_file, "NULL (%d)\n", arg_ftr->rdir_last );
    }

    fprintf( arg_file, "END          : " );
    ptr = arg_ftr->name_root;
    while ( ptr < arg_ftr->name_end ) { fputc( ' ', arg_file ); ++ ptr; };
    fputc( '"', arg_file );
    while ( * ptr ) { fput_byte( * ptr, arg_file ); ++ ptr; };
    fputs( "\"\n", arg_file );

    return 0;
}

//-----------------------------------------------------------------------------
// program	ftr-test
//
// purpose	Demonstrate the ftr_new(), ftr_get(), ftr_end(), and related
//		functions and macros, showing name variations available.
//
// syntax	ftr-test  [ filename ]
//
// returns	(int) >= 0 : success
//		(int) == EOF : error
//-----------------------------------------------------------------------------
int
main (
    int		argc
    ,
    char * *	argv
    ,
    char * *	envp
    )
{
    FTR			this_ftr	;
    char *		argp		;
    int			argi		;
    int			ftype		;


    argp = ( argi = 1 ) < argc ? argv[ argi ] : NULL;
    fputc( '\n', stdout );
    do {
	if ( argp )	fprintf( stdout, "calling ftr_new( \"%s\" ) in \"", argp );
	else		fprintf( stdout, "calling ftr_new( NULL ) in \"" );
        fput_cwd( stdout );
        fprintf( stdout, "\"\n" );

	this_ftr = ftr_new( argp );
	if ( ! this_ftr ) {
	    if ( argp )	fprintf( stdout, "ftr_new( \"%s\" ) fails: %s\n", argp, strerror( errno ) );
	    else	fprintf( stdout, "ftr_new( NULL ) fails: %s\n", strerror( errno ) );
	}
	else {
	    if ( argp )	fprintf( stdout, "ftr_new( \"%s\" ) returns %8p\n", argp, this_ftr );
	    else	fprintf( stdout, "ftr_new( NULL ) returns %8p\n", this_ftr );

#if 0
	    // see what we have open here:
	    {
		char cmd[4096];
		snprintf( cmd, sizeof cmd, "lsof -p %d", (int) getpid() );
		fflush( stdout );
		system( cmd );
		fflush( stdout );
	    }
#endif

	    ftr_name_dump( this_ftr, stdout );
	    fputc( '\n', stdout );
	    fflush( stdout );

	    for (;;) {
		ftype = ftr_get( this_ftr );
		if ( ftype < 33 || ftype > 126 ) break;
		fprintf( stdout, "ftr_get() returns '%c' (%d) - depth is %d\n",
			 ftype, ftype, ftr_depth_curr( this_ftr ) );

#if 0
		// see what we have open here:
		{
		    char cmd[4096];
		    snprintf( cmd, sizeof cmd, "lsof -p %d", (int) getpid() );
		    fflush( stdout );
		    system( cmd );
		    fflush( stdout );
		}
#endif

		ftr_name_dump( this_ftr, stdout );
		fputc( '\n', stdout );
		fflush( stdout );
		if ( ferror( stdout ) || ferror( stderr ) ) break;
	    }

	    fprintf( stdout, "ftr_get() returns %d\n", ftype );
	    fflush( stdout );
	    ftr_end( this_ftr );
	    if ( ferror( stdout ) || ferror( stderr ) ) break;
	}

	fputc( '\n', stdout );
	fflush( stdout );

    } while ( ++ argi < argc && ( argp = argv[ argi ] ) );

#if 0
    // see what did not get closed
    {
	char cmd[4096];
	snprintf( cmd, sizeof cmd, "lsof -p %d", (int) getpid() );
	fflush( stdout );
	system( cmd );
	fflush( stdout );
    }
#endif

    return 0;
}

