/****************************************************************************
**
**  Name:  SSYM.C
**
**  Description:
**      Process and load symbols from Srecord files.
**
**  Status:  CODED
**
**  $Log:   S:/tbird/mt2_68k/loader/srec/ssym.c_v  $
** 
**    Rev 1.0   30 Sep 1997 16:03:30   gene
** Initial revision.
** 
**    Rev 1.9   04 Jun 1993 10:40:04   nghia
** Revised to meet coding standard.
** Reported error using only the Warning() and WarningEx() routines.
** PIP for Source.
** 
**    Rev 1.8   12 Feb 1993 18:11:10   nghia
** Removed ADDSYM #if and Added comments
** Updated for release.
** 
**    Rev 1.7   03 Dec 1992 17:45:56   courtney
** Fixed symbol processing.  All have correctly stripped leading
** underscore now.
** 
**    Rev 1.6   04 Nov 1992 17:41:28   courtney
** Use ErrDisplayString to report errors with additional info.
** 
**    Rev 1.5   22 Oct 1992 17:18:12   courtney
** Need to skip over symbols even if no symbols are requested to
** be loaded.
** 
**    Rev 1.4   22 Oct 1992 16:16:32   courtney
** Cleanup error reporting to use generic loader's string resource messages.
** 
**    Rev 1.3   25 Sep 1992 21:07:36   courtney
** Added symbol support and global symbol parse routine.
** 
**    Rev 1.2   25 Sep 1992 05:45:18   courtney
** Keep summary of n modules loaded.
** 
**    Rev 1.1   21 Aug 1992 10:27:52   courtney
** Check retcodes.
** 
**    Rev 1.0   31 Dec 1991 09:38:00   courtney
** Initial revision.
** 
**  $Header:   S:/tbird/mt2_68k/loader/srec/ssym.c_v   1.0   30 Sep 1997 16:03:30   gene  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/
                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include <ctype.h>
#include <io.h>
#include <string.h>
#ifndef _SYMBLSVR_
#include "symblsvr.h"
#endif
#ifndef _SLDR_
#include "sldr.h"
#endif
#ifndef __ERR__
#include "err.h"
#endif

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
STATIC U32 nmodsLoaded;

                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
#define IS_CLEADING(x)  (isalpha(x) || (x) == '_')

extern S8 errbuf[];
                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/

/* local prototypes */
PRIVATE LPSTR StripName(LPSTR);
                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/


/******************************************************************************
**
**  ProcessSymbols
**
******************************************************************************/
S16 ProcessSymbols(FILE *fHandle, U32 *pnmods, BOOLEAN symflag) {
    U8 srecord[MAX_RECLEN];
    S16 stype;
    RETCODE symerr;
    S8 mname[MAX_RECLEN];
    S8 *sp;  /* current srecord buffer pointer */

    /* even if user does not want symbols loaded (symflag FALSE), we
       need to skip over them to get to data records */
    nmodsLoaded = 0L;
    /* process module and symbol records */
    while (1) {
        stype = GetSrec(fHandle, srecord);
        if (stype == S_RECORD) {
            PushSrec(srecord);
            break;
        } 
        /* shortcut */
        if (!symflag)
            continue;
        sp = (S8 *)srecord;
        /* symbol type record */
        if (stype == S_MODULE) {
            sp = GetModule(sp, mname);
            /* address unknown for modules */
            if ((symerr = SymAddLabel((LPSTR)mname, SSYM_INDEX, 0L)) != GOOD)
                return(symerr);
            ++nmodsLoaded;
        } else if (stype == S_SYMBOL) {
            ProcessGlobalSyms(sp);
        } /* else error - bad record type */
    }
    *pnmods = nmodsLoaded;

    return (GOOD);
}  /* ProcessSymbols */


/******************************************************************************
**
**  ProcessGlobalSyms
**
******************************************************************************/
VOID ProcessGlobalSyms(S8 *sptr) {
    S8 lname[MAX_SYMNAME_LENGTH];
    S8 *pos;
    S8 ascAddr[MAX_ASC_LENGTH];
    RETCODE err;
    U32 addr;
    LPSTR sname;  /* pointer to underscore-stripped name */    
    /* we will parse symbol-type srecords one token at a time */

    /* Modified 12-1-92 cpm
       Was stripping all leading underscores from first symbol token
       found on line (causes duplicate symbols). */
    while (!IS_CLEADING(*sptr))
        ++sptr;
    while (1) {
        /* get name/address for each global symbol */
        if ((pos = strtok(sptr, " ")) == NULL)
            break;
        strcpy(lname, pos);
        if ((pos = strtok(NULL, " ")) == NULL)
            /* error in parsing */
            break;
        /* skip over leading '$' and convert from ascii to long address */
        strcpy(ascAddr, pos+1);
        NextAddr(ascAddr, 4, &addr);

        /* mod 12-1-92  cpm
           Need to strip leading underscore from public symbols */
        sname = StripName((LPSTR)lname);
        if (SymAddLabelPublic((LPSTR)sname, SSYM_INDEX, addr) != GOOD) {
            err = LERR_CANNOT_ADD_SYM;
            /* will inherit format specifier from generic loader */
            WarningEx(err, (LPSTR)sname);
            /* continue anyhow */
        }
        sptr = NULL;  /* start things anew */
    }
}  /* ProcessGlobalSyms */

/* get time info from disk file specified by handle,
   munge info to timestamp type for use by symbol table
*/

/******************************************************************************
**
**  GetTimestamp
**
******************************************************************************/
S16 GetTimestamp(HANDLE hfile, TIMESTAMP_TYPE *pts) {
    struct ftime ft;

    /* DOS-specific */
    getftime(hfile, &ft);
    pts->year = ft.ft_year+1980;
    pts->month = ft.ft_month;
    pts->day = ft.ft_day;
    pts->hour = ft.ft_hour;
    pts->minute = ft.ft_min;
    pts->second = ft.ft_tsec*2;

    return(0);
}  /* GetTimestamp */

/* Strip leading underscore from public symbols (code and data symbols).
   In this way, publics which were extern records during symbol loading
   of the Debug Part of the file will correctly be found and updated
   with address information from the Public Part.  Also, symbols linked
   in from library code/non-C objects will look proper to the user, who
   does not expect to find an underscore prepended (unless their mind
   has been warped by excessive exposure to Unix environments..)

   Return pointer to stripped-string.
*/

/******************************************************************************
**
**  StripName
**
******************************************************************************/
PRIVATE LPSTR StripName(LPSTR lpn1) {
   /* lpn1 - pointer to original string */
   if (lpn1[0] == '_')
		return ((LPSTR)&lpn1[1]);

   return (lpn1);
}  /* StripName */

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