// utf-8

/*	Copyright  (c)	Günter Woigk   1999-2001
  					mailto:kio@little-bat.de

	This file is free software

 	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.  

 	Permission to use, copy, modify, distribute, and sell this software and
 	its documentation for any purpose is hereby granted without fee, provided
 	that the above copyright notice appear in all copies and that both that
 	copyright notice and this permission notice appear in supporting
 	documentation, and that the name of the copyright holder not be used
 	in advertising or publicity pertaining to distribution of the software
 	without specific, written prior permission. The copyright holder makes no
 	representations about the suitability of this software for any purpose.
 	It is provided "as is" without express or implied warranty.

 	THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 	INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 	EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 	CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 	DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 	TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 	PERFORMANCE OF THIS SOFTWARE.

 
	error handling and logging

	01.jan.1999	kio	first work on this file
	16.sep.1999 kio	added string version
	17.feb.2001 kio	added possibility to #include custom error file
	09.nov.2001	kio	added support for class String, renamed ErrorText() to ErrorStr() / ErrorString()
*/

#define	SAFE	1
#define	LOG		0

#include	"config.h"
#include	<string.h>
#include	<unistd.h>
#include	"errors.h"		// get enumeration
#include	"ustring/sstring.h"


// ==========================================================================
// ============================== error messages ============================
// ==========================================================================

char customError[1024];
cstr ETEXT[] =
#define		EMAC(a,b)	b
#include	"errors.h"		// get the texts




/* ----	conversion table ----------------------------------------------------
		OS errors -> my error numbers		
		see file "MacErrors.h"
*/
#if defined(_MACINTOSH)
	static OSErr etoe[] =
	{
		dupFNErr,		dupfilename,
		fBsyErr,		fileisbusy,
		eofErr,			endoffile,
		fnOpnErr,		filenotopen,
		unitEmptyErr,	ioerror,
		opWrErr,		filewritelocked,		/*file already open with write permission*/
		dskFulErr,		diskfull,
		nsvErr,			volumenotfound,
		fnfErr,			filenotfound,
		wPrErr,			diskwriteprot,			/*disk is write protected.*/
		vLckdErr,		volumewriteprot,		/*volume is locked*/
		wrPermErr,		filewriteprot,			/*write permissions error*/
		dirNFErr,		directorynotfound,
		0,0
	};
#endif


/* ----	convert OS error code to "errors.cp" error code ------------------
*/
#if defined(_MACINTOSH)
	static OSErr ErrorToError ( OSErr err )
	{
		if ( err>=EBAS && err<EBAS+(int)NELEM(ETEXT) ) 
			return err;						// already my error code
	
		for ( OSErr* p=etoe; p<etoe+NELEM(etoe); p+=2 )
		{
			if (p[0]==err) return p[1];		// my error code found -> return it
		}
		return err;							// no own found -> return OS error
	}
#endif


/* ----	get default error text for error ------------------------------------------------
*/
cstr ErrorStr ( OSErr err )
{
	if (err==0)  return "no error";

	if (err==-1) return "unknown error (-1)";

	if (err>=EBAS && err<EBAS+(int)NELEM(ETEXT)) return ETEXT[err-EBAS];
#if defined(_MACINTOSH)
	err = ErrorToError(err);
	if (err>=EBAS && err<EBAS+(int)NELEM(ETEXT)) return ETEXT[err-EBAS];
#endif

	return Using("%s (%i)",strerror(err),(int)err);
}


/* ----	get error text for current error ------------------------------------------------
*/
cstr ErrorStr ( )
{
	XTRAP(NoError()&&customError[0]);		// note: clear error with ClearError() !!!

	if (customError[0]) return DupStr(customError);
	else                return ErrorStr(Error());
}



/* ----	set error code & text ------------------------------------------------
*/
void ForceError ( OSErr err, cstr custom_msg )
{
	ForceError(err);
	ptr z = customError;
	cptr q = custom_msg;
	uint i = 0;
	for ( ; i<NELEM(customError); i++ ) { if ( (z[i] = q[i]) == 0 ) return; }
	customError[NELEM(customError)-1] = 0;
}



static OSErr err[4];
static cstr  msg[4];
static uint  idx;

void PushError ( )
{
	XTRAP(idx==NELEM(err));
	err[idx] = Error();
	msg[idx] = customError ? NewCopy(customError) : NULL;
	idx++;
	ClearError();
}


void PopError ( )
{
	XXTRAP(idx==0);
	idx--;
	if(msg[idx]) { ForceError(err[idx],msg[idx]); delete[] msg[idx]; }
	else if(err[idx]) ForceError(err[idx]); else ClearError();
}


















