#pragma once
#ifndef ErrorFunctionsH
   #define ErrorFunctionsH

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

enum {NO_ERROR, NULL_POINTER, BUFFER_UNDERFLOW, BUFFER_OVERFLOW, NEG_POINTER_INDEX};

#define macro_arg(argomento) #argomento

#define TEST_MAX_INDEX 1

int ErrorFunction(char *pcFormatOut, char *pcfile_name, int ifile_line, char *pcvett_ind_str, int ivett_ind, int iMaxDim, int iErrorType)
{

  static int icntError = 0;

  icntError++;

  /* NULL POINTER
     Example:
     int *p;
     p = NULL;
    *p = 1;    */
  if(iErrorType == NULL_POINTER)
  {
    printf("\nPointer %s is NULL! \n", pcFormatOut);
    printf("file: %s  line :\t%d\n", pcfile_name, ifile_line);

    {
      FILE *fp_debug;

      if(icntError == 1)
        fp_debug = fopen("Errors.txt", "w");
      else
        fp_debug = fopen("Errors.txt", "a");

      if(fp_debug != NULL)
      {
       fprintf(fp_debug, "\nError n. \t%d  \n", icntError);

       fprintf(fp_debug, "\nPointer %s is NULL! \n", pcFormatOut);
       fprintf(fp_debug, "file: %s  line :\t%d\n", pcfile_name, ifile_line);

       fclose(fp_debug);
      }
    }

    exit(1);
  }

  /* BUFFER UNDERFLOW
     Example:
     int x[10];
     x[-1] = 0;  */
  else if(iErrorType == BUFFER_UNDERFLOW)
  {
    printf("\nNegative index: \"%s\"\n", pcFormatOut);
    printf("Index name     :\t%s\n", pcvett_ind_str);
    printf("Index value    :\t%d\n", ivett_ind);
    printf("file: %s  line :\t%d\n", pcfile_name, ifile_line);

    {
      FILE *fp_debug;

      if(icntError == 1)
        fp_debug = fopen("Errors.txt", "w");
      else
        fp_debug = fopen("Errors.txt", "a");

      if(fp_debug != NULL)
      {
       fprintf(fp_debug, "\nError n. \t%d  \n", icntError);

       fprintf(fp_debug, "\nNegative index: \"%s\"\n", pcFormatOut);
       fprintf(fp_debug, "Index name     :\t%s\n", pcvett_ind_str);
       fprintf(fp_debug, "Index value    :\t%d\n", ivett_ind);
       fprintf(fp_debug, "file: %s  line :\t%d\n", pcfile_name, ifile_line);

       fclose(fp_debug);
      }
    }

    exit(1);
  }

  /* BUFFER_OVERFLOW
     Example:
     int x[10];
     x[12] = 0;  */
  else if(iErrorType == BUFFER_OVERFLOW)
  {
    printf("\nMaximum index allowed for \"%s\": %d\n", pcFormatOut, iMaxDim);
    printf("Index name     :\t%s\n", pcvett_ind_str);
    printf("Index value    :\t%d\n", ivett_ind);
    printf("file: %s  line :\t%d\n", pcfile_name, ifile_line);

    {
      FILE *fp_debug;

      if(icntError == 1)
        fp_debug = fopen("Errors.txt", "w");
      else
        fp_debug = fopen("Errors.txt", "a");

      if(fp_debug != NULL)
      {
       fprintf(fp_debug, "\nError n. \t%d  \n", icntError);

       fprintf(fp_debug, "\nMaximum index allowed for \"%s\": %d\n", pcFormatOut, iMaxDim);
       fprintf(fp_debug, "Index name     :\t%s\n", pcvett_ind_str);
       fprintf(fp_debug, "Index value    :\t%d\n", ivett_ind);
       fprintf(fp_debug, "file: %s  line :\t%d\n", pcfile_name, ifile_line);

       fclose(fp_debug);
      }
    }

    exit(1);
  }

  /* NEGATIVE POINTER INDEX
     Example:
     int x[10];
     int *p, *q;
    
     p = x;
     p[-1] = 1;  //Error
    
     q = &x[1];
     q[-1] = 1;  //No Error  */
  else  if(iErrorType == NEG_POINTER_INDEX)
  {
    printf("\nWARNING!! It can be out of range\n");
    printf("Pointer name   : \"%s\"\n", pcFormatOut);

    printf("Index name     :\t%s\n", pcvett_ind_str);
    printf("Index value    :\t%d\n", ivett_ind);
    printf("file: %s  line :\t%d\n", pcfile_name, ifile_line);

    {
      FILE *fp_debug;

      if(icntError == 1)
        fp_debug = fopen("Errors.txt", "w");
      else
        fp_debug = fopen("Errors.txt", "a");

      if(fp_debug != NULL)
      {
       fprintf(fp_debug, "\nError n. \t%d  \n", icntError);
       fprintf(fp_debug, "\nWARNING!! It can be out of range\n");
       fprintf(fp_debug, "Pointer name   : \"%s\"\n", pcFormatOut);

       fprintf(fp_debug, "Index name     :\t%s\n", pcvett_ind_str);
       fprintf(fp_debug, "Index value    :\t%d\n", ivett_ind);
       fprintf(fp_debug, "file: %s  line :\t%d\n", pcfile_name, ifile_line);

       fclose(fp_debug);
      }
    }
  }

  return ivett_ind;

}

#endif


#ifndef io_sper_functionsH
   #define io_sper_functionsH

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define macro_arg(argomento) #argomento


void write_str(char *Format, char *IndexStr, char *FormatOut, int *io_index)
{
int Index;

int IndexIo;
char IndexIoStr[20];

char IndexStrAUX[200];

char *CarFormat;
char *CarFormat2;

char *CarIndex;
char *NextIndex;

      strcpy(IndexStrAUX, IndexStr);

      CarFormat = Format;
      CarFormat2 = CarFormat;

      CarIndex = IndexStr;

      Index = 0;

      FormatOut[0] = '\0';

      CarFormat = strstr(CarFormat, "%d");
      while(CarFormat != NULL)
        {
         NextIndex = IndexStrAUX + Index;
         CarIndex = strtok(NextIndex, " ");
         
         strncat(FormatOut, CarFormat2, CarFormat-CarFormat2);
         CarFormat2 = CarFormat + 2;  

         IndexIo = atoi(CarIndex);

         sprintf(IndexIoStr, "%d", io_index[IndexIo]);
         strcat(FormatOut, IndexIoStr);

         CarFormat = CarFormat + 1;
         CarFormat = strstr(CarFormat, "%d");

         Index = (CarIndex-IndexStrAUX) + strlen(CarIndex) + 1;
        }

      strncat(FormatOut, CarFormat2, Format + strlen(Format)-CarFormat2);
}

int io_sper(int vett_ind, int i, int *io_index, void *vett, void *add_vett, void *add_vett_0, int size_of_vett, int size_of_vett_0, 
            char *vett_ind_str, char *Format, char *IndexStr, char *file_name, int file_line)
{
int iMaxDim = 0;

char FormatOut[200];


  /* NULL POINTER
     Example:
     int *p;
     p = NULL;
    *p = 1;    */
if(vett == NULL)
  {
   write_str(Format, IndexStr, FormatOut, io_index);
   
   vett_ind = ErrorFunction(FormatOut, file_name, file_line, vett_ind_str, vett_ind, iMaxDim, NULL_POINTER);
  }

/* STATIC VECTOR */
else if(add_vett == add_vett_0)
  {

   /* BUFFER UNDERFLOW
      Example:
      int x[10];
      x[-1] = 0;  */
   if(vett_ind < 0)
     {
    
      write_str(Format, IndexStr, FormatOut, io_index);

      vett_ind = ErrorFunction(FormatOut, file_name, file_line, vett_ind_str, vett_ind, iMaxDim, BUFFER_UNDERFLOW);
     }

   /* BUFFER_OVERFLOW
      Example:
      int x[10];
      x[12] = 0;  */
   else if(size_of_vett/size_of_vett_0 < vett_ind + 1)
     {

      write_str(Format, IndexStr, FormatOut, io_index);
   
      iMaxDim = size_of_vett/size_of_vett_0 - 1;

      vett_ind = ErrorFunction(FormatOut, file_name, file_line, vett_ind_str, vett_ind, iMaxDim, BUFFER_OVERFLOW);
     } 
  }
else /* POINTER TESTING */
  {
     
   write_str(Format, IndexStr, FormatOut, io_index);

   /* NEGATIVE POINTER INDEX
      Example:
      int x[10];
      int *p, *q;
    
      p = x;
      p[-1] = 1;  //Error
    
      q = &x[1];
      q[-1] = 1;  //No Error  */
   if(vett_ind < 0)
     vett_ind = ErrorFunction(FormatOut, file_name, file_line, vett_ind_str, vett_ind, iMaxDim, NEG_POINTER_INDEX);
  }

io_index[i] = vett_ind;

return vett_ind;
}

#endif


#define ORIG_FILE "D:\\SDT\\Examples\\Eclipse\\Console_Examples\\Ex02_Multiple_Buffer\\Ex02_Multiple_Buffer\\src\\Ex02_Multiple_Buffer.cpp"
#line 1
                                                                              
                                         
                            
                
                                 
                                               
                                                                              

#include <iostream>
using namespace std;

int main() { int io_index[3];             
                       
                

                                   
                                        
                                                           

                                                     

    int y[10][10][10];

    y[io_sper(10, 0, io_index, (void *)y, (void *)&y, (void *)&(y[0]), sizeof(y), sizeof(y[0]), macro_arg(10), "y", "", ORIG_FILE, __LINE__)][io_sper(3, 1, io_index, (void *)y[io_index[0]], (void *)&y[io_index[0]], (void *)&(y[io_index[0]][0]), sizeof(y[io_index[0]]), sizeof(y[io_index[0]][0]), macro_arg(3), "y[%d]", " 0", ORIG_FILE, __LINE__)][io_sper(4, 2, io_index, (void *)y[io_index[0]][io_index[1]], (void *)&y[io_index[0]][io_index[1]], (void *)&(y[io_index[0]][io_index[1]][0]), sizeof(y[io_index[0]][io_index[1]]), sizeof(y[io_index[0]][io_index[1]][0]), macro_arg(4), "y[%d][%d]", " 0 1", ORIG_FILE, __LINE__)] = 5;
    y[io_sper(3, 0, io_index, (void *)y, (void *)&y, (void *)&(y[0]), sizeof(y), sizeof(y[0]), macro_arg(3), "y", "", ORIG_FILE, __LINE__)][io_sper(10, 1, io_index, (void *)y[io_index[0]], (void *)&y[io_index[0]], (void *)&(y[io_index[0]][0]), sizeof(y[io_index[0]]), sizeof(y[io_index[0]][0]), macro_arg(10), "y[%d]", " 0", ORIG_FILE, __LINE__)][io_sper(7, 2, io_index, (void *)y[io_index[0]][io_index[1]], (void *)&y[io_index[0]][io_index[1]], (void *)&(y[io_index[0]][io_index[1]][0]), sizeof(y[io_index[0]][io_index[1]]), sizeof(y[io_index[0]][io_index[1]][0]), macro_arg(7), "y[%d][%d]", " 0 1", ORIG_FILE, __LINE__)] = 11;
    y[io_sper(3, 0, io_index, (void *)y, (void *)&y, (void *)&(y[0]), sizeof(y), sizeof(y[0]), macro_arg(3), "y", "", ORIG_FILE, __LINE__)][io_sper(2, 1, io_index, (void *)y[io_index[0]], (void *)&y[io_index[0]], (void *)&(y[io_index[0]][0]), sizeof(y[io_index[0]]), sizeof(y[io_index[0]][0]), macro_arg(2), "y[%d]", " 0", ORIG_FILE, __LINE__)][io_sper(10, 2, io_index, (void *)y[io_index[0]][io_index[1]], (void *)&y[io_index[0]][io_index[1]], (void *)&(y[io_index[0]][io_index[1]][0]), sizeof(y[io_index[0]][io_index[1]]), sizeof(y[io_index[0]][io_index[1]][0]), macro_arg(10), "y[%d][%d]", " 0 1", ORIG_FILE, __LINE__)] = 8;
    y[io_sper(-3, 0, io_index, (void *)y, (void *)&y, (void *)&(y[0]), sizeof(y), sizeof(y[0]), macro_arg(-3), "y", "", ORIG_FILE, __LINE__)][io_sper(6, 1, io_index, (void *)y[io_index[0]], (void *)&y[io_index[0]], (void *)&(y[io_index[0]][0]), sizeof(y[io_index[0]]), sizeof(y[io_index[0]][0]), macro_arg(6), "y[%d]", " 0", ORIG_FILE, __LINE__)][io_sper(4, 2, io_index, (void *)y[io_index[0]][io_index[1]], (void *)&y[io_index[0]][io_index[1]], (void *)&(y[io_index[0]][io_index[1]][0]), sizeof(y[io_index[0]][io_index[1]]), sizeof(y[io_index[0]][io_index[1]][0]), macro_arg(4), "y[%d][%d]", " 0 1", ORIG_FILE, __LINE__)] = 5;
    y[io_sper(3, 0, io_index, (void *)y, (void *)&y, (void *)&(y[0]), sizeof(y), sizeof(y[0]), macro_arg(3), "y", "", ORIG_FILE, __LINE__)][io_sper(-4, 1, io_index, (void *)y[io_index[0]], (void *)&y[io_index[0]], (void *)&(y[io_index[0]][0]), sizeof(y[io_index[0]]), sizeof(y[io_index[0]][0]), macro_arg(-4), "y[%d]", " 0", ORIG_FILE, __LINE__)][io_sper(9, 2, io_index, (void *)y[io_index[0]][io_index[1]], (void *)&y[io_index[0]][io_index[1]], (void *)&(y[io_index[0]][io_index[1]][0]), sizeof(y[io_index[0]][io_index[1]]), sizeof(y[io_index[0]][io_index[1]][0]), macro_arg(9), "y[%d][%d]", " 0 1", ORIG_FILE, __LINE__)] = 12;
    y[io_sper(3, 0, io_index, (void *)y, (void *)&y, (void *)&(y[0]), sizeof(y), sizeof(y[0]), macro_arg(3), "y", "", ORIG_FILE, __LINE__)][io_sper(5, 1, io_index, (void *)y[io_index[0]], (void *)&y[io_index[0]], (void *)&(y[io_index[0]][0]), sizeof(y[io_index[0]]), sizeof(y[io_index[0]][0]), macro_arg(5), "y[%d]", " 0", ORIG_FILE, __LINE__)][io_sper(-2, 2, io_index, (void *)y[io_index[0]][io_index[1]], (void *)&y[io_index[0]][io_index[1]], (void *)&(y[io_index[0]][io_index[1]][0]), sizeof(y[io_index[0]][io_index[1]]), sizeof(y[io_index[0]][io_index[1]][0]), macro_arg(-2), "y[%d][%d]", " 0 1", ORIG_FILE, __LINE__)] = 7;

                      

	cout << "!!!Hello World!!!" << endl;                            
	return 0;
}
