text: /*         
   *  Copyright 2002-2018 Barcelona Supercomputing Center (www.bsc.es)
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  #include <stdlib.h>
  #include <limits.h>
  #include <string.h>
  #include <ctype.h>
  #include "backend.h"
  #include "semantic.h"
  #include "backendlib.h"
  #include "types.h"
  
  static FILE *stubsFile = NULL;
  static FILE *workerFile = NULL;
  static FILE *includeFile = NULL;
  
  static FILE *const_file = NULL;
  static char includeName[PATH_MAX];
  
  static char *c_types[] = {
    "int",		// boolean_dt
    "char",		// char_dt
    "unsigned char",	// byte_dt
    "short",		// short_dt
    "int",		// int_dt
    "long",		// long_dt
    "float",		// float_dt
    "double",		// double_dt
    "char *",		// string_dt
    "file",		// file_dt
    "void *",		// object_dt
    "void *",		// psco_dt
    "void *",		// external_psco_dt
    
    "char", 		// wchar_dt
    "char *", 		// wstring_dt
    "long long", 		// longlong_dt
    "void", 		// void_dt
    "void",		// any_dt
    "error"		// null_dt
  };
  
  static char *c_out_types[] = {
    "int",                  // boolean_dt
    "char",                 // char_dt
    "unsigned char",        // byte_dt
    "short",                // short_dt
    "int",                  // int_dt
    "long",                 // long_dt
    "float",                // float_dt
    "double",               // double_dt
    "char *",               // string_dt
    "file",                 // file_dt
    "void *",               // object_dt
    "void *",               // psco_dt
    "void *",               // external_psco_dt
    
    "char",                 // wchar_dt
    "char *",               // wstring_dt
    "long long",            // longlong_dt
    "void",                 // void_dt
    "void",                 // any_dt
    "error"                 // null_dt
  };
  
  
  void generate_stubs_prolog()
  {
  
    fprintf(stubsFile, "/* This file has been autogenerated from '%s'. */\n", get_filename());
    fprintf(stubsFile, "/* CHANGES TO THIS FILE WILL BE LOST */\n");
    fprintf(stubsFile, "\n");
    fprintf(stubsFile, "#include <stdio.h>\n");
    fprintf(stubsFile, "#include <stdlib.h>\n");
    fprintf(stubsFile, "#include <limits.h>\n");
    fprintf(stubsFile, "#include <string.h>\n");
    fprintf(stubsFile, "#include <fstream>\n");
    //Text serialization uncomment and comment binary to change (TODO: Add an ifdef)
    //fprintf(stubsFile, "#include <boost/archive/text_iarchive.hpp>\n");
    //fprintf(stubsFile, "#include <boost/archive/text_oarchive.hpp>\n");
    //Added for binary serialization
    fprintf(stubsFile, "#include <boost/archive/binary_iarchive.hpp>\n");
    fprintf(stubsFile, "#include <boost/archive/binary_oarchive.hpp>\n");
  
    fprintf(stubsFile, "#include <GS_compss.h>\n");
    fprintf(stubsFile, "#include <param_metadata.h>\n");
    fprintf(stubsFile, "#include \"%s\"\n", includeName);
  
    fprintf(stubsFile, "\n");
    fprintf(stubsFile, "using namespace std;\n");
    fprintf(stubsFile, "using namespace boost;\n");
  
    fprintf(stubsFile, "\n");
  
  }
  
  void generate_worker_prolog()
  {
  
    fprintf(workerFile, "/* This file has been autogenerated from '%s'. */\n", get_filename());
    fprintf(workerFile, "/* CHANGES TO THIS FILE WILL BE LOST */\n");
    fprintf(workerFile, "\n");
    fprintf(workerFile, "#include <stdio.h>\n");
    fprintf(workerFile, "#include <stdlib.h>\n");
    fprintf(workerFile, "#include <limits.h>\n");
    fprintf(workerFile, "#include <string.h>\n");
    fprintf(workerFile, "#include <fstream>\n");
    fprintf(workerFile, "#include <compss_worker_lock.h>\n");
    //Text serialization uncomment and comment binary to change (TODO: Add an ifdef)
    //fprintf(workerFile, "#include <boost/archive/text_iarchive.hpp>\n");
    //fprintf(workerFile, "#include <boost/archive/text_oarchive.hpp>\n");
    //added for binary serialization
    fprintf(workerFile, "#include <boost/archive/binary_iarchive.hpp>\n");
    fprintf(workerFile, "#include <boost/archive/binary_oarchive.hpp>\n");
  
    fprintf(workerFile, "#include \"%s\"\n", includeName);
    fprintf(workerFile, "\n");
    fprintf(workerFile, "using namespace std;\n");
    fprintf(workerFile, "\n");
  
  }
  
  void generate_executor_prototype()
  {
    fprintf(workerFile, "int execute(int argc, char **argv, std::map<std::string, void*>& cache, std::map<std::string, int>& types, int serializeOuts) {\n");
    fprintf(workerFile, "\n");
    // Args consistent with Runtime [0, NUM_INTERNAL_ARGS]: executable, tracing, taskId, workerDebug, storageConf, method_type, className, methodName, 
    //                                                      numSlaves, [slaves], numCus, hasTarget, returnType, numAppParams
    fprintf(workerFile, "\t cout << endl;\n");
    fprintf(workerFile, "\t cout << \"----------------- C WORKER -----------------\" << endl;\n");
    fprintf(workerFile, "\t cout << \"Total number of parameters: \" << argc << endl;\n");
    fprintf(workerFile, "\t if (argc < MIN_NUM_INTERNAL_ARGS) {\n");
    fprintf(workerFile, "\t\t cout << \"ERROR: Incorrect number of COMPSs internal parameters\"<< endl;\n");
    fprintf(workerFile, "\t\t cout << \"Aborting...\" << endl;\n");
    fprintf(workerFile, "\t\t return -1; \n");
    fprintf(workerFile, "\t }\n");
    fprintf(workerFile, "\n");
    // Log args
    fprintf(workerFile, "\t cout << \"Executable: \" << argv[0] << endl;\n");
    fprintf(workerFile, "\t cout << \"Tracing: \" <<  argv[1] << endl;\n");
    fprintf(workerFile, "\t cout << \"Task Id: \" << argv[2] << endl;\n");
    fprintf(workerFile, "\t cout << \"Worker Debug: \" << argv[3] << endl;\n");
    fprintf(workerFile, "\t cout << \"StorageConf: \" << argv[4] << endl;\n");
    fprintf(workerFile, "\t cout << \"MethodType: \" << argv[5] << endl;\n");
    fprintf(workerFile, "\t cout << \"ClassName: \" << argv[6] << endl;\n");
    fprintf(workerFile, "\t cout << \"MethodName: \" << argv[7] << endl;\n");
    fprintf(workerFile, "\t cout << \"NumSlaves: \" << argv[8] << endl;\n");
    fprintf(workerFile, "\t int numSlaves=atoi(argv[8]);\n");
    fprintf(workerFile, "\t for (int i = 0; i < numSlaves; ++i) {\n");
    fprintf(workerFile, "\t\t cout <<\"Slave \" << i << \" has name \" << argv[NUM_BASE_ARGS + i] << endl;\n");
    fprintf(workerFile, "\t }\n");
    fprintf(workerFile, "\t int NUM_INTERNAL_ARGS=NUM_BASE_ARGS + numSlaves;\n");
    fprintf(workerFile, "\t cout << \"NumComputingUnits: \" << argv[NUM_INTERNAL_ARGS++] << endl;\n");
  
    fprintf(workerFile, "\t cout << \"HasTarget: \" << argv[NUM_INTERNAL_ARGS++] << endl;\n");
    fprintf(workerFile, "\t cout << \"ReturnType: \" << argv[NUM_INTERNAL_ARGS++] << endl;\n");
    fprintf(workerFile, "\t cout << \"Num App Params: \" << argv[NUM_INTERNAL_ARGS++] << endl;\n");
  
    fprintf(workerFile, "\t cout << \"Application Arguments:\" << endl;\n");
    fprintf(workerFile, "\t for(int i = NUM_INTERNAL_ARGS; i < argc; i++) { \n");
    fprintf(workerFile, "\t\t cout << \"\t\" << argv[i] << endl;\n");
    fprintf(workerFile, "\t }\n");
    fprintf(workerFile, "\t cout << flush;\n");
    fprintf(workerFile, "\n");
  
    // Get OpName and OpCode
    fprintf(workerFile, "\t enum operationCode opCod;\n");
    fprintf(workerFile, "\t char *opName;\n");
    fprintf(workerFile, "\t opName = strdup(argv[METHOD_NAME_POS]);\n");
    fprintf(workerFile, "\t cout << \"OpName: \" << opName << endl;\n");
    fprintf(workerFile, "\n");
    fprintf(workerFile, "\tfor(int i=0; i < N_OPS; i++) {\n");
    fprintf(workerFile, "\t\tif(strcmp(operationName[i], opName) == 0) {\n");
    fprintf(workerFile, "\t\t\topCod=(enum operationCode)i;\n");
    fprintf(workerFile, "\t\t\tbreak;\n");
    fprintf(workerFile, "\t\t}\n");
    fprintf(workerFile, "\t}\n");
    fprintf(workerFile, "\t cout << \"OpCode: \" << (int)opCod << endl;\n");
    fprintf(workerFile, "\n");
  
    // Add end header logger
    fprintf(workerFile, "\t cout << \"--------------------------------------------\"<< endl << endl << flush;\n");
  
  
    fprintf(workerFile, "\t cout << \"data in cache after removal\" << endl;\n");
  
    fprintf(workerFile, "\t for(std::map<std::string, void*>::iterator it = cache.begin(); it != cache.end(); it++){\n");
    fprintf(workerFile, "\t\t cout << it->first << endl;\n");
    fprintf(workerFile, "\t }\n");
  
  
  
  
    // OpCode switch
    fprintf(workerFile, "\t int arg_offset = NUM_INTERNAL_ARGS;\n");
    fprintf(workerFile, "\t switch(opCod)\n");
    fprintf(workerFile, "\t {\n");
  }
  
  void generate_includes_prolog()
  {
    // Include file headers
    char *c;
    fprintf(includeFile, "/* This file must be #included in the actual implementation file. */\n");
    fprintf(includeFile, "/* This file has been autogenerated from '%s'. */\n", get_filename());
    fprintf(includeFile, "/* CHANGES TO THIS FILE WILL BE LOST */\n");
    fprintf(includeFile, "\n");
    fprintf(includeFile, "#ifndef _GSS_");
    for (c = includeName; *c; c++) {
      if (isalnum(*c)) {
        fprintf(includeFile, "%c", toupper(*c));
      } else {
        fprintf(includeFile, "_");
      }
    }
    fprintf(includeFile, "\n");
  
    fprintf(includeFile, "#define _GSS_");
    for (c = includeName; *c; c++) {
      if (isalnum(*c)) {
        fprintf(includeFile, "%c", toupper(*c));
      } else {
        fprintf(includeFile, "_");
      }
    }
    fprintf(includeFile, "\n");
    fprintf(includeFile, "#include <GS_compss.h>\n");
    fprintf(includeFile, "#include <GS_templates.h>\n");
    fprintf(includeFile, "#include <param_metadata.h>\n");
    fprintf(includeFile, "\n");
    fprintf(includeFile, "typedef char* file;\n");
    fprintf(includeFile, "\n");
  
  }
  
  void generate_prolog()
  {
    char name[PATH_MAX];
    
    strncpy(name, get_filename_base(), PATH_MAX);
    strncat(name, "-stubs.cc", PATH_MAX);
    rename_if_clash(name);
    stubsFile = fopen(name, "w");
    if (stubsFile == NULL) {
      fprintf(stderr, "Error: Could not open %s for writing.\n", name);
      exit(1);
    }
    
    strncpy(name, get_filename_base(), PATH_MAX);
    strncat(name, "-executor.cc", PATH_MAX);
    rename_if_clash(name);
    workerFile = fopen(name, "w");
    if (workerFile == NULL) {
      fprintf(stderr, "Error: Could not open %s for writing.\n", name);
      exit(1);
    }
    
    strncpy(includeName, get_filename_base(), PATH_MAX);
    strncat(includeName, ".h", PATH_MAX);
    rename_if_clash(includeName);
    includeFile = fopen(includeName, "w");
    if (includeFile == NULL) {
      fprintf(stderr, "Error: Could not open %s for writing.\n", includeName);
      exit(1);
    }
    
    generate_stubs_prolog();
    
    generate_worker_prolog();
  
    generate_includes_prolog();
   
  }
  
  void generate_executor_end(){
    // Close switch clause
    fprintf(workerFile, "\t }\n");
    fprintf(workerFile, "\n");
    // If this point is reached, no operation has been selected
    // Raise error for incorrect method execution
    fprintf(workerFile, "\t cout << \"Incorrect Operation Code. Aborting...\"<< endl << flush;\n");
    fprintf(workerFile, "\t return -1;\n");
    fprintf(workerFile, "}\n");
  }
  
  void generate_epilogue(void)
  {
    char *c;
    fprintf(includeFile, "\n");
    fprintf(includeFile, "#endif /* _GSS_");
    for (c = includeName; *c; c++) {
      if (isalnum(*c)) {
        fprintf(includeFile, "%c", toupper(*c));
      } else {
        fprintf(includeFile, "_");
      }
    }
    
    fprintf(includeFile, " */\n");
    
    fclose(stubsFile);
    fclose(workerFile);
    fclose(includeFile);
  }
  
  static void generate_enum(FILE *outFile, function *first_function)
  {
    function *func;
    int is_first = 1;
    int n = 0;
    
    fprintf(outFile, "enum operationCode {");
    
    func = first_function;
    while (func != NULL) {
      if (is_first) {
        is_first = 0;
      } else {
        fprintf(outFile, ", ");
      }
      char *func_name = strdup(func->name);
      replace_char(func_name, ':', '_');
      fprintf(outFile, "%sOp", func_name);
      n++;
      func = func->next_function;
    }
    
    fprintf(outFile, "};\n");
    
    is_first = 1;
    
    fprintf(outFile, "static const char *operationName[] = {");
    
    func = first_function;
    while (func != NULL) {
      if (is_first) {
        is_first = 0;
      } else {
        fprintf(outFile, ", ");
      }
      fprintf(outFile, "\"%s\"", func->name);
      func = func->next_function;
    }
    
    fprintf(outFile, "};\n");
  
    // Add constants (according to COMPSs Runtime)
    fprintf(outFile, "static const int N_OPS=%d;\n", n);
    fprintf(outFile, "static const int NUM_BASE_ARGS = 9;\n");
    fprintf(outFile, "static const int MIN_NUM_INTERNAL_ARGS = 13;\n");
    fprintf(outFile, "static const int METHOD_NAME_POS = 7;\n");
    fprintf(outFile ,"\n");
  }
  
  
  static void generate_prototype(FILE *outFile, function *current_function)
  {
    argument *current_argument;
    
    if (current_function->return_type != void_dt ) {
      fprintf(outFile, "%s %s(", current_function->return_typename, current_function->name);
    } else {
      fprintf(outFile, "%s %s(", c_types[current_function->return_type], current_function->name);
    }
    current_argument = current_function->first_argument;
    while (current_argument != NULL) {
      if (current_argument->dir == in_dir) {
        switch (current_argument->type) {
  	case char_dt:
  	case wchar_dt:
  	case boolean_dt:
  	case short_dt:
  	case long_dt:
  	case longlong_dt:
  	case int_dt:
  	case float_dt:
  	case double_dt:
  	  fprintf(outFile, "%s %s", c_out_types[current_argument->type], current_argument->name);
  	  break;
  	case object_dt:
  	  fprintf(outFile, "%s *%s", current_argument->classname, current_argument->name);
  	  break;
  	case string_dt:
  	case wstring_dt:
  	  fprintf(outFile, "%s %s", c_out_types[current_argument->type], current_argument->name);
  	  break;
  	case file_dt:
  	  fprintf(outFile, "%s %s", c_out_types[current_argument->type], current_argument->name);
  	  break;
  	case void_dt:
  	case any_dt:
  	case null_dt:
  	default:;
        }
      } else {
        switch (current_argument->type) {
  	case char_dt:
  	case wchar_dt:
  	case boolean_dt:
  	case short_dt:
  	case long_dt:
  	case longlong_dt:
  	case int_dt:
  	case float_dt:
  	case double_dt:
  	  fprintf(outFile, "%s *%s", c_out_types[current_argument->type], current_argument->name);
  	  break;
  	case object_dt:
  	  fprintf(outFile, "%s *%s", current_argument->classname, current_argument->name);
  	  break;
  	case string_dt:
  	case wstring_dt:
  	  fprintf(outFile, "%s *%s", c_out_types[current_argument->type], current_argument->name);
  	  break;
  	case file_dt:
  	  fprintf(outFile, "%s %s", c_out_types[current_argument->type], current_argument->name);
  	  break;
  	case void_dt:
  	case any_dt:
  	case null_dt:
  	default:;
        }
      }
      current_argument = current_argument->next_argument;
      if (current_argument != NULL) {
        fprintf(outFile, ", ");
      }
    }
    fprintf(outFile, ")");
  }
  
  
  static void generate_remove_and_serialize_case(FILE *outFile, Types current_types)
  {
    int i;
    fprintf(outFile, "void removeData(string id, std::map<std::string, void*>& cache, std::map<std::string, int>& types)\n");
    fprintf(outFile, "{\n"); 
    fprintf(outFile, "\n"); 
  
    fprintf(outFile, "\t cout << \"[C Binding] Removing from cache data \" << id  << endl;\n");
  
    
    //fprintf(outFile, "\t for(std::map<std::string, void*>::iterator it = cache.begin(); it != cache.end(); it++){\n");
    //fprintf(outFile, "\t\t cout << it->first << endl;\n");
    //fprintf(outFile, "\t }\n");
  
    fprintf(outFile, "\t bool found;\n");
    fprintf(outFile, "\t get_compss_worker_lock();\n");
    fprintf(outFile, "\t found = (cache.find(id) != cache.end());\n");
    fprintf(outFile, "\t release_compss_worker_lock();\n");
  
    fprintf(outFile, "\t if (found){\n");
    fprintf(outFile, "\t\t cout << \"[C Binding] Data found in cache \" << endl;\n");
    fprintf(outFile, "\t\t int typeCode = types[id];\n");
    fprintf(outFile, "\t\t switch(typeCode)\n");
    fprintf(outFile, "\t\t {\n");
    for (i=0; i< current_types.num; i++){
  	//remove treatment
  	char * dataType = current_types.types[i];
    	fprintf(outFile, "\t\t\t case %d:\n", i);
  	fprintf(outFile, "\t\t\t\t %s *data_%d;\n", dataType, i);
      fprintf(outFile, "\t\t\t\t get_compss_worker_lock();\n");
  	fprintf(outFile, "\t\t\t\t data_%d = (%s*)cache[id];\n", i , dataType);
  	fprintf(outFile, "\t\t\t\t cout << \"[C Binding] Erasing from cache data structures...\" << endl;\n");
      fprintf(outFile, "\t\t\t\t cache.erase(id);\n");
      fprintf(outFile, "\t\t\t\t types.erase(id);\n");
      fprintf(outFile, "\t\t\t\t release_compss_worker_lock();\n");
  
  	fprintf(outFile, "\t\t\t\t cout << \"[C Binding] Deleting object from memory...\" << endl;\n");
  	fprintf(outFile, "\t\t\t\t delete(data_%d);\n",i);
      fprintf(outFile, "\t\t\t\t cout << \"[C Binding] Object \" << id << \" has been removed from the cache.\" << endl << flush;\n");
  	fprintf(outFile, "\t\t\t\t break;\n");
    }
    fprintf(outFile, "\t\t }\n");
    fprintf(outFile, "\t }\n"); 
  
    //fprintf(outFile, "\t cout << \"data in cache after removal\" << endl;\n");
    //fprintf(outFile, "\t for(std::map<std::string, void*>::iterator it = cache.begin(); it != cache.end(); it++){\n");
    //fprintf(outFile, "\t\t cout << it->first << endl;\n");
    //fprintf(outFile, "\t }\n");
  
  
    fprintf(outFile, "}\n");
    fprintf(outFile, "\n");
  
    fprintf(outFile, "int serializeData(string id, const char* filename, std::map<std::string, void*>& cache, std::map<std::string, int>& types)\n");
    fprintf(outFile, "{\n");
  
    fprintf(outFile, "\n");
    fprintf(outFile, "\t cout << \"[C Binding] serializing from cache data \" << id  << endl;\n");
  
    //Text serialization uncomment and comment binary to change (TODO: Add an ifdef) 
    //fprintf(outFile, "\t ofstream ofs(filename, std::ofstream::trunc);\n");
    //fprintf(outFile, "\t archive::text_oarchive oa(ofs);\n");
    //Binary serialization
    fprintf(outFile, "\t ofstream ofs(filename, std::ofstream::trunc | std::ios::binary);\n");
    fprintf(outFile, "\t archive::binary_oarchive oa(ofs);\n");
  
  
  
    fprintf(outFile, "\t bool found;\n");
    fprintf(outFile, "\t get_compss_worker_lock();\n");
    fprintf(outFile, "\t found = (cache.find(id) != cache.end());\n");
    fprintf(outFile, "\t release_compss_worker_lock();\n");
  
    fprintf(outFile, "\t if (found){\n");
    fprintf(outFile, "\t\t get_compss_worker_lock();\n");
    fprintf(outFile, "\t\t int typeCode = types[id];\n");
    fprintf(outFile, "\t\t release_compss_worker_lock();\n");
  
  
    fprintf(outFile, "\t\t switch(typeCode)\n");
    fprintf(outFile, "\t\t {\n");
  
    for (i=0; i< current_types.num; i++){
  	//serialize treatment
  	char * dataType = current_types.types[i];
  	fprintf(outFile, "\t\t\t case %d:\n", i);
  	fprintf(outFile, "\t\t\t\t cout << \"[C Binding] Object \" << id << \" is about to be serialized.\" << endl << flush;\n");
      fprintf(outFile, "\t\t\t\t %s *data_%d;\n", dataType, i);
      fprintf(outFile, "\t\t\t\t get_compss_worker_lock();\n");
      fprintf(outFile, "\t\t\t\t data_%d = (%s*)cache[id];\n", i, dataType);
      fprintf(outFile, "\t\t\t\t release_compss_worker_lock();\n");
  	fprintf(outFile, "\t\t\t\t oa << *data_%d;\n", i);
  	fprintf(outFile, "\t\t\t\t cout << \"[C Binding] Object \" << id << \" has been serialized.\" << endl << flush;\n");
      fprintf(outFile, "\t\t\t\t break;\n");
    }
  
    fprintf(outFile, "\t\t }\n");
    fprintf(outFile, "\t }\n");
    fprintf(outFile, "\t ofs.flush();\n");
    fprintf(outFile, "\t ofs.close();\n");
  
    fprintf(outFile, "}\n");
    fprintf(outFile, "\n");
  }
  
  
  static void generate_class_includes_and_check_types(FILE *outFile, Types *current_types, function *current_function)
  {
    argument *current_argument;
    if (current_function->classname != NULL){
  	if (!containsType(current_function->classname, *(current_types))){
                  addType(current_function->classname, current_types);
  		fprintf(outFile, "#include \"%s.h\";\n", current_function->classname);
  	}
    }
    if (current_function->return_type == object_dt){
  	if (!containsType(current_function->return_typename, *(current_types))){
                  addType(current_function->return_typename, current_types);
  		fprintf(outFile, "#include \"%s.h\";\n", current_function->return_typename);
  	}
    }  
    current_argument = current_function->first_argument;
    while (current_argument != NULL) {
      if (current_argument->type == object_dt) {
  	if (!containsType(current_argument->classname, *(current_types))){
  		addType(current_argument->classname, current_types);
  		fprintf(outFile, "#include \"%s.h\";\n", current_argument->classname);
  	}
      }
      current_argument = current_argument->next_argument;
    }
  }
  
  static void generate_parameter_buffers(FILE *outFile, function *func)
  {
    int k = 0;
    //There is a target object
    if (( func->classname != NULL ) && (func->access_static == 0)) k = k + 5;
    //There is a return type
    if ( func->return_type != void_dt ) k = k + 5;
    
    fprintf(outFile, "\t void *arrayObjs[%d];\n", k + func->argument_count * 5);
    fprintf(outFile, "\t int found;\n");
    fprintf(outFile, "\n");
  }
  
  static void add_object_arg_master_treatment(FILE *outFile, argument *arg, int i)
  {
  	fprintf(outFile, "\t char *%s_filename;\n", arg->name);
          fprintf(outFile, "\t found = GS_register(%s, (datatype)%d, (direction)%d, \"%s\", %s_filename);\n", arg->name, arg->type, arg->dir, arg->classname, arg->name);
  	if (( arg->dir == in_dir) || (arg->dir == inout_dir)){
            	fprintf(outFile, "\t if (!found) {\n");
            	fprintf(outFile, "\t\t debug_printf(\"Object not found in registry. Serializing to %%s \\n\", %s_filename);\n" , arg->name);
  		//Text serialization uncomment and comment binary to change (TODO: Add an ifdef) 
  //          	fprintf(outFile, "\t\t ofstream %s_ofs(%s_filename, std::ofstream::trunc);\n", arg->name, arg->name);
  //              fprintf(outFile, "\t\t archive::text_oarchive %s_oa(%s_ofs);\n", arg->name, arg->name);
  		//Added for binary serialization
  		fprintf(outFile, "\t\t ofstream %s_ofs(%s_filename, std::ofstream::trunc | std::ios::binary);\n", arg->name, arg->name);
            	fprintf(outFile, "\t\t archive::binary_oarchive %s_oa(%s_ofs);\n", arg->name, arg->name);
            	if (arg->type == string_dt || arg->type == wstring_dt){
  			fprintf(outFile, "\t\t string %s_out_string (*%s);\n", arg->name, arg->name);
  		        fprintf(outFile, "\t\t %s_oa << %s_out_string;\n", arg->name, arg->name);
  		} else {
  			fprintf(outFile, "\t\t %s_oa << *%s;\n", arg->name, arg->name);
  		}
            	fprintf(outFile, "\t\t %s_ofs.flush();\n", arg->name);
            	fprintf(outFile, "\t\t %s_ofs.close();\n", arg->name);
            	fprintf(outFile, "\t }\n");
  	}
          fprintf(outFile, "\t arrayObjs[%d] = &%s_filename;\n", i, arg->name);
          fprintf(outFile, "\t int param%d = %d;\n", i+1, file_dt);
          fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+1, i+1);
          fprintf(outFile, "\t int param%d = %d;\n", i+2, arg->dir);
          fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+2, i+2);
          fprintf(outFile, "\t int param%d = %d;\n", i+3, 3);
          fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+3, i+3);
          fprintf(outFile, "\t char *param%d = \"null\";\n", i+4);
          fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+4, i+4);
  	
  }
  
  static void add_other_arg_master_treatment(FILE *outFile, argument *arg, int i)
  {
  
  	if ( arg->dir == in_dir){
  	  fprintf(outFile, "\t arrayObjs[%d] = &%s;\n", i, arg->name);
  	  fprintf(outFile, "\t int param%d = %d;\n", i+1, arg->type);
            fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+1, i+1);
            fprintf(outFile, "\t int param%d = %d;\n", i+2, arg->dir);
            fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+2, i+2);
            fprintf(outFile, "\t int param%d = %d;\n", i+3, 3);
            fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+3, i+3);
            fprintf(outFile, "\t char *param%d = \"null\";\n", i+4);
            fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+4, i+4);
  	}else{
  	  switch (arg->type) {
          	case char_dt:
          	case wchar_dt:
          	case boolean_dt:
          	case short_dt:
          	case long_dt:
          	case longlong_dt:
          	case int_dt:
          	case float_dt:
          	case double_dt:
          	case object_dt:
          	case string_dt:
          	case wstring_dt:
            		add_object_arg_master_treatment(outFile,arg,i);
  			break;
          	case file_dt:
            		fprintf(outFile, "\t arrayObjs[%d] = &%s;\n", i, arg->name);
            		fprintf(outFile, "\t int param%d = %d;\n", i+1, arg->type);
            		fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+1, i+1);
            		fprintf(outFile, "\t int param%d = %d;\n", i+2, arg->dir);
            		fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+2, i+2);
                          fprintf(outFile, "\t int param%d = %d;\n", i+3, 3);
      			fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+3, i+3);
      			fprintf(outFile, "\t char *param%d = \"null\";\n", i+4);
      			fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+4, i+4);
            		break;
          	case void_dt:
          	case any_dt:
          	case null_dt:
          	default:;
  	  }
        	}
  		
  
  }
  
  static void generate_parameter_marshalling(FILE *outFile, function *func)
  {
    argument *arg;
    int j = 0;
    int i = 0;
    
    if (( func->classname != NULL ) && (func->access_static == 0)){
      i = j*5;
      fprintf(outFile, "\t char *this_filename;\n");
      fprintf(outFile, "\t found = GS_register(this, (datatype)%d, (direction)%d, \"%s\", this_filename);\n", object_dt, inout_dir, func->classname);
      fprintf(outFile, "\t if (!found) {\n");
      fprintf(outFile, "\t\t cout << \"Target object not found in registry. Serializing to \" << this_filename << endl << flush;\n");
      //Text serialization uncomment and comment binary to change (TODO: Add an ifdef) 
  //    fprintf(outFile, "\t\t ofstream this_ofs(this_filename, std::ofstream::trunc);\n");
  //    fprintf(outFile, "\t\t archive::text_oarchive this_oa(this_ofs);\n");
      //Added for binary serialization
      fprintf(outFile, "\t\t ofstream this_ofs(this_filename, std::ofstream::trunc | std::ios::binary);\n");
      fprintf(outFile, "\t\t archive::binary_oarchive this_oa(this_ofs);\n");
  
      fprintf(outFile, "\t\t this_oa << *this;\n");
      fprintf(outFile, "\t\t this_ofs.flush();\n");
      fprintf(outFile, "\t\t this_ofs.close();\n");
      fprintf(outFile, "\t }\n");
      
      fprintf(outFile, "\t arrayObjs[%d] = &this_filename;\n", i);
      
      fprintf(outFile, "\t int param%d = %d;\n", i+1, file_dt);
      fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+1, i+1);
      
      fprintf(outFile, "\t int param%d = %d;\n", i+2, inout_dir);
      fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+2, i+2);
     
      fprintf(outFile, "\t int param%d = %d;\n", i+3, 3);
      fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+3, i+3);
  
      fprintf(outFile, "\t char *param%d = \"null\";\n", i+4);
      fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+4, i+4);
      
      fprintf(outFile, "\n");
      j++;
    }
    
    if ( func->return_type != void_dt ){
      //i = j*3;
      i = j*5;
      fprintf(outFile, "\t %s return_object;\n", func->return_typename);
      fprintf(outFile, "\t char *return_filename;\n");
      fprintf(outFile, "\t found = GS_register(&return_object, (datatype)%d, (direction)%d, \"%s\", return_filename);\n", object_dt, out_dir, func->return_typename);
      //TODO: Return type should not be serialized
      fprintf(outFile, "\t if (!found) {\n");
      fprintf(outFile, "\t\t cout << \"Return object not found in registry. Serializing to \" << return_filename << endl << flush;\n");
      //Text serialization uncomment and comment binary to change (TODO: Add an ifdef) 
  //    fprintf(outFile, "\t\t ofstream return_ofs(return_filename, std::ofstream::trunc);\n");
  //    fprintf(outFile, "\t\t archive::text_oarchive return_oa(return_ofs);\n");
      //Added for binary serialization
      fprintf(outFile, "\t\t ofstream return_ofs(return_filename, std::ofstream::trunc | std::ios::binary);\n");
      fprintf(outFile, "\t\t archive::binary_oarchive return_oa(return_ofs);\n");
      fprintf(outFile, "\t\t return_oa << return_object;\n");
      fprintf(outFile, "\t\t return_ofs.flush();\n");
      fprintf(outFile, "\t\t return_ofs.close();\n");
      fprintf(outFile, "\t }\n");
      
      fprintf(outFile, "\t arrayObjs[%d] = &return_filename;\n", i);
      
      fprintf(outFile, "\t int param%d = %d;\n", i+1, file_dt);
      fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+1, i+1);
      
      fprintf(outFile, "\t int param%d = %d;\n", i+2, out_dir);
      fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+2, i+2);
      
      fprintf(outFile, "\t int param%d = %d;\n", i+3, 3);
      fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+3, i+3);
  
      fprintf(outFile, "\t char *param%d = \"null\";\n", i+4);
      fprintf(outFile, "\t arrayObjs[%d] = &param%d;\n", i+4, i+4);
   
      fprintf(outFile, "\n");
      j++;
    }
    
    
    arg = func->first_argument;
    while (arg != NULL) {
      i = j*5;
      //i = j*3;
        switch (arg->type) {
  	case char_dt:
  	case wchar_dt:
  	case boolean_dt:
  	case short_dt:
  	case long_dt:
  	case longlong_dt:
  	case int_dt:
  	case float_dt:
  	case double_dt:
  	case string_dt:
          case wstring_dt:
  	case file_dt:
  		add_other_arg_master_treatment(outFile,arg,i);
  		break;
  	case object_dt:
  		add_object_arg_master_treatment(outFile,arg,i);
  	  	break;
  	case void_dt:
  	case any_dt:
  	case null_dt:
  	default:;
        }
      
      
      fprintf(outFile, "\n");
      
      arg = arg->next_argument;
      j++;
    }
    
    fprintf(outFile, "\n");
  }
  
  static void generate_execute_call(FILE *outFile, function *func)
  {
    char *appId = "0L";
    char *class_name = strdup("NULL");
    char *hasTarget = strdup("false");
    
    int arg_count = func->argument_count;
    
    if ( func->classname != NULL ){
  	class_name = func->classname; 
  	if (func->access_static == 0) {
  		arg_count++;
          	hasTarget = strdup("true");
  	}
    }
  
    if ( func->return_type != void_dt ) arg_count++;
    
    fprintf(outFile, "\t char *method_name = strdup(\"%s\");\n", func->name);
    
    fprintf(outFile, "\t GS_ExecuteTask(0L, \"%s\", method_name, 0, %s, %d, (void**)arrayObjs);\n", class_name, hasTarget, arg_count);
    fprintf(outFile, "\t debug_printf(\"[   BINDING]  -  @%%s  -  Task submited in the runtime\\n\", method_name);\n"); 
    fprintf(outFile, "\n");
    
    if ( func->return_type != void_dt ){
  	if ( func->return_type != object_dt){
      		fprintf(outFile, "\t debug_printf(\"[   BINDING]  -  @%%s  -  Implicit synchronization of return value\\n\", method_name);\n");
      		fprintf(outFile, "\t compss_wait_on(return_object);\n");
  	}
      	fprintf(outFile, "\n\t return return_object;\n");
      	fprintf(outFile, "\n");
    }
    fprintf(outFile, "\t debug_printf(\"[   BINDING]  -  @%%s  -  Free method name\\n\", method_name);\n");
    fprintf(outFile, "\t free(method_name);\n");
    fprintf(outFile, "\t debug_printf(\"[   BINDING]  -  End of task submission.\\n\");\n");
    
  }
  
  static void add_object_arg_worker_treatment(FILE *outFile, argument *arg, int initOffset, Types current_types)
  {
  	fprintf(outFile, "\t\t\t cout << \"[C Binding] Treating object %s ...\" << endl << flush;\n", arg->name);
  	fprintf(outFile, "\t\t\t arg_offset += %d;\n", initOffset);
          fprintf(outFile, "\t\t\t char* %s_filename_og = strdup(argv[arg_offset]);\n", arg->name);
          fprintf(outFile, "\t\t\t char* %s_filename, *%s_orig_id, *%s_dest_id, *%s_pres_data, *%s_write_data;\n", arg->name, arg->name, arg->name, arg->name, arg->name);
  	fprintf(outFile, "\t\t\t %s_filename = %s_filename_og ;\n", arg->name, arg->name);
          fprintf(outFile, "\t\t\t %s_orig_id = strsep(&%s_filename,\":\");\n", arg->name, arg->name);
  	fprintf(outFile, "\t\t\t cout << \"[C Binding] Checking object data id for %s ...\" << endl << flush;\n", arg->name);
          //Check if there is data id information in the value
  	fprintf(outFile, "\t\t\t if (%s_orig_id != NULL && %s_filename != NULL){ \n", arg->name, arg->name);
  	// There is data information
  	fprintf(outFile, "\t\t\t\t cout << \"[C Binding] Managing object data id for %s ...\" << endl << flush;\n", arg->name);
          fprintf(outFile, "\t\t\t\t %s_dest_id = strsep(&%s_filename,\":\");\n", arg->name, arg->name);
          fprintf(outFile, "\t\t\t\t %s_pres_data = strsep(&%s_filename,\":\");\n", arg->name, arg->name);
          fprintf(outFile, "\t\t\t\t %s_write_data = strsep(&%s_filename,\":\");\n", arg->name, arg->name);
  	
          fprintf(outFile, "\t\t\t\t string %s_orig_id_str(%s_orig_id);\n", arg->name, arg->name);
          fprintf(outFile, "\t\t\t\t string %s_dest_id_str(%s_dest_id);\n", arg->name, arg->name);
  	int position = getTypeNumber(arg->classname, current_types);
          if (position < 0){
                printf("ERROR: Position for type %s not found", arg->classname);
  	      exit(1);
          }
  	switch (arg->dir){
  	    case in_dir: 
  		//when argument is in
  		fprintf(outFile, "\t\t\t\t cout << \"[C Binding] Checking if object %s with id \"<< %s_orig_id_str << \" is in cache.\" << endl << flush;\n", arg->name, arg->name);
  
          fprintf(outFile, "\t\t\t\t bool found;\n");
          fprintf(outFile, "\t\t\t\t get_compss_worker_lock();\n");
          fprintf(outFile, "\t\t\t\t found = (cache.find(%s_orig_id_str) != cache.end());\n", arg->name);
          fprintf(outFile, "\t\t\t\t release_compss_worker_lock();\n");
  
          fprintf(outFile, "\t\t\t\t if (!found){\n");
          fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Deserializing object %s.\" << endl << flush;\n", arg->name);
  		//Text serialization uncomment and comment binary to change (TODO: Add an ifdef) 
  //        	fprintf(outFile, "\t\t\t\t\t ifstream %s_ifs(%s_filename);\n", arg->name, arg->name);
  //        	fprintf(outFile, "\t\t\t\t\t archive::text_iarchive %s_ia(%s_ifs);\n", arg->name, arg->name);
  		//Added for binary serialization
          	fprintf(outFile, "\t\t\t\t\t ifstream %s_ifs(%s_filename, std::ios::binary);\n", arg->name, arg->name);
                  fprintf(outFile, "\t\t\t\t\t archive::binary_iarchive %s_ia(%s_ifs);\n", arg->name, arg->name);
  		if (arg->type == string_dt || arg->type == wstring_dt){
  			fprintf(outFile, "\t\t\t\t\t string %s_in_string;\n", arg->name);
            		fprintf(outFile, "\t\t\t\t\t %s_ia >> %s_in_string;\n", arg->name, arg->name);
            		fprintf(outFile, "\t\t\t\t\t %s_ifs.close();\n", arg->name);
            		fprintf(outFile, "\t\t\t\t\t %s = strdup(%s_in_string.c_str());\n", arg->name, arg->name);
  		} else {
  			fprintf(outFile, "\t\t\t\t\t %s_ia >> *%s;\n", arg->name, arg->name);
          		fprintf(outFile, "\t\t\t\t\t %s_ifs.close();\n", arg->name);
  		}
  		//cache treatment
          fprintf(outFile, "\t\t\t\t\t get_compss_worker_lock();\n");
         	fprintf(outFile, "\t\t\t\t\t cache[%s_dest_id_str] = (void*)%s;\n", arg->name, arg->name);
  		fprintf(outFile, "\t\t\t\t\t types[%s_dest_id_str] = %d;\n", arg->name, position);
          fprintf(outFile, "\t\t\t\t\t release_compss_worker_lock();\n");
         	fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Object \" << %s_dest_id_str << \" has been added to the cache with type %d.\" << endl << flush;\n", arg->name, position);
         	fprintf(outFile, "\t\t\t\t } else {\n");
          fprintf(outFile, "\t\t\t\t\t get_compss_worker_lock();\n");
         	fprintf(outFile, "\t\t\t\t\t %s = (%s*)cache[%s_orig_id_str];\n", arg->name, arg->classname, arg->name);
          fprintf(outFile, "\t\t\t\t\t release_compss_worker_lock();\n");
         	fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Object \" << %s_orig_id_str << \" has been read from the cache.\" << endl << flush;\n", arg->name);
  		fprintf(outFile, "\t\t\t\t }\n");
          
  		/*fprintf(outFile, "\t\t\t\t if (serializeOuts < 1){\n");
  		fprintf(outFile, "\t\t\t\t\t remove(%s_dest_id);\n", arg->name);
          	fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] removed file \" <<  %s_dest_id << endl;\n", arg->name);
  		fprintf(outFile, "\t\t\t\t }\n");*/
  
  		break;
  	    case inout_dir:
          	//when argument is inout
  		fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Checking object %s with id \"<< %s_orig_id_str << \" and preserve_data \" << %s_pres_data << \" is in cache.\" << endl << flush;\n", arg->name, arg->name, arg->name);
  //		fprintf(outFile, "\t\t\t\t if ((string(%s_pres_data) == \"true\")|| (cache.find(%s_orig_id_str) == cache.end())){\n", arg->name, arg->name, arg->name);
  
          fprintf(outFile, "\t\t\t\t bool found;\n");
          fprintf(outFile, "\t\t\t\t get_compss_worker_lock();\n");
          fprintf(outFile, "\t\t\t\t found = (cache.find(%s_orig_id_str) != cache.end());\n", arg->name);
          fprintf(outFile, "\t\t\t\t release_compss_worker_lock();\n");
  
          fprintf(outFile, "\t\t\t\t if (!found){\n");
  	  	fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Deserializing object %s.\" << endl << flush;\n", arg->name);
  		//Text serialization uncomment and comment binary to change (TODO: Add an ifdef) 
  //		fprintf(outFile, "\t\t\t\t\t ifstream %s_ifs(%s_filename);\n", arg->name, arg->name);
  //          	fprintf(outFile, "\t\t\t\t\t archive::text_iarchive %s_ia(%s_ifs);\n", arg->name, arg->name);
                  //Added for binary serialization
  		fprintf(outFile, "\t\t\t\t\t ifstream %s_ifs(%s_filename, std::ios::binary);\n", arg->name, arg->name);
                  fprintf(outFile, "\t\t\t\t\t archive::binary_iarchive %s_ia(%s_ifs);\n", arg->name, arg->name);
            	if (arg->type == string_dt || arg->type == wstring_dt){
                          fprintf(outFile, "\t\t\t\t\t string %s_in_string;\n", arg->name);
  			fprintf(outFile, "\t\t\t cout << \"[C Binding] Object \" << id << \" about to be serialized as input.\" << endl << flush;\n");
                          fprintf(outFile, "\t\t\t\t\t %s_ia >> %s_in_string;\n", arg->name, arg->name);
                          fprintf(outFile, "\t\t\t\t\t %s_ifs.close();\n", arg->name);
  			fprintf(outFile, "\t\t\t cout << \"[C Binding] Object has been serialized as input.\" << endl << flush;\n");
                          fprintf(outFile, "\t\t\t\t\t %s = strdup(%s_in_string.c_str());\n", arg->name, arg->name);
                  } else {
                          fprintf(outFile, "\t\t\t\t\t %s_ia >> *%s;\n", arg->name, arg->name);
                          fprintf(outFile, "\t\t\t\t\t %s_ifs.close();\n", arg->name);
                  }
  		//cache treatment
          fprintf(outFile, "\t\t\t\t\t get_compss_worker_lock();\n");
          fprintf(outFile, "\t\t\t\t\t cache[%s_dest_id_str] = (void*)%s;\n", arg->name, arg->name);
          fprintf(outFile, "\t\t\t\t\t types[%s_dest_id_str] = %d;\n", arg->name, position);
          fprintf(outFile, "\t\t\t\t\t release_compss_worker_lock();\n");
          fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Object \" << %s_dest_id_str << \" has been added to the cache with type %d.\" << endl << flush;\n", arg->name, position);
  
  	    fprintf(outFile, "\t\t\t\t } else if (string(%s_pres_data) == \"true\"){\n", arg->name, arg->name, arg->name);     
  		fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Deserializing object %s.\" << endl << flush;\n", arg->name);
  		//Text serialization uncomment and comment binary to change (TODO: Add an ifdef) 
  //        	fprintf(outFile, "\t\t\t\t\t ifstream %s_ifs(%s_orig_id);\n", arg->name, arg->name);
  //            	fprintf(outFile, "\t\t\t\t\t archive::text_iarchive %s_ia(%s_ifs);\n", arg->name, arg->name);
                  //Added for binary serialization
  
      fprintf(outFile, "\t\t\t\t\t if (found){\n");
      fprintf(outFile, "\t\t\t\t\t\t ofstream %s_ofs(%s_orig_id, std::ios::binary);\n", arg->name, arg->name);
      fprintf(outFile, "\t\t\t\t\t\t archive::binary_oarchive %s_oa(%s_ofs);\n", arg->name, arg->name);
  
      fprintf(outFile, "\t\t\t\t %s *o_data;\n", arg->classname);
      fprintf(outFile, "\t\t\t\t get_compss_worker_lock();\n");
      fprintf(outFile, "\t\t\t\t o_data = (%s*)cache[%s_orig_id];\n", arg->classname, arg->name);
      fprintf(outFile, "\t\t\t\t release_compss_worker_lock();\n");
      fprintf(outFile, "\t\t\t\t %s_oa << *o_data;\n", arg->name);
  
  //    fprintf(outFile, "\t\t\t\t\t\t %s_oa << *%s;\n", arg->name, arg->name);
      fprintf(outFile, "\t\t\t\t\t\t %s_ofs.flush();\n", arg->name);
      fprintf(outFile, "\t\t\t\t\t\t %s_ofs.close();\n", arg->name);
      fprintf(outFile, "\t\t\t\t\t }\n");
  
  
  
  	        fprintf(outFile, "\t\t\t\t\t ifstream %s_ifs(%s_orig_id, std::ios::binary);\n", arg->name, arg->name);
                  fprintf(outFile, "\t\t\t\t\t archive::binary_iarchive %s_ia(%s_ifs);\n", arg->name, arg->name);
                  if (arg->type == string_dt || arg->type == wstring_dt){
                      	fprintf(outFile, "\t\t\t\t\t string %s_in_string;\n", arg->name);
                      	fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Object \" << id << \" about to be serialized as input.\" << endl << flush;\n");
                          fprintf(outFile, "\t\t\t\t\t %s_ia >> %s_in_string;\n", arg->name, arg->name);
                          fprintf(outFile, "\t\t\t\t\t %s_ifs.close();\n", arg->name);
                          fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Object has been serialized as input.\" << endl << flush;\n");
                          fprintf(outFile, "\t\t\t\t\t %s = strdup(%s_in_string.c_str());\n", arg->name, arg->name);
                  } else {
                          fprintf(outFile, "\t\t\t\t\t %s_ia >> *%s;\n", arg->name, arg->name);
                          fprintf(outFile, "\t\t\t\t\t %s_ifs.close();\n", arg->name);
                  }
              //cache treatment
                  fprintf(outFile, "\t\t\t\t\t get_compss_worker_lock();\n");
                  fprintf(outFile, "\t\t\t\t\t cache[%s_dest_id_str] = (void*)%s;\n", arg->name, arg->name);
                  fprintf(outFile, "\t\t\t\t\t types[%s_dest_id_str] = %d;\n", arg->name, position);
                  fprintf(outFile, "\t\t\t\t\t release_compss_worker_lock();\n");
                  fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Object \" << %s_dest_id_str << \" has been added to the cache with type %d.\" << endl << flush;\n", arg->name, position);
  
            	fprintf(outFile, "\t\t\t\t } else {\n");
            	fprintf(outFile, "\t\t\t\t\t %s = (%s*)cache[%s_orig_id_str];\n", arg->name, arg->classname, arg->name);
  		fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Object \" << %s_orig_id_str << \" has been read from the cache.\" << endl << flush;\n", arg->name);
  
              fprintf(outFile, "\t\t\t\t\t get_compss_worker_lock();\n");
            	fprintf(outFile, "\t\t\t\t\t if (string(%s_pres_data) == \"false\"){\n", arg->name);
          	fprintf(outFile, "\t\t\t\t\t\t cache.erase(%s_orig_id_str);\n", arg->name);
  		fprintf(outFile, "\t\t\t\t\t\t types.erase(%s_orig_id_str);\n", arg->name);
          	fprintf(outFile, "\t\t\t\t\t\t cout << \"[C Binding] Object \" << %s_orig_id_str << \" has been removed from the cache.\" << endl << flush;\n", arg->name);
          	fprintf(outFile, "\t\t\t\t\t }\n");
            	fprintf(outFile, "\t\t\t\t\t cache[%s_dest_id_str] = (void*)%s;\n", arg->name, arg->name);
  		fprintf(outFile, "\t\t\t\t\t types[%s_dest_id_str] = %d;\n", arg->name, position);
            	fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Object \" << %s_dest_id_str << \" has been added to the cache with type %d.\" << endl << flush;\n", arg->name, position);
              fprintf(outFile, "\t\t\t\t\t release_compss_worker_lock();\n");
  
            	fprintf(outFile, "\t\t\t\t }\n");
  		fprintf(outFile, "\t\t\t\t if (serializeOuts < 1){\n");
  		fprintf(outFile, "\t\t\t\t\t remove(%s_dest_id);\n", arg->name);
              	fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Removed file \" << %s_dest_id << endl;\n", arg->name);
  		fprintf(outFile, "\t\t\t\t }\n");
  
  		break;
  	    case out_dir:
  		//when argument is out
          fprintf(outFile, "\t\t\t\t\t get_compss_worker_lock();\n");
  		fprintf(outFile, "\t\t\t\t cache[%s_dest_id_str] = (void*)%s;\n", arg->name, arg->name);
  		fprintf(outFile, "\t\t\t\t types[%s_dest_id_str] = %d;\n", arg->name, position);
          fprintf(outFile, "\t\t\t\t\t release_compss_worker_lock();\n");
        		fprintf(outFile, "\t\t\t\t cout << \"[C Binding] Object \" << %s_dest_id_str << \" has been added to the cache with type %d.\" << endl << flush;\n", arg->name, position);
  		fprintf(outFile, "\t\t\t\t if (serializeOuts < 1){\n");
                  fprintf(outFile, "\t\t\t\t\t remove(%s_dest_id);\n", arg->name);
                  fprintf(outFile, "\t\t\t\t\t cout << \"[C Binding] Removed file \" << %s_dest_id << endl;\n", arg->name);
                  fprintf(outFile, "\t\t\t\t }\n");
  
  		break;
  	    default:;
  		
  	}
  
  	//No data information case (required for GAT Adaptor)
  	fprintf(outFile, "\t\t\t } else {\n");
  	fprintf(outFile, "\t\t\t\t cout << \"[C Binding] Data ID not found in argument value. Reseting filename \" << endl << flush;\n", arg->name);
  	fprintf(outFile, "\t\t\t\t %s_filename = %s_filename_og ;\n", arg->name, arg->name);
  	switch (arg->dir){
              case in_dir:
  	    case inout_dir:
  		//Text serialization uncomment and comment binary to change (TODO: Add an ifdef)
  //		fprintf(outFile, "\t\t\t\t\t ifstream %s_ifs(%s_filename);\n", arg->name, arg->name);
  //              fprintf(outFile, "\t\t\t\t\t archive::text_iarchive %s_ia(%s_ifs);\n", arg->name, arg->name);
  		//Added for binary serialization
  		fprintf(outFile, "\t\t\t\t\t ifstream %s_ifs(%s_filename, std::ios::binary);\n", arg->name, arg->name);
                  fprintf(outFile, "\t\t\t\t\t archive::binary_iarchive %s_ia(%s_ifs);\n", arg->name, arg->name);
                  if (arg->type == string_dt || arg->type == wstring_dt){
                          fprintf(outFile, "\t\t\t\t\t string %s_in_string;\n", arg->name);
                          fprintf(outFile, "\t\t\t\t\t %s_ia >> %s_in_string;\n", arg->name, arg->name);
                          fprintf(outFile, "\t\t\t\t\t %s_ifs.close();\n", arg->name);
                          fprintf(outFile, "\t\t\t\t\t %s = strdup(%s_in_string.c_str());\n", arg->name, arg->name);
                  } else {
                          fprintf(outFile, "\t\t\t\t\t %s_ia >> *%s;\n", arg->name, arg->name);
                          fprintf(outFile, "\t\t\t\t\t %s_ifs.close();\n", arg->name);
                  }
  	    break;
  	}
  	fprintf(outFile, "\t\t\t }\n");
          fprintf(outFile, "\t\t\t\t arg_offset += 1;\n\n");
  }
  
  static void add_file_arg_worker_treatment(FILE *outFile, argument *arg)
  {
          fprintf(outFile, "\t\t\t arg_offset += 3;\n");
  	fprintf(outFile, "\t\t\t %s_og = strdup(argv[arg_offset]);\n", arg->name);
          fprintf(outFile, "\t\t\t char *%s, *%s_orig_id, *%s_dest_id, *%s_pres_data, *%s_write_data;\n", arg->name, arg->name, arg->name, arg->name, arg->name);
  	fprintf(outFile, "\t\t\t %s = %s_og;\n", arg->name, arg->name);
  	fprintf(outFile, "\t\t\t %s_orig_id = strsep(&%s,\":\");\n", arg->name, arg->name);
  	fprintf(outFile, "\t\t\t if (%s_orig_id != NULL && %s != NULL){ \n", arg->name, arg->name);
          fprintf(outFile, "\t\t\t\t %s_dest_id = strsep(&%s,\":\");\n", arg->name, arg->name);
          fprintf(outFile, "\t\t\t\t %s_pres_data = strsep(&%s,\":\");\n", arg->name, arg->name);
          fprintf(outFile, "\t\t\t\t %s_write_data = strsep(&%s,\":\");\n", arg->name, arg->name);
  	fprintf(outFile, "\t\t\t } else {\n");
  	fprintf(outFile, "\t\t\t\t %s = %s_og;\n", arg->name, arg->name);
  	fprintf(outFile, "\t\t\t }\n");
          fprintf(outFile, "\t\t\t arg_offset += 1;\n\n");
  }
  
  static void add_other_arg_worker_treatment(FILE *outFile, argument *arg, Types current_types){
        // arg_offset -> type
        // arg_offset+1 -> stream
        // arg_offset+2 -> prefix
        // arg_offset+3 -> value
        if (arg->dir == in_dir){
  	fprintf(outFile, "\t\t\t arg_offset += 3;\n");
  	switch (arg->type) {
          	case char_dt:
          	case wchar_dt:
  			fprintf(outFile, "\t\t\t %s = argv[arg_offset][0];\n", arg->name);
  			break;	
          	case boolean_dt:
            		fprintf(outFile, "\t\t\t %s = argv[arg_offset]? 1 : 0;\n", arg->name);
            		break;
  		case int_dt:
          	case short_dt:
            		fprintf(outFile, "\t\t\t %s = atoi(argv[arg_offset]);\n", arg->name);
            		break;
          	case long_dt:
            		fprintf(outFile, "\t\t\t %s = atol(argv[arg_offset]);\n", arg->name);
            		break;
          	case longlong_dt:
            		fprintf(outFile, "\t\t\t %s = atoll(argv[arg_offset]);\n", arg->name);
            		break;
          	case float_dt:
            		fprintf(outFile, "\t\t\t %s = strtof(argv[arg_offset], NULL);\n", arg->name);
            		break;
          	case double_dt:
            		fprintf(outFile, "\t\t\t %s = strtod(argv[arg_offset], NULL);\n", arg->name);
            		break;
          	case string_dt:
          	case wstring_dt:
            		fprintf(outFile, "\t\t\t int %s_nwords = atoi(argv[arg_offset]);\n", arg->name);
            		fprintf(outFile, "\t\t\t int word_i;\n");
            		fprintf(outFile, "\t\t\t int %s_size = 0;\n", arg->name);
            		fprintf(outFile, "\t\t\t for (word_i=1; word_i<=%s_nwords; word_i++) {\n", arg->name);
            		fprintf(outFile, "\t\t\t\t %s_size += strlen(argv[arg_offset + word_i]);\n", arg->name);
            		fprintf(outFile, "\t\t\t }\n");
            		fprintf(outFile, "\t\t\t %s = (char *) malloc(%s_size + %s_nwords);\n", arg->name,arg->name,arg->name);
            		fprintf(outFile, "\t\t\t for (word_i=1; word_i<=%s_nwords; word_i++) {\n", arg->name);
            		fprintf(outFile, "\t\t\t\t arg_offset += 1;\n");
  			fprintf(outFile, "\t\t\t\t if (word_i == 1)\n");
            		fprintf(outFile, "\t\t\t\t\t strcpy(%s, argv[arg_offset]);\n", arg->name);
            		fprintf(outFile, "\t\t\t\t else {\n");
            		fprintf(outFile, "\t\t\t\t\t strcat(%s, \" \");\n", arg->name);
            		fprintf(outFile, "\t\t\t\t\t strcat(%s, argv[arg_offset]);\n", arg->name);
            		fprintf(outFile, "\t\t\t\t }\n");
            		fprintf(outFile, "\t\t\t }\n");
            		break;
  		default:;
        	}
  	fprintf(outFile, "\t\t\t arg_offset += 1;\n\n");
        }else{
  	add_object_arg_worker_treatment(outFile, arg,3, current_types);
        }		
  }
  
  static void generate_worker_case(FILE *outFile, Types current_types, function *func)
  {
    argument *arg;
    int j = 0;
    int is_first_arg = 1;
    
    char *func_name = strdup(func->name);
    replace_char(func_name, ':', '_');
    fprintf(outFile, "\t case %sOp:\n", func_name);
    fprintf(outFile, "\t\t {\n");
    printf("\t\t Adding parameter unmarshalling...\n");
    fflush(NULL); 
    if (( func->classname != NULL ) && (func->access_static == 0)){
  	argument *th = (argument *)malloc(sizeof(argument));
  	th->name="target_obj";
  	th->type=object_dt;
  	th->dir=inout_dir;
  	th->classname=func->classname;
          printf("\t\t Adding target object unmarshalling...\n");
  	fflush(NULL);
  	fprintf(outFile, "\t\t\t %s* %s = new %s();\n", th->classname, th->name, th->classname);
  	add_object_arg_worker_treatment(outFile, th, 3, current_types);
  	free(th);
    }
    
    if ( func->return_type != void_dt ){
          argument *ret = (argument *)malloc(sizeof(argument));
          ret->name="return_object";
          ret->type=object_dt;
          ret->dir=out_dir;
  	ret->classname=func->return_typename;
          fprintf(outFile, "\t\t\t %s* %s = new %s();\n", ret->classname, ret->name, ret->classname);
          add_object_arg_worker_treatment(outFile, ret, 3, current_types);
    }
    
    arg = func->first_argument;
    while (arg != NULL) {
      switch (arg->type) {
        case char_dt:
        case wchar_dt:
  	fprintf(outFile, "\t\t\t char %s;\n", arg->name);
  	break;
        case boolean_dt:
  	fprintf(outFile, "\t\t\t int %s;\n", arg->name);
  	break;
        case short_dt:
  	fprintf(outFile, "\t\t\t short %s;\n", arg->name);
  	break;
        case long_dt:
  	fprintf(outFile, "\t\t\t long %s;\n", arg->name);
  	break;
        case longlong_dt:
  	fprintf(outFile, "\t\t\t long long %s;\n", arg->name);
  	break;
        case int_dt:
  	fprintf(outFile, "\t\t\t int %s;\n", arg->name);
  	break;
        case float_dt:
  	fprintf(outFile, "\t\t\t float %s;\n", arg->name);
  	break;
        case double_dt:
  	fprintf(outFile, "\t\t\t double %s;\n", arg->name);
  	break;
        case file_dt:
  	fprintf(outFile, "\t\t\t char *%s_og;\n", arg->name);
  	break;
        case string_dt:
        case wstring_dt:
  	fprintf(outFile, "\t\t\t char *%s = NULL;\n", arg->name);
  	break;
        case object_dt:
  	fprintf(outFile, "\t\t\t %s* %s = new %s();\n", arg->classname, arg->name, arg->classname);
  	break;
        case void_dt:
        case any_dt:
        case null_dt:
        default:
  	;
      }
      arg = arg->next_argument;
    }
    fprintf(outFile, "\t\t\t \n");
    
    arg = func->first_argument;
    while (arg != NULL) { 
        switch (arg->type) {
  	case char_dt:
  	case wchar_dt:
  	case boolean_dt:
  	case short_dt:
  	case long_dt:
  	case longlong_dt:
  	case int_dt:
  	case float_dt:
  	case double_dt:
  	case string_dt:
          case wstring_dt:
  	  add_other_arg_worker_treatment(outFile, arg, current_types);
  	  break;
  	case file_dt:
  	  add_file_arg_worker_treatment(outFile, arg); 
  	  break;
  	case object_dt:
  	  add_object_arg_worker_treatment(outFile, arg, 3, current_types);
  	  break;
  	case void_dt:
  	case any_dt:
  	case null_dt:
  	default:;
        }
      arg = arg->next_argument;
    }
    printf("\t\t Adding function call unmarshalling...\n");
    fflush(NULL);
    //Add function call
    fprintf(outFile, "\t\t\t cout << \"[C Binding] Calling function %s.%s\" << endl << flush;\n", func->classname, func->methodname);
  
    if (( func->classname != NULL ) && (func->access_static == 0) && (func->return_type == void_dt)){
      fprintf(outFile, "\t\t\t target_obj->%s(", func->methodname);
    } else if (( func->classname != NULL ) && (func->access_static == 0) && (func->return_type == void_dt)){
      fprintf(outFile, "\t\t\t *return_object = target_obj->%s(", func->methodname);
    } else if ( func->return_type != void_dt ){
      fprintf(outFile, "\t\t\t *return_object = %s(", func->name);
    } else {
      fprintf(outFile, "\t\t\t %s(", func->name);
    }
    
    
    is_first_arg = 1;
    arg = func->first_argument;
    while (arg != NULL) {
      if (is_first_arg) {
        is_first_arg = 0;
      } else {
        fprintf(outFile, ", ");
      }
      if (arg->dir == in_dir) {
        switch (arg->type) {
  	case char_dt:
  	case wchar_dt:
  	case boolean_dt:
  	case short_dt:
  	case long_dt:
  	case longlong_dt:
  	case int_dt:
  	case float_dt:
  	case double_dt:
  	  fprintf(outFile, "%s", arg->name);
  	  break;
  	case object_dt:
  	  fprintf(outFile, "%s", arg->name);
  	  break;
  	case string_dt:
  	case wstring_dt:
  	  fprintf(outFile, "%s", arg->name);
  	  break;
  	case file_dt:
  	  fprintf(outFile, "%s", arg->name);
  	  break;
  	case void_dt:
  	case any_dt:
  	case null_dt:
  	default:
  	  ;
        }
      } else { /* out_dir || inout_dir */
        switch (arg->type) {
  	case char_dt:
  	case wchar_dt:
  	case boolean_dt:
  	case short_dt:
  	case long_dt:
  	case longlong_dt:
  	case int_dt:
  	case float_dt:
  	case double_dt:
  	  fprintf(outFile, "&%s", arg->name);
  	  break;
  	case object_dt:
  	  fprintf(outFile, "%s", arg->name);
  	  break;
  	case string_dt:
  	case wstring_dt:
  	  fprintf(outFile, "&%s", arg->name);
  	  break;
  	case file_dt:
  	  fprintf(outFile, "%s", arg->name);
  	  break;
  	case void_dt:
  	case any_dt:
  	case null_dt:
  	default:
  	  ;
        }
      }
      arg = arg->next_argument;
    }
    
    fprintf(outFile, ");\n");
    
    fprintf(outFile, "\n");
    
    printf("\t\t Adding out parameter marshalling...\n");
    fflush(NULL);
    //TODO: Generate if for activating/deactivating serialization of outputs. Uncomment lines and test 
     
    fprintf(outFile, "\t\t\t if (serializeOuts){\n");
    
    fprintf(outFile, "\t\t\t cout << \"[C Binding] Object will be serialized as output.\" << endl << flush;\n");
  
    if (( func->classname != NULL ) && (func->access_static == 0)){
      
      fprintf(outFile, "\t\t\t\t cout << \"[C Binding] Treating target object\" << endl << flush;\n");
      //Text serialization uncomment and comment binary to change (TODO: Add an ifdef)
  //    fprintf(outFile, "\t\t\t\t ofstream this_ofs(target_obj_filename, std::ofstream::trunc);\n");
  //    fprintf(outFile, "\t\t\t\t archive::text_oarchive this_oa(this_ofs);\n");
      //Binary serialization
      fprintf(outFile, "\t\t\t\t ofstream this_ofs(target_obj_filename, std::ofstream::trunc | std::ios::binary);\n");
      fprintf(outFile, "\t\t\t\t archive::binary_oarchive this_oa(this_ofs);\n");
      fprintf(outFile, "\t\t\t\t cout << \"[C Binding] Deserializing target object\" << endl << flush;\n");
      fprintf(outFile, "\t\t\t\t this_oa << *target_obj;\n");
      fprintf(outFile, "\t\t\t\t this_ofs.flush();\n");
      fprintf(outFile, "\t\t\t\t this_ofs.close();\n");
      j++;
    }
    
    if ( func->return_type != void_dt ){
      fprintf(outFile, "\t\t\t\t cout << \"[C Binding] Treating return object\" << endl << flush;\n");
      //Text serialization uncomment and comment binary to change (TODO: Add an ifdef)
  //    fprintf(outFile, "\t\t\t\t ofstream return_ofs(return_object_filename, std::ofstream::trunc);\n");
  //    fprintf(outFile, "\t\t\t\t archive::text_oarchive return_oa(return_ofs);\n");
      //Binary serialization
      fprintf(outFile, "\t\t\t\t ofstream return_ofs(return_object_filename, std::ofstream::trunc | std::ios::binary);\n");
      fprintf(outFile, "\t\t\t\t archive::binary_oarchive return_oa(return_ofs);\n");
      fprintf(outFile, "\t\t\t\t cout << \"[C Binding] Deserializing return object\" << endl << flush;\n");
      fprintf(outFile, "\t\t\t\t return_oa << *return_object;\n");
      fprintf(outFile, "\t\t\t\t return_ofs.flush();\n");
      fprintf(outFile, "\t\t\t\t return_ofs.close();\n");
      j++;
    }
    
    is_first_arg = 1;
    arg = func->first_argument;
    while (arg != NULL) {
      if (arg->dir == out_dir || arg->dir == inout_dir) {
        switch (arg->type) {
  	case char_dt:
  	case wchar_dt:
  	case boolean_dt:
  	case short_dt:
  	case long_dt:
  	case longlong_dt:
  	case int_dt:
  	case float_dt:
  	case double_dt:
  	case object_dt:
  	  //Text serialization uncomment and comment binary to change (TODO: Add an ifdef)
  //          fprintf(outFile, "\t\t\t\t ofstream %s_ofs(%s_filename, std::ofstream::trunc);\n", arg->name, arg->name);
  //          fprintf(outFile, "\t\t\t\t archive::text_oarchive %s_oa(%s_ofs);\n", arg->name, arg->name);
  	  //Added for binary serialization
  	  fprintf(outFile, "\t\t\t\t ofstream %s_ofs(%s_filename, std::ofstream::trunc | std::ios::binary);\n", arg->name, arg->name);
  	  fprintf(outFile, "\t\t\t\t archive::binary_oarchive %s_oa(%s_ofs);\n", arg->name, arg->name);
  	  fprintf(outFile, "\t\t\t\t %s_oa << *%s;\n", arg->name, arg->name);
  	  fprintf(outFile, "\t\t\t\t %s_ofs.flush();\n", arg->name);
  	  fprintf(outFile, "\t\t\t\t %s_ofs.close();\n", arg->name);
  	  break;
  	case string_dt:
  	case wstring_dt:
  	  //Text serialization uncomment and comment binary to change (TODO: Add an ifdef)
  //	  fprintf(outFile, "\t\t\t\t ofstream %s_ofs(%s_filename, std::ofstream::trunc);\n", arg->name, arg->name);
  //	  fprintf(outFile, "\t\t\t\t archive::text_oarchive %s_oa(%s_ofs);\n", arg->name, arg->name);
            //Added for binary serialization
            fprintf(outFile, "\t\t\t\t ofstream %s_ofs(%s_filename, std::ofstream::trunc | std::ios::binary);\n", arg->name, arg->name);
            fprintf(outFile, "\t\t\t\t archive::binary_oarchive %s_oa(%s_ofs);\n", arg->name, arg->name);
  	  fprintf(outFile, "\t\t\t\t string %s_out_string (%s);\n", arg->name, arg->name);
  	  fprintf(outFile, "\t\t\t\t %s_oa << %s_out_string;\n", arg->name, arg->name);
  	  fprintf(outFile, "\t\t\t\t %s_ofs.flush();\n", arg->name);
  	  fprintf(outFile, "\t\t\t\t %s_ofs.close();\n", arg->name);
  	  break;
  	case file_dt:
  	  break;
  	case void_dt:
  	case any_dt:
  	case null_dt:
  	default:;
        }
      }
      
      fprintf(outFile, "\n");
      
      arg = arg->next_argument;
      j++;
    }
    //TODO: end of if for activating/deactivating serialization of outputs. Uncomment lines and test 
     
    fprintf(outFile, "\t\t\t cout << \"[C Binding] Object has been serialized as output.\" << endl << flush;\n");
  
    fprintf(outFile, "\t\t\t }\n");
      
  
    printf("\t\t Adding memory free...\n");
    fflush(NULL);
    if (( func->classname != NULL ) && (func->access_static == 0)){
  	fprintf(outFile, "\t\t\t free(target_obj_filename_og);\n", func->classname);
    }
    if ( func->return_type != void_dt ){
  	fprintf(outFile, "\t\t\t free(return_object_filename_og);\n");
    }
    arg = func->first_argument;
    while (arg != NULL) {
      switch (arg->type) {
        case char_dt:
        case wchar_dt:
        case boolean_dt:
        case short_dt:
        case long_dt:
        case longlong_dt:
        case int_dt:
        case float_dt:
        case double_dt:
          if (arg->dir != in_dir) {
                  fprintf(outFile, "\t\t\t free(%s_filename_og);\n", arg->name);
          }
  	break;
        case object_dt:
          fprintf(outFile, "\t\t\t free(%s_filename_og);\n", arg->name);
          break;
        case file_dt:
          fprintf(outFile, "\t\t\t free(%s_og);\n", arg->name);
          break;
        case string_dt:
        case wstring_dt:
          if (arg->dir != in_dir) {
                  fprintf(outFile, "\t\t\t free(%s_filename_og);\n", arg->name);
          }
  	fprintf(outFile, "\t\t\t free(%s);\n", arg->name);
  	break;
        case void_dt:
        case any_dt:
        case null_dt:
        default:
  	;
      }
      arg = arg->next_argument;
    }
  
    //fprintf(workerFile, "\t cout << \"data in cache after removal\" << endl;\n");
    //fprintf(workerFile, "\t for(std::map<std::string, void*>::iterator it = cache.begin(); it != cache.end(); it++){\n");
    //fprintf(workerFile, "\t\t cout << it->first << endl;\n");
    //fprintf(workerFile, "\t }\n");
   
    // Operation correctly executed
    fprintf(outFile, "\t\t\t return 0;\n");
    
    // Close enum case
    fprintf(outFile, "\t\t }\n");
    fprintf(outFile, "\t\t break;\n");  
  }	
  
  
  void generate_body(void)
  {
    Types current_types;
    initTypes(&current_types);
    function *current_function;
    generate_executor_prototype();
   
    generate_enum(includeFile, get_first_function());
    
    fprintf(stubsFile, "\n");
    
    fprintf(includeFile, "/* Functions to be implemented. We sugest that you create a file */\n");
    fprintf(includeFile, "/* with name '%s-functions.cc' and implement them there. */\n", get_filename_base());
    
    current_function = get_first_function();
    while (current_function != NULL) {
      printf("Treating function: %s\n", current_function->name);
      printf("\t Generating prototype in stubs... \n");
      fflush(NULL);
      generate_prototype(stubsFile, current_function);
      fprintf(stubsFile, "\n");
      fprintf(stubsFile, "{\n");
      printf("\t Generating parameters' buffers in stubs... \n");
      fflush(NULL);
      generate_parameter_buffers(stubsFile, current_function);
      printf("\t Generating parameters' marshalling in stubs... \n");
      fflush(NULL);
      generate_parameter_marshalling(stubsFile, current_function);
      printf("\t Generating runtime execute calls in stubs... \n");
      fflush(NULL);
      generate_execute_call(stubsFile, current_function);
      fprintf(stubsFile, "}\n");
      fprintf(stubsFile, "\n");
  
      // If the current function is not an object method
      printf("\t Generating class includes and types... \n");
      fflush(NULL);
      generate_class_includes_and_check_types(includeFile, &current_types, current_function);
      // If the current function is not an object method
      if ( strstr(current_function->name, "::") == NULL) {
        printf("\t Generating prototypes in ...\n");
        fflush(NULL);
        generate_prototype(includeFile, current_function);
        fprintf(includeFile, ";\n");
      }
  
      printf("\t Generating worker functions... \n");
      fflush(NULL);
      generate_worker_case(workerFile, current_types, current_function);
      
      current_function = current_function->next_function;
    }
    generate_executor_end();
    printf("\t Generating worker remove and serialize functions... \n");
    fflush(NULL); 
    generate_remove_and_serialize_case(workerFile, current_types); 
  
  }
  
  