/*************************************************************************
** ^FILE: stest.c - test program for parseargs()
**
** ^DESCRIPTION:
**    This file is the test program for the parseargs(3) function libarary.
**    It is used to test parseargs for all command-line styles (which presently
**    includes: UNIX, VMS, AmigaDOS, MS-DOS, and OS/2).
**
** ^HISTORY:
**    --/--/--	Brad Appleton	<brad@ssd.csd.harris.com>	
**    - Added structured block comments
**    - Added an extra test for both old-style and new-style argument arrays
**    - Added a test for triggers (ARGNOVAL arguments)
**    - Added a test for arguments with optional values (using parsecntl())
**    - Added arg-vector arguments
**
**    --/--/--	Peter da Silva	<peter@ferranti.com>	
**
**    --/--/--	Eric P. Allman	<eric@Berkeley.EDU> 	Created
***^^**********************************************************************/

#include <useful.h>
#include <parseargs.h>

#ifdef vms
# include <ssdef.h>
#endif

VERSIONID("$Header: stest.c,v 2.0 89/12/24 00:56:29 eric Exp $");

static char Mode[4] = "OFF";

/***************************************************************************
** ^FUNCTION: argMine - example ARGNOVAL argument translation routine
**
** ^SYNOPSIS:
*/
#ifndef __ANSI_C__
   BOOL argMine( ad, vp, copyf )
/*
** ^PARAMETERS:
*/
   ARGDESC *ad;
/*    -- the argument descriptor for this parameter.
*/
   char *vp;
/*    -- a pointer to the string input value.
*/
   BOOL copyf;
/*    -- if TRUE, the value will be destroyed later, and so should be
**       copied if it will be retained (as for a string).
*/
#endif  /* !__ANSI_C__ */

/* ^DESCRIPTION:
**    This routine is provided as a (very) simple example of how to use
**    the ARGNOVAL flag to set up "trigger" arguments. Depending upon the
**    implementation of the "trigger" function (this routine), the position
**    of the corresponding argument on the command line may (or may not) be
**    important.
**
** ^REQUIREMENTS:
**    ad should have ARGNOVAL set and this function as its ad_type.
**
** ^SIDE-EFFECTS:
**    The static global variable Mode is (re)written.
**
** ^RETURN-VALUE:
**    TRUE.
**
** ^ALGORITHM:
**    Trivial.
***^^**********************************************************************/
/*ARGSUSED*/
#ifdef __ANSI_C__
   BOOL argMine( ARGDESC *ad, char *vp, BOOL copyf )
#endif
{
   strcpy(Mode, "ON");
   return TRUE;
}

/*************************************************************************/
   /* declare variables to hold values from the command-line */
#define DEF_STR "Default String"

typedef ARGVEC_T(char *)  strvec_t;

static int	RepCount;
static char	*Name;
static char	*Str     = DEF_STR;
static char	*DirName = ".";
static BOOL	XRated   = FALSE;
static BOOL	XFlag    = FALSE;
static BOOL	YFlag    = TRUE;
static BOOL	ZFlag    = FALSE;
static char	TabChar  = ':';
static ARGVEC_T(int) Integers = ARGVEC_EMPTY(int);
static strvec_t Groups = ARGVEC_EMPTY(char *);
static ArgList  *Argv  = (ArgList *)NULL;

/*************************************************************************/
   /* declare a new style argument-descriptor array */
static
CMD_OBJECT
   Cmd

CMD_NAME
   "stest -- test program for parseargs"

CMD_DESCRIPTION
   "This program is used to test parseargs for each desired command-line \
style and for both old and new style argument-array declarations.  The actual \
name of the command will be <os>_test.  parseargs will be called twice (with \
the same command-line description) in order to test both the old and the new \
syntax for declaring argument arrays."

CMD_ARGUMENTS
   'n', ARGREQ|ARGPOS, argStr,  __ &Name,  "name (name to look for)",
   's', ARGVALOPT, argStr,  __ &Str,       "STRing (optional string to use)",
   'g', ARGVEC,    argStr,  __ &Groups,    "newsGROUPS (newsgroups to test)",
   'c', ARGOPT,    argInt,  __ &RepCount,  "REP=count (repeat count per group)",
   'd', ARGOPT,    argStr,   __ &DirName,  "DIRname (work directory)",
   'i', ARGVEC,    argInt,   __ &Integers, "INTegerS (vector of numbers)",
   '#', ARGHIDDEN, argBool,  __ &XRated,   "XratedMODE (naughty! naughty!)",

   'x', ARGOPT, argSBool, __ &XFlag, "Xflag (set X flag)",
   'y', ARGOPT, argUBool, __ &YFlag, "Yflag (unset Y flag)",
   'z', ARGOPT, argTBool, __ &ZFlag, "Zflag (toggle Z flag)",

   't', ARGOPT,   argChar, __ &TabChar, "TAB=char (field delimiter)",
   'r', ARGNOVAL, argMine, __ NULL,     "raw (trigger raw-mode \
before processing any more arguments on the command-line)",

   ' ', ARGLIST, listStr, __ &Argv, "file (list of files)",

   END_ARGUMENTS
CMD_END


/*************************************************************************/
   /* declare an old style argument-descriptor array */
static ARGDESC	Args[] =
{
   STARTOFARGS,

   'n', ARGREQ|ARGPOS, argStr,  __ &Name,  "name (name to look for)",
   's', ARGVALOPT, argStr,  __ &Str,       "STRing (optional string to use)",
   'g', ARGVEC,    argStr,  __ &Groups,    "newsGROUPS (newsgroups to test)",
   'c', ARGOPT,    argInt,  __ &RepCount,  "REP=count (repeat count per group)",
   'd', ARGOPT,    argStr,   __ &DirName,  "DIRname (work directory)",
   'i', ARGVEC,    argInt,   __ &Integers, "INTegerS (vector of numbers)",
   '#', ARGHIDDEN, argBool,  __ &XRated,   "XratedMODE (naughty! naughty!)",

   'x', ARGOPT, argSBool, __ &XFlag, "Xflag (set X flag)",
   'y', ARGOPT, argUBool, __ &YFlag, "Yflag (unset Y flag)",
   'z', ARGOPT, argTBool, __ &ZFlag, "Zflag (toggle Z flag)",

   't', ARGOPT,   argChar, __ &TabChar, "TAB=char (field delimiter)",
   'r', ARGNOVAL, argMine, __ NULL,     "raw (trigger raw-mode \
before processing any more arguments on the command-line)",

   ' ', ARGLIST, listStr, __ &Argv, "file (list of files)",

   ENDOFARGS
};


/***************************************************************************
** ^FUNCTION: reset_args - reset argument values for another pass
**
** ^SYNOPSIS:
*/
#ifndef __ANSI_C__
   static VOID reset_args()
#endif
/*  
** ^PARAMETERS:
**    None.
**
** ^DESCRIPTION:
**    Reset_args resets all the argument values to their corresponding
**    default values so that we can (re)test the parseargs library.
**
** ^REQUIREMENTS:
**    None.
**
** ^SIDE-EFFECTS:
**    All the static-global argument variables are rewritten.
**
** ^RETURN-VALUE:
**    None.
**
** ^ALGORITHM:
**    Trivial.
***^^**********************************************************************/
#ifdef __ANSI_C__
   static void reset_args( void )
#endif
{
   RepCount = 0;
   Name     = CHARNULL;
   Str      = DEF_STR;
   DirName  = ".";
   XRated   = FALSE;
   XFlag    = FALSE;
   YFlag    = TRUE;
   ZFlag    = FALSE;
   TabChar  = ':';

   vecFree(Integers, int);
   vecDeepFree(Groups, char *);
   listFree( Argv );
   Argv = ARGLISTNULL;
}


/***************************************************************************
** ^FUNCTION: print_args - print current argument values
**
** ^SYNOPSIS:
*/
#ifndef __ANSI_C__
   static void print_args( argd )
/*
** ^PARAMETERS:
*/
   ARGDESC *argd;
/*    -- the command whose arg-values are to be printed
*/
#endif  /* !__ANSI_C__ */

/* ^DESCRIPTION:
**    Print the current values of all the command-line settings
**
** ^REQUIREMENTS:
**    The command-line should have already been parsed by one of the
**    Xparseargs functions.
**
** ^SIDE-EFFECTS:
**    Prints on stdout.
**
** ^RETURN-VALUE:
**    None.
**
** ^ALGORITHM:
**    Trivial.
***^^**********************************************************************/
#ifdef __ANSI_C__
   static void print_args( const ARGDESC *argd )
#endif
{
   int  i;
   argMask_t flags;
   ArgList *ls;

   printf( "Name = \"%s\", DirName = \"%s\", RepCount = %d,\n",
           Name, DirName, RepCount );

   printf( "XFlag = %d, YFlag = %d, ZFlag = %d, TabChar='%c'(%03o);\n",
           XFlag, YFlag, ZFlag, TabChar, TabChar );

   printf( "XRated=%d, Raw-Mode = \"%s\"\n", XRated, Mode );

      /* to call parsecntl() to see if the optional value was supplied */
   i = parsecntl( (ARGDESC *)argd, pc_ARGFLAGS, pc_READ, "string", &flags);

   if ( BTEST(flags, ARGGIVEN) && !BTEST(flags, ARGVALGIVEN) ) {
      printf("String=!No Value Given on CmdLine!\n" );
   }
   else {
      printf("String=\"%s\"\n", Str);
   }

   if (Groups.count) {
      printf("Newsgroups:");
      for (i = 0 ; i < Groups.count ; i++ ) {
         printf(" %s", Groups.array[i]);
      }
      putchar('\n');
   }

   if (Integers.count) {
      printf("Integers:");
      for (i = 0 ; i < Integers.count ; i++ ) {
         printf(" %d", Integers.array[i]);
      }
      putchar('\n');
   }

   if (Argv)  printf("Remaining args: ");
   for ( ls = Argv ; ls ; L_ADVANCE(ls) ) {
      printf("%s", L_STRING(ls));
      if ( L_NEXT(ls) ) {
         putchar(' ');
      }
      else {
         putchar('\n');
      }
   }/*for*/
}


/*ARGSUSED*/
MAIN(argc, argv)
{
   parseargs(argv, Cmd);   /* parse the command-line */
   print_args(Cmd);        /* print what we found */

   putchar('\n');
   reset_args();           /* reset args for another pass */

   parseargs(argv, Args);  /* parse same command-line using old-style argd */
   print_args(Args);       /* print what we found (should be same as before) */

#ifdef vms
   exit(SS$_NORMAL);
#else
   exit(0);  /* wave bye-bye */
#endif
}
