#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\\Ex03_Struct_Test\\Ex03_Struct_Test\\src\\Ex03_Struct_Test.cpp"
#line 1
                                                                              
                                     
                            
                
                                 
                                               
                                                                              

#include <iostream>

typedef struct test_s {                              
char a[10];
char b[10];
char c[10][5];
} TEST;

using namespace std;

int main() { int io_index[2];             
                       
                

                                   
                                        
                                                           

                                                     

    TEST test;

    test.a[io_sper(-1, 0, io_index, (void *)test.a, (void *)&test.a, (void *)&(test.a[0]), sizeof(test.a), sizeof(test.a[0]), macro_arg(-1), "test.a", "", ORIG_FILE, __LINE__)] = 3;
    test.a[io_sper(10, 0, io_index, (void *)test.a, (void *)&test.a, (void *)&(test.a[0]), sizeof(test.a), sizeof(test.a[0]), macro_arg(10), "test.a", "", ORIG_FILE, __LINE__)] = 6;
    test.b[io_sper(-2, 0, io_index, (void *)test.b, (void *)&test.b, (void *)&(test.b[0]), sizeof(test.b), sizeof(test.b[0]), macro_arg(-2), "test.b", "", ORIG_FILE, __LINE__)] = 7;
    test.b[io_sper(11, 0, io_index, (void *)test.b, (void *)&test.b, (void *)&(test.b[0]), sizeof(test.b), sizeof(test.b[0]), macro_arg(11), "test.b", "", ORIG_FILE, __LINE__)] = 4;
    test.c[io_sper(-2, 0, io_index, (void *)test.c, (void *)&test.c, (void *)&(test.c[0]), sizeof(test.c), sizeof(test.c[0]), macro_arg(-2), "test.c", "", ORIG_FILE, __LINE__)][io_sper(3, 1, io_index, (void *)test.c[io_index[0]], (void *)&test.c[io_index[0]], (void *)&(test.c[io_index[0]][0]), sizeof(test.c[io_index[0]]), sizeof(test.c[io_index[0]][0]), macro_arg(3), "test.c[%d]", " 0", ORIG_FILE, __LINE__)] = 7;
    test.c[io_sper(10, 0, io_index, (void *)test.c, (void *)&test.c, (void *)&(test.c[0]), sizeof(test.c), sizeof(test.c[0]), macro_arg(10), "test.c", "", ORIG_FILE, __LINE__)][io_sper(2, 1, io_index, (void *)test.c[io_index[0]], (void *)&test.c[io_index[0]], (void *)&(test.c[io_index[0]][0]), sizeof(test.c[io_index[0]]), sizeof(test.c[io_index[0]][0]), macro_arg(2), "test.c[%d]", " 0", ORIG_FILE, __LINE__)] = 4;
    test.c[io_sper(0, 0, io_index, (void *)test.c, (void *)&test.c, (void *)&(test.c[0]), sizeof(test.c), sizeof(test.c[0]), macro_arg(0), "test.c", "", ORIG_FILE, __LINE__)][io_sper(19, 1, io_index, (void *)test.c[io_index[0]], (void *)&test.c[io_index[0]], (void *)&(test.c[io_index[0]][0]), sizeof(test.c[io_index[0]]), sizeof(test.c[io_index[0]][0]), macro_arg(19), "test.c[%d]", " 0", ORIG_FILE, __LINE__)] = 4;
    test.c[io_sper(8, 0, io_index, (void *)test.c, (void *)&test.c, (void *)&(test.c[0]), sizeof(test.c), sizeof(test.c[0]), macro_arg(8), "test.c", "", ORIG_FILE, __LINE__)][io_sper(-1, 1, io_index, (void *)test.c[io_index[0]], (void *)&test.c[io_index[0]], (void *)&(test.c[io_index[0]][0]), sizeof(test.c[io_index[0]]), sizeof(test.c[io_index[0]][0]), macro_arg(-1), "test.c[%d]", " 0", ORIG_FILE, __LINE__)] = 4;

                      

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