/****************************************************************************
**
**  Name:  lprofile.c
**
**  Description:
**     Provides profile services for the IEEE695 loader.
**     1. Use CLIULIB to locates PWRVIEWS.INI
**     2. Extract [Compiler] - Compiler definition.
**     3. If ToolUsing == "Unknown" then popup a dialog box to let
**        the user selects the compiler using - save as default.
**
**  Status:  CODED | REVIEWED | TESTED
**
**  $Log:   S:/tbird/mt2_186/loader/lprofile.cpv  $
** 
**    Rev 1.1   26 Feb 1997 11:50:10   Judy
** 
**    Rev 1.0   14 Jun 1996 17:25:40   Judy
** Initial revision.
** 
**    Rev 1.3   17 Jun 1994 11:38:32   nghia
** Fixed Compiler warning on pointer conversion.
** 
**    Rev 1.2   03 Jun 1994 15:02:10   nghia
** Used LdrSendMessageToCLI to output message.
** 
**    Rev 1.1   23 May 1994 16:52:08   nghia
** Corrected GetToolUse operation to write the selection to the INI file.
** 
**    Rev 1.0   18 May 1994 17:00:20   nghia
** Initial revision.
** 
**  $Header:   S:/tbird/mt2_186/loader/lprofile.cpv   1.1   26 Feb 1997 11:50:10   Judy  $
**
**  Copyright (C) 1993 Microtek International.  All rights reserved.
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include <stdio.h>
#include <string.h>
#include <mem.h>
#include <stdlib.h>

#ifndef _BASEWIND_
#include "basewind.h"
#endif

#ifndef _CPU_
#include "cpu.h"
#endif

#ifndef _HEAP_
#include "heap.h"
#endif

#ifndef  _LOADER_
#include "loader.h"
#endif

#ifndef __LPROFILE__
#include "lprofile.h"
#endif

#ifndef _PROC_
#include "proc.h"
#endif

#ifndef _HLPENTRY_
#include "hlpentry.h"   // provide help hook up
#endif

#ifndef __LDROBJ__
#include "ldrobj.h"     // provide declaration of LdrLauncher object
#endif

#ifndef _INIUTIL_
#include "iniutil.h"    // provide INI accessing routines
#endif

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/

/* Table of pointer to all names in toolsSupport */
CHAR *toolNameTbl[MAX_NUM_TOOLS_SUPPORT];
U8 numToolsSupport = 0;

// Selected ToolName
CHAR selToolName[MAX_STRING_SIZE];
// SelTool DlgBox Global variables 
U16 selToolId = 0;
BOOLEAN mergeSections = FALSE;

                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
extern HANDLE hLib;                 // defined in LIBMAIN
extern PTLdrLauncher LoaderServer;

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/
PRIVATE RETCODE GetToolsSupport(VOID);
PRIVATE RETCODE GetUserSelectTool(HWND);
PRIVATE VOID ClearToolNameTable(VOID);

                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/
/* IMPORTANT:
** This module must be compiled with BYTE aligment.
** Only support Borland compiler for now. Any other compiler needs to check
** for options to compile with BYTE alignment.
*/
#ifdef __BORLANDC__
#pragma option -a-
#endif

/******************************************************************************
**
**  LdrGetToolUse
**
******************************************************************************/
RETCODE EXPORT LdrGetToolUse(U32 parentWnd, LPSTR toolName,
                             BOOLEAN selectNewTool) {
   RETCODE err;

   // only open dialog if Caller said so
   if (selectNewTool && parentWnd &&
      ((err = GetToolUseDialog((HWND)parentWnd)) != GOOD)) {
      // user not required to specify tool,
      // so don't flag unknown as error 
      if (err != ER_NO_TOOLUSE_DEFINED)
         return err;
   }
   // a Tool is selected.
   // If Caller specified a buffer then copy the selToolName to return
   if (toolName && selToolName)
      lstrcpy(toolName, selToolName);
   return GOOD;
}

/******************************************************************************
**
**  LdrCliSetToolUse
**
******************************************************************************/
RETCODE EXPORT LdrCliSetToolUse(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err = GOOD;
   CHAR tmpString[80];
   U16 strLength;

   if (!LoaderServer || LoaderServer->Status() != GOOD)
      return ER_LDR_INVALID_SERVER;

   // make sure thers is no load operation going 
   if (LoaderServer->IsLoading())
      return(ER_LDR_IN_PROGRESS);
   
   // User enter :>CompilerUsed to view the current CompilerUsed setting
   // print out the current setting
   if (argc < 2) {
      // get CompilerUsed information from PWRVIEWS.INI 
      if ((err = IniGetString((LPSTR) LAPP_NAME, (LPSTR) LAPP_TOOL_USE,
         PWRVIEWS_INI_DEFAULT, (LPSTR) selToolName)) != GOOD)
         return err;
      // init tmpString to empty string and form the result message
      tmpString[0] = (CHAR)'\0';
      lstrcat((LPSTR)tmpString, (LPSTR)&cmdString[(U16)argv[0]]);
      lstrcat((LPSTR)tmpString, "=");
      lstrcat((LPSTR)tmpString, (LPSTR) selToolName);
      return LdrSendMessageToCLI(tmpString);
   }

   // get the "CompilerUsed" specified and verify 
   if ((lstrcpy((LPSTR) selToolName,
                (LPSTR) &cmdString[(U16)argv[1]]) == NULL)
                || ((strLength = strlen(selToolName)) == 0)) 
      return ER_MUST_DEFINE_TOOLUSE;
   // check if input tool name is greater than the MAX_TOOL_NAME
   if (strLength > MAX_TOOL_NAME)
      return ER_CLI_SYNTAX;
   
   // check if the arguments is none - Set "CompilerUsed" = UNKNOWN 
   if (strcmpi(selToolName, ARG_NONE) == 0) {
      strcpy(selToolName, TOOL_UNKNOWN);
   } else {
      if (selToolName[0] == '=')
		  return ER_CLI_SYNTAX;
	}
   // Save the selToolName to PWRVIEWS.INI
   if ((err = IniSetString((LPSTR) LAPP_NAME,(LPSTR) LAPP_TOOL_USE,
                   PWRVIEWS_INI_DEFAULT, (LPSTR) selToolName)) != GOOD) {
      // set selToolName to NULL
      selToolName[0] = '\0'; 
      return err;
   }
   // "CompilerUsed" has been defined and saved into the PWRVIEWS.INI
   return SetToolUse();
}

/******************************************************************************
**
**  LdrCliSetSecNames
**
******************************************************************************/
RETCODE EXPORT LdrCliSetSecNames(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err = GOOD;
   CHAR sectionNames[MAX_STRING_SIZE], tmpString[MAX_STRING_SIZE];

   if (!LoaderServer || LoaderServer->Status() != GOOD)
      return ER_LDR_INVALID_SERVER;

   /* Check semaphore to prevent statics from getting trashed */
   if (LoaderServer->IsLoading())
      return ER_LDR_IN_PROGRESS;
 
   // User enter :>SectionNamesUsed to view the current SectionNames setting
   // initialize sectionNames to NULL 
   sectionNames[0] = '\0'; 
   if ((IniGetString((LPSTR) LAPP_NAME, (LPSTR) LAPP_TOOL_USE,
        PWRVIEWS_INI_DEFAULT, (LPSTR) selToolName) != GOOD)
        || (strcmpi(selToolName, TOOL_UNKNOWN) == 0))
      return ER_NO_TOOLUSE_DEFINED;

   if (argc < 2) {
      if ((IniGetString((LPSTR) LAPP_NAME, (LPSTR) selToolName,
                       NULL, (LPSTR) sectionNames) != GOOD) ||
            (strlen(sectionNames) == 0))
         return ER_NO_SECTION_NAME_DEFINED;
      tmpString[0] = '\0'; /* init tmpString */
      lstrcat((LPSTR)tmpString, (LPSTR)selToolName);
      lstrcat((LPSTR)tmpString, "=");
      lstrcat((LPSTR)tmpString, (LPSTR)sectionNames);
      return LdrSendMessageToCLI(tmpString);
   }

   //  get the "sectionNames" specified and verify */
   if ((lstrcpy((LPSTR) sectionNames,
                (LPSTR)&cmdString[(U16)argv[1]]) == NULL) ||
                (lstrlen(sectionNames) == 0)) {
      return(ER_NO_SECTION_NAME_DEFINED);
   }
   // check for sectionNames delimiter ',' for validity 
   if (_fstrstr((LPSTR)sectionNames, (LPSTR) DELIMITER_SET) == NULL)
      return(ER_INVALID_SECTION_NAME);
   //
   // Save the user specified section names back into the PWRVIEWS.INI
   // using "CompilerUsed" as key for the sectionNames.
   //
   if ((err = IniSetString((LPSTR) LAPP_NAME, (LPSTR) selToolName,
         PWRVIEWS_INI_DEFAULT, (LPSTR) sectionNames)) != GOOD) 
      return err;

   // Section names of "CompilerUsed" has been defined and saved into
   // the PWRVIEWS.INI
   return(GOOD);
}

/******************************************************************************
**
**  LdrCliMergeSections
**
******************************************************************************/
RETCODE EXPORT LdrCliMergeSections(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   BOOLEAN mergeValue;
   CHAR tmpString[80];
   U32 tmpVal = 0;
   
   if (!LoaderServer || LoaderServer->Status() != GOOD)
      return ER_LDR_INVALID_SERVER;

   /* Check semaphore to prevent statics from getting trashed */
   if (LoaderServer->IsLoading())
      return(ER_LDR_IN_PROGRESS);

   /* User enter :>MergeSections to view the current MergeSections setting */
   if (argc < 2) {
      // Get <MergeSections> value from PWRVIEWS.INI file
      if ((err = IniGetNumber((LPSTR) LAPP_NAME, (LPSTR) LAPP_MERGE_SEC,
          PWRVIEWS_INI_DEFAULT, (U32 FAR *)&tmpVal)) != GOOD)
         return err;
      mergeValue = (BOOLEAN) tmpVal;    
      tmpString[0] = (CHAR)'\0'; /* init tmpString */
      lstrcat((LPSTR)tmpString, (LPSTR)&cmdString[(U16)argv[0]]);
      lstrcat((LPSTR)tmpString, "=");
      if (mergeValue)
         lstrcat((LPSTR)tmpString, (LPSTR)"on");
      else
         lstrcat((LPSTR)tmpString, (LPSTR)"off");

      // Return the result to CLI 
      return LdrSendMessageToCLI(tmpString);
   }
   
	// Save the specified value to PWRVIEWS.INI 
   if (lstrcmpi((LPSTR)"on", &cmdString[(U16)argv[1]]) == 0) {
      if ((err = IniSetNumber((LPSTR) LAPP_NAME, (LPSTR) LAPP_MERGE_SEC,
           PWRVIEWS_INI_DEFAULT, 1L)) != GOOD)
         return err;
      mergeSections = TRUE;      
   }
   else if (lstrcmpi((LPSTR)"off", &cmdString[(U16)argv[1]]) == 0) {
      if ((err = IniSetNumber((LPSTR) LAPP_NAME, (LPSTR) LAPP_MERGE_SEC,
           PWRVIEWS_INI_DEFAULT, 0L)) != GOOD)
         return err;
      mergeSections = FALSE;
   }
   else {
      return ER_CLI_SYNTAX;
   }
   /* "MergeSections" has been defined and saved into the PWRVIEWS.INI */
   return GOOD;
}

/******************************* LOCAL FUNCTIONS ****************************/

/******************************************************************************
**
**  GetToolUseDialog
**
**  Status: CODED | REVIEWED | TESTED
**
**  Description:
**     Create a dialog for LdrGetToolUse.  Get user select <CompilerUsed>.
**
**  Parameters:
**     input:
**        none.
**     output:
**        none.
**
******************************************************************************/
RETCODE GetToolUseDialog(HWND parentWnd) {
   RETCODE err;

   /* Popup a dialog box to get ToolUse from the user */
   if (((err = GetUserSelectTool(parentWnd)) != GOOD) &&
      (err != ER_NO_TOOLUSE_DEFINED)) return err;
   //
   // GetUserSelectTool set the selToolId as index into toolNames table.
   // Save the user select tool name back into the PWRVIEWS.INI
   // "CompilerUsed" as the default from now on.
   //
   return IniSetString((LPSTR) LAPP_NAME,(LPSTR) LAPP_TOOL_USE,
                   PWRVIEWS_INI_DEFAULT, (LPSTR) selToolName);
}

/******************************************************************************
**
**  GetToolsSupport
**
**  Status: CODED | REVIEWED | TESTED
**
**  Description: Extract all tools name that PowrViews currently supported.
**        Read them from the PRWVIEWS.INI file [ToolChain] - "Compilers"
**
**  Parameters:
**     input:
**        none
**     output:
**        none
**
******************************************************************************/
PRIVATE RETCODE GetToolsSupport(VOID) {
   LOOP_VAR i = 0;
   U8 strSize;
   CHAR tmpStr[MAX_STRING_SIZE], *loopPtr, *toolNamePtr = NULL;

   if (numToolsSupport > 0)
      return GOOD;
   if (IniGetString((LPSTR) LAPP_NAME, (LPSTR) LAPP_TOOLS_SUPPORT,
          PWRVIEWS_INI_DEFAULT, (LPSTR) tmpStr) != GOOD) {
      return(ER_NO_TOOLS_SUPPORT_DEFINED);
   }
   else {
      /* initialize toolNameTbl[] */
      for (i = 0; i < MAX_NUM_TOOLS_SUPPORT; i++)
         toolNameTbl[i] = NULL;

      /* Parse tmpStr into tool names and store into toolNameTbl[] table */
      loopPtr = tmpStr;
      i = 0;
      do {
         // strtok return the pointer to the token found in tmpStr 
         if ((toolNamePtr = strtok(loopPtr, DELIMITER_SET)) != NULL) {
            if ((strSize = strlen(toolNamePtr)+1) > MAX_TOOL_NAME)
               return(ER_TOOL_NAME_TOO_LONG);
            else {
               // Allocate memory for toolNameTbl[i] 
               if ((toolNameTbl[i] = (CHAR *)TMalloc(strSize)) == NULL)
                 return(ER_NO_MEMORY);
            }
            // Copy the name into table
            if (strncpy(toolNameTbl[i], toolNamePtr, strSize) == NULL)
               return(ER_CANNOT_GET_TOOL_NAME);
         }
         else {
            // Something wrong with the defined string 
            if (i == 0) return(ER_MISSING_TOOLS_SUPPORT);
            // As long as we have some tools defined we're happy to exit :-) 
            break;
         }
         ++i;
         // reset to walk the rest of the string tmpStr 
         loopPtr = NULL; 
      } while (i < MAX_NUM_TOOLS_SUPPORT);
   }
   // Save the number of toolsSupport read in 
   numToolsSupport = (i <= MAX_NUM_TOOLS_SUPPORT) ? i : MAX_NUM_TOOLS_SUPPORT;
   return(GOOD);
}

/******************************************************************************
**
** LdrSelToolDlgProc
**
** Description: Get the index of CompilerUsed to locate the tool name in the
**    global table toolNameTbl[].
**
** Parameters:
**    input:
**       hDlg          - The window handle for this message
**       iMsg          - The message number
**       wParam        - The WORD parmater for this message
**       lParam        - The LONG parmater for this message
**
**    output:
**       depend on message
**
******************************************************************************/
#pragma argsused
BOOL FAR PASCAL LdrSelToolDlgProc(HWND hDlg, WORD iMsg, WORD wParam,
   LONG lParam) {
   /* NOTES: without static modifier, local variables will not hold value */
   static WORD maxNumItems, newselToolId;

   switch(iMsg) {
      case WM_INITDIALOG:
         /* Used the global numToolsSupport to compute the maxNumItems */
         newselToolId = selToolId;
         maxNumItems = IDD_UNKNOWN+numToolsSupport;
         CheckRadioButton(hDlg, IDD_UNKNOWN, maxNumItems,
                             newselToolId+IDD_UNKNOWN);
         /* Set to the next item to have dialog focus */
         SetFocus(GetDlgItem(hDlg, newselToolId+IDD_UNKNOWN));
         return(TRUE);

      case WM_COMMAND:
         switch(wParam) {
            case IDD_OK:
               /* Get the new tool selected */   
               selToolId = newselToolId;
               EndDialog(hDlg, TRUE);
               return(TRUE);

            case IDD_CANCEL:
               EndDialog(hDlg, FALSE);
               return(TRUE);

            case IDHELP:
               WinHelp(hDlg, "PWRVIEWS.HLP",
                  HELP_CONTEXT, HE_SELECT_COMPILER_DIALOG);
               return (FALSE);

            default:
               /* Process all button ID */
               if ((wParam >= IDD_UNKNOWN) && (wParam <= maxNumItems)) {
                  newselToolId = wParam - IDD_UNKNOWN;
                  CheckRadioButton(hDlg, IDD_UNKNOWN, maxNumItems, wParam);
                  return(TRUE);
               }
               return(FALSE);
         } /* end of switch(wParam) */

   }
   return(FALSE);
}

/******************************************************************************
**
**  GetUserSelectTool
**
**  Status: CODED | REVIEWED | TESTED
**
**  Description:
**     Since the "CompilerUsed" is Unknown, user must specify the toolused to
**     allow the loader loads the section names.
**
**  Parameters:
**     input:
**        none
**     output:
**        none
**
******************************************************************************/
PRIVATE RETCODE GetUserSelectTool(HWND parentWnd) {
   RETCODE err;
   HANDLE  hDlgTemplate = 0;
   FARPROC lpfnLdrSelToolDlgProc;
   S16     dlgStatus;
   
   /* Extract all ToolsSupport names and save into global numToolsSupport */
   if ((err = GetToolsSupport()) != GOOD) {
      /* Free up the toolNameTbl table */
      ClearToolNameTable();
      return(err);
   }
   /* Dynamically create the Tools Select dialog box - used hDlgTemplate */
   if ((err = CreateDlgTemplate((HANDLE *)&hDlgTemplate)) != GOOD) {
      /* Free up the toolNameTbl table - No longer need it */
      ClearToolNameTable();
      GlobalFree(hDlgTemplate);
      return(err);
   }

   /* Indirectly create a dialog box and run it modal */
   if ((lpfnLdrSelToolDlgProc = (FARPROC) MakeProcInstance(
               (FARPROC)LdrSelToolDlgProc, hLib)) != NULL) {
      /*
      ** IMPORTANT: DialogBoxIndirect requires hDlgTemplate to be a Global
      ** handle. So do not attempt to change it to pointer, or it won't work.
      ** DialogBoxIndirect() return parameter of EndDialog() - TRUE/FALSE
      */
      if ((dlgStatus = DialogBoxIndirect(hLib, hDlgTemplate, parentWnd,
                                         lpfnLdrSelToolDlgProc)) == -1) {
         ClearToolNameTable();
         GlobalFree(hDlgTemplate);
         FreeProcInstance(lpfnLdrSelToolDlgProc);
         return(ER_NO_TOOLUSE_DEFINED);
      }
      /* Clean up */
      FreeProcInstance(lpfnLdrSelToolDlgProc);
      /* Copy user select name to global selToolName variable */
      strcpy(selToolName, toolNameTbl[selToolId]);
   }
   /* CreateDlgTemplate() allocates memory for hdlgTemplate,
   ** so free it when exit.
   */
   ClearToolNameTable();
   GlobalFree(hDlgTemplate);
   if (!dlgStatus) // User cancel the dialog - no change
      return GOOD;
   return (selToolId != 0) ? GOOD : ER_NO_TOOLUSE_DEFINED;
}

/******************************************************************************
**
**  ClearToolNameTable
**
******************************************************************************/
PRIVATE VOID ClearToolNameTable(VOID) {
   LOOP_VAR i;

   for (i = 0; i < numToolsSupport; i++) {
       if (toolNameTbl[i] != NULL)
          TFree(toolNameTbl[i]);
   }
   numToolsSupport = 0;
}

/****************************************************************************
**
** SetToolUse
**
*****************************************************************************/
RETCODE SetToolUse(VOID) {
   LOOP_VAR i;
     
   // Extract all ToolsSupport names and save into global numToolsSupport 
   if (GetToolsSupport() == GOOD) {
      // Need to set selToolId for dialogbox
      for (i = 0; i < numToolsSupport; i++) {
         if (lstrcmp((LPSTR)toolNameTbl[i], (LPSTR) selToolName) == 0) {
            selToolId = i;
            break;  // found the selToolId - exit
         }
      }
   }
   // Free up the toolNameTbl table 
   ClearToolNameTable();
   return GOOD;
}

/******************************** E O F ***********************************/

