/* This program can be compiled using a C compiler
#!/bin/ch
*/
/* File: port47to50.ch for porting .c file from v4.7 to v5.0 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LINESIZE 1024
#define TRUE  1
#define FALSE 0

int main(int argc, char *argv[]) {
    char line[LINESIZE], newline[LINESIZE];
    char *filename, dfilename[] = "port47to50.cpp"; 
    FILE *stream, *stream2;
    int isEmbeddedCh = FALSE, isMain = FALSE, isEXPORTCHchdl = FALSE;
    int isSpecial = FALSE, isFirstTime = TRUE; /* special case for handling pointer to function file */
    char *p;

    if(argc > 4)  {
        printf("Usage: port47to50.ch [-s] filename [newfilename]\n");
        exit(EXIT_FAILURE);
    }
    argv++;
    if(argc > 1 && !strcmp(*argv, "-s")) {
        isSpecial = TRUE; 
        argc--;
        argv++;
    }

    filename = (argc >= 2 ? *argv:dfilename);
    stream = fopen(filename, "r");
    if(stream == NULL) {
        printf("Error: cannot open file '%s'\n", filename);
        exit(EXIT_FAILURE);
    }
    if(argc == 3) {
      argv++;
      stream2 = fopen(*argv, "w");
      if(stream2 == NULL) {
          printf("Error: cannot open file '%s'\n", *argv);
          exit(EXIT_FAILURE);
      }
    }
    else {
      stream2 = fopen("_junktmp", "w");
      if(stream2 == NULL) {
          printf("Error: cannot open file '%s'\n", "_junktmp");
          exit(EXIT_FAILURE);
      }
    }

    fgets(line, LINESIZE , stream);
    while(!feof(stream)) {
        /* Add "  ChInterp_t interp;" in embedded Ch line below main() */
        if(isEmbeddedCh && isMain) {
          p = line;
          while(*p == ' ') { /* skip space */
              p++;
          }
          if(*p == '{')  {   /* skip the line with '{' */
             fprintf(stream2, "%s", line);
             fgets(line, LINESIZE , stream);
             continue;
          }
          else {
            isMain = FALSE;
            p = line;
            while(*p == ' ') {
                p++;
                fprintf(stream2, " ");
            }
            fprintf(stream2, "ChInterp_t interp;\n");
          }
        }
        p = strstr(line, "#include");
        if(p != NULL) {
            p = strstr(line, "<embedch.h>");
            if(p != NULL) {
               isEmbeddedCh = TRUE;
            }
        }
        p = strstr(line, " main");
        if(p != NULL) {
            p += 5;
            while(*p == ' ') /* skip space */
                p++;
            if(*p == '(' && isEmbeddedCh == TRUE) {
                isMain = TRUE;
            }
        }


        /* Add "    ChInterp_t interp;" in below EXPORTCH xxx_chdl(void *varg) */
        if(isEXPORTCHchdl) {
            p = line;
            while(*p == ' ') { /* skip space */
                p++;
            }
            if(*p == '{')  {   /* skip the line with '{' */
               fprintf(stream2, "%s", line);
               fgets(line, LINESIZE , stream);
               continue;
            }
            else if(!strncmp(p, "#else", strlen("#else")))  /* skip the line with '#else' till #endif */
            {
               while(strncmp(p, "#endif", strlen("#endif")))  {
                 fprintf(stream2, "%s", line);
                 fgets(line, LINESIZE , stream);
               }
               fprintf(stream2, "%s", line);
               fgets(line, LINESIZE , stream);
               continue;
            }
            else {
                p = line;
                while(*p == ' ') {
                  p++;
                  fprintf(stream2, " ");
                }
                fprintf(stream2, "ChInterp_t interp;\n");
                isEXPORTCHchdl = FALSE;
            }
        }

        if(isSpecial == TRUE) { /* special case for handling pointer to function file */
           if(isFirstTime == TRUE) {
              p = strstr(line, "static ");
              if(p != NULL) {
                  isFirstTime = FALSE;
                  fprintf(stream2, "static ChInterp_t interp;\n");
                  fprintf(stream2, "%s", line);
                  fgets(line, LINESIZE , stream);
                  continue;
              }
           }
        }
        else {
          p = strstr(line, "EXPORTCH");
          if(p != NULL) {
/* uncomment this part of code for EXPORTCH in a separate line
            p += strlen("EXPORTCH");
            while(*p == ' ') {
              p++;
            }
            if(*p == '\n') {
               fprintf(stream2, "%s", line);
               fgets(line, LINESIZE , stream);
            }
*/
            p = strstr(line, "_chdl");
            if(p) {
                p += 5;
                while(*p == ' ') {
                    p++;
                }
                if(*p == '(') {
                    isEXPORTCHchdl = TRUE;
                }
            }
          }
        }

        strcpy(newline, line);
        /* change Ch_Initialize(NULL, xxx) to Ch_Initialize(&interp, xxx) */
        p = strstr(line, "Ch_Initialize");
        if(p != NULL) {
            strncpy(newline, line, p-line);
            newline[p-line] = '\0';
            while(*p == ' ')
                p++;
            p += strlen("Ch_Initialize");
            if(*p == '(') {
                p++;
                strcat(newline, "Ch_Initialize(&interp, ");
                while(*p == ' ')
                   p++;

                if(strncmp(p, "NULL", strlen("NULL"))) {
                   printf("Error: program '%s' has already been ported to version 5.0\n", filename);
                   fclose(stream);
                   fclose(stream2);
                   if(argc == 3) 
                     remove(*argv);
                   else 
                     remove("_junktmp");
                   exit(1);
                }
                p += 4;
                p = strchr(p, ',');
                p++;
                while(*p == ' ')
                    p++;
                strcat(newline, p);
            }
            else {
                strcat(newline, p-1);
            }
        }
        else if (p = strstr(line, "Ch_")) {
           while(*p != '(' && *p != ']' && *p != '\0')
               p++;
           if(*p == ']' || *p == '\0' ) { /* not a valid API */
               fprintf(stream2, "%s", line);
               fgets(line, LINESIZE , stream);
               continue;
           }
           while(*p == ' ')
               p++;
           p++;
           strncpy(newline, line, p-line);
           newline[p-line] = '\0';
           /* change Ch_RunScript(NULL, argvv) to Ch_RunScript(interp, argvv) */
           if(!strncmp(p, "NULL", strlen("NULL"))) {
               strcat(newline, "interp");
               p += 4;
               strcat(newline, p);
           }
           else if(*p == ')') /* for comment such as Ch_RunScript() */
           {   /* exception for Ch_Home() and Ch_VarArgsCreate() are handled later */
               strcat(newline, p);
           }
           /* change Ch_VaArg(ap, int) to Ch_VaArg(interp, ap, int) */
           else {
               strcat(newline, "interp, ");
               strcat(newline, p);
           }
        }

        strcpy(line, newline);
        /* change Ch_Home() to Ch_Home(interp) */
        p = strstr(line, "Ch_Home");
        if(p != NULL) {
            strncpy(newline, line, p-line);
            newline[p-line] = '\0';
            strcat(newline, "Ch_Home");
            p += strlen("Ch_Home");
            while(*p == ' ')
                p++;
            if(*p == '(') {
                p++; 
                strcat(newline, "(interp");
            } 
            strcat(newline, p);
            strcpy(line, newline);
        }
        /* change Ch_VarArgsCreate() to Ch_VarArgsCreate(interp) */
        p = strstr(line, "Ch_VarArgsCreate");
        if(p != NULL) {
            strncpy(newline, line, p-line);
            newline[p-line] = '\0';
            strcat(newline, "Ch_VarArgsCreate");
            p += strlen("Ch_VarArgsCreate");
            while(*p == ' ')
                p++;
            if(*p == '(') {
                p++; 
                strcat(newline, "(interp");
            } 
            strcat(newline, p);
            strcpy(line, newline);
        }
        /* change Ch_GetSymbol(interp, xxx) to Ch_SymbolAddrByName(interp, xxx) */
        p = strstr(line, "Ch_GetSymbol");
        if(p != NULL) {
            strncpy(newline, line, p-line);
            newline[p-line] = '\0';
            strcat(newline, "Ch_SymbolAddrByName");
            p += strlen("Ch_GetSymbol");
            strcat(newline, p);
            strcpy(line, newline);
        }
        /* change Ch_VaElementtype(interp, xxx) to Ch_VaDataype(interp, xxx) */
        p = strstr(line, "Ch_VaElementtype");
        if(p != NULL) {
            strncpy(newline, line, p-line);
            newline[p-line] = '\0';
            strcat(newline, "Ch_VaDataType");
            p += strlen("Ch_VaElementtype");
            strcat(newline, p);
            strcpy(line, newline);
        }

        fprintf(stream2, "%s", newline);
        fgets(line, LINESIZE , stream);
    }
    fclose(stream);
    fclose(stream2);
    if(argc == 2) {
      char cmd[1024];
      strcpy(cmd, "cp _junktmp ");
      strcat(cmd, filename);
      system(cmd);
      remove("_junktmp");
    }
    return 0;
}
