Ejemplo n.º 1
0
bool checkArrays(af_backend activeBackend, T a, Args... arg)
{
    return checkArray(activeBackend, a) && checkArrays(activeBackend, arg...);
}
Ejemplo n.º 2
0
int 
plotCellWave(int argc, char *argv[])
{
  Overture::start(argc,argv);  // initialize Overture

  cout << "Type: `plotCellWave fileName [file.cmd]' to read the show file called fileName \n";
  cout << "       and optionally start reading a command file \n";

  aString nameOfShowFile, commandFileName;
  nameOfShowFile="";
  if( argc > 1 )
  {
    nameOfShowFile=argv[1];
    int l=nameOfShowFile.length()-1;
    if( l>2 && nameOfShowFile(l-3,l)==".cmd" )
    {
      commandFileName=nameOfShowFile;
      nameOfShowFile="";
    }
    else if( argc>2 )
      commandFileName=argv[2];
  }
  
  bool done=FALSE;
    
// create a Graphics Interface
  GenericGraphicsInterface & ps 
    = *Overture::getGraphicsInterface("CellWave visualization",TRUE); 
  GraphicsParameters psp;       // create an object that is used to pass parameters
  aString movieFileName;
    
  // By default start saving the command file called "plotStuff.cmd"
  aString logFile="out_plotCellWave.cmd";
  ps.saveCommandFile(logFile);
  cout << "User commands are being saved in the file `" << (const char *)logFile << "'\n";

  // read from a command file if given
  if( commandFileName!="" )
    ps.readCommandFile(commandFileName);

  checkArrays("plotStuff: before loop");
  aString *sequenceName = NULL;

  // this loop is used to look at more than one file
  while( !done )
  {
    // cout << ">> Enter the name of the show file:" << endl;
    // cin >> nameOfShowFile;
    if( nameOfShowFile=="" )
      ps.inputString(nameOfShowFile,">> Enter the name of the show file:");

    ShowFileReader showFileReader(nameOfShowFile);

    int numberOfFrames=showFileReader.getNumberOfFrames();
    int numberOfSolutions = max(1,numberOfFrames);
    int numberOfComponents;
    int numberOfSequences=showFileReader.getNumberOfSequences();
    if( numberOfSequences>0 )
    {
      delete [] sequenceName;
      sequenceName = new aString[numberOfSequences];
      showFileReader.getSequenceNames(sequenceName,numberOfSequences);
    }
    

    CompositeGrid cg;  

    // set up a function for contour plotting:
    Range all;
    realCompositeGridFunction u;

    char buff[120];
    aString answer,answer2;
    aString menu0[]= { "!plotStuff",
		       "contour",
		       "line plot",
		       "probe plot",
		       "stream lines",
		       "grid",
		       ">sequence",
		       "<next",
		       "previous",
		       ">choose a component", 
		       "<>choose a solution", 
		       "<next component",
		       "previous component", 
		       "derived types",
		       "movie",
		       "movie and save",
		       ">plot bounds",
		       "set plot bounds",
		       "use default plot bounds",
		       "<check mappings with grid",
		       "erase",
		       "redraw",
		       "open a new file",
		       "file output",
		       "help",
		       "exit",
		       "" };
    aString help[]= { 
       "contour                    : plot contours (surfaces)",
       "line plot                  : plot line cut across solution field",
       "probe plot                 : plot timehistory of field at probe locations",
       "stream lines               : draw stream lines",
       "grid                       : plot the grid",
       "sequence                   : plot a sequence that has been saved in the show file",
       "next                       : plot the next solution of all items on the screen",
       "previous                   : plot the previous solution of all items on the screen" ,
       "choose a component         : plot a different component of all items on the screen", 
       "choose a solution          : plot a different solution of all items on the screen", 
       "next component             : plot the next component of all items on the screen",
       "previous component         : plot the previous component of all items on the screen", 
       "derived types              : define new quantities such as vorticity, derivatives etc.",
       "movie                      : plot the next `n' solutions",
       "movie and save             : plot the next `n' solutions and save each as a postscript file",
       "set plot bounds            : specify fixed bounds for plotting. Useful for movies.",
       "use default plot bounds    : let plotStuff determine the plotting bounds",
       "check mappings with grid   : call the checkMapping routine",
       "erase                      : erase everything",
       "redraw                     : force a redraw (useful to call from command files)",
       "open a new file            : open a new show file to read",
       "file output                : output solutions to a file (ascii)",
       "help",
       "exit",
       "" };

    int plotOptions = 0;
    bool plotNewFunction = FALSE;
    bool plotNewComponent= FALSE;
    bool movieMode=FALSE;
    int numberOfMovieFrames=numberOfFrames;
    int solutionNumber=1;
    int component = 0;
    int numberOfHeaderComments;
    
    const aString *headerComment; // This array holds the comments that should go in the plot
    showFileReader.getASolution(solutionNumber,cg,u);
    headerComment=showFileReader.getHeaderComments(numberOfHeaderComments);
    numberOfComponents=u.getComponentDimension(0);
    const int numberOfComponents0=numberOfComponents;
    
    // this next class knows how to form derived quantities such as vorticity, derivatives etc.
    DerivedFunctions derivedFunctions(showFileReader);

    // create the real menu by adding in the component names, these will appear as a 
    // cascaded menu

    int chooseAComponentMenuItem;  // menu[chooseAComponentMenuItem]=">choose a component"
    int chooseASolutionMenuItem;  
    int numberOfSolutionMenuItems=0;
    int chooseASequenceMenuItem;  
    int numberOfSequenceMenuItems=0;
    const int maxMenuSolutions=25;  // cascade solution menu if there are more than this many solutions
    const int maximumNumberOfSolutionsInTheMenu=400;  // stride through the solutions if there are more
                                                      // than this many solutions.
    int solutionIncrement=1;                          // Here is the stride.

    const int maxMenuSequences=25;  // cascade sequence menu if there are more than this many sequences
    const int maximumNumberOfSequencesInTheMenu=400;  // stride through the sequences if there are more
                                                      // than this many sequences.
    int sequenceIncrement=1;                          // Here is the stride.

    aString *menu=NULL;
    buildMainMenu( menu0,
		   menu,
                   u,
                   sequenceName,
                   numberOfSolutions,
                   numberOfComponents,
                   numberOfSequences,
		   chooseAComponentMenuItem,
		   chooseASolutionMenuItem,
		   numberOfSolutionMenuItems,
		   chooseASequenceMenuItem,
		   numberOfSequenceMenuItems,
		   maxMenuSolutions,
		   maximumNumberOfSolutionsInTheMenu,
                   solutionIncrement,
		   maxMenuSequences,
		   maximumNumberOfSequencesInTheMenu,
		   sequenceIncrement );


    psp.set(GI_TOP_LABEL,headerComment[0]);  // set title
    psp.set(GI_TOP_LABEL_SUB_1,headerComment[1]);  
    psp.set(GI_TOP_LABEL_SUB_2,headerComment[2]);  
    if( cg.numberOfDimensions()==1 )
      psp.set(GI_COLOUR_LINE_CONTOURS,TRUE);
    
    // set default prompt
    ps.appendToTheDefaultPrompt("plotCellWave>");

    int menuItem=-1;
    for( int it=0; ; it++)
    {
      checkArrays("plotCellWave: in for(;;)");

      if( it==0 && numberOfFrames<=0 )
        answer="grid";
      else
        menuItem=ps.getMenuItem(menu,answer);
      if( answer=="grid" )
      {
	PlotIt::plot(ps, cg, psp);   // plot the composite grid
	if( psp.getObjectWasPlotted() ) 
	  plotOptions |= 1;

	if( false )
	{
	  for( int grid=0; grid<cg.numberOfComponentGrids(); grid++ )
	    cg[grid].displayComputedGeometry();
	}
      }
      else if( answer=="contour" )
      {
	PlotIt::contour(ps, u, psp);  // contour/surface plots
	if( psp.getObjectWasPlotted() & 1 ) 
	  plotOptions |= 2;
	if( psp.getObjectWasPlotted() & 2 )  // grid was also plotted
	  plotOptions |= 1;
      }
      else if( answer=="line plot" )
      {
	printf(" -- ERROR: line plot not available yet. --\n");

	int oldPBGG = ps.getPlotTheBackgroundGrid();
	int oldKAR  = ps.getKeepAspectRatio();
	const GridCollection & gc = *(u.gridCollection);
	RealArray xBound(2,3);
	PlotIt::getPlotBounds(gc,psp,xBound);
	
	// plot solution on lines that cut the 2D grid
	//contourCuts(gi, uGCF,psp );
	PlotIt::contourCuts(ps, u,  psp );
	
	// Restore plotbackgroundgrid and keepAspectRatio after this call
	ps.setPlotTheBackgroundGrid(oldPBGG);
	
	psp.keepAspectRatio=oldKAR;
	ps.setKeepAspectRatio(psp.keepAspectRatio); 

	// the boundingbox is messed up (set for 1D) after this call
	ps.setGlobalBound(xBound);
	
	// erase the labels and replot them
	ps.eraseLabels(psp);

	// replot the 3D object
	//plotObject = TRUE;
	//plotContours = TRUE;

	//PlotIt::contour(ps, u, psp);  // contour/surface plots
	//if( psp.getObjectWasPlotted() & 1 ) 
	//  plotOptions |= 2;
	//if( psp.getObjectWasPlotted() & 2 )  // grid was also plotted
	//  plotOptions |= 1;
      }
      else if( answer=="probe plot" )
      {
	printf(" -- ERROR: probe plot not available yet. --\n");
	//	PlotIt::contour(ps, u, psp);  // contour/surface plots
	//if( psp.getObjectWasPlotted() & 1 ) 
	//  plotOptions |= 2;
	//if( psp.getObjectWasPlotted() & 2 )  // grid was also plotted
	//  plotOptions |= 1;
      }
      else if( answer=="stream lines" )
      {
	PlotIt::streamLines(ps, u, psp);  // streamlines
	if( psp.getObjectWasPlotted() ) 
	  plotOptions |= 4;
      }
      else if( answer=="derived types" )
      {
        if( numberOfComponents>0 )
	{
	  aString *componentNames = new aString [numberOfComponents];
	  for( int n=0; n<numberOfComponents; n++ )
	    componentNames[n]=u.getName(n);
	  
	  derivedFunctions.update(ps,numberOfComponents,componentNames);
          delete [] componentNames;

          derivedFunctions.getASolution(solutionNumber,cg,u);

          numberOfComponents=numberOfComponents0+derivedFunctions.numberOfDerivedTypes();
	  buildMainMenu( menu0,
			 menu,
			 u,
			 sequenceName,
			 numberOfSolutions,
			 numberOfComponents, 
			 numberOfSequences,
			 chooseAComponentMenuItem,
			 chooseASolutionMenuItem,
			 numberOfSolutionMenuItems,
			 chooseASequenceMenuItem,
			 numberOfSequenceMenuItems,
			 maxMenuSolutions,
			 maximumNumberOfSolutionsInTheMenu,
			 solutionIncrement,
			 maxMenuSequences,
			 maximumNumberOfSequencesInTheMenu,
			 sequenceIncrement );


	}
	else
	{
	  printf("ERROR: no components are available\n");
	}
      }
      else if( menuItem > chooseASequenceMenuItem && menuItem <= chooseASequenceMenuItem+numberOfSequenceMenuItems )
      {
        // plot a sequence
	int sequenceNumber=menuItem-chooseASequenceMenuItem;
        if( numberOfSequences>maxMenuSequences )
	{
          // adjust the sequence number when there are many sequences since we add in extra menu items
          // into the list.
          int extra = 1+ sequenceNumber/maxMenuSequences;  
          extra=1+ (sequenceNumber-extra)/maxMenuSequences;
          sequenceNumber-=extra;
          // printf("menuItem-chooseASequenceMenuItem=%i, extra=%i sequenceNumber=%i\n",
          //     menuItem-chooseASequenceMenuItem,extra,sequenceNumber);
	}
        sequenceNumber=(sequenceNumber-1)*sequenceIncrement;

        assert( sequenceNumber>=0 && sequenceNumber<numberOfSequences );
	aString name;
	realArray time,value;
	const int maxComponentName1=25, maxComponentName2=1;
	aString componentName1[maxComponentName1], componentName2[maxComponentName2];
	  
	showFileReader.getSequence(sequenceNumber,name,time,value,
				   componentName1,maxComponentName1,
				   componentName2,maxComponentName2);
	// printf("sequence %i: name=%s\n",sequenceNumber,(const char*)name);
        // display(value,"value");
	
	  
	ps.erase();
	psp.set(GI_PLOT_THE_OBJECT_AND_EXIT,FALSE);
	psp.set(GI_TOP_LABEL_SUB_1,"");
	psp.set(GI_TOP_LABEL_SUB_2,"");
        Range all;
	PlotIt::plot(ps, time, value(all,all,value.getBase(2)), name, "t", componentName1, psp);
	psp.set(GI_PLOT_THE_OBJECT_AND_EXIT,TRUE);
	ps.erase();

      }
      else if( answer=="next" )
      {
	solutionNumber = (solutionNumber % numberOfSolutions) +1;
	plotNewFunction=TRUE;
      }
      else if( answer=="previous" )
      {
	solutionNumber = ((solutionNumber-2+numberOfSolutions) % numberOfSolutions) +1;
	plotNewFunction=TRUE;
      }
      else if( answer=="next component" )
      {
	component= (component+1) % numberOfComponents;
	plotNewComponent=TRUE;
      }
      else if( answer=="previous component" )
      {
	component= (component-1+numberOfComponents) % numberOfComponents;
	plotNewComponent=TRUE;
      }
      else if( menuItem > chooseAComponentMenuItem && menuItem <= chooseAComponentMenuItem+numberOfComponents )
      {
	component=menuItem-chooseAComponentMenuItem-1 + u.getComponentBase(0);
	plotNewComponent=TRUE;
	// cout << "chose component number=" << component << endl;
      }
      else if( answer=="choose a component" )
      { // *** not used *** Make a menu with the component names. If there are no names then use the component numbers
	aString *menu2 = new aString[numberOfComponents+1];
	for( int i=0; i<numberOfComponents; i++ )
	{
	  menu2[i]=u.getName(u.getComponentBase(0)+i);
	  if( menu2[i] == "" || menu2[i]==" " )
	    menu2[i]=sPrintF(buff,"component%i",u.getComponentBase(0)+i);
	}
	menu2[numberOfComponents]="";   // null string terminates the menu
	component = ps.getMenuItem(menu2,answer2);
	component+=u.getComponentBase(0);
	delete [] menu2;
	plotNewComponent=TRUE;
      }
      else if( menuItem > chooseASolutionMenuItem && menuItem <= chooseASolutionMenuItem+numberOfSolutionMenuItems )
      {
	solutionNumber=menuItem-chooseASolutionMenuItem;
        if( numberOfSolutions>maxMenuSolutions )
	{
          // adjust the solution number when there are many solutions since we add in extra menu items
          // into the list.
          int extra = 1+ solutionNumber/maxMenuSolutions;  
          extra=1+ (solutionNumber-extra)/maxMenuSolutions;
          solutionNumber-=extra;
          // printf("menuItem-chooseASolutionMenuItem=%i, extra=%i solutionNumber=%i\n",
          //     menuItem-chooseASolutionMenuItem,extra,solutionNumber);
	}
        solutionNumber=(solutionNumber-1)*solutionIncrement+1;
	
	plotNewFunction=TRUE;
      }
      else if( answer=="choose a solution" )
      { // ***** not used ****  Make a menu with the solution Names
	aString *menu2 = new aString[numberOfFrames+1];
	for( int i=0; i<numberOfFrames; i++ )
	  menu2[i]=sPrintF(buff,"solution%i",i);
	menu2[numberOfFrames]="";   // null string terminates the menu
	solutionNumber = ps.getMenuItem(menu2,answer2)+1;
	delete [] menu2;
	plotNewFunction=TRUE;
      }
      else if( answer=="movie" || answer=="movie and save" )
      {
	movieMode=TRUE;
	numberOfMovieFrames=numberOfFrames;
	ps.inputString(answer2,sPrintF(buff,"Enter the number of frames (total=%i)",numberOfFrames));
	if( answer2 !="" && answer2!=" ")
	{
	  sScanF(answer2,"%i",&numberOfMovieFrames);
	  printf("number of frames = %i \n",numberOfMovieFrames);
	}
        if( answer=="movie and save" )
	{
	  ps.inputString(answer2,"Enter basic name for the ppm files (default=plot)");
	  if( answer2 !="" && answer2!=" ")
	    movieFileName=answer2;
          else
	    movieFileName="plot";
          ps.outputString(sPrintF(buff,"pictures will be named %s0.ppm, %s1.ppm, ...",
            (const char*)movieFileName,(const char*)movieFileName));
	}
	
      }
      else if( answer=="set plot bounds" )
      {
        RealArray xBound(2,3);
	xBound=0.;
        xBound(1,Range(0,2))=1.;
        if( cg.numberOfDimensions()==2 )
  	  ps.inputString(answer2,sPrintF(buff,"Enter bounds xa,xb, ya,yb "));
        else
  	  ps.inputString(answer2,sPrintF(buff,"Enter bounds xa,xb, ya,yb, za,zb "));
        if( answer2!="" )
 	  sScanF(answer2,"%e %e %e %e %e %e",&xBound(0,0),&xBound(1,0),&xBound(0,1),&xBound(1,1),
              &xBound(0,2),&xBound(1,2));
	
        ps.resetGlobalBound(ps.getCurrentWindow());
	ps.setGlobalBound(xBound);
	
	psp.set(GI_PLOT_BOUNDS,xBound); // set plot bounds
	psp.set(GI_USE_PLOT_BOUNDS,TRUE);  // use the region defined by the plot bounds
      }
      else if( answer=="use default plot bounds" )
      {
        psp.set(GI_USE_PLOT_BOUNDS,FALSE);  // use the region defined by the plot bounds
      }
      else if( answer=="check mappings with grid" )
      {
	for( int grid=0; grid<cg.numberOfComponentGrids(); grid++ )
	{
	  if( cg[grid].mapping().mapPointer==NULL )
	  {
	    cout << "ERROR: This grid has no mappings! \n";
	    break;
	  }
	  cg[grid].mapping().checkMapping();
	}
      }
      else if( answer=="erase" )
      {
	ps.erase();
	plotOptions=0;
      }
      else if( answer=="redraw" )
      { // force a redraw -- add to command files to force the drawing of the screen
	ps.redraw(TRUE);
      }
      else if( answer=="open a new file" )
      {
        nameOfShowFile=""; // do this so we prompt for a new name
	break;
      }
      else if( answer=="file output" )
      {
        fileOutput(ps, u);
      }
      else if( answer=="exit" )
      {
        done=TRUE;
	break;
      }
      else if( answer=="help" )
      {
	for( int i=0; help[i]!=""; i++ )
	   ps.outputString(help[i]);
      }
      else
      {
        cout << "unknown response, answer=[" << answer << "]\n";
	ps.stopReadingCommandFile();
      }
      if( movieMode )
      { // ************** Movie Mode *******************
	psp.set(GI_PLOT_THE_OBJECT_AND_EXIT,TRUE);
	for( int frame=1; frame<=numberOfMovieFrames; frame++ )
	{
          if( answer=="movie and save" )
	  { // save a ppm file
            psp.set(GI_HARD_COPY_TYPE,GraphicsParameters::ppm);
            ps.outputString(sPrintF(buff,"Saving file %s%i.ppm",(const char*)movieFileName,frame-1));
	    ps.hardCopy(    sPrintF(buff,            "%s%i.ppm",(const char*)movieFileName,frame-1),psp);
            psp.set(GI_HARD_COPY_TYPE,GraphicsParameters::postScript);
	  }

	  solutionNumber = (solutionNumber+numberOfSolutions) % numberOfSolutions +1;

          // showFileReader.getASolution(solutionNumber,cg,u);
          derivedFunctions.getASolution(solutionNumber,cg,u);

          headerComment=showFileReader.getHeaderComments(numberOfHeaderComments);
          numberOfComponents=u.getComponentDimension(0);

	  psp.set(GI_TOP_LABEL,headerComment[0]);  // set title
	  psp.set(GI_TOP_LABEL_SUB_1,headerComment[1]);  
	  psp.set(GI_TOP_LABEL_SUB_2,headerComment[2]);  
	  ps.erase();
	  if( plotOptions & 1 )
	    PlotIt::plot(ps, cg, psp );
	  if( plotOptions & 2 )
	    PlotIt::contour(ps, u, psp );
	  if( plotOptions & 4 )
	    PlotIt::streamLines(ps, u, psp ); 

	  ps.redraw(TRUE);   // *****
	}
	if( answer=="movie and save" )
	{ // save a ppm file
          psp.set(GI_HARD_COPY_TYPE,GraphicsParameters::ppm);
	  ps.outputString(sPrintF(buff,"Saving file %s%i.ppm",(const char*)movieFileName,numberOfMovieFrames));
	  ps.hardCopy(    sPrintF(buff,            "%s%i.ppm",(const char*)movieFileName,numberOfMovieFrames),psp);
	  psp.set(GI_HARD_COPY_TYPE,GraphicsParameters::postScript);
	}

	psp.set(GI_PLOT_THE_OBJECT_AND_EXIT,FALSE);
	movieMode=FALSE;
      }      
      else if( plotNewFunction || plotNewComponent )
      {
	if( plotNewFunction )
	{
          // showFileReader.getASolution(solutionNumber,cg,u);
          derivedFunctions.getASolution(solutionNumber,cg,u);

          headerComment=showFileReader.getHeaderComments(numberOfHeaderComments);
          numberOfComponents=u.getComponentDimension(0);

	  psp.set(GI_TOP_LABEL,headerComment[0]);  // set title
	  psp.set(GI_TOP_LABEL_SUB_1,headerComment[1]);  
	  psp.set(GI_TOP_LABEL_SUB_2,headerComment[2]);  
	  plotNewFunction=FALSE;
	}
	if( plotNewComponent )
	{
	  psp.set(GI_COMPONENT_FOR_CONTOURS,component);
	  plotNewComponent=FALSE;
	}
	psp.set(GI_PLOT_THE_OBJECT_AND_EXIT,TRUE);
	ps.erase();
	if( plotOptions & 1 )
	  PlotIt::plot(ps, cg, psp );
	if( plotOptions & 2 )
	  PlotIt::contour(ps, u, psp );
	if( plotOptions & 4 )
	  PlotIt::streamLines(ps, u, psp );

	psp.set(GI_PLOT_THE_OBJECT_AND_EXIT,FALSE);
      }
    } // end for(;;)

    delete [] menu;
    ps.unAppendTheDefaultPrompt(); // reset defaultPrompt

    if( true )
    {
      for( int grid=0; grid<cg.numberOfComponentGrids(); grid++ )
	cg[grid].displayComputedGeometry();
    }
  } // end while not done
  
  
  delete [] sequenceName;


  Overture::finish();          
  return 0;
}
Ejemplo n.º 3
0
int main(int argc, const char** argv)
{
	ArgParse::apflag showhelp = false;
	ArgParse::apint myint = 0;

	ArgParse ap;
	ap.allowOneCharOptionsToBeCombined();
	ap.usageHeader(ArgParse::apstring("Usage: ") + argv[0] + " [options]");
	ap.argFlag("help", "\aprint this help, then exit", &showhelp);
	ap.argInt("integer", "=value\aa random integer you can give for no reason",
	          &myint);
	ap.alias("help", "h");
	ap.alias("integer", "i");
	if (!ap.parse(argc-1, argv+1))
	{
		Aqsis::log() << ap.errmsg() << std::endl << ap.usagemsg();
		return 1;
	}

	if (ap.leftovers().size() > 0)
	{
		Aqsis::log() << "Extra crud \"" << ap.leftovers()[0] << "\" on command line";
		Aqsis::log() << std::endl << ap.usagemsg();
		return 1;
	}

	if (myint != 0)
	{
		cout << "Your favorite integer is " << myint << endl;
	}

	if (showhelp)
	{
		cout << ap.usagemsg();
		return 0;
	}

	int bad = 0;

	cout << "Testing flags and integers... ";
	myint = 3;
	showhelp = false;
	int ok = 0;
	const char* av[100];

	if (ap.parse(0, av) && !showhelp && myint == 3 && ap.leftovers().size() == 0)
		ok++;

	av[0] = "-h";
	if (ap.parse(1, av) && showhelp && myint == 3 && ap.leftovers().size() == 0)
		ok++;

	showhelp = false;
	av[0] = "--help";
	if (ap.parse(1, av) && showhelp && myint == 3 && ap.leftovers().size() == 0)
		ok++;

	showhelp = false;
	av[0] = "--integer";
	av[1] = "5";
	if (ap.parse(2, av) && !showhelp && myint == 5 && ap.leftovers().size() == 0)
		ok++;

	myint = 3;
	av[0] = "-i";
	if (ap.parse(2, av) && !showhelp && myint == 5 && ap.leftovers().size() == 0)
		ok++;

	myint = 3;
	av[2] = "--help";
	if (ap.parse(3, av) && showhelp && myint == 5 && ap.leftovers().size() == 0)
		ok++;

	av[0] = "-h";
	av[1] = "-i";
	av[2] = "5";
	myint = 3;
	showhelp = false;
	if (ap.parse(3, av) && showhelp && myint == 5 && ap.leftovers().size() == 0)
		ok++;

	av[0] = "-hi";
	av[1] = "5";
	myint = 3;
	showhelp = false;
	if (ap.parse(2, av) && showhelp && myint == 5 && ap.leftovers().size() == 0)
		ok++;

	av[0] = "-hi=5";
	myint = 3;
	showhelp = false;
	if (ap.parse(1, av) && showhelp && myint == 5 && ap.leftovers().size() == 0)
		ok++;

	av[0] = "-help";
	if (!ap.parse(1, av) &&
	        ap.errmsg() == "-help: 'e' is an unrecognized option")
		ok++;

	av[0] = "--integer=5";
	myint = 3;
	showhelp = false;
	if (ap.parse(1, av) && !showhelp && myint == 5 && ap.leftovers().size() == 0)
		ok++;

	av[0] = "--integer:5";
	myint = 3;
	if (ap.parse(1, av) && !showhelp && myint == 5 && ap.leftovers().size() == 0)
		ok++;

	av[0] = "-ih";
	av[1] = "5";
	if (!ap.parse(2, av) &&
	        ap.errmsg() == "-ih: 'i' requires an argument")
		ok++;

	av[0] = "--help=5";
	if (!ap.parse(1, av) &&
	        ap.errmsg() == "--help=5: doesn't take an argument")
		ok++;

	av[0] = "--nohelp";
	showhelp = true;
	myint = 3;
	if (ap.parse(1, av) && !showhelp && myint == 3 && ap.leftovers().size() == 0)
		ok++;

	av[1] = "--help";
	if (!ap.parse(2, av) &&
	        ap.errmsg() == "--help: negated flag used with non-negated flag")
		ok++;

	if (ok == 16)
	{
		cout << "PASS" << endl;
	}
	else
	{
		cout << "FAIL" << endl;
		bad++;
	}

	ok = 0;
	cout << "Testing strings and floats... ";

	ArgParse::apfloat tex;
	ArgParse::apfloat metafont;
	ArgParse::apstring kpathsea;
	ArgParse t1;
	t1.argFloat("tex", "\aversion of TeX", &tex);
	t1.argFloat("metafont", "\aversion of Metafont", &metafont);
	t1.argString("kpathsea", "\aversion of Kpathsea", &kpathsea);

	av[0] = "-tex";
	av[1] = "3.14159";
	av[2] = "--metafont=2.7182";
	av[3] = "--kpathsea";
	av[4] = "3.3.1";
	if (t1.parse(5, av) && t1.leftovers().size() == 0 &&
	        tex == 3.14159 && metafont == 2.7182 && kpathsea == "3.3.1")
		ok++;

	av[1] = "blech";
	if (!t1.parse(5, av) &&
	        t1.errmsg() ==  "-tex: \"blech\" is not a valid floating-point number")
		ok++;

	if (ok == 2)
	{
		cout << "PASS" << endl;
	}
	else
	{
		cout << "FAIL" << endl;
		bad++;
	}

	ok = 0;
	cout << "Testing usage message... ";

	ArgParse::apflag junkf;
	ArgParse t2;
	t2.usageHeader("GNU `tar' saves blah, blah, blah\n\n"
	               "Main operation mode:", 26);
	t2.argFlag("t", "\alist the contents of an archive", &junkf);
	t2.argFlag("x", "\aextract files from an archive", &junkf);
	t2.argFlag("delete",
	           "\adelete from the archive (not on mag tapes!)", &junkf);
	t2.alias("t", "list");
	t2.alias("x", "extract");
	t2.alias("x", "get");
	t2.usageHeader("\nOperation modifiers:", 29);
	t2.argFlag("G", "\ahandle old GNU-format incremental backup", &junkf);
	t2.argFlag("g", "=FILE\ahandle new GNU-format incremental backup", &junkf);
	t2.alias("G", "incremental");
	t2.alias("g", "listed-incremental");
	t2.usageHeader("\nArchive format selection:", 37);
	t2.argFlag("V", "=NAME\acreate archive with volume name NAME\n      "
	           "        PATTERN\aat list/extract time, a globbing PATTERN",
	           &junkf);
	t2.alias("V", "label");
	t2.allowOneCharOptionsToBeCombined();
	if (t2.usagemsg() ==
	        "GNU `tar' saves blah, blah, blah\n"
	        "\n"
	        "Main operation mode:\n"
	        "  -t, --list              list the contents of an archive\n"
	        "  -x, --get, --extract    extract files from an archive\n"
	        "      --delete            delete from the archive (not on mag tapes!)\n"
	        "\n"
	        "Operation modifiers:\n"
	        "  -G, --incremental          handle old GNU-format incremental backup\n"
	        "  -g, --listed-incremental=FILE\n"
	        "                             handle new GNU-format incremental backup\n"
	        "\n"
	        "Archive format selection:\n"
	        "  -V, --label=NAME                   create archive with volume name NAME\n"
	        "              PATTERN                at list/extract time, a globbing PATTERN\n")
		ok++;

	if (ok == 1)
	{
		cout << "PASS" << endl;
	}
	else
	{
		cout << "FAIL" << endl;
		bad++;
	}

	ok = 0;
	cout << "Testing arrays... ";
	ArgParse::apintvec foo;
	ArgParse::apfloatvec bar;
	ArgParse::apstringvec baz;
	ArgParse t3;
	t3.argInts("foo", "", &foo);
	t3.argFloats("bar", "", &bar);
	t3.argStrings("baz", "", &baz);

	av[0] = "eins";
	av[1] = "-baz=one";
	av[2] = "-foo=1";
	av[3] = "zwei";
	av[4] = "drei";
	av[5] = "-baz";
	av[6] = "two";
	av[7] = "vier";
	av[8] = "-foo=2";
	av[9] = "-bar=1";
	av[10] = "-bar=2";
	av[11] = "-bar";
	av[12] = "3";
	av[13] = "-bar:4";
	av[14] = "-foo=3";
	av[15] = "--baz=three";
	av[16] = "-baz:four";
	av[17] = "-foo=4";
	if (t3.parse(18, av) && checkArrays(foo, bar, baz, t3.leftovers()))
		ok++;

	foo.clear();
	bar.clear();
	baz.clear();
	ArgParse t4;
	t4.argInts("foo", "", &foo, ArgParse::SEP_ARGV);
	t4.argFloats("bar", "", &bar, ArgParse::SEP_ARGV);
	t4.argStrings("baz", "", &baz, ArgParse::SEP_ARGV);
	av[0] = "eins";
	av[1] = "zwei";
	av[2] = "-baz=one";
	av[3] = "two";
	av[4] = "-foo";
	av[5] = "1";
	av[6] = "2";
	av[7] = "3";
	av[8] = "-baz=three";
	av[9] = "-bar=1";
	av[10] = "-bar=2";
	av[11] = "-bar";
	av[12] = "3";
	av[13] = "4";
	av[14] = "-foo=4";
	av[15] = "--baz";
	av[16] = "four";
	av[17] = "--";
	av[18] = "drei";
	av[19] = "vier";
	if (t4.parse(20, av) && checkArrays(foo, bar, baz, t4.leftovers()))
		ok++;

	foo.clear();
	bar.clear();
	baz.clear();
	ArgParse t5;
	t5.argInts("foo", "", &foo, ',');
	t5.argFloats("bar", "", &bar, ',');
	t5.argStrings("baz", "", &baz, ',');
	av[0] = "-foo";
	av[1] = "1,2";
	av[2] = "eins";
	av[3] = "-baz=one,two,three";
	av[4] = "zwei";
	av[5] = "-bar:1,2,3,4";
	av[6] = "--baz=four";
	av[7] = "drei";
	av[8] = "-foo";
	av[9] = "3,4";
	av[10] = "vier";
	if (t5.parse(11, av) && checkArrays(foo, bar, baz, t5.leftovers()))
		ok++;

	if (ok == 3)
	{
		cout << "PASS" << endl;
	}
	else
	{
		cout << "FAIL" << endl;
		bad++;
	}

	return bad;
}