/*
	PsychError.h		

	AUTHORS:

		Allen.Ingling@nyu.edu		awi 

	HISTORY:
	
		08/18/02  awi	Wrote it.
		11/16/04  awi	Added PsychErorr_argumentValueOutOfRange

	DESCRIPTION:
	

	TO DO: 
  
		ĄThe present system for reporting errors works pretty well, here was an early ambitious scheme to improve it:
  
			Errors should be pointers to structures which hold information about 
			the error. Errors of each type should be generated by error-generator
			functions which dynamically allocate a variant structure for storing 
			error-specific information.  For example:

			theError = GenError_invalidArg();   //
			theError = GenError_none();         //returns null

			or perhaps the constructors could accept more info:

			theError = GenError_missingArg(Input, 1);
			theError = GetError_none(); 

			An acceptable alternative would be to have one generator function and
			pass it an enumerated type identifying the error class, for example:

			theError = GenError(PsychError_missingArg, Input, 1);
			theError = Generror(PsychError_none);


			Currrently, errors are variables which hold an enumerated
			type classifying the error.  Additional information about the error
			is stashed in static variables within Psychtoolbox library files but 
			1) It is not attached to the error and there is no organizing 
			principle to suggest where it might be found. 2) It has no state,
			so subsequent errors will overwrite or invalidate the information 
			held within the static state variables.  This is particularly a 
			problem with PsychErrorExitMsg(), which must now be called immediatlty
			after the error or else the error information is lost.    

			If error are pointers to structures then this adds two complications:
			1- We need to dynamically allocate memory to hold the error structure
			and clean it up on exit.  For prototyping purposes, we could 
			statically allocate an array of variant structures and limit the 
			maximum number of concurrent errors to the length of the array.   2-
			Testing for the error type can no longer be done directly with the 
			equals operator unless it were  overloaded.  A comparison function
			which dereferenced the error and examined the type would have to be
			supplied. Something like:

			if(ErrorEqual(error1, error2)) ....  

			or

			if(GetErrorType(error1) == GetErrorType(error2))....
	  

*/


//begin include once 
#ifndef PSYCH_IS_INCLUDED_PsychError
#define PSYCH_IS_INCLUDED_PsychError

//define the PsychErrorExitMsg Macro
#define PsychErrorExitMsg(pse1, pse2)	PsychErrorExitC(pse1, pse2, __LINE__, __func__, __FILE__) 
#define PsychErrorExit(pse1)		PsychErrorExitC(pse1, NULL, __LINE__, __func__, __FILE__) 

#include "Psych.h"

//types of error.
typedef enum  
{
	PsychError_none = 0,
	
	//these four constants describe different ways the user can give an invalid argument.  They are treated specially by PsychErrorExitC
	// (called by macros PsychErrorExit and PsychErrorExitMsg) which gives an extra verbose report for these errors,  relying on 
	// cached argument descriptors to make its report.
	PsychError_invalidArg_absent,
	PsychError_invalidArg_extra,
	PsychError_invalidArg_type,
	PsychError_invalidArg_size,
	
	//these three four contants are used for the cap an limit calls at the head of module sufunctions.  They don't cause the special behavior in 
	//PsychErrorExit.  
	PsychError_extraInputArg,
	PsychError_missingInputArg,
	PsychError_extraOutputArg,
	PsychError_missingOutputArg,
	
	PsychError_toomanyWin,
	PsychError_outofMemory,
	PsychError_scumberNotWindex,
	PsychError_windexNotScumber,
	PsychError_invalidIntegerArg, 
	PsychError_invalidWindex,
	PsychError_invalidScumber,
	PsychError_invalidNumdex,
	PsychError_invalidColorArg,
	PsychError_invalidDepthArg,
	PsychError_invalidRectArg,
	PsychError_invalidNumberBuffersArg,		//invalid number of video buffers specified to SCREEN OpenWindow
	PsychError_nullWinRecPntr,
	PsychError_registerLimit,
	PsychError_registered,
	PsychError_longString,
	PsychError_longStringPassed,
	PsychError_unimplemented,				//unimplemented feature	
	PsychError_internal,					//catch-all category for INTERNAL PSYCHTOOLBOX ERRORS.
	PsychError_system,						//errors reported by system calls
	PsychError_invalidArgRef,
	PsychError_OpenGL,
	PsychError_SDL,
	PsychError_SurfaceLockFailed,
	PsychError_SurfaceAlreadyLocked,
	PsychError_InvalidWindowRecord,
	PsychError_unsupportedVideoMode, 
	PsychError_user,							//catch-all category for USER ERRORS.
	PsychError_unrecognizedPreferenceName,
	PsychError_unsupportedOS9Preference,
	PsychError_inputMatrixIllegalDimensionSize,
	PsychError_stringOverrun,
	PsychErorr_argumentValueOutOfRange
} PsychError;
//This should be "PsychErrorType", not "PsychError"



/*
Enumerated types and structures used to describe arguments passed from the scripting environment.  The ScriptingGlue functions which 
retrieve arguments can push a description of the desired arguments and push a description of the found
arguments and then return an error if there is a discrepancy.  PsychErrorExitMsg can then pop the descriptions
if the error type is PsychError_invalidInArgType or PsychError_invalidArgs to generate an error message 
telling the user why the argument passed was bogus.
*/
  
  
typedef enum
{	
	#define PsychArgType_MIN		PsychArgType_unspecified
	PsychArgType_none				= 0,
	PsychArgType_unspecified		= 1,
	PsychArgType_unclassified		= 2, 
	PsychArgType_char				= 4,  	   
	PsychArgType_uint8				= 8,
	PsychArgType_uint16				= 16,
	PsychArgType_uint32				= 32,
	PsychArgType_int8				= 64,
	PsychArgType_int16				= 128,
	PsychArgType_int32				= 256,        
	PsychArgType_double 			= 512,
	PsychArgType_boolean			= 1024,
	PsychArgType_structArray		= 2048,
	PsychArgType_cellArray			= 4096,
	PsychArgType_single				= 8192,
	PsychArgType_uint64				= 2^14,
	PsychArgType_default			= 2^15, 
	#define PsychArgType_MAX		PsychArgType_default
	#define PsychArgType_NUMTYPES	16	//this does not include the PsychArgType_none		
} PsychArgFormatType;  //change this to PsychArgType for brevity


typedef enum
{
	PsychArgIn,  //change to PsychArg_in for consistant style
	PsychArgOut
} PsychArgDirectionType;


typedef enum
{
	kPsychArgAbsent = 0,		
	kPsychArgPresent = 1,
	kPsychArgFixed =2			//Arguments which are always present, the first return argument in MATLAB. 
} PsychArgPresenceType;


typedef enum
{
	kPsychArgOptional = 0,			//Argument may be either absent or present and of the specified type
	kPsychArgRequired = 1,			//Argument must be present and of the specified type
	kPsychArgAnything = 2			//Argument may be present with specified type, absent, or of a different type.  
} PsychArgRequirementType;


typedef struct
{
	int							position;
	PsychArgDirectionType		direction;
	PsychArgPresenceType		isThere;
	PsychArgRequirementType		isRequired;
	PsychArgFormatType			type;
	int							numDims;		// used only to set the received descriptor, to catch > 3 dims.    
	psych_int64					mDimMin;  		// 1 is lowest
	psych_int64					mDimMax; 		// kPsychUnboundedArraySize = -1 is infinity
	psych_int64					nDimMin;		// 1 is lowest
	psych_int64					nDimMax;		// kPsychUnboundedArraySize = -1 is infinity
	psych_int64					pDimMin;		// 0 is lowest.  (this should be changed to make 1 the lowest, so it agrees with n) 
	psych_int64					pDimMax;		// kPsychUnboundedArraySize = -1 is infinity. Set p min and max to zero to forbid 
} PsychArgDescriptorType;

#define 						kPsychUnboundedArraySize	(psych_int64) -1
#define							kPsychUnusedArrayDimension  (psych_int64) -2 


//function prototypes

PsychError InitPsychError(void);
void PsychErrorExitC(	PsychError error, 
						const char *extraErrorString, 
						int	lineNum, 
						const char *funcName, 
						const char *fileName);
						
PsychError PsychStoreArgDescriptor(	PsychArgDescriptorType *specified, 
									PsychArgDescriptorType *provided);

PsychError PsychGetArgDescriptor(	PsychArgDescriptorType **specified, 
									PsychArgDescriptorType **provided);
									
int PsychDecomposeArgFormat(PsychArgFormatType argType,  const char **names);

void PsychDumpArgDescriptors(void);



//This is dumb, but we define the PsychFunctionPtr type inside of PsychError.
typedef PsychError (*PsychFunctionPtr)(void);





//end include once
#endif


	
	
	
		


