/************************************************************************/
/*	Copyright (C) 2004  Michael C. Shultz				*/
/*									*/
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or (at*/
/* your option) any later version.					*/
/*									*/
/* 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.  See the	*/
/* GNU General Public License for more details. 			*/
/*									*/
/* You should have received a copy of the GNU General Public License	*/
/* along with this program; if not, write to the Free Software		*/
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA		*/
/*  02111-1307, USA.							*/
/* 									*/
/* Michael C. Shultz							*/
/* ringworm@inbox.lv							*/
/* Box 3238 Landers, CA 92285						*/
/************************************************************************/

/************************************************/
/* 	macro index:				*/
/*		MGmSetString( var, string )	*/
/*		MGmDbArray( b, c , d )		*/
/*		MGmDbArrayFree( a ) 		*/
/************************************************/
#ifndef	__LIBMG_H__
#define __LIBMG_H__	1

#ifndef __errno__
extern	int	errno;
#define __errno__	1
#endif

/*
#include	<config.h>
*/

#include	<dirent.h>
#include	<signal.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<sys/stat.h>
#include	<sys/time.h>
#include	<sys/types.h>
#include	<sys/wait.h>
#include	<sysexits.h>
#include	<unistd.h>

#include	<sys/resource.h>

#ifndef CR
#define	CR	13
#endif

#ifndef LF
#define	LF	10
#endif

#ifndef SPACE
#define	SPACE	32
#endif

#ifndef TAB
#define	TAB	9
#endif

/*.................................................
structure	MGsDb
Used to contain the various elements of a data base

name		= path + name of data base file
mode	 	= mode data base is to be opened
		"r" read only
		"r+" read/write
		"a" append
..................................................*/
typedef struct
{
	char*		buffer; 	/* buffer used to contain data base */
	char*		field;
	char*		mode;		/* mode in which to open file */
	char*		name;		/* name and path of data base file */
	char**		record;
	char**		recordStartAddress;
	char*** 	array;		/* data base array */
	FILE*		stream; 	/* assigned to data base file after it is opened */
	int		bufferPtr1;
	unsigned	int	eof;		/* size of data base file in bytes */
	int		fieldPtr1;
	int		fieldIdx;
	int		fieldQty;	/* quantity of fields per record */
	int		recordIdx;
	int		recordQty;	/* quantity of records per data base */
} MGsDb;

/*.................................................
					<a name="MGsProperty">
structure	MGsProperty
					</a>

intended use is to provide a consistant means of organizing an
application's top level property structure.  See MGsProperty(7)
for a detailed description 

id		= assigned application's name
version 	= assigned application's version, in a string
feedback	= determines the level of verbosity as application executes
		  best to set this with MGrCommandLine(3) but it may of course
		  be set or adjused elsewhere
..................................................*/
typedef struct
{
	char*	id;
	char*	version;
	int	feedBack;
} MGsProperty;


/***********************************
MACROS
************************************/
/***********************************
MGmDbArray:
b = dbase  structure name
c = dbase file name string
d = open mode string
************************************/
#define MGmDbArrayFree( a )												\
	free( a.buffer );													\
	free( a.mode ); 													\
	free( a.name ); 													\
	free( a.recordStartAddress );										\
	free( a.array );													\
	fclose( a.stream );
	
#define MGmDbArray( b, c, d )																						\
	do{	\
	errno = 0;																										\
	if( !( b.name = ( char*)malloc( (unsigned int)sizeof( c ) + 1 ) ) )															\
	{																												\
		fprintf( stderr, "MGmDbArray error: Unable to allocate memory for %s\n", c );								\
		perror( "system message" );																					\
		errno = 1; 																									\
	}																												\
	if( errno==0 )																									\
	{																												\
		strcpy( b.name, c );																						\
		if( !( b.mode = ( char*)malloc( (unsigned int)sizeof( d ) + 1 ) ) )														\
		{																											\
			fprintf( stderr, "MGmDbArray error:  Unable to allocate 2 bytes %s mode  %s\n", c, d );				\
			perror( "system message" );																				\
			errno = 1;																								\
		}																											\
		if( errno==0 )																								\
		{																											\
			strcpy( b.mode, d );																					\
			if( !( b.eof = MGrFileSize( b.name ) ) ) 																\
			{																										\
				fprintf( stderr, "MGmDbArray warning:  MGrFileSize returned a size of %d for %s\n", b.eof, b.name );				\
				errno = 2;																							\
			}																										\
			if( errno==0 )																							\
			{																										\
				if(!(b.buffer=(char*)malloc((unsigned int)b.eof)))																\
				{																									\
					fprintf( stderr, "MGmDbArray error:  unable to	reallocate %d bytes memory for %s\n",			\
										b.eof, b.name );															\
					perror( "system message" );																		\
					errno = 1;																						\
				}																									\
				if( errno==0 )																						\
				{																									\
					if( !( b.stream = fopen( b.name, b.mode ) ) )													\
					{																								\
						fprintf( stderr, "MGmDbArray error: unable to open file %s\n", b.name );				\
						perror( "system message" );																	\
						errno = 1;																					\
					}																								\
					if( errno==0 )																					\
					{																								\
						fread( b.buffer, b.eof, 1, b.stream );														\
						if( ferror( b.stream ) )																	\
						{																							\
							fprintf( stderr, "MGmDbArray error: reading file %s into b.buffer\n", b.name );			\
							perror( "system message" );																\
							errno = 1;																				\
						}																							\
						if( errno==0 )																				\
						{																							\
							b.bufferPtr1	= 0;																	\
							b.fieldQty	= 0;																		\
							while( b.buffer[b.bufferPtr1] != LF ) 													\
							{																						\
								if( !( b.buffer[b.bufferPtr1] )  )													\
								{																					\
									b.fieldQty++;																	\
								}																					\
								b.bufferPtr1++;																		\
							}																						\
							b.bufferPtr1	= 0;																	\
							b.fieldPtr1	= 0;																		\
							b.recordQty	= 0;																		\
							while( b.bufferPtr1 < b.eof ) 															\
							{																						\
								while( b.buffer[b.bufferPtr1] != LF )												\
								{																					\
									if( !( b.buffer[b.bufferPtr1] )  )												\
									{																				\
										b.fieldPtr1++;  															\
									}																				\
									b.bufferPtr1++;																	\
								}																					\
								if( b.fieldPtr1 != b.fieldQty )														\
								{																					\
									fprintf( stderr,																\
				"MGmDbArray error: inconsitant field count at record %d. field count is	%d and should be %d\n", 	\
										b.recordQty, b.fieldPtr1,													\
										b.fieldQty ); 																\
									errno = 1;																		\
									break;																			\
								}																					\
								b.bufferPtr1++;																		\
								b.recordQty++;  																	\
								b.fieldPtr1	= 0;																	\
							}																						\
							if( errno==0 )																			\
							{																						\
								if(!(b.record=(char**)malloc((unsigned int)b.recordQty*(unsigned int)b.fieldQty*(unsigned int)sizeof(char**))))				\
								{																					\
									fprintf( stderr,																\
										"MGmDbArray error: realloc failed to allocate %d bytes for records\n",		\
										b.fieldQty * sizeof( char* ) ); 											\
									perror( "system message" ); 													\
									errno = 1;																		\
								}																					\
								if( errno==0 )																		\
								{																					\
									b.recordStartAddress	= b.record; 											\
									if( !( b.array = ( char*** )malloc((unsigned int)b.recordQty * (unsigned int)sizeof( char** ) ) ) ) 		\
									{																				\
										fprintf( stderr,															\
											"MGmDbArray error: malloc failed to allocate %d bytes for dBase\n", 	\
											b.recordQty * sizeof( char** ) );										\
										perror( "system message" ); 												\
										errno = 1;																	\
									}																				\
									if( errno==0 )																	\
									{																				\
										b.field	= b.buffer; 														\
										b.record[0]	= ( char* )b.field;												\
										b.array[0]	= ( char** )b.record;											\
										b.recordIdx		= 0;														\
										while( b.recordIdx < b.recordQty )											\
										{																			\
											b.fieldIdx	= 0;														\
											while( 1==1 )															\
											{																		\
												b.record[b.fieldIdx]	= b.field;									\
												b.fieldPtr1	= ( int )b.field;										\
												if( !( b.field = strchr( ( char* )b.fieldPtr1, 0) ) ) 				\
												{																	\
													fprintf( stderr, "MGmDbArray error: next field not found\n" );	\
													perror( "system message" );										\
													errno = 1;														\
													break;															\
												}																	\
												b.field = b.field + 1;												\
												b.fieldIdx++;														\
												if( b.field[0] == LF )  											\
												{																	\
													b.field = b.field + 1;											\
													break;															\
												} 																	\
											}																		\
											if( errno!=0 )															\
											{																		\
												break;																\
											}																		\
											b.array[b.recordIdx]		= ( char** )b.record;						\
											b.fieldIdx	= 0;														\
											while( b.fieldIdx	< b.fieldQty )										\
											{																		\
												b.record++;   														\
												b.fieldIdx++;														\
											}																		\
											b.recordIdx++;  														\
										}																			\
									}																				\
								}																					\
							}																						\
						}																							\
					}																								\
				}																									\
			}																										\
		}																											\
	}}	\
	while (0)

#define MGmSetString( var, string )				\
	errorCode	= 0;					\
	if( !( var = ( char* )malloc((unsigned int)strlen( string ) + 1 ) ) )\
	{							\
		errorCode	= 1;				\
	}							\
	strncpy( var, string, strlen(string)+1 );

#include	<MGrFileSize.h>
#include	<MGrFileTime.h>
#include	<MGrIfFileExist.h>
#include	<MGrInStringSwap.h>
#include	<MGrIntToString.h>
#include	<MGrStripComment.h>


#endif