/****************************************************************************
**
**  Name:  lprofile.c
**
**  Description:
**     Provides profile control services for the IEEE695 loader.
**     1. Locates MICEPACK.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.
**     4. Extract compiler's section names.
**
**  Status:  CODED | REVIEWED | TESTED
**
**  $Log:   S:/tbird/arcppc/l695/lprofile.c_v  $
** 
**    Rev 1.0   17 Jan 1997 09:21:28   kevin
** Initial revision.
** 
**    Rev 1.2   09 Sep 1996 09:47:36   kevin
** Hera's modification
** 
**    Rev 1.1   02 Aug 1996 12:58:26   Judy
** 
**    Rev 1.0   10 Jul 1996 15:31:20   Judy
** Initial revision.
** 
**    Rev 1.0   07 Sep 1995 10:32:20   gene
** Initial revision.
** 
**    Rev 1.15   29 Mar 1994 18:06:20   nghia
** Removed the un-official WhiteSmith Tool - not COSMIC.
** 
**    Rev 1.14   03 Mar 1994 11:56:12   john
** Added CPU32+ handling
** 
**    Rev 1.13   25 Feb 1994 16:43:52   nghia
** Changes pwrViewsDir[] size to use the global MAX_PATH_SIZE definition.
** 
**    Rev 1.12   26 Oct 1993 17:45:34   nghia
** Fixed PPR 9038 - selectTool is changed when user presses CANCEL/ESC.
** 
**    Rev 1.11   23 Sep 1993 11:06:22   nghia
** Fixed PPR 8767 and 8812 - CompilerUsed dialog box should show the current
** compiler selection.
** - InitDialog will select button according to the tooSelect value (index)
** - Get ToolUseName will check for toolSelect value at start up.
** 
**    Rev 1.9   23 Aug 1993 10:44:38   nghia
** Fixed bug 'mergeSections command does not function.
** Remove unnescessary check for toolSeclect id - it must be > IDD_UNKNOWN.
** 
**    Rev 1.8   03 Aug 1993 17:43:20   nghia
** Fixed PPR 8734:
** - Loader check for PWRVIEWS dir and toolUseName once.  Shell command 
** CompilerUsed will automatically set/get the new toolUsed.
** - Removed LERR_xxxx to use standard error codes.
** 
**    Rev 1.7   27 Jul 1993 22:39:10   nghia
** Cleanup.
** 
**    Rev 1.6   26 Jul 1993 17:29:44   tom
** Finished changes for PPRs 8614, 8628.
** 
**    Rev 1.5   26 Jul 1993 14:13:58   tom
** ppr 8614, 8628
** 
**    Rev 1.4   22 Jul 1993 16:19:52   ron
** pprs 8378, 8379, 8380: select compiler used dialog needs less whitespace,
** help button, shortcut keys.
** 
**    Rev 1.3   16 Jun 1993 08:26:56   mindy
** When the compiler string is updated we need to inform the CPU server
** which register to use as the frame pointer.
** 
**    Rev 1.1   18 Mar 1993 17:15:20   nghia
** Revised to moved GetSetionNames to private.
** Fixed bug in setting global flag.
** 
**    Rev 1.0   08 Mar 1993 10:09:50   nghia
** Initial revision.
**
**  $Header:   S:/tbird/arcppc/l695/lprofile.c_v   1.0   17 Jan 1997 09:21:28   kevin  $
**
**  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 __LDR__
#include "ldr.h"
#endif

#ifndef __ERR__
#include "err.h"
#endif

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

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

#ifndef _HLPENTRY_
#include "hlpentry.h"
#endif
                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/


/* Global table of Section Names */
CHAR sectionNames[MAX_NUM_SECTION_NAMES][SIZE_SECTION_NAME];

/* Global MICEPACK.INI path */
CHAR pwrViewsDir[MAX_PATH_SIZE];

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

CHAR toolUseName[MAX_STR_SIZE];
U8 numToolsSupport = 0;
BOOLEAN hasToolUseDefined = FALSE;
BOOLEAN hasPwrViewsDir = FALSE;

/* SelTool DlgBox Global variables */
U16 toolSelect = 0;

//**Hera 08/27/96**/
BOOLEAN MRI45;
//**Hera**/

                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
extern HWND hWnd;                   /* defined in LDR.C */
extern HANDLE hInst;                /* defined in LINIT.C */
extern BOOLEAN mergeSections;       /* defined in LSECTION.C */     

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/
PRIVATE RETCODE GetToolsSupport(VOID);
BOOL FAR PASCAL LdrSelToolDlgProc(HWND hDlg, WORD iMsg, WORD wParam,
   LONG lParam);
RETCODE GetUserSelectTool(VOID);
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

/******************************************************************************
**
**  FindIniFile
**
**  Description:
**     Locate the MICEPACK.INI file for the Loader to extract profile strings.
**
**  Parameters:
**     input:
**        none
**     output:
**        ErrorCode (GOOD or ER_XXX).
**
******************************************************************************/
RETCODE FindIniFile(VOID) {
   CHAR tmpStr[MAX_STR_SIZE];
   S16 numChars;
   FILE *tmpFile;

   /* Get "pwrviewsdir" from WIN.INI */
   if (hasPwrViewsDir)
      return(GOOD);
   if ((numChars = GetProfileString((LPSTR) WAPP_NAME, (LPSTR) WAPP_KEY,
      (LPSTR) "", (LPSTR) tmpStr, MAX_STR_SIZE)) == 0) {
      /* Find the Windows directory to look again */
      if ((numChars = GetWindowsDirectory(tmpStr, MAX_STR_SIZE)) == 0)
         return(ER_CANNOT_FIND_WDIR);
      else {
         /* Build path to locate MICEPACK.INI file in WINDOWS  dir */
         strcat(tmpStr, "\\micepack.ini");
         if ((tmpFile = fopen(tmpStr, "r")) == NULL)
            return(ER_CANNOT_FIND_PFILE);
      }
   }
   else {
      /* Check to makesure the fielname specified in WIN.INI exist */
      strcat(tmpStr, "\\micepack.ini");
      if ((tmpFile = fopen(tmpStr, "r")) == NULL)
         return(ER_CANNOT_FIND_PFILE);
   }
   /* Save the file name to global variable for later use */
   strcpy(pwrViewsDir, tmpStr);
   hasPwrViewsDir = TRUE;
   fclose(tmpFile);
   return(GOOD);
}

/******************************************************************************
**
**  LdrGetToolUse:  public entry point to GetToolUse.
**
******************************************************************************/
RETCODE EXPORT LdrGetToolUse(VOID) {
   RETCODE err;

   if (((err = FindIniFile()) != GOOD) ||
      ((err = GetToolUseDialog()) != GOOD)) {
      /* user not required to specify tool, so don't flag unknown as error */
      if (err != ER_NO_TOOLUSE_DEFINED)
         return(err);
   }
   /* Get sectionNames of the toolUseName */
   if ((err = GetSectionNames()) != GOOD)
      return(err);
   hasToolUseDefined = TRUE;
   
   return(GOOD);
}

/******************************************************************************
**
**  GetToolUse
**
**  Status: CODED | REVIEWED | TESTED
**
**  Description:
**     Extract the name of ToolUse from MICEPACK.INI file. Save the tool
**     name into toolUseName variable.
**
**  Parameters:
**     input:
**        none.
**     output:
**        none.
**
******************************************************************************/
RETCODE GetToolUse(VOID) {
   RETCODE err;

   //reset -- **Hera 08/30/96**/
   MRI45 = FALSE;
   //**Hera**/

   if (hasToolUseDefined)
      return(GOOD);
   /* Check if name of ToolUse is valid - otherwise ask user to select */
   if ((GetPrivateProfileString((LPSTR) LAPP_NAME, (LPSTR) LAPP_TOOL_USE,
      "", (LPSTR)toolUseName, MAX_STR_SIZE,(LPSTR) pwrViewsDir) == 0) ||
      (strcmpi(toolUseName, TOOL_UNKNOWN) == 0) )  {
      /* Check if the first time user run the system and load from the CLI */
      if (hWnd == NULL) return(ER_MUST_DEFINE_TOOLUSE);
      if ((err = GetToolUseDialog()) != GOOD)  return(err);
   }
   /* Get MergeSections flag from MICEPACK.INI */
   mergeSections = (BOOLEAN) GetPrivateProfileInt((LPSTR) LAPP_NAME,
      (LPSTR)LAPP_MERGE_SEC, (S16) FALSE, (LPSTR) pwrViewsDir);

   /* Extract sectionNames of the toolUsed */
   if ((err = GetSectionNames()) != GOOD) return(err);
   /* Only set when ToolUseName and SectionNames defined */
   hasToolUseDefined = TRUE;
   return(GOOD);
}

/******************************************************************************
**
**  GetToolUseDialog
**
**  Status: CODED | REVIEWED | TESTED
**
**  Description:
**     Create a dialog for GetToolUse, LdrGetToolUse.  Get user select
**  compilerUsed.
**
**  Parameters:
**     input:
**        none.
**     output:
**        none.
**
******************************************************************************/
RETCODE GetToolUseDialog(VOID) {
   RETCODE err;

   /* Popup a dialog box to get ToolUse from the user */
   if ((err = GetUserSelectTool()) != GOOD)
      return(err);
   /*
   ** GetUserSelectTool set the toolSelect as index into toolNames table.
   ** Save the user select tool name back into the MICEPACK.INI
   ** "CompilerUsed" as the default from now on.
   */
   return(SetToolUse());
}

/******************************************************************************
**
**  GetSectionNames
**
**  Status: CODE
**
**  Description:
**     Extract all toolUse's section names from the MICEPACK.INI file.
**     Use the global toolUseName for "CompilerUsed" key.
**
**  Parameters:
**     input:
**        none.
**     output:
**        none.
**
******************************************************************************/
RETCODE GetSectionNames(VOID) {
   LOOP_VAR i;
   U8 sectNameLen;
   CHAR tmpStr[MAX_STR_SIZE], *loopPtr, *sectionNamePtr = NULL;

   /* Get all section names */
   if (GetPrivateProfileString((LPSTR) LAPP_NAME, (LPSTR) toolUseName,
          "", (LPSTR) tmpStr, MAX_STR_SIZE, (LPSTR) pwrViewsDir) == 0) {
      return(ER_NO_SECTION_NAME_DEFINED);
   }
   else {
      /* Parse the string into section names */
      i = 0;
      loopPtr = tmpStr;
      do {
         /* strtok return the pointer to the token found in tmpStr */
         if ((sectionNamePtr = strtok(loopPtr, DELIMITER_SET)) != NULL) {
            sectNameLen = strlen(sectionNamePtr) + 1; /* string terminator */
            if ((sectNameLen > SIZE_SECTION_NAME)
               || (strncpy(sectionNames[i], sectionNamePtr,
                 sectNameLen) == NULL)) {
               return(ER_INVALID_SECTION_NAME);
            }
         }
         else {
            if (i < MAX_NUM_SECTION_NAMES)
               return(ER_MISSING_SECTION_NAME);
            break;
         }
         ++i;
         loopPtr = NULL; /* Reset to walk the rest of the string tmpStr */
      } while (i < MAX_NUM_SECTION_NAMES);
   }
   return(GOOD);
}

/******************************************************************************
**
**  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_STR_SIZE], *loopPtr, *toolNamePtr = NULL;

   if (GetPrivateProfileString((LPSTR) LAPP_NAME, (LPSTR) LAPP_TOOLS_SUPPORT,
          "", (LPSTR) tmpStr, MAX_STR_SIZE, (LPSTR) pwrViewsDir) == 0) {
      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) > SIZE_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;
         loopPtr = NULL; /* Reset to walk the rest of the string tmpStr */
      } while (i < MAX_NUM_TOOLS_SUPPORT);
   }
   /* Save the number of toolsSupport read in */
   numToolsSupport = min(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, newToolSelect;

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

      case WM_COMMAND:
         switch(wParam) {
            case IDD_OK:
               /* Get the new tool selected */   
               toolSelect = newToolSelect;
               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)) {
                  newToolSelect = 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
**
******************************************************************************/
RETCODE GetUserSelectTool(VOID) {
   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 = MakeProcInstance(LdrSelToolDlgProc, hInst))
               != 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(hInst, hDlgTemplate, hWnd,
                                         lpfnLdrSelToolDlgProc)) == -1) {
         GlobalFree(hDlgTemplate);
         FreeProcInstance(lpfnLdrSelToolDlgProc);
         return(ER_NO_TOOLUSE_DEFINED);
      }
      /* Clean up */
      FreeProcInstance(lpfnLdrSelToolDlgProc);

      /* Only if dlgStatus is TRUE (OK pressed) and toolSelect is valid */
      if (dlgStatus && (toolSelect > 0) && (toolSelect <= numToolsSupport)) {
         /* Copy user select name to global toolUseName variable */
         strcpy(toolUseName, toolNameTbl[toolSelect]);
         ClearToolNameTable();
         /* CreateDlgTemplate() allocates memory for hdlgTemplate,
         ** so free it when exit.
         */
         GlobalFree(hDlgTemplate);
         return(GOOD);
      }
   }
   /* CreateDlgTemplate() allocates memory for hdlgTemplate,
   ** so free it when exit.
   */
   GlobalFree(hDlgTemplate);
   return(ER_NO_TOOLUSE_DEFINED);
}

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

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

/****************************************************************************
** SetToolUse
**
** This routine initialize loader variables.
** Save the user select tool name back into the MICEPACK.INI
** "CompilerUsed" as the default from now on.
** Also need to inform the CPU which register to use as the frame ptr.
*****************************************************************************/
RETCODE SetToolUse(VOID) {
   PROC_CPU cpu;
   RETCODE err;
   LOOP_VAR i;

   // <Judy 7/22/96>
   // Extract all ToolsSupport names and save into global numToolsSupport 
   if (GetToolsSupport() == GOOD) {
      // Need to set toolSelect for dialogbox
      for (i = 0; i < numToolsSupport; i++) {
         if (lstrcmpi((LPSTR)toolNameTbl[i], (LPSTR) toolUseName) == 0){
            toolSelect = i;
            break;
         }
      }
   }
   if (i==numToolsSupport)
      return(ER_CANNOT_GET_TOOL_NAME);
   /*******/
   
   if(!WritePrivateProfileString((LPSTR) LAPP_NAME,(LPSTR) LAPP_TOOL_USE,
                                 (LPSTR) toolUseName, (LPSTR) pwrViewsDir)){
      toolUseName[0] = '\0'; /* Set toolUseName to NULL */
      return(ER_CANNOT_WRITE_TO_FILE);
   }
   
   // Need to setup frame pointer according to cmpiler in Use.
   if((err=ProcReturnCpu(&cpu))!=GOOD) return(err);
   switch (cpu) {
      case PROC_CPU_CPU16:
         if (stricmp(toolUseName, TOOL_WHITESMITHS) == 0 )
            err = CpuSetFramePtrRegister(SDN_IX-SDN_REG00);
         else
            err = CpuSetFramePtrRegister(SDN_IZ-SDN_REG00);
         break;
      case PROC_CPU_CPU32:
      case PROC_CPU_CPU32P:
      case PROC_CPU_68000:
         err = CpuSetFramePtrRegister(SDN_A6-SDN_REG00);
         break;
      default:
         err = CpuSetFramePtrRegister(2);  /* default position in sds list */
         break;
   }
   /* <Judy 7/22/96>
    Extract all ToolsSupport names and save into global numToolsSupport
   if (GetToolsSupport() == GOOD) {
      Need to set toolSelect for dialogbox
      for (i = 0; i < numToolsSupport; i++) {
         if (lstrcmpi((LPSTR)toolNameTbl[i], (LPSTR) toolUseName) == 0)
            toolSelect = i;
      }
   }
   */
   // Free up the toolNameTbl table 
   ClearToolNameTable();
   return(err);
}

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

