/* Copyright (c) 2001-2009 by SoftIntegration, Inc. All Rights Reserved */
/* Copyright (c) 2001-2004 by SoftIntegration, Inc. All Rights Reserved */
/************************************************************************
 * This function process a header file readily for c2chf program.
 * Parameters:
 *   starttok:   the start token for a function prototype such as
 *                "extern" starting at a new line
 *   flag:        1 for keeping the starttok, 0 for remove starttok,
 *                in fileto.
 *   endtok:     the end token for a function prototype such as ";"
 *   filefrom:   the original header file
 *   fileto:     the ouput header file for c2chf program
 *   deletefuncmacro: Function macro to be deleted.
 *   update Sept. 23, 2004
 *   1. the bug with the starttok with more characters after starttok like:
 *        starttok="extern" but "external" in the head file
 *
 ***********************************************************************/
#include <string.h>
#include <stdio.h>
#define SPACE ' '
#define PARENTACY '('
//#define DEBUG printf 
#define DEBUG //

int processhfile(char *starttok, int flag, char *endtok, char *filefrom, char *fileto, char *deletefuncmacro)
{
    string_t string_from, string_to, string_tmp, string_tmp2;
    string_t filefromnew  = "_processhfile_tmp_";
    string_t filefromnew2 = "_processhfile_tmp2_";
    char *start_ptr, *mid_ptr, *end_ptr, *ptr_tmp, *toke2d_ptr;
    int hasStar = 0;
    char *tmp_ptr;
    char *second_ptr;
    int first_flag = 1;
    int anytoken = 0;
    int processany(string_t string_from, string_t &string_to);

    DEBUG("%s\n", filefrom);
    if(start_ptr = strstr(starttok, "?"))
      anytoken = 1;
// REDUNDENT CODE
//    else
//      anytoken = 0;

    if(start_ptr = strstr(starttok, "*")){
      hasStar = 1;
      starttok = strstr(starttok, "*")+1;
    }
// REDUNDENT CODE
//    else{
//      hasStar = 0;
//    }

    /* remove comments */
    rmcom $filefrom $filefromnew
 

    /* processany requires that 'typedef' be left in the file */
    if(anytoken)
    {
      /* remove 'LOAD_CHDL' if it exists in header files */
      sed "/LOAD_CHDL/d" $filefromnew > $filefromnew2
      mv -f $filefromnew2 $filefromnew
    }
    else
    {
      /* remove 'typedef' and 'LOAD_CHDL' if it exists in header files */
      sed -e "/typedef/d" -e "/LOAD_CHDL/d" $filefromnew > $filefromnew2
      mv -f $filefromnew2 $filefromnew
    }

#if defined(_WIN32_)
    string_from = ``cat $filefromnew``; 
    rm -rf $filefromnew
#else
    /* remove 
 for header files in Windows */
    sed -e "s/
//g" $filefromnew > $filefromnew2
    rm -rf $filefromnew
    string_from = ``cat $filefromnew2``; 
    rm -rf $filefromnew2
#endif
    tmp_ptr = *(char **)&string_from; // get address of string
    start_ptr = tmp_ptr;
    if(anytoken)
    {
      processany(string_from, string_to);
    }
    else if(hasStar){
      /* dele comments lines */
      mid_ptr = strstr(start_ptr, "/*");
      if(mid_ptr){
       if((mid_ptr-start_ptr)>0)
       strncpy(string_tmp, start_ptr, mid_ptr-start_ptr);
      }
      else
       strncpy(string_tmp, start_ptr, strlen(start_ptr)+1);
      while(mid_ptr){
       end_ptr= strstr(mid_ptr, "*/");
       end_ptr = end_ptr + 2;
       start_ptr = end_ptr;
       mid_ptr = strstr(start_ptr, "/*");
       if(mid_ptr==NULL)
         strncat(string_tmp, start_ptr, strlen(start_ptr)+1); 
       else{
         if(mid_ptr-start_ptr>0)	   
           strncat(string_tmp, start_ptr, mid_ptr-start_ptr);
       }
      }
      strncpy(string_tmp2, string_tmp, strlen(string_tmp)+1);

      /* dele definition */
      start_ptr = *(char **)&string_tmp2;
      mid_ptr = strstr( start_ptr, "#");
      if(mid_ptr)
       strncpy(string_tmp, start_ptr, mid_ptr-start_ptr);
      else
       strncpy(string_tmp, start_ptr, strlen(start_ptr)+1);

      while(mid_ptr){
       tmp_ptr = strstr(mid_ptr, "\n");
       if(strstr(mid_ptr,"\\"))
         if(strstr(mid_ptr, "\\")<tmp_ptr){
           mid_ptr = tmp_ptr+1;
         continue;
       }
       if(tmp_ptr==NULL)
         break;
       start_ptr = tmp_ptr+1;
       mid_ptr = strstr( start_ptr, "#");
       if(mid_ptr==NULL)
         strncat(string_tmp, start_ptr, strlen(start_ptr)+1);
       else
         strncat(string_tmp, start_ptr, mid_ptr-start_ptr);
      }
      strncpy(string_tmp2, string_tmp, strlen(string_tmp)+1);

      tmp_ptr = *(char **)&string_tmp2;
      start_ptr = tmp_ptr;
      while(*start_ptr==' '){
        start_ptr++;
      }
      while(start_ptr = strstr(start_ptr, "\n")){
        if(first_flag){              //first line
          start_ptr = tmp_ptr;
        }
        else{                        //next line
          tmp_ptr = start_ptr+strlen("\n");
          start_ptr = tmp_ptr;
        }

        // find the first "new line" char in the remain of file
        second_ptr = strstr(start_ptr, "\n");

        // find the first starttok in the remain of file
        start_ptr = strstr(start_ptr, starttok);
        
        //In the case the word mixed with starttok and any other characters.
        //for example: extern/external
        if(start_ptr)
        while(*(start_ptr+strlen(starttok))>SPACE){
           // if the character after starttok is '(', go ahead
           if (*(start_ptr+strlen(starttok))==PARENTACY)
              break;
           start_ptr = strstr(start_ptr, starttok);
           if(start_ptr==NULL)
              break;
        }

	//if no starttok in the current line
        //or no content in the remain of file 
	if(start_ptr == NULL || start_ptr > second_ptr){
          if(first_flag){
            first_flag = 0;
          }
	  // All content is done
          if(start_ptr == NULL){
            break;
          }
	  // next line 
          start_ptr = tmp_ptr;
        }
        else{
          if(flag) // keep starttok
            start_ptr = tmp_ptr;
          else{
            printf("Error: flag should be set to 1\n");
            exit (-1);
          }

          end_ptr = strstr(start_ptr, endtok);
          strncat(string_to, start_ptr, end_ptr-start_ptr+1);
          //prepare for next start_toke for next valid token
          start_ptr = start_ptr + (end_ptr-start_ptr+1);
          strcat(string_to, "\n");
          if( first_flag ){
            first_flag = 0;
          }
        }
      }	
    }
    else{ //updated ZQ, 04/25/2004
      while(start_ptr = strstr(start_ptr, stradd("\n", starttok))) {
        //In the case the word mixed with starttok and any other characters.
        //for example: extern/external
        if(*(start_ptr+strlen(starttok)+strlen("\n"))>SPACE){
           //if the charater is '(' after starttok, go ahead
           if(*(start_ptr+strlen(starttok)+strlen("\n"))!=PARENTACY){
             start_ptr = start_ptr+strlen(starttok);
             continue;
           }
        }
        if(flag) // keep starttok 
          start_ptr = start_ptr + strlen("\n");
        else{
          start_ptr = start_ptr + strlen(starttok)+strlen("\n");
        }
        // this point is just for the case in C++ "C",
        toke2d_ptr = strstr(start_ptr, stradd("\n", starttok));
        ptr_tmp = strstr(start_ptr,"\"C\"");
        if(ptr_tmp){
          if( ptr_tmp < toke2d_ptr){
            start_ptr = strstr(start_ptr,"\"C\"");
            continue;
          }
        }
        end_ptr = strstr(start_ptr, endtok);
        //get the string betwwen start token and end_token
        strncpy(string_tmp, start_ptr, end_ptr-start_ptr+strlen(endtok));
        strcat(string_tmp, "\n");
        ptr_tmp = *(char **)&string_tmp;
        //delete extra "start token", keep the last one.
        /*
        if(!flag)
        while(end_ptr = strstr(ptr_tmp+strlen(starttok), starttok)){
            ptr_tmp = end_ptr;
        }
        */
        if(!flag){ 
        // remove starttok
       	    if(strcmp(ptr_tmp,string_tmp)!=0){
                ptr_tmp= ptr_tmp + strlen(starttok);
            }
        }
        // if it is not function, it will be ignored
        if(strstr(ptr_tmp, "(")){ 
          strncat(string_to, ptr_tmp, strlen(ptr_tmp));
	  *(ptr_tmp+strlen(ptr_tmp)-1)='\0';
          //prepare for next start_toke for next valid token
          start_ptr = strstr(start_ptr, ptr_tmp);
          start_ptr = start_ptr + strlen(ptr_tmp);
        }
      }
      if(deletefuncmacro) { // remove  MACRO(fun(value)) 
        start_ptr = *(char **)&string_to;
        while(start_ptr = strstr(start_ptr, deletefuncmacro)) {
          int closeparenthesis=1;
          end_ptr = strstr(start_ptr, "(");
          while(closeparenthesis!=0) {
            end_ptr++;
            if(*(end_ptr) == '(') {
              closeparenthesis++;
            }
            else if(*(end_ptr) == ')') {
              closeparenthesis--;
            }
          }
          end_ptr++;
          memset(start_ptr, ' ', end_ptr-start_ptr);
          start_ptr = end_ptr;
        }
      }
    }
    //printf("%s",string_to);
    FILE *stream;
    if(!(stream = fopen(fileto, "w"))) {
        perror(fileto);
        return -1;
    }
    fprintf(stream, "%s", string_to);
    fclose(stream);
    return 0;
}

int processany(string_t string_from, string_t &string_to)
{
    string_t 
       dele_tok[3]  = { "struct", "union", "enum"},
       dele_tok2[3] = { "BEGIN_DECL", "END_DECL"},
       string_tmp   = "\0";

    char 
       *start_str = NULL,
       *mid_str   = NULL;

    int 
       num  = 3, // NUMBER OF TYPES IN 'dele_tok'
       num2 = 2, // NUMBER OF TYPES IN 'dele_tok2'
       i    = 0, 
       k    = 0;


    // COPY THE INPUT STRING TO OUTPUT STRING. 
    // THE MAKES EACH MODULAR SECTION INDEPENDENT FROM THE
    // PREVIOUS ONE.
    strcpy(string_to, string_from);

/********************** REMOVE LINES WITH '#' *********************/
    DEBUG("\tRemoving lines with '#'...\n");

    // COPY OUTPUT TO TEMPORARY AND RESET OUTPUT
    strcpy(string_tmp, string_to);
    string_to = "\0";

    // SET START PTR TO BEGINING OF TEMPORARY STRING 
    start_str = *(char **)&string_tmp;

    // FIND FIRST '#'. IF NONE EXIST, JUST COPY THE INPUT STRING
    // TO THE OUTPUT.
    while((mid_str = strstr( start_str, "#")) != NULL)
    {
       // FOUND '#'. COPY EVERYTHING FROM 'start_str' TO
       // CURRENT POSTION OF 'mid_str' TO TEMPORARY STRING.
       strncat(string_to, start_str, mid_str - start_str);


       // SEARCH FOR '\' AT THE END OF THE LINE. 
       // IF EXISTS, THEN GO TO THE LAST LINE OF THE SERIES.
       i = 0;
       while( (strstr(mid_str,"\\") != NULL ) && 
             (strstr(mid_str, "\\") < strstr(mid_str, "\n")) && i++ < 20)
       {
          // SET 'mid_str' TO END OF LINE WITH '\'.
          mid_str = strstr(mid_str, "\n");

          // CHECK TO SEE IF '\' MEANS CONTINUE TO NEXT LINE.
          // COULD BE
          //   #define junk "\2343\2342\2342";
          while( *(--mid_str) == ' ' || *mid_str == '\t');

          // IF '\' DOES NOT MEANS CONTINUE TO NEXT LINE,
          if(*(++mid_str-1) != '\\')
          {
            // SET 'start_str' TO END OF LINE AFTER LINE WITH '\'.
            start_str = strstr(mid_str, "\n")+1;
            break;
          }

          // IF '\' DOES MEANS CONTINUE TO NEXT LINE,
          // SET 'mid_str' TO BEGINNING OF NEXT LINE.
          mid_str = strstr(mid_str, "\n")+1;
       }

       // IF CANNOT FIND '\n', REACHED EOF AND 'start_str' == NULL.
       mid_str = start_str = strstr(mid_str, "\n");
    }

    // GET THE REST OF THE FILE. 
    // IF NO '#' WERE FOUND, GET ALL OF THE FILE.
    strcat(string_to, start_str);


/*******************  END REMOVE LINES WITH '#' ********************/

/***************** REMOVE BEGIN_DECLS  & END_DECLS *****************/
    DEBUG("\tRemoving BEGIN_DECLS and END_DECLS ...\n");

    for(i=0; i<num2; i++)
    {
      // COPY OUTPUT TO TEMPORARY AND RESET OUTPUT
      strcpy(string_tmp, string_to);
      string_to = "\0";

      // SET START PTR TO BEGINING OF TEMPORARY STRING 
      start_str = *(char **)&string_tmp;

      // CHECK FOR NEXT LINE AVAILABILITY
      while( (mid_str = strstr( start_str, dele_tok2[i])) != NULL)
      {
         // GOTO BEGINNING OF LINE
         while(--mid_str != start_str && *(mid_str-1) != '\n');

         // COPY EVERYTHING FROM 'start_str' TO
         // CURRENT POSTION OF 'mid_str' TO TEMPORARY STRING.
         strncat(string_to, start_str, mid_str - start_str);

         // SET 'start_str' TO END OF LINE.
         start_str = strstr(mid_str, "\n"); 
      }

      // GET THE REST OF THE FILE. 
      // IF 'BEGIN_DECLS' and 'END_DECLS' WERE NOT FOUND, 
      // GET ALL OF THE FILE.
      strcat(string_to, start_str);
    }

/*************** END REMOVE BEGIN_DECLS  & END_DECLS ***************/

/************************ REMOVE 'const' ***************************/
    DEBUG("\tRemoving 'const'...\n");

    // COPY OUTPUT TO TEMPORARY AND RESET OUTPUT
    strcpy(string_tmp, string_to);
    string_to = "\0";

    // SET START PTR TO BEGINING OF TEMPORARY STRING 
    start_str = *(char **)&string_tmp;

    //FIND "const"
    while( (mid_str = strstr(start_str, "const")) != NULL )
    {
       // COPY EVERYTHING FROM 'start_str' 
       // IT TO THE CURRENT POSTION OF 'mid_str'. 
       strncat(string_to, start_str, mid_str - start_str);

       // SET START TO AFTER "const".
       start_str = mid_str + strlen("const");

       // CHECK TO SEE IF PART OF FUNCTION NAME OR VARIABLE NAME
       if( *start_str > 32 ) 
       {
          strcat(string_to, "const");
          continue;
       }

       // DELETE SPACE AFTER "const" IF EXISTS
       if(*start_str == ' ' || *start_str == '\t') ++start_str;
    }

    // GET THE REST OF THE FILE. 
    // IF NO 'const' WERE FOUND, GET ALL OF THE FILE.
    strcat(string_to, start_str);

/********************** END REMOVE 'const' *************************/

/********************** REMOVE extern C LINE ***********************/
    DEBUG("\tRemoving lines with 'extern C'...\n");

    // COPY OUTPUT TO TEMPORARY AND RESET OUTPUT
    strcpy(string_tmp, string_to);
    string_to = "\0";

    // SET START PTR TO BEGINING OF TEMPORARY STRING 
    start_str = *(char **)&string_tmp;


    //IF FIND "C", LOCATE THE BEGINNING OF THE LINE 
    while( (mid_str = strstr(start_str, "\"C\"")) != NULL )
    {
       while( (*mid_str!='\n') && (mid_str!=start_str)) mid_str--;

       // FOUND BEGINNING OF LINE. COPY EVERYTHING FROM 'start_str' 
       // IT TO THE CURRENT POSTION OF 'mid_str'. 
       strncat(string_to, start_str, mid_str - start_str);

       // SET START TO THE BEGINNING OF THE NEXT LINE
       start_str = strstr(mid_str, "\n")+1;
    }

    // GET THE REST OF THE FILE. 
    // IF NO 'extern C' WERE FOUND, GET ALL OF THE FILE.
    strcat(string_to, start_str);

/******************* END REMOVE extern C LINE **********************/

/************************ REMOVE 'typedef' *************************/
    DEBUG("\tRemoving lines with 'typedef'...\n");

    // COPY OUTPUT TO TEMPORARY AND RESET OUTPUT
    strcpy(string_tmp, string_to);
    string_to = "\0";

    // SET START PTR TO BEGINING OF TEMPORARY STRING 
    start_str = *(char **)&string_tmp;

    // FIND FIRST 'typedef'. IF NONE EXIST, JUST COPY THE INPUT STRING
    // TO THE OUTPUT.
    while( (mid_str = strstr( start_str, "typedef")) != NULL)
    {
         // FOUND 'typedef'. COPY EVERYTHING FROM 'start_str' TO
         // CURRENT POSTION OF 'mid_str' TO TEMPORARY STRING.
         strncat(string_to, start_str, mid_str - start_str);

         // MOVE 'start_str' PAST 'typedef'. 
         // IF ERROR BELOW, WE DON'T GET STUCK IN ENDLESS LOOP
         start_str = start_str + strlen("typedef ");

         // SEARCH FOR ';' AT THE END OF 'typedef'. 
         // MUST EXIST OR ERROR IN CODE SO SKIP.
         if( strstr(mid_str,";") != NULL ) 
         {
             // SEARCH FOR '{' AND SEE IF IT IS BEFORE THE ';'.
             // SEARCH FOR '}'.
             if( strstr(mid_str, "{") != NULL &&
                 strstr(mid_str, "{") < strstr(mid_str, ";") && 
                 strstr(mid_str, "}") != NULL) 
             {
                // SET 'mid_str' TO "{" POSITION.
                mid_str = strstr(mid_str, "{")+1;

                // SEARCH FOR EMBEDDED STRUCTS, UNIONS, ... 
                //   typedef struct name
                //   {
                //      union { char value; } name2;
                //   };
                while( strstr(mid_str, "{") != NULL && 
                       strstr(mid_str, "{") < strstr(mid_str, "}"))
                    mid_str = strstr(mid_str, "}")+1;

                
               // SET 'mid_str' TO "}" POSITION IF EXISTS.
               if( strstr(mid_str, "}") != NULL ) 
               {
                  mid_str = strstr(mid_str, "}")+1;

                // SEARCH FOR ';'. 
                // IF DOES NOT EXIST, SKIP THIS 'typedef' 
                // AND ADD BACK TO OUTPUT STRING.
                if( strstr(mid_str, ";") != NULL)
                   start_str = strstr(mid_str, ";")+1; 
                else
                   strcat(string_to, "typedef ");
               }
               else
                  strcat(string_to, "typedef ");
             }
             else
             {
                // ONLY HAVE 
                //    'typedef type newtype;' 
                //    'typedef rettype (*funcptr)(arg1,
                //                                arg2);' 
                
                // SET 'start_str' TO BEGINNING OF LINE AFTER ';'. 
                // SEARCH FOR ';'. IF DOES NOT EXIST, SKIP THIS 'typedef' 
                // AND ADD BACK TO OUTPUT STRING.
                if( strstr(mid_str, ";") != NULL)
                   start_str = strstr(mid_str, ";")+1; 
                else
                    strcat(string_to, "typedef ");
             }
         }
         // SINCE WE ARE SKIPPING THIS 'typedef', WE MUST ADD IT
         // BACK INTO THE STRING.
         else
           strcat(string_to, "typedef ");
    }

    // GET THE REST OF THE FILE. 
    // IF NO 'typedef' WERE FOUND, GET ALL OF THE FILE.
    strcat(string_to, start_str);

/********************** END REMOVE 'typedef' ***********************/

/******************* REMOVE 'struct' AND OTHERS ********************/
    DEBUG("\tRemoving 'struct {}', 'union {}', and 'enum {}'...\n");

    // GO THROUGH ALL POSSIBLE TYPES IN THE LIST. 
    for(i=0; i< num; i++)
    {
      // COPY OUTPUT TO TEMPORARY AND RESET OUTPUT
      strcpy(string_tmp, string_to);
      string_to = "\0";

      // SET START PTR TO BEGINING OF TEMPORARY STRING 
      start_str = *(char **)&string_tmp;

      // FIND FIRST TYPE. IF NONE EXIST, JUST COPY THE INPUT STRING
      // TO THE OUTPUT.
      while( (mid_str = strstr( start_str, dele_tok[i])) != NULL)
      {      
         // FOUND 'dele_tok[i]'. COPY EVERYTHING FROM 'start_str' TO
         // CURRENT POSTION OF 'mid_str' TO TEMPORARY STRING.
         strncat(string_to, start_str, mid_str - start_str);

         // MOVE 'start_str' PAST 'dele_tok[i]'. 
         // IF ERROR BELOW, WE DON'T GET STUCK IN ENDLESS LOOP
         start_str = mid_str + strlen(dele_tok[i]);

         // CHECK TO SEE IF PART OF A FUNCTION
         //    rettype func(struct NAME name, arg2);
         //    rettype func2(union NAME name, arg2);
         if(strstr(mid_str, "{") != NULL &&
            (strstr(mid_str, ")") == NULL ||
            strstr(mid_str, "{") < strstr(mid_str, ")")) )
         {
            // SEARCH FOR ';' AT THE END OF TYPE. 
            // MUST EXIST OR ERROR IN CODE SO SKIP.
            if( strstr(mid_str,";") != NULL ) 
            {
               // SEARCH FOR '{' AND SEE IF IT IS BEFORE THE ';'.
               // SEARCH FOR '}'.
               if( strstr(mid_str, "{") != NULL &&
                   strstr(mid_str, "{") < strstr(mid_str, ";") && 
                   strstr(mid_str, "}") != NULL) 
               {
                  // SET 'mid_str' TO "{" POSITION.
                   mid_str = strstr(mid_str, "{")+1;

                   // SEARCH FOR EMBEDDED STRUCTS, UNIONS, ... 
                   //   typedef struct name
                   //   {
                   //      union { char value; } name2;
                   //   };
                   while( strstr(mid_str, "{") != NULL && 
                          strstr(mid_str, "{") < strstr(mid_str, "}"))
                       mid_str = strstr(mid_str, "}")+1;
                
                  // SET 'mid_str' TO "}" POSITION IF EXISTS.
                  if( strstr(mid_str, "}") != NULL ) 
                  {
                     mid_str = strstr(mid_str, "}")+1;

                   // SEARCH FOR ';'. 
                   // IF DOES NOT EXIST, SKIP THIS 'dele_tok' 
                   // AND ADD BACK TO OUTPUT STRING.
                   if( strstr(mid_str, ";") != NULL)
                      start_str = strstr(mid_str, ";")+1; 
                   else
                      // ADD REMOVED 'dele_tok' BACK TO OUTPUT STRING.
                      strcat(string_to, dele_tok[i]);
                  }
                  else
                     // ADD REMOVED 'dele_tok' BACK TO OUTPUT STRING.
                     strcat(string_to, dele_tok[i]);
               }
            }
         }
         else
         {
            // COPY WHAT WE PASSED AND CONTINUE 
            strcat(string_to, dele_tok[i]);
         }
      }
      // GET THE REST OF THE FILE. 
      // IF NO 'typedef' WERE FOUND, GET ALL OF THE FILE.
      strcat(string_to, start_str);
    }

/***************** END REMOVE 'struct' AND OTHERS ******************/

/********************** REMOVE INLINE FUNCS ************************/
    DEBUG("\tRemoving inline functions...\n");

    // COPY OUTPUT TO TEMPORARY AND RESET OUTPUT
    strcpy(string_tmp, string_to);
    string_to = "\0";

    // SET START PTR TO BEGINING OF TEMPORARY STRING 
    start_str = *(char **)&string_tmp;

    // FIND FIRST 'inline'. IF NONE EXIST, JUST COPY THE INPUT STRING
    // TO THE OUTPUT.
    while((mid_str = strstr( start_str, "inline")) != NULL)
    {
       // FOUND 'inline'. MOVE TO END OF PREVIOUS FUNCTION
       // DECLERATION.
       while( mid_str != start_str && *(--mid_str) != ';' && *mid_str != '}'); 

       if(mid_str != start_str) ++mid_str;

       // COPY EVERYTHING FROM 'start_str' TO
       // CURRENT POSTION OF 'mid_str' TO TEMPORARY STRING.
       strncat(string_to, start_str, mid_str - start_str);

       // SEARCH FOR '{' AND SEE IF IT IS BEFORE A '}'.
       if( strstr(mid_str, "{") != NULL &&
           strstr(mid_str, "}") != NULL && 
           strstr(mid_str, "{") < strstr(mid_str, "}")) 
       {
          mid_str = strstr(mid_str, "{");
           
          int number = 1;
          //SEARCH FOR THE END 
          while(*(++mid_str) != '\0')
          {
             if(*mid_str == '{') ++number;
             if(*mid_str == '}') --number;
             if(!number) break;
          }

          if(!number)
             start_str = mid_str + 1;
          else
             mid_str = strstr(mid_str, "inline") + strlen("inline");
       }

    }
    // GET THE REST OF THE FILE. 
    // IF NO 'inline' WERE FOUND, GET ALL OF THE FILE.
    strcat(string_to, start_str);
/******************** END REMOVE INLINE FUNCS **********************/

/************************** REMOVE LAST '}' ************************/
    DEBUG("\tRemoving last line with '}'...\n");
    // COPY OUTPUT TO TEMPORARY AND RESET OUTPUT
    strcpy(string_tmp, string_to);
    string_to = "\0";

    // SET START PTR TO BEGINING OF TEMPORARY STRING 
    start_str = *(char **)&string_tmp;

    // FIND FIRST '}'. IF NONE EXIST, JUST COPY THE INPUT STRING
    // TO THE OUTPUT.
    while((mid_str = strstr( start_str, "}")) != NULL)
    {

       // FOUND '}'. COPY EVERYTHING FROM 'start_str' TO
       // CURRENT POSTION OF 'mid_str' TO TEMPORARY STRING.
       strncat(string_to, start_str, mid_str - start_str);

       // SEARCH FOR '\n' AT THE END OF THE LINE. 
       if( (strstr(mid_str,"\n") != NULL ) )
       {
             // SET 'mid_str' TO END OF LINE WITH.
             mid_str = strstr(mid_str, "\n")+1;
             start_str = mid_str;
       }
       else
          // SET 'start_str' PAST '}'.
          start_str = mid_str+1;
    }

    // GET THE REST OF THE FILE. 
    // IF NO '}' WERE FOUND, GET ALL OF THE FILE.
    strcat(string_to, start_str);

/*********************** END REMOVE LAST '}' ***********************/

/********* REMOVE GLOBAL VARIABLES AND WHAT MAY NOT BE FUNCS *******/

    DEBUG("\tRemoving global variables...\n");

    // COPY OUTPUT TO TEMPORARY AND RESET OUTPUT
    strcpy(string_tmp, string_to);
    string_to = "\0";

    // SET START PTR TO BEGINING OF TEMPORARY STRING 
    start_str = *(char **)&string_tmp;

    // SET 'mid_str' TO BEGINNING OF STRING.
    mid_str = start_str;

    // CHECK FOR NEXT ';' AVAILABILITY
    while((strstr(mid_str, ";")) != NULL)
    {
       // COPY EVERYTHING FROM 'start_str' TO
       // CURRENT POSTION OF 'mid_str' TO TEMPORARY STRING.
       strncat(string_to, start_str, mid_str - start_str);

       // MOVE 'start_str' TO 'mid_str'.
       start_str = mid_str;

       // SET 'mid_str' TO NEXT ';'.
       mid_str = strstr(start_str, ";")+1;

       // CHECK FOR '(' BEFORE ';'. IF NOT, NOT A FUNCTION
       // PROTOTYPE.
       if( strstr(start_str, "(") == NULL ||
           strstr(start_str, "(") > strstr(start_str, ";"))
       {
         start_str = mid_str; 
       }
    }

    // GET THE REST OF THE FILE. 
    // IF NO '\n' WERE FOUND, GET ALL OF THE FILE.
    strcat(string_to, start_str);
    
/******* END REMOVE GLOBAL VARIABLES AND WHAT MAY NOT BE FUNCS *****/

/*********************** REMOVE BLANK LINES ************************/
    DEBUG("\tRemoving blank lines...\n");

    // COPY OUTPUT TO TEMPORARY AND RESET OUTPUT
    strcpy(string_tmp, string_to);
    string_to = "\0";

    // SET START PTR TO BEGINING OF TEMPORARY STRING 
    start_str = *(char **)&string_tmp;

    // SET 'mid_str' TO BEGINNING OF STRING.
    mid_str = start_str;

    // CHECK FOR NEXT LINE AVAILABILITY
    while((strstr( start_str, "\n")) != NULL)
    {
       // COPY EVERYTHING FROM 'start_str' TO
       // CURRENT POSTION OF 'mid_str' TO TEMPORARY STRING.
       strncat(string_to, start_str, mid_str - start_str);

       // SET 'start_str' TO BEGINNING OF LINE.
       // THEN GO THROUGH ALL CHARACTERS IN LINE.
       // IF ALL SPACES OR TABS THEN REMOVE LINE.
       start_str = mid_str;
       while( *mid_str == ' '  || *mid_str == '\t' || 
              *mid_str == '\n' || *mid_str == '\r')
           mid_str++;

       start_str = mid_str; 
       if(strstr(start_str, "\n") != NULL)
           mid_str = strstr(start_str, "\n")+1;
    }

    // GET THE REST OF THE FILE. 
    // IF NO '\n' WERE FOUND, GET ALL OF THE FILE.
    strcat(string_to, start_str);
    
/******************* END REMOVE LAST BLANK LINES *******************/

    return 0;
}
