/* suffx.c
 *
 * For a file name:
 *
 *	-r	return the root = all chars before the last '.'
 *	-s	return the suffix = all chars after the last '.'
 *
 *	-f	replace "last" in the above with "first"
 *
 *	-i	return d for d '.'s in filename
 *	-n m	return mth segment of filename 
 *	-S c	Substitute c for dot as separator.
 * ----------------------------------------------------------------------
 * E.g.:
 *	suffx -r s.sdate.c	->	s.sdate
 *	suffx -s s.sdate.c	->	c
 *
 *	suffx -fr s.sdate.c	->	s
 *	suffx -fs s.sdate.c	->	sdate.c
 *
 *	suffx -i s.sdate.c	->	2
 *	suffx -n 0 s.sdate.c	->	s
 *	suffx -n 1 s.sdate.c	->	sdate
 *	suffx -n 2 s.sdate.c	->	c
 *
 * Option syntax: [[-S <c>][-[rs][f]] | [-i] | -n[0-m]]
 *
 *                where m is the output with -i option.
 */
#define NO_PROTOTYPE

#include <stdio.h>
#include  <stdfun.h> 
#include <string.h>
#include  <ascii.h> 

#define OPTUSAGE  "[[-S <c>][-[rs][f]] | [-i] | -n[0-m]]\n\t\twhere m is the output with -i option."
#define OPTSTRING "frsS:n:i:"

#define DOT '.'

char sepr_char = DOT;

char _sccsid[] = { " suffx.c 1.4 9/22/97 " };

int main( argc, argv )
int argc;
char *argv[];
{

	extern int getopt();
	extern int optind;

	void usage(), gtseg();
	int fnsepr_char();

	extern char *optarg;
	char *pf, f[ LFNMAX + 1 ];
	int c_opt;
	int segm = -1;

	int last = 1;
	int root = 0;
	int suff = 1;

	if( argc == 1 )    {
		usage( argv[ 0 ] );
		exit( 1 );
	}

	while( ( c_opt = getopt( argc, argv, OPTSTRING ) ) != EOF )    {
		switch( c_opt )    {
			case 'i':
				/* -i (optarg is the filename) */
				strcpy( f, optarg );
				printf( "%d", fnsepr_char( f ) );
				exit( 0 );
			case 'n':
				/* -n <d> */
				if( sscanf( optarg, "%d", &segm ) != 1 )    {
					fprintf( stderr, "%s: Missing argument to -%c\n", argv[ 0 ], c_opt );
					usage( argv[ 0 ] );
					exit( 1 );
				}
				suff = 0;
				root = 0;
				break;
			case 'S':
				/* -S <c> */
				if( sscanf( optarg, "%c", &sepr_char ) != 1 )    {
					fprintf( stderr, "%s: Missing argument to -%c\n", argv[ 0 ], c_opt );
					usage( argv[ 0 ] );
					exit( 1 );
				}
				break;
			case 'r':
				/* -r */
				root = 1;
				suff = 0;
				break;
			case 's':
				/* -s */
				/* The default */
				suff = 1;
				root = 0;
				break;
			case 'f':
				/* -f */
				last = 0;
				break;
			default:
				fprintf( stderr, "Bad Option -%c\n", c_opt );
				usage( argv[ 0 ] );
				exit( 1 );
		}
	}

	/* On exiting loop of option parsing optind indexes the next
	 * argv[] argument to the function.
	 */

	strcpy( f, argv[ optind ] );
	if( *(pf = f) == sepr_char )
		++pf;

	/* -------------------- Option syntax checks --------------------- */

	if( root && suff )    {
		fprintf( stderr, "Options -r and -s are mutually exclusive\n" );
		usage( argv[ 0 ] );
		exit( 1 );
	}
	if( last == 0 )    {
		/* -f option has been specified; it is only valid with either
		 * -r | -s
		 */
		if( (root * suff) != 0 )    {
			fprintf( stderr, "Option -f is valid only with either -r | -s.\n" );
			usage( argv[ 0 ] );
			exit( 1 );
		}
	}

	/* ---------------------------------------------------------------- */

	if( segm != -1 )    {
		/* And we are here, -n option has been specified */
		if( root || suff || !last )    {
			fprintf( stderr, "Option -n is valid no other option.\n" );
			usage( argv[ 0 ] );
			exit( 1 );
		}
		if( segm > fnsepr_char( f ) )    {
			fprintf( stderr, "Argument to -n is out of bounds.\n" );
			usage( argv[ 0 ] );
			exit( 1 );
		}
		gtseg( f, segm );
		exit( 0 );
	}

	if( last )    {
		pf = strrchr( pf, sepr_char );
	}
	else    {
		pf = strchr( pf, sepr_char );
	}

	if( root )    {
		*pf = '\0';
	}
	else    {
		sprintf( f, "%s", (pf + 1) );
	}

	printf( "%s", f );

	exit( 0 );
	return( 0 );

} /* End main() */

int fnsepr_char( f )
char *f;
{
	char *dptr = f;
	int n = 0;

	while( (dptr = strchr( dptr, sepr_char ) ) != NULL )   {
		++n;
		/* Skip over sepr_char */
		++dptr;
	}

	return( n );
}

/* The segm-th segment of f lies between the segm-th sepr_char
 * and the (segm+1)-th sepr_char.
 */
void gtseg( f, segm )
char *f;
int segm;
{
	int pr = 0;		/* Printing switch */
	int nd = 0;		/* Number of sepr_char found */
	char *dptr = f;

nextsepr_char:
	if( segm == nd )
		/* Turn printing on */
		pr = 1;

	while( *dptr != sepr_char && *dptr != NUL  )    {
		if( pr )
			putchar( *dptr );
		++dptr;
	}
	if( *dptr == NUL )
		return;
	++nd;
	/* Skip over found sepr_char */
	++dptr;
	if( (segm + 1) == nd )    {
		/* Turn printing off by returning */
		return;
	}
	/* Else continue sepr_char search */
	goto nextsepr_char;

}

void usage( prog )
char *prog;
{
fprintf( stderr, "Usage: %s %s <filename>\n\n", prog, OPTUSAGE );
fprintf( stderr, "\t%s -r <filename> return the root = all chars before the last sepr_char\n", prog );
fprintf( stderr, "\t%s -s <filename> return the suffix = all chars after the last sepr_char\n", prog );
fprintf( stderr, "\t%s -f[rs] <filename> replace \"last\" with either of the above two\n\t                    options with \"first\"\n", prog );
fprintf( stderr, "\t%s -f <filename> return the root = all chars before the first sepr_char\n", prog );
fprintf( stderr, "\t%s -i <filename> return number of dots in <filename>.\n", prog );
fprintf( stderr, "\t%s -n <0-d> <filename> return dth segment of <filename>.\n", prog );
}


Return to Home Page
Return to Metayoga Page
Return to C Language Page


The URL for this document is:
http://graham.main.nc.us/~bhammel/graham/CPROGS/suffx.html
Created: 1997
Last Updated: May 28, 2000 Email me, Bill Hammel at
bhammel@graham.main.nc.us
READ WARNING BEFORE SENDING E-MAIL