/*+MHDR*/
/*
#  Clearcase: @@/main/40
#  VersionId: Tau 4.3.0
+------------------------------------------------------------------------------+
|  Modulname    : makegen .c                                                   |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description  : This module does the generation of the main makefile. To get |
|                 the rules of the generated file(s) a sub-makefile (generated |
|                 by the Code Generator) will be included.                     |
|  The sub-makefile looks like:                                                |
|                                                                              |
|  # sub makefile generated for node R2D2                                      |
|                                                                              |
|  GENERATEDMODULES  = 3                                                       |
|                                                                              |
|  sctOBJECTFILES  =                                                           |
|                                                                              |
|  sctSOURCEFILE1  = cfile1                                                    |
|  sctSEXTENSION1  = .c                                                        |
|  sctHEADER1      =                                                           |
|                                                                              |
|  sctSOURCEFILE2  = cfile2                                                    |
|  sctSEXTENSION2  = .c                                                        |
|  sctHEADER2      =                                                           |
|                                                                              |
|  sctSOURCEFILE3  = cfile3                                                    |
|  sctSEXTENSION3  = .c                                                        |
|  sctHEADER3      =                                                           |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-MHDR*/

/*
+------------------------------------------------------------------------------+
|                                                                              |
|  Copyright by Telelogic AB 1993 - 2001                                       |
|                                                                              |
|  This Program is owned by Telelogic and is protected by national             |
|  copyright laws and international copyright treaties. Telelogic              |
|  grants you the right to use this Program on one computer or in              |
|  one local computer network at any one time.                                 |
|  Under this License you may only modify the source code for the purpose      |
|  of adapting it to your environment. You must reproduce and include          |
|  any copyright and trademark notices on all copies of the source code.       |
|  You may not use, copy, merge, modify or transfer the Program except as      |
|  provided in this License.                                                   |
|  Telelogic does not warrant that the Program will meet your                  |
|  requirements or that the operation of the Program will be                   |
|  uninterrupted and error free. You are solely responsible that the           |
|  selection of the Program and the modification of the source code            |
|  will achieve your intended results and that the results are actually        |
|  obtained.                                                                   |
|                                                                              |
+------------------------------------------------------------------------------+
*/

#ifndef _MAKEGEN_C_
#define _MAKEGEN_C_

/*+IMPORT*/
/*====================  I M P O R T  =========================================*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <time.h>

#ifdef WIN32
  #include <io.h>
  #define DLL_API __declspec(dllexport)
#else
  #include <unistd.h>
  #define DLL_API
#endif


#include "ini_api.h"
#include "makegen.h"

#ifdef MAKEGEN
  #include "pdm_api.h"
#else
  #include "versions.h"
#endif



/*--------------------  Functions   ------------------------------------------*/

/*--------------------  Variables   ------------------------------------------*/

/*============================================================================*/
/*-IMPORT*/

/*+EXPORT*/
/*====================  E X P O R T  =========================================*/

/*--------------------  Functions   ------------------------------------------*/

extern const char* SUGetTAUVersionString( void );

/*--------------------  Variables   ------------------------------------------*/

#ifndef _MAX_PATH
  #define _MAX_PATH 260
#endif

/*============================================================================*/
/*-EXPORT*/

/*+MGI*/
/*====================  V A L U E S  OF  T H I S  M O D U L E  ===============*/

/*--------------------  Constants, Macros  -----------------------------------*/

#ifndef XMK_UNIX
  #define SEPARATION_CHAR '\\'
#else
  #define SEPARATION_CHAR '/'
#endif

#ifndef TRUE
  #define TRUE 1
#endif

#ifndef FALSE
  #define FALSE 1
#endif


/*--------------------  Typdefinitions  --------------------------------------*/

/*--------------------  Functions  -------------------------------------------*/

static int  MakefileHeader           ( void );
static int  MakefileBase             ( const char* ap_component );

static int  CmicroObjects            ( void );
static int  CmicroFiles              ( void ); 
static int  CoderObjects             ( void ); 
static int  CoderFiles               ( void ); 
static int  MakefileEntries          ( void ); 
static int  StandardFiles            ( void ); 
static int  StandardObjects          ( void ); 
static int  AdditionalFiles          ( void ); 
static int  AdditionalObjects        ( void ); 
static int  ConvertCCOptions         ( char* ap_options, 
                                       const char* ap_cfile, 
                                       const char* ap_objfile,
                                       const char* ap_include);
static int ConvertCC2or3Options      ( char* ap_options, 
                                       const char* ap_cfile, 
                                       const char* ap_objfile);
static int  ConvertLDOptions         ( char* ap_options, 
                                       const char* ap_exefile);
static int  ConvertAROptions         ( char* ap_options );
static void GetFileOnly              ( char* ap_file, 
                                       const char* ap_fullfile );
static int  GetCodeGeneratorMakefile ( void );
static int  CodeGeneratorObjects     ( void );
static int  CodeGeneratorFiles       ( void ); 
static int  ReadUserSections         ( void );
static int  CheckFilenameForSpaces   ( const char* );

static void WriteOneObject           ( const char* ap_filename, 
                                       const char* ap_extension,
                                       int a_flag);
static int  WriteOneRule             ( const char* ap_cfile,
                                       int a_flag );
static void WriteCommand             ( FILE* ap_file, 
                                       const char* ap_cmd, 
                                       const char* ap_options );

/*--------------------  Variables  -------------------------------------------*/

static FILE *fp;
static char ExecutableName[256];
static char CodeGeneratorMakefile[2048];
static int  GeneratedModules;
static int  MakeApplicationOffset;
static char UserObjects[20000];
static char UserRules[20000];
static int  CodersUsed;
static int  UserCcAvailable;
static int  GenericFuncUsed;
static int  sdtdirGotSpaces;

static const char* UserObjectsStart = "######## UserObjectsStart (Do not edit this line!) ##########";
static const char* UserObjectsEnd   = "######## UserObjectsEnd   (Do not edit this line!) ##########";
static const char* UserRulesStart   = "######## UserRulesStart (Do not edit this line!) ##########";
static const char* UserRulesEnd     = "######## UserRulesEnd   (Do not edit this line!) ##########";

/*============================================================================*/
/*-MGI*/

/*+FHDR E*/
/*
+------------------------------------------------------------------------------+
|  Functionname : GenerateMakefile                                             |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: This is the access function to the makefile generation. It     |
|               calls all the other functions in this module and comes back    |
|               with an errorcode. Only if this errorcode is ret_make_OKAY     |
|               the makefile is completely generated and ready for use.        |
|                                                                              |
|  Parameter:  const char*  IN   path of this component/node/application       |
|              const char*  IN   name of the makefile to be generated          |
|              const char*  IN   name of the component/node/application        |
|  Return:     int          -    errorcode                                     |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR E*/

/*+FDEF E*/
int GenerateMakefile( const char* ap_path, 
                      const char* ap_name, 
                      const char* ap_compname,
                      int a_genericfunc)
/*-FDEF E*/
{
  char  filename[2048];
  int   result;

  GenericFuncUsed = a_genericfunc;

  /*
  ** Check if user_cc.h is available
  ** If yes, it will be put to all the files depandancy (compilation rule)
  */
  sprintf(filename, 
          "%s%cuser_cc.h", 
          ap_path,
          SEPARATION_CHAR);
  if(access(filename, 0) == 0)
    UserCcAvailable = TRUE;
  else
    UserCcAvailable = FALSE;


  /*
  ** build needed file names
  */
  sprintf(filename, 
          "%s%c%s", 
          ap_path,
          SEPARATION_CHAR, 
          ap_name);

  sprintf(CodeGeneratorMakefile, 
          "%s%c%s_gen.m",
          ap_path,
          SEPARATION_CHAR, 
          ap_compname);
  
  strcpy(ExecutableName, ap_compname);

  /*
  ** Read old makefile
  */
  sprintf(UserObjects, 
          "%s\nuserOBJECTFILES1=\n\nuserOBJECTFILES2 = \n\n%s\n",
          UserObjectsStart,
          UserObjectsEnd);
  sprintf(UserRules, 
          "%s\n\n%s\n",
          UserRulesStart,
          UserRulesEnd);
  if((fp = fopen(filename, "r")) != NULL)
  {
    ReadUserSections();
    fclose( fp );
  }

  if((strcmp( GetIniValue( GET_GenerateSDLCoder), "NO" ) != 0 ) ||
     (strcmp( GetIniValue( GET_GenerateASNCoder), "NO" ) != 0 ))
  {
    CodersUsed = 1; /* coders used, but no library manager */
    if(strlen(GetIniValue( GET_Library_Tool )) > 0)
      CodersUsed = 2; /* coders used, with library manager */
  }
  else
    CodersUsed = 0; /* coders not used at all */

  
  /*
  ** Generate new makefile
  */
  if((fp = fopen(filename, "w")) == NULL)
  {
    return ret_make_FILEOPEN;
  }
  else
  {
    if( (result = MakefileHeader()) != ret_make_OKAY)
    {
      fclose( fp );
      return result;
    }
    else
    {
      if( (result = MakefileBase( ap_compname )) != ret_make_OKAY)
      {
        fclose( fp );
        return result;
      }
    }
    fclose( fp );
  }
  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : MakefileHeader                                               |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The makefile header with the definition of all the used        |
|               variables is generated in this function.                       |
|                                                                              |
|  Parameter:   -                                                              |
|                                                                              |
|  Return:      int - errorcode                                                |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int MakefileHeader( void )
/*-FDEF S*/
{
  const char *p;
  char  timestring[100];
  time_t today;

  today = time(NULL);
  strcpy(timestring,ctime(&today));

  fprintf( fp ,"#\n");
  #ifdef SDTTAEX
    fprintf( fp ,"# This makefile is generated by the SDL Targeting Expert\n");
  #else  //MAKEGEN
    fprintf( fp ,"# This makefile is generated by an external makefile generator\n");
  #endif
  fprintf( fp ,"# generated for %s\n", GetIniValue( GET_Make_Tool ));
  fprintf( fp, "# Date: %s\n", timestring);
  fprintf( fp ,"#\n");

  fprintf( fp ,"\n");
  fprintf( fp ,"#\n");
  fprintf( fp ,"# Used directories\n");
  fprintf( fp ,"#\n");
  fprintf( fp ,"# All pathes which are not absolute should be seen as relative\n");
  fprintf( fp ,"# to the directory where this makefile is placed in.\n");
  fprintf( fp ,"#\n");

  p = GetIniValue( GET_LibraryDirectory );

  if( strchr( p, ' ') != NULL)
    sdtdirGotSpaces = TRUE;
  else
    sdtdirGotSpaces = FALSE;

  fprintf( fp, "sdtdir= %s\n", p);

  if((strcmp( GetIniValue( GET_GeneratorName), "Cadvanced" ) == 0 ) ||
     (strcmp( GetIniValue( GET_GeneratorName), "Cbasic" ) == 0 ))
  {
    fprintf( fp, "sctuseinclude= %s%cINCLUDE\n", p, SEPARATION_CHAR );
    {
      char temp[2048];
      strcpy( temp, p);
      if( strrchr( temp, SEPARATION_CHAR ) != NULL)
        *(strrchr( temp, SEPARATION_CHAR )) = '\0';
      fprintf( fp, "sctrtosinclude= %s%cRTOS%cINCLUDE\n", temp, SEPARATION_CHAR, SEPARATION_CHAR); 
      fprintf( fp, "sctrtosbase= %s%cRTOS\n", temp, SEPARATION_CHAR ); 
    }
  }

  if( strcmp( GetIniValue( GET_GeneratorName), "Cmicro" ) == 0 )
  {
    fprintf( fp, "sctkerneldir= $(sdtdir)%ccmicro%ckernel\n", SEPARATION_CHAR, SEPARATION_CHAR );
    fprintf( fp, "scttesterdir= $(sdtdir)%ccmicro%ctester\n", SEPARATION_CHAR, SEPARATION_CHAR );
    fprintf( fp, "sctincludedir= $(sdtdir)%ccmicro%cinclude\n", SEPARATION_CHAR, SEPARATION_CHAR );
  }
  fprintf( fp, "sctobjdir= %s\n", GetIniValue( GET_ObjectDirectory )); 
  fprintf( fp, "scttargetdir= .\n" );

  fprintf( fp ,"#\n");
  fprintf( fp ,"# CODER directories\n");
  fprintf( fp ,"#\n");
  fprintf( fp, "sctCODERDIR= $(sdtdir)%ccoder\n", SEPARATION_CHAR);
  fprintf( fp, "sctTCPIPDIR= $(sdtdir)%ctcpip\n", SEPARATION_CHAR);

  fprintf( fp ,"\n");
  fprintf( fp ,"#\n");
  fprintf( fp ,"# user defined entries\n");
  fprintf( fp ,"#\n");
  MakefileEntries();

  fprintf( fp ,"\n");
  fprintf( fp ,"#\n");
  fprintf( fp ,"# Compiler/Linker definitions for kernel/library files\n");
  fprintf( fp ,"#\n");
  fprintf( fp ,"sctCC            = %s\n", GetIniValue( GET_Compiler_Tool ));
  fprintf( fp ,"#sctCCFLAGS used = %s %s\n", GetIniValue( GET_Compiler_LibFlag ), GetIniValue( GET_Compiler_Options ));
  fprintf( fp ,"sctCC2           = %s\n", GetIniValue( GET_Compiler_Tool2 ));
  fprintf( fp ,"sctCC3           = %s\n", GetIniValue( GET_Compiler_Tool3 ));
  fprintf( fp ,"sctLD            = %s\n", GetIniValue( GET_Linker_Tool ));
  fprintf( fp ,"#sctLDFLAGS used = %s\n", GetIniValue( GET_Linker_Options ));
  fprintf( fp ,"sctAR            = %s\n", GetIniValue( GET_Library_Tool ));
  fprintf( fp ,"#sctARFLAGS used = %s\n", GetIniValue( GET_Library_Options ));
  fprintf( fp ,"sctOEXTENSION    = %s\n", GetIniValue( GET_ObjectExtension ));
  fprintf( fp ,"sctI2EXTENSION   = %s\n", GetIniValue( GET_Input2Extension ));
  fprintf( fp ,"sctI3EXTENSION   = %s\n", GetIniValue( GET_Input3Extension ));
  fprintf( fp ,"sctEXTENSION     = %s\n", GetIniValue( GET_ExecutableExtension ));
  fprintf( fp ,"sctLIBEXTENSION  = %s\n", GetIniValue( GET_LibraryExtension ));
  
  fprintf( fp ,"\n");
  fprintf( fp ,"#\n");
  fprintf( fp ,"# Compiler definitions for additional files\n");
  fprintf( fp ,"#\n");
  fprintf( fp ,"addCC            = %s\n", GetIniValue( GET_AddCompiler_Tool ));
  fprintf( fp ,"#addCCFLAGS used = %s\n", GetIniValue( GET_AddCompiler_Options ));
  fprintf( fp ,"addOEXTENSION    = %s\n", GetIniValue( GET_AddObjectExtension ));

  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : MakefileBase                                                 |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The base of the makefile will be generated here containing the |
|               list of objects                                                |
|               default target                                                 |
|               the rule for the executable                                    | 
|               the rules for the C files                                      |
|                                                                              |
|  Parameter:   -                                                              |
|                                                                              |
|  Return:      int - errorcode                                                |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int MakefileBase( const char* ap_component )
/*-FDEF S*/
{
  int result;
  int marker;
  const char *p;
  char temp[1024];
  char ConvertedOptions[1024];

  strcat(ExecutableName, GetIniValue( GET_ExecutableExtension ));

  /*
  ** Stuff from the CodeGenerator
  */
  if((result = GetCodeGeneratorMakefile()) != ret_make_OKAY)
    return result;

  /*
  ** User objectfiles inserted by hand
  */
  fprintf( fp, UserObjects );
  
  /*
  ** List of all objects
  */
  fprintf( fp, "\nsctOBJECTLIST = $(sctOBJECTFILES) \\\n" );
  fprintf( fp, "                $(userOBJECTFILES1) \\\n" );
  
  if((result = CodeGeneratorObjects()) == ret_make_OKAY)
    if((result = StandardObjects()) == ret_make_OKAY)
      if((result = AdditionalObjects()) == ret_make_OKAY)
      {
        if( p = GetIniValue( GET_FirstObjectToLink ))
        {
          do
          {
            if(CheckFilenameForSpaces( p ))
              fprintf( fp, "                \"%s\" \\\n", p);
            else
              fprintf( fp, "                %s \\\n", p);
          }while((p = GetIniValue( GET_NextObjectToLink )) != NULL );
        }

        if( strcmp( GetIniValue( GET_GeneratorName), "Cmicro" ) == 0 )
        {
          CmicroObjects();
        }
        if(CodersUsed == 1) /*without library manager*/
        {
          CoderObjects();
        }

        fprintf( fp, "                $(userOBJECTFILES2) \n\n" );
 
        if(CodersUsed != 0) /*with or without library manager*/
        {
          fprintf( fp, "\nsctCODEROBJECTLIST = " );
          CoderObjects();
          fprintf( fp, "\n\n" );
        }

        /*
        ** list of all libraries
        */
        fprintf( fp, "\nsctLIBRARYLIST = " );
        marker = FALSE;  
        if(CodersUsed == 2) /* coders used, with library manager */
        {
          fprintf( fp, "sctCoderLibrary$(sctLIBEXTENSION) ");
          marker = TRUE;
        }
        if( p = GetIniValue( GET_FirstLibraryToLink ))
        { 
          do
          {
            if(marker)
              fprintf( fp, " \\\n");

            if(CheckFilenameForSpaces( p ) || sdtdirGotSpaces)
              fprintf( fp, "                \"%s\"", p);
            else
              fprintf( fp, "                %s", p);

            marker = TRUE;
          }while((p = GetIniValue( GET_NextLibraryToLink ))!= NULL );
        }
        fprintf( fp, "\n\n" );


        /*
        ** TARGETS
        */
        fprintf( fp, "\n\n#\n# Default target\n#\n");

        if( strlen(p = GetIniValue( GET_PreMake )) > 0)
        {
          fprintf( fp, "\ndefault: PreMake %s\n", ExecutableName);

          /*
          ** PreMake
          */
          fprintf( fp, "\n#\n# Rule for the pre-make action\n#\n");

          p = GetIniValue( GET_PreMake );
          if(strstr( p, "%s") != NULL)
          {
            sprintf( temp, p, ap_component);
            fprintf( fp, "PreMake: \n\t%s\n", temp);
          }
          else
          {
            fprintf( fp, "PreMake: \n\t%s\n", p);
          }
        }
        else
        {
          fprintf( fp, "\ndefault: %s\n", ExecutableName);
        }

        if(CodersUsed == 2) /* coders used, with library manager */
        {
          fprintf( fp, "\n#\n# Rule for the coder library\n#\n");

          fprintf( fp, "\nsctCoderLibrary$(sctLIBEXTENSION): $(sctCODEROBJECTLIST)\n");
    
          strcpy(ConvertedOptions, GetIniValue( GET_Library_Options ));

          if((result = ConvertAROptions( ConvertedOptions )) != ret_make_OKAY)
            return result;

          WriteCommand( fp, "$(sctAR)", ConvertedOptions );
        }

        /*
        ** Executable
        */
        fprintf( fp, "\n#\n# Rule for the executable\n#\n");
        switch(CodersUsed)
        {
          case 0: /* not used */
          case 1: /* used but without library manager */
               fprintf( fp, "%s: $(sctOBJECTLIST)\n", ExecutableName);
               break;

          case 2: /* used with library manager */
               fprintf( fp, "%s: $(sctOBJECTLIST) sctCoderLibrary$(sctLIBEXTENSION)\n", ExecutableName);
               break;
        }

        strcpy(ConvertedOptions, GetIniValue( GET_Linker_Options ));

        if((result = ConvertLDOptions( ConvertedOptions, ExecutableName )) == ret_make_OKAY)
        {
          WriteCommand( fp, "$(sctLD)", ConvertedOptions );

          if(strlen( p = GetIniValue( GET_PostLink )) > 0)
          {
            if(strstr( p, "%s") != NULL)
            {
              sprintf( temp, p, ExecutableName);
              fprintf( fp, "\t%s\n", temp);
            }
            else
            {
              fprintf( fp, "\t%s\n", p);
            }
          }

          /*
          ** RULES
          */
          fprintf( fp, "\n#\n# Rules for the C files\n#\n\n");

          if( strcmp( GetIniValue( GET_GeneratorName), "Cmicro" ) == 0 )
          {
            if(sdtdirGotSpaces)
              fprintf( fp, "HEADERS = ml_mcf.h \"$(sctincludedir)%cml_typ.h\"", SEPARATION_CHAR);
            else
              fprintf( fp, "HEADERS = ml_mcf.h $(sctincludedir)%cml_typ.h", SEPARATION_CHAR);
          }
          else
          {
            if( strstr(GetIniValue(GET_Compiler_Options), "USER_CONFIG") == NULL)
            {
              if(sdtdirGotSpaces)
                fprintf( fp, "HEADERS = \"$(sctuseinclude)%cscttypes.h\"", SEPARATION_CHAR);
              else
                fprintf( fp, "HEADERS = $(sctuseinclude)%cscttypes.h", SEPARATION_CHAR);
            }
            else
            {
              if(sdtdirGotSpaces) 
                fprintf( fp, "HEADERS = sct_mcf.h \"$(sctuseinclude)%cscttypes.h\"", SEPARATION_CHAR);
              else
                fprintf( fp, "HEADERS = sct_mcf.h $(sctuseinclude)%cscttypes.h", SEPARATION_CHAR);
            }
          }

          if(UserCcAvailable)
            fprintf( fp, " user_cc.h\n\n");
          else
            fprintf( fp, "\n\n");

          if((result = CoderFiles()) == ret_make_OKAY)
            if((result = CmicroFiles()) == ret_make_OKAY)
              if((result = StandardFiles()) == ret_make_OKAY)
                if((result = AdditionalFiles()) == ret_make_OKAY)
                  if((result = CodeGeneratorFiles( )) == ret_make_OKAY )
                    fprintf( fp, UserRules );
        } /* ... if((result = ConvertLDOptions( ConvertedOptions, ExecutableName )) == ret_make_OKAY) */
      } /* ... if((result = AdditionalObjects()) == ret_make_OKAY) */
        
  return result;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : CmicroObjects                                                |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The object list of the compiled Cmicro files will be written   |
|               here.                                                          |
|                                                                              |
|  Parameter:   -                                                              |
|                                                                              |
|  Return:      int - errorcode                                                |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int CmicroObjects( void )
/*-FDEF S*/
{
  const char *p;
  char file_only[2048];
   
  if((p = GetIniValue( GET_FirstTesterFile )) != NULL )
  {
    do
    {
      GetFileOnly( file_only, p );

      fprintf( fp, "              $(sctobjdir)%c%s$(sctOEXTENSION) \\\n", SEPARATION_CHAR, file_only);
    }while((p = GetIniValue( GET_NextTesterFile )) != NULL );
  }
  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : CmicroFiles                                                  |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: Here the rules for the compilation of all the used Cmicro C    |
|               files will be written.                                         |
|                                                                              |
|  Parameter:   -                                                              |
|                                                                              |
|  Return:      int - errorcode                                                |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int CmicroFiles( void )
/*-FDEF S*/
{
  int result;
  const char *p;

  if( strcmp( GetIniValue( GET_GeneratorName), "Cmicro" ) == 0 )
  {   
    if((p = GetIniValue( GET_FirstTesterFile )) != NULL )
    {
      do
      {
        if((result = WriteOneRule( p, 0 )) != ret_make_OKAY)
          return result;
      }while((p = GetIniValue( GET_NextTesterFile )) != NULL );
    }
  }

  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : CoderObjects                                                 |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The object list of the compiled Coder files will be written    |
|               here.                                                          |
|                                                                              |
|  Parameter:   -                                                              |
|                                                                              |
|  Return:      int - errorcode                                                |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int CoderObjects( void )
/*-FDEF S*/
{
  const char *p;

  if((p = GetIniValue( GET_FirstCoderFile )) != NULL )
  {
    do
    {
      fprintf( fp, " \\\n" );
      WriteOneObject( p, "$(sctOEXTENSION)", 0 );
    }while((p = GetIniValue( GET_NextCoderFile )) != NULL );
  }
 
  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : CoderFiles                                                   |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: Here the rules for the compilation of all the used Coder C     |
|               files will be written.                                         |
|                                                                              |
|  Parameter:   -                                                              |
|                                                                              |
|  Return:      int - errorcode                                                |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int CoderFiles( void )
/*-FDEF S*/
{
  int result;
  const char *p;

  if(CodersUsed)
  {
    if((p = GetIniValue( GET_FirstCoderFile )) != NULL )
    {
      do
      { 
        if((result = WriteOneRule( p, 0 )) != ret_make_OKAY)
          return result;
      }while((p = GetIniValue( GET_NextCoderFile )) != NULL );
    }
  }

  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : StandardObjects                                              |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The object list of the compiled standard files will be written |
|               here.                                                          |
|                                                                              |
|  Parameter:   -                                                              |
|                                                                              |
|  Return:      int - errorcode                                                |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int StandardObjects( void )
/*-FDEF S*/
{
  const char *p;

  if( p = GetIniValue( GET_FirstFileToCompile ))
  {
    do
    {
      WriteOneObject( p, "$(sctOEXTENSION)", 0 );
      fprintf( fp, " \\\n" );
    }while((p = GetIniValue( GET_NextFileToCompile )) != NULL );
  }
 
  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : MakefileEntries                                              |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: Here the makefile entries will be written                      |
|                                                                              |
|  Parameter:   -                                                              |
|                                                                              |
|  Return:      int - errorcode                                                |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int MakefileEntries( void )
/*-FDEF S*/
{
  const char *p;

  if( p = GetIniValue( GET_FirstMakefileEntry ))
  {
    do
    {
      fprintf( fp, "%s\n",p);
    }while((p = GetIniValue( GET_NextMakefileEntry )) != NULL );
  }
  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : StandardFiles                                                |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: Here the rules for the compilation of all the used standard    |
|               files will be written.                                         |
|                                                                              |
|  Parameter:   -                                                              |
|                                                                              |
|  Return:      int - errorcode                                                |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int StandardFiles( void )
/*-FDEF S*/
{
  int result;
  const char *p;

  if( p = GetIniValue( GET_FirstFileToCompile ))
  {
    do
    {
      if((result = WriteOneRule( p, 0 )) != ret_make_OKAY)
        return result;
    }while((p = GetIniValue( GET_NextFileToCompile )) != NULL );
  }

  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : AdditionalObjects                                            |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The object list of the compiled sdditional files will be       |
|               written here.                                                  |
|                                                                              |
|  Parameter:   -                                                              |
|                                                                              |
|  Return:      int - errorcode                                                |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int AdditionalObjects( void )
/*-FDEF S*/
{
  const char *p;
 
  if( p = GetIniValue( GET_FirstAddFileToCompile ))
  {
    do
    {
      WriteOneObject( p, "$(addOEXTENSION)", 0 );
      fprintf( fp, " \\\n" );
    }while((p = GetIniValue( GET_NextAddFileToCompile )) != NULL );
  }

  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : AdditionalFiles                                              |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: Here the rules for the compilation of all the used additional  |
|               files will be written.                                         |
|                                                                              |
|  Parameter:   -                                                              |
|                                                                              |
|  Return:      int - errorcode                                                |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int AdditionalFiles( void )
/*-FDEF S*/
{
  int result;
  const char *p;
  char ConvertedOptions[1024];
  char file_only[1024];
  char obj_file[1024];

  if( p = GetIniValue( GET_FirstAddFileToCompile ))
  {
    do
    {
      GetFileOnly( file_only, p);
      
      if(CheckFilenameForSpaces( file_only ))
      {
        sprintf( obj_file, "\"$(sctobjdir)%c%s$(addOEXTENSION)\"", SEPARATION_CHAR, file_only);
        sprintf( file_only, "\"%s\"", p);
      }
      else
      {
        sprintf( obj_file, "$(sctobjdir)%c%s$(addOEXTENSION)", SEPARATION_CHAR, file_only);
        sprintf( file_only, "%s", p);
      }

      strcpy(ConvertedOptions, GetIniValue( GET_AddCompiler_Options ));

      if((result = ConvertCCOptions( ConvertedOptions, 
                                     file_only,
                                     obj_file, 
                                     GetIniValue( GET_AddCompiler_Include ) )) != ret_make_OKAY)
      {
        return result;
      }
      else
      {
        if(CheckFilenameForSpaces( p ))
        {
          fprintf( fp, 
                   "%s: $(HEADERS) \"%s\" %s\n", 
                   obj_file,
                   p,
                   GetIniValue(GET_AddCompiler_Depend ) );

          WriteCommand( fp, "$(addCC)", ConvertedOptions );
        }
        else
        {
          fprintf( fp, 
                   "%s: $(HEADERS) %s %s\n", 
                   obj_file,
                   p,
                   GetIniValue(GET_AddCompiler_Depend ) );
          WriteCommand( fp, "$(addCC)", ConvertedOptions );
        }
      }
    }while((p = GetIniValue( GET_NextAddFileToCompile )) != NULL );
  }

  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : ConvertCCOptions                                             |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The constants %o, %s and %I will be replaced by the            |
|               correct filename(s) in the compiler options.                   |
|                                                                              |
|  Parameter:  char *        IN/OUT compiler options containing %o, %s and %I  |
|              const char*   IN     name of C file                             |
|              const char*   IN     name of object file                        |
|              const char    IN     include pathes                             |
|  Return:     int           -      errorcode                                  |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int ConvertCCOptions (char* ap_options, 
                             const char* ap_cfile, 
                             const char* ap_objfile,
                             const char* ap_include) 
/*-FDEF S*/
{
  char *p;
  char temp1[1024];
  char temp2[1024];

  strcpy( temp1, ap_options );
  if((p = strstr( temp1, "%s")) != NULL)
  {
    *p = '\0';
    strcpy( temp2, p+2 );
    strcat( temp1, ap_cfile );
    strcat( temp1, temp2 );

    strcpy( ap_options, temp1 );
  }
  else
  { 
    return ret_make_MISSING_s;
  }

  strcpy( temp1, ap_options );
  if((p = strstr( temp1, "%o")) != NULL)
  {
    *p = '\0';
    strcpy( temp2, p+2 );
    strcat( temp1, ap_objfile );
    strcat( temp1, temp2 );

    strcpy( ap_options, temp1 );
  }
  else
  { 
    return ret_make_MISSING_o;
  }

  strcpy( temp1, ap_options );
  if((p = strstr( temp1, "%I")) != NULL)
  {
    *p = '\0';
    strcpy( temp2, p+2 );
    strcat( temp1, ap_include );
    strcat( temp1, temp2 );

    strcpy( ap_options, temp1 );
  }
  else
  { 
    return ret_make_MISSING_I;
  }
  
  if( (p = strchr( ap_options, '%' )) != NULL)
  {
    strcpy( temp2, p+1 );
    *p = '\0';
    strcpy( temp1, ap_options );
    strcat( temp1, "%%" );
    strcat( temp1, temp2 );

    strcpy( ap_options, temp1 );
  }

  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : ConvertCC2or3Options                                         |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The constants %o and %s will be replaced by the correct        |
|                filename(s) in the compiler options.                          |
|                                                                              |
|  Parameter:  char *        IN/OUT compiler options containing %o, %s and %I  |
|              const char*   IN     name of C file                             |
|              const char*   IN     name of object file                        |
|  Return:     int           -      errorcode                                  |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int ConvertCC2or3Options      ( char* ap_options, 
                                       const char* ap_cfile, 
                                       const char* ap_objfile)
/*-FDEF S*/
{
  char *p;
  char temp1[1024];
  char temp2[1024];

  strcpy( temp1, ap_options );
  if((p = strstr( temp1, "%s")) != NULL)
  {
    *p = '\0';
    strcpy( temp2, p+2 );
    strcat( temp1, ap_cfile );
    strcat( temp1, temp2 );

    strcpy( ap_options, temp1 );
  }
  else
  { 
    return ret_make_MISSING_s;
  }

  strcpy( temp1, ap_options );
  if((p = strstr( temp1, "%o")) != NULL)
  {
    *p = '\0';
    strcpy( temp2, p+2 );
    strcat( temp1, ap_objfile );
    strcat( temp1, temp2 );

    strcpy( ap_options, temp1 );
  }
  else
  { 
    return ret_make_MISSING_o;
  }
  
  if( (p = strchr( ap_options, '%' )) != NULL)
  {
    strcpy( temp2, p+1 );
    *p = '\0';
    strcpy( temp1, ap_options );
    strcat( temp1, "%%" );
    strcat( temp1, temp2 );

    strcpy( ap_options, temp1 );
  }

  return ret_make_OKAY;
}
/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : ConvertLDOptions                                             |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The constants %O, %L and %e will be replaced by the            |
|               correct filename(s) in the linker options.                     | 
|                                                                              |
|  Parameter: char*       IN/OUT Linker options containing %O, %L and %e       |
|             const char* IN     name of executable file                       |
|  Return:    int         -      errorcode                                     |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int  ConvertLDOptions ( char* ap_options, 
                               const char* ap_exefile)
/*-FDEF S*/
{
  char *p = NULL;
  char temp1[1024];
  char temp2[1024];


  strcpy(temp1, ap_options );
  if((p = strstr( temp1, "%O")) != NULL)
  {
    *p = '\0';
    strcpy( temp2, p+2);
    strcat( temp1, "$(sctOBJECTLIST)" );
    strcat( temp1, temp2);

    strcpy( ap_options, temp1 );
  }
  else
  { 
    /*
    ** for DOS compilers it is not possible to transfer
    ** the complete object list via command line
    ** return ret_make_MISSING_O;
    */
  }

  strcpy(temp1, ap_options );
  if((p = strstr( temp1, "%e")) != NULL)
  {
    *p = '\0';
    strcpy( temp2, p+2);
    strcat( temp1, ap_exefile );
    strcat( temp1, temp2);

    strcpy( ap_options, temp1 );
  }
  else
  { 
    /*
    ** e.g. KEIL compiler is not able to handle
    ** the executable name via command line
    ** return ret_make_MISSING_e; 
    */
  }

  strcpy(temp1, ap_options );
  if((p = strstr( temp1, "%L")) != NULL)
  {
    *p = '\0';
    strcpy( temp2, p+2);
    strcat( temp1, "$(sctLIBRARYLIST) " );
    strcat( temp1, temp2);

    strcpy( ap_options, temp1 );
  }
 
  if( (p = strchr( ap_options, '%' )) != NULL)
  {
    strcpy( temp2, p+1 );
    *p = '\0';
    strcpy( temp1, ap_options );
    strcat( temp1, "%%" );
    strcat( temp1, temp2 );

    strcpy( ap_options, temp1 );
  }

  return ret_make_OKAY;
}



/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : ConvertAROptions                                             |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The constants %O and %l will be replaced by the correct        |
|               filename(s) in the library manager options.                    | 
|                                                                              |
|  Parameter: char*       IN/OUT Linker options containing %O and %l           |
|  Return:    int         -      errorcode                                     |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int  ConvertAROptions ( char* ap_options )
/*-FDEF S*/
{
  char *p = NULL;
  char temp1[4096];
  char temp2[4096];
  char coderobjects[4096];

  #ifdef WIN32
    if(strcmp(GetIniValue( GET_Library_Tool ), "tlib") == 0)
    {
      /*
      ** workaround for Borland compiler
      */  
      const char *p;
      char file_only[2048];
      strcpy(coderobjects, "");
      if((p = GetIniValue( GET_FirstCoderFile )) != NULL )
      {
        do
        {
          strcat( coderobjects, "+$(sctobjdir)\\");
          GetFileOnly( file_only, p);
          strcat( coderobjects, file_only);
          strcat( coderobjects, "$(sctOEXTENSION) ");
        }while((p = GetIniValue( GET_NextCoderFile )) != NULL );
      }
    }
    else
  #endif
  {
    strcpy(coderobjects, "$(sctCODEROBJECTLIST)");
  }


  strcpy(temp1, ap_options );
  if((p = strstr( temp1, "%O")) != NULL)
  {
    *p = '\0';
    strcpy( temp2, p+2);
    strcat( temp1, coderobjects );
    strcat( temp1, temp2);

    strcpy( ap_options, temp1 );
  }
  else
  { 
    /*
    ** for DOS compilers it is not possible to transfer
    ** the complete object list via command line
    ** return ret_make_MISSING_O;
    */
  }

  strcpy(temp1, ap_options );
  if((p = strstr( temp1, "%l")) != NULL)
  {
    *p = '\0';
    strcpy( temp2, p+2);
    strcat( temp1, "sctCoderLibrary$(sctLIBEXTENSION)" );
    strcat( temp1, temp2);

    strcpy( ap_options, temp1 );
  }
  else
  { 
    /*
    ** e.g. KEIL compiler is not able to handle
    ** the executable name via command line
    ** return ret_make_MISSING_e; 
    */
  }

  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : GetFileOnly                                                  |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: This function removes the leading path and the file extension. |
|                                                                              |
|  Parameter:  char* i     IN/OUT filename without path and extension          |
|              const char* IN     filename with path and extension             |
|                                                                              |
|  Return:     -                                                               |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static void GetFileOnly( char* ap_file, const char* ap_fullfile )
/*-FDEF S*/
{
  char *p1;
  char *p2;

  strcpy( ap_file, ap_fullfile );

  if((p1 = strrchr( ap_file, '.')) != NULL)
  {
    *p1 = '\0';
  }

  if((p2 = strrchr(ap_file, '\\')) != NULL)
    strcpy( ap_file, p2+1);

  if((p2 = strrchr(ap_file, '/')) != NULL)
    strcpy( ap_file, p2+1);

  if((p2 = strrchr(ap_file, ')')) != NULL)
    strcpy( ap_file, p2+1);

}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : GetCodeGeneratorMakefile                                     |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The sub-makefile written by the Code Generator will be read    |
|               and copied into the makefile written here.                     |
|                                                                              |
|  Parameter:  -                                                               |
|                                                                              |
|  Return:     int - ret_make_OKAY                                             |
|                    ret_make_MAKEFILE_MISSING                                 |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int  GetCodeGeneratorMakefile( void )
/*-FDEF S*/
{
  FILE *fp_in;
  char readline[512];

  if((fp_in = fopen( CodeGeneratorMakefile, "r")) != NULL)
  {
    fprintf( fp, "\n");
    fprintf( fp, "######################################################\n");
    fprintf( fp, "# BEGIN of the section generated by the Code Generator\n");
    fprintf( fp, "######################################################\n");
    while( fgets( readline, 255, fp_in) != NULL)
    {
      if(strncmp( readline, "GENERATEDMODULES = ", 19) == 0)
      {
        GeneratedModules = atoi( &readline[19] );
        break;
      }
    }
    while( fgets( readline, 255, fp_in) != NULL)
    {
      fprintf( fp, readline );
    }
    fclose( fp_in );
    fprintf( fp, "\n");
    fprintf( fp, "######################################################\n");
    fprintf( fp, "# END of the section generated by the Code Generator  \n");
    fprintf( fp, "######################################################\n");
    return ret_make_OKAY;
  }

  return ret_make_MAKEFILE_MISSING;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : CodeGeneratorObjects                                         |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The list of objects that result in compilation of the generated|
|               files will be written to the list of objects to link.          |
|                                                                              |
|  Parameter:  -                                                               |
|                                                                              |
|  Return:     int -  ret_make_OKAY                                            |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int  CodeGeneratorObjects( void )
/*-FDEF S*/
{
  int i;
  char temp[2048];

  for(i=1; i <= GeneratedModules; i++)
  {
    sprintf( temp, "$(sctSOURCEFILE%d)", i);
    WriteOneObject( temp, "$(sctOEXTENSION)", 1 );
    fprintf( fp, " \\\n" );
  }
  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : CodeGeneratorFiles                                           |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description:  The compilation rules for the generated files will be written |
|                                                                              |
|  Parameter:  -                                                               |
|                                                                              |
|  Return:     int - error code                                                |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int  CodeGeneratorFiles( void )
/*-FDEF S*/
{
  int i;
  int result;
  char src_file[1024];

  for(i=1; i <= GeneratedModules; i++)
  {
    sprintf( src_file, "$(sctSOURCEFILE%d)$(sctSEXTENSION%d)", i, i);

    if((result = WriteOneRule( src_file, 1 )) != ret_make_OKAY)
        return result;
  }  
  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : WriteOneRule                                                 |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: One rule for the compilation of a source file will be written. |
|               Note: This does NOT work for additional files!                 |
|                                                                              |
|  Parameter:   const char* IN the filename                                    |
|               int         IN flag telling if codegenerator file or not       |
|                                                                              |
|  Return:      int         -  result code                                     |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
int  WriteOneRule ( const char* ap_cfile, int a_flag )
/*-FDEF S*/
{
  int result = ret_make_OKAY;
  char ConvertedOptions[2048];
  char file_only[2048];
  char in_file[2048];
  char obj_file[2048];
  char includes[2048];
  char extension[256];
  char* p;
  int marker;
  
  /*
  ** Strip extension and path
  */
  if(a_flag)
  {
    strcpy( file_only, ap_cfile); 
    if((p = strrchr( file_only, '$')) != NULL) //Code Generator file
    {
      *p = '\0';
    }
  }
  else
    GetFileOnly( file_only, ap_cfile);

  /*
  ** surround by " if spaces in filename
  */
  if(CheckFilenameForSpaces( ap_cfile ) || sdtdirGotSpaces)
  {
    marker = TRUE;
    sprintf( in_file, "\"%s\"", ap_cfile);
    fprintf( fp, "\"$(sctobjdir)%c%s$(sctOEXTENSION)\": $(HEADERS) %s\n", SEPARATION_CHAR, file_only, in_file);
  }
  else
  {
    marker = FALSE;
    sprintf( in_file, "%s", ap_cfile);
    fprintf( fp, "$(sctobjdir)%c%s$(sctOEXTENSION): $(HEADERS) %s\n", SEPARATION_CHAR, file_only, in_file);
  }

  /*
  ** Generate pre-compile-step for code generator files
  */
  if(a_flag)
  {
    const char* PreCompileStep;
    if(strlen(PreCompileStep = GetIniValue( GET_PreCompile )) > 0)
    {
      fprintf( fp, "\t");
      if(strstr(PreCompileStep, "%s") !=NULL)
      {
        if(strstr(PreCompileStep, "%s %s") !=NULL)
          fprintf( fp, PreCompileStep, ap_cfile, ap_cfile);
        else
          fprintf( fp, PreCompileStep, ap_cfile);
      }
      else
      {
        fprintf( fp ,PreCompileStep );
      }
      fprintf( fp, "\n");
    }
  }

  /*
  ** check if C parser is used
  */
  if(strlen(GetIniValue( GET_Compiler_Tool2 )) == 0)
    strcpy( extension , "sctOEXTENSION" );
  else
    strcpy( extension , "sctI2EXTENSION" );
       
  /*
  ** calculate command for first compiler tool (normally the only one)
  */
  if(marker)
    sprintf( obj_file, "\"$(sctobjdir)%c%s$(%s)\"", SEPARATION_CHAR, file_only, extension);
  else
    sprintf( obj_file, "$(sctobjdir)%c%s$(%s)", SEPARATION_CHAR, file_only, extension);

  

  /*
  ** workaround for generic functions
  */
  if((strcmp( GetIniValue( GET_GeneratorName), "Cmicro" ) != 0 ) &&
     (strstr(GetIniValue(GET_Compiler_Options), "USER_CONFIG") == NULL) &&
     ( GenericFuncUsed ))
    sprintf( ConvertedOptions, "-DXUSE_GENERIC_FUNC %s", GetIniValue( GET_Compiler_Options ));
  else
    strcpy( ConvertedOptions, GetIniValue( GET_Compiler_Options ));

  if(CodersUsed)
    sprintf(includes, 
            "%s %s %s", 
            GetIniValue( GET_Compiler_LibFlag ), 
            GetIniValue( GET_Compiler_Include ),
            GetIniValue( GET_Compiler_CodInclude ));
  else
    sprintf(includes, 
            "%s %s", 
            GetIniValue( GET_Compiler_LibFlag ), 
            GetIniValue( GET_Compiler_Include ));

  if((result = ConvertCCOptions( ConvertedOptions, 
                                 in_file,
                                 obj_file, 
                                 includes )) == ret_make_OKAY)
  {
    WriteCommand( fp, "$(sctCC)", ConvertedOptions );
  }

  if(strlen(GetIniValue( GET_Compiler_Tool2 )) > 0)
  {
    strcpy( in_file, obj_file );
    /*
    ** check if assembler is used
    */
    if(strlen(GetIniValue( GET_Compiler_Tool3 )) == 0)
      strcpy( extension , "sctOEXTENSION" );
    else
      strcpy( extension , "sctI3EXTENSION" );

    /*
    ** calculate command for second compiler tool (i.e. C parser)
    */
    if(marker)
      sprintf( obj_file, "\"$(sctobjdir)%c%s$(%s)\"", SEPARATION_CHAR, file_only, extension);
    else
      sprintf( obj_file, "$(sctobjdir)%c%s$(%s)", SEPARATION_CHAR, file_only, extension);

    strcpy( ConvertedOptions, GetIniValue( GET_Compiler_Options2 ));

    if((result = ConvertCC2or3Options( ConvertedOptions, 
                                       in_file,
                                       obj_file)) == ret_make_OKAY)
    {
      WriteCommand( fp, "$(sctCC2)", ConvertedOptions );
    }

    if(strlen(GetIniValue( GET_Compiler_Tool3 )) > 0)
    {
      strcpy( in_file, obj_file );
      /*
      ** calculate command for second compiler tool (i.e. assembler)
      */
      if(marker)
        sprintf( obj_file, "\"$(sctobjdir)%c%s$(sctOEXTENSION)\"", SEPARATION_CHAR, file_only);
      else
        sprintf( obj_file, "$(sctobjdir)%c%s$(sctOEXTENSION)", SEPARATION_CHAR, file_only);

      strcpy( ConvertedOptions, GetIniValue( GET_Compiler_Options3 ));

      if((result = ConvertCC2or3Options( ConvertedOptions, 
                                         in_file,
                                         obj_file)) == ret_make_OKAY)
      {
        WriteCommand( fp, "$(sctCC3)", ConvertedOptions );
      }
    }
  }

  fprintf( fp, "\n" );
  return result;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : WriteOneObject                                               |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: An object-list entry for the given file with the given         |
|               extension is generated                                         |
|                                                                              |
|  Parameter:   const char* IN the filename without path and extension         |
|               const char* IN the extension                                   |
|               int         IN flag telling if codegenerator file or not       |
|                                                                              |
|  Return:      -                                                              |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static void WriteOneObject( const char* ap_filename, 
                            const char* ap_extension, 
                            int a_flag)
/*-FDEF S*/
{
  char file_only[2048];

  if(a_flag)
    strcpy( file_only, ap_filename); //Code Generator file
  else
    GetFileOnly( file_only, ap_filename);

  if(CheckFilenameForSpaces( file_only ))
    fprintf( fp, "                \"$(sctobjdir)%c%s%s\"", SEPARATION_CHAR, file_only, ap_extension); 
  else
    fprintf( fp, "                $(sctobjdir)%c%s%s", SEPARATION_CHAR, file_only, ap_extension); 
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : WriteCommand                                                 |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The complete compiler command line is written into file        |
|                                                                              |
|  Parameter:   FILE*        IN  filepointer                                   |
|               const char*  IN  compiler tool                                 |
|               const char*  IN  compiler options                              |
|                                                                              |
|  Return:      -                                                              |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static void WriteCommand ( FILE* ap_file, 
                           const char* ap_cmd, 
                           const char* ap_options )
/*-FDEF S*/
{
  const char *p;

  fprintf( fp, "\t%s ", ap_cmd );

  p = GetIniValue( GET_Make_ResponseStart );
  while( *p != '\0' )
  {
    if( *p == '\\' )
    {
      if(*(p+1) == 'n' ) 
        { fputc( (int) '\n', fp); p+=2; }
      else
         if(*(p+1) == 't' ) 
           { fputc( (int) '\t', fp); p+=2; }
         else
           { fputc( (int) *p, fp); p++; }
    }
    else
    {
      fputc( (int) *p, fp);
      p++;
    }
  } 

  fprintf( fp, ap_options );

  p = GetIniValue( GET_Make_ResponseEnd );
  while( *p != '\0' )
  {
    if( *p == '\\' )
    {
      if(*(p+1) == 'n' ) 
        { fputc( (int) '\n', fp); p+=2; }
      else
         if(*(p+1) == 't' ) 
           { fputc( (int) '\t', fp); p+=2; }
         else
           { fputc( (int) *p, fp); p++; }
    }
    else
    {
      fputc( (int) *p, fp);
      p++;
    }
  }

  fprintf( fp, "\n" );
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : ReadUserSections                                             |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: The user section will be read in and saved.                    |
|                                                                              |
|  Parameter:  -                                                               |
|                                                                              |
|  Return:     int - ret_make_OKAY                                             |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int ReadUserSections( void )
/*-FDEF S*/
{
  char readline[512];

  while(fgets(readline, 256, fp) != NULL)
  {
    if(strncmp(readline, UserObjectsStart, strlen(UserObjectsStart)) == 0)
    {
      strcpy(UserObjects, readline);
      while(fgets(readline, 256, fp) != NULL)
      {
        strcat(UserObjects, readline);
        if(strncmp(readline, UserObjectsEnd, strlen(UserObjectsEnd)) == 0)
        {
          break;
        }
      } 
    }
    if(strncmp(readline, UserRulesStart, strlen(UserRulesStart)) == 0)
    {
      strcpy(UserRules, readline);
      while(fgets(readline, 256, fp) != NULL)
      {
        strcat(UserRules, readline);
        if(strncmp(readline, UserRulesEnd, strlen(UserRulesEnd)) == 0)
        {
          break;
        }
      } 
    }
  }
  return ret_make_OKAY;
}

/*+FHDR S*/
/*
+------------------------------------------------------------------------------+
|  Functionname : CheckFilenameForSpaces                                       |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: This function checks if a filename contains spaces.            |
|                                                                              |
|  Parameter:   const char* IN the filename                                    |
|                                                                              |
|  Return:      int         - 1 = spaces found , 0 = no spaces found           |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR S*/

/*+FDEF S*/
static int  CheckFilenameForSpaces( const char* a_filename)
/*-FDEF S*/
{
  const char* p = a_filename;

  for( ; *p != '\0'; p++)
  {
    if(*p == ' ') return 1;
  }
  return 0;
}

#ifdef MAKEGEN
/*+FHDR E*/
/*
+------------------------------------------------------------------------------+
|  Functionname : main                                                         |
+------------------------------------------------------------------------------+
|                                                                              |
|  Description: This main function is used only if an external makefile        |
|               generator will be build.                                       |
|               it reads in the parameter file and generates the makefile.     |
|                                                                              |
|  Parameter:   argc                                                           |
|               argv                                                           |
|                                                                              |
|  Return:      int  - error code                                              |
|                                                                              |
+------------------------------------------------------------------------------+
*/
/*-FHDR E*/

/*+FDEF E*/
int main( int argc, char* argv[] )
/*-FDEF E*/
{
  int generic_func = FALSE;

  if( argc < 5 )
  {
    fprintf( stderr, "MAKEGEN %s\n", SUGetTAUVersionString());
    fprintf( stderr, "ERROR: Wrong number of arguments!\n");
    fprintf( stdout, "       Usage: makegen <parameter_file> <targetdirectory> <selected_item> <genericfunctions>\n");
    fprintf( stdout, "This application is used by the Targeting Expert (sdttaex) to generate a makefile.\n");
  }
  else
  {
    if(ReadParameterFile( argv[1] ) == 0)
    { 
      if( strcmp(argv[4], "YES") == 0)
        generic_func = TRUE;

      switch( GenerateMakefile( argv[2], GetIniValue( GET_MakefileName ), argv[3], generic_func) )
      {
        case ret_make_OKAY:
             return 0;
             break;

        case ret_make_FILEOPEN:
             fprintf( stderr, 
                      "Cannot open makefile <%s> for writing.\n", 
                      GetIniValue( GET_MakefileName ));
             break;

        case ret_make_MISSING_s:
             fprintf( stderr, 
                      "%s not found in Compiler or additional Compiler options.\n");
             break;

        case ret_make_MISSING_o:
             fprintf( stderr, 
                      "%o not found in Compiler or additional Compiler options.\n");
             break;

        case ret_make_MISSING_I:
             fprintf( stderr, 
                      "%I not found in Compiler or additional Compiler options.\n");
             break;

        case ret_make_MISSING_O:
             fprintf( stderr, 
                      "%O not found in Linker options.\n");
             break;

        case ret_make_MISSING_e:
             fprintf( stderr, 
                      "%e not found in Linker options.\n");
             break;

        case ret_make_MAKEFILE_MISSING:
             fprintf( stderr, 
                      "The Code Generator's makefile >%s_gen.m< was not found.\n",
                      argv[3]);
             break;

        case ret_make_MAKETOOLUNKNOWN:
             fprintf( stderr, 
                      "Selected make tool is not known.\n");
             break;

        case ret_make_ERROR:
        default:
             fprintf( stderr, 
                      "Unspecified error in makefile generation.\n");
             break;
      }
    }
  }
  return -1;
}
#endif

#endif /* ... _MAKEGEN_C_ */

