#include "std.h"

#ifndef RETAIL
#include <stdarg.h>
#endif

DeclAssertFile;


CODECONST(unsigned char) mpcoltypcb[] =
	{
	0,					/* JET_coltypNil (coltypNil is used for vltUninit parms) */
	sizeof(char),		/* JET_coltypBit */
	sizeof(char),		/* JET_coltypUnsignedByte */
	sizeof(short),		/* JET_coltypShort */
	sizeof(long),		/* JET_coltypLong */
	sizeof(long)*2,		/* JET_coltypCurrency */
	sizeof(float),		/* JET_coltypIEEESingle */
	sizeof(double),		/* JET_coltypIEEEDouble */
	sizeof(double),		/* JET_coltypDateTime */
	0,					/* JET_coltypBinary */
	0,					/* JET_coltypText */
	sizeof(long),		/* JET_coltypLongBinary */
	sizeof(long),		/* JET_coltypLongText */
	0,					/* JET_coltypDatabase */
	sizeof(JET_TABLEID)	/* JET_coltypTableid */
	};


static CODECONST(unsigned char) rgbValidName[16] = {
	0xff,			       /* 00-07 No control characters */
	0xff,			       /* 08-0F No control characters */
	0xff,			       /* 10-17 No control characters */
	0xff,			       /* 18-1F No control characters */
	0x02,			       /* 20-27 No ! */
	0x40,			       /* 28-2F No . */
	0x00,			       /* 30-37 */
	0x00,			       /* 38-3F */
	0x00,			       /* 40-47 */
	0x00,			       /* 48-4F */
	0x00,			       /* 50-57 */
	0x28,			       /* 58-5F No [ or ] */
	0x00,			       /* 60-67 */
	0x00,			       /* 68-6F */
	0x00,			       /* 70-77 */
	0x00,			       /* 78-7F */
	};


unsigned CchUTILIValidateName(char  *pchName, const char  *lpchName, unsigned cchName)
	{
	char			*pch;
	unsigned		cch;
	char			*pchLast;
	unsigned char	ch;

	/* A name may not begin with a space */
	if ( *lpchName == ' ' )
		return(0);
	pch = pchName;
	cch = 0;
	/* To detect zero length names */
	pchLast = pchName;

	while (((ch = (unsigned char) *lpchName++) != '\0') && (cch < cchName))
		{
		/*	The name too long check is inside the loop to prevent
		/*	overflowing the output buffer which is only JET_cbNameMost
		/*	characters long.  This means than insignificant trailing
		/*	spaces will trigger an error.
		/**/
		/* Name too long */
		if ( ++cch > JET_cbNameMost )
			return(0);

		/* Extended characters always valid */
		if (ch < 0x80)
			{
			if ((rgbValidName[ch >> 3] >> (ch & 0x7)) & 1)
				return(0);
			}

		*pch++ = (char) ch;

		/* Last significant character */
		if (ch != ' ')
			pchLast = pch;
		}

	/* Length of significant portion */
	cch = (unsigned)(pchLast - pchName);

	return(cch);
	}


ERR ErrUTILCheckName( char *szNewName, const char *szName, int cchName )
	{
	unsigned int	cch;

	cch = CchUTILIValidateName( szNewName, szName, cchName );

	if ( cch == 0 )
		{
		return ErrERRCheck( JET_errInvalidName );
		}
	else
		{
		szNewName[cch] = '\0';
		}

	return JET_errSuccess;
	}


#ifndef RETAIL

typedef void ( *PFNvprintf)(const char  *, va_list);

struct {
	PFNvprintf pfnvprintf;
	}  pfn = { NULL };


void VARARG DebugPrintf(const char  *szFmt, ...)
	{
	va_list arg_ptr;

	if (pfn.pfnvprintf == NULL)	       /* No op if no callback registered */
		return;

	va_start(arg_ptr, szFmt);
	(*pfn.pfnvprintf)(szFmt, arg_ptr);
	va_end(arg_ptr);
	}


	/*	The following pragma affects the code generated by the C
	/*	compiler for all FAR functions.  Do NOT place any non-API
	/*	functions beyond this point in this file.
	/**/

void JET_API JetDBGSetPrintFn(JET_SESID sesid, PFNvprintf pfnParm)
	{
	pfn.pfnvprintf = pfnParm;
	}

/*
 *	level 0 - all log s.
 *	level 1 - log read and update operations.
 *	level 2 - log update operations only.
 */

static CODECONST(unsigned char) mpopLogLevel[opMax] = {
/*							0	*/		0,
/*  opIdle					1	*/		2,
/*	opGetTableIndexInfo		2	*/		1,
/*	opGetIndexInfo			3	*/		1,
/*	opGetObjectInfo			4	*/		1,
/*	opGetTableInfo			5	*/		1,
/*	opCreateObject			6	*/		2,
/*	opDeleteObject			7	*/		2,
/*	opRenameObject			8	*/		2,
/*	opBeginTransaction		9	*/		2,
/*	opCommitTransaction		10	*/		2,
/*	opRollback				11	*/		2,
/*	opOpenTable				12	*/		1,
/*	opDupCursor				13	*/		1,
/*	opCloseTable			14	*/		1,
/*	opGetTableColumnInfo	15	*/		1,
/*	opGetColumnInfo			16	*/		1,
/*	opRetrieveColumn		17	*/		1,
/*	opRetrieveColumns		18	*/		1,
/*	opSetColumn				19	*/		2,
/*	opSetColumns			20	*/		2,
/*	opPrepareUpdate			21	*/		2,
/*	opUpdate				22	*/		2,
/*	opDelete				23	*/		2,
/*	opGetCursorInfo			24	*/		1,
/*	opGetCurrentIndex		25	*/		1,
/*	opSetCurrentIndex		26	*/		1,
/*	opMove					27	*/		1,
/*	opMakeKey				28	*/		1,
/*	opSeek					29	*/		1,
/*	opGetBookmark			30	*/		1,
/*	opGotoBookmark			31	*/		1,
/*	opGetRecordPosition		32	*/		1,
/*	opGotoPosition			33	*/		1,
/*	opRetrieveKey			34	*/		1,
/*	opCreateDatabase		35	*/		2,
/*	opOpenDatabase			36	*/		1,
/*	opGetDatabaseInfo		37	*/		1,
/*	opCloseDatabase			38	*/		1,
/*	opCapability			39	*/		1,
/*	opCreateTable			40	*/		2,
/*	opRenameTable			41	*/		2,
/*	opDeleteTable			42	*/		2,
/*	opAddColumn				43	*/		2,
/*	opRenameColumn			44	*/		2,
/*	opDeleteColumn			45	*/		2,
/*	opCreateIndex			46	*/		2,
/*	opRenameIndex			47	*/		2,
/*	opDeleteIndex			48	*/		2,
/*	opComputeStats			49	*/		2,
/*	opAttachDatabase		50	*/		2,
/*	opDetachDatabase		51	*/		2,
/*	opOpenTempTable			52	*/		2,
/*	opSetIndexRange			53	*/		1,
/*	opIndexRecordCount		54	*/		1,
/*	opGetChecksum			55	*/		1,
/*	opGetObjidFromName		56	*/		1,
};

/* function in logapi to store jetapi calls */
extern void LGJetOp( JET_SESID sesid, int op );

void DebugLogJetOp( JET_SESID sesid, int op )
	{
	// UNDONE: should be controlled by a system parameter to decide
	// UNDONE: which log level it should be.

	/* log level 2 operations */
	if ( mpopLogLevel[ op ] >= lAPICallLogLevel )
		LGJetOp( sesid, op );
	}

#endif	/* !RETAIL */
