/****************************************************************************
**
**  Name:  LRECORD.C
**
**  Description:
**      Record operations on IEEE 695 binary file.
**
**  Status:  CODED
**
**  $Log:   S:/tbird/mt2_68k/l695/lrecord.c_v  $
** 
**    Rev 1.3   04 Dec 1997 11:08:14   hera
** Fix Get695TIndex for MRI45 or later
** 
**    Rev 1.2   04 Dec 1997 11:04:06   gene
** No change.
** 
**    Rev 1.1   21 Aug 1997 13:55:14   gene
** Modify Get695Idn() to handle long record name (over 127 bytes).
** The long record name existed in C++ language.
** 
**    Rev 1.0   13 Feb 1997 08:51:00   gene
** Initial revision.
** 
**    Rev 1.3   23 Sep 1996 14:43:18   kevin
** Hera's modification
** 
**    Rev 1.2   09 Sep 1996 09:47:06   kevin
** Hera's modification
** 
**    Rev 1.1   12 Aug 1996 11:44:42   Judy
** To support SDS Version 6.35.
** 
**    Rev 1.0   10 Jul 1996 15:31:32   Judy
** Initial revision.
** 
**    Rev 1.0   07 Sep 1995 10:32:24   gene
** Initial revision.
** 
**    Rev 1.28   01 Mar 1994 09:00:10   nghia
** Fixed bug PV2.1: Revised SkipOver() to handle two consecutive BE.
** 
**    Rev 1.27   30 Sep 1993 14:44:50   nghia
** Revised SkipOver() to handle blockSize == 0.
** 
**    Rev 1.26   23 Sep 1993 10:59:52   nghia
** Revised SyncTo() to return when it detects either a BB or a BE signature.
** 
**    Rev 1.25   23 Aug 1993 11:03:10   nghia
** Fixed bugs:
** 1. Fixed Seek695File() to return the correct file position by compensation 
** the pushback char whenever needed.
** 2. Fixed Get695Num() to get single byte value of 0x7F.  
** 3. Removed dead code - use ER_NOTYET_IMPL error.
** 4. Cleanup.
** 
**    Rev 1.24   03 Aug 1993 17:46:56   nghia
** Removed LERR_xxxx to use standard error codes.
** 
**    Rev 1.23   27 Jul 1993 22:38:24   nghia
** Cleanup compiler warning.
** 
**    Rev 1.22   15 Jul 1993 16:52:18   courtney
** Fixed 'value truncated to 16-bits' (again) to return error, as
** Mindy's fix, in Get695Number.  The caller will check if needed
** (though there are internal cases where such an error is expected,
** like when the Loader falls from one section to another with different
** types of section record types..)
** 
**    Rev 1.21   13 Jul 1993 10:25:50   ernie
** TBIRDERR macro is obsolete
** 
**    Rev 1.20   13 Jul 1993 10:16:18   ernie
** Changed Get695Bytes to return RETCODE
** 
**    Rev 1.19   25 Jun 1993 15:03:04   mindy
** 
**    Rev 1.18   14 Jun 1993 11:26:14   nghia
** Merged "pv bmwa" and Ernie changes.
** 
**    Rev 1.17   06 Jun 1993 21:59:30   courtney
** Removed calls to ErrExit
** 
**    Rev 1.16   06 Jun 1993 21:21:44   courtney
** Cleanup warnings on compile; comment on fall thru.
** 
**    Rev 1.15   25 May 1993 10:38:12   ernie
** Added file buffering.  Since the low-level (i.e. non-stream) version of
** the file I/O does not support file buffering, the buffering was done
** in this file.  This change improves symbol loading performance by about
** 10 times (10 seconds -> 1 second).
** 
**    Rev 1.14   20 Apr 1993 12:35:38   courtney
** Remedy Nghia's over-zealous formatting changes on SyncTo().
** Since this function now returns RETCODE, indicate error in return
** parameter.  RETCODE != GOOD is now only a serious seek error, not
** a failure to sync.
** 
**    Rev 1.13.1.3   07 Jun 1993 12:06:18   courtney
** Revisions for release 1.4.
** 
**    Rev 1.13.1.2   03 Jun 1993 18:52:06   nghia
** Revised to use the new error code.
** Reported error using only the Warning() and WarningEx() routines.
** 
**    Rev 1.13.1.1   19 May 1993 17:55:34   nghia
** Rev 1.13.1.0 is rev 1.14
** Revised SyncTo() to unget the byte when it detect a BB.
** Handled ATN16 from MRI v4.3d
** 
**    Rev 1.13.1.0   18 May 1993 16:23:52   nghia
** No change.
** 
**    Rev 1.13   12 Apr 1993 17:55:22   nghia
** Revised Get695STrecord to use the new #define for record types.
** Revised Get695SRecord() and SyncTo().
** 
**    Rev 1.12   31 Mar 1993 17:51:46   nghia
** Cleanup for coding standard.
** 
**    Rev 1.11   23 Mar 1993 17:05:52   nghia
** Revised MatchRecord and Match2Record to return RETCODE.
** Minor cleanup.
** 
**    Rev 1.10   23 Mar 1993 10:12:24   nghia
** Fixed ppr7994 - Optimized code detection stuck forever.
** Added comment blocks for coding standard.
** Revised Close695File() to close file handle before exit on error.
** 
**    Rev 1.9   08 Mar 1993 10:52:02   nghia
** Major cleanup for names and comments.
** Revised some routines for better readability.
** 
**    Rev 1.8   03 Dec 1992 17:26:14   courtney
** . Modified _Get695Idn wrt blank section identifier case;
** . Open695File now uses _lopen (uses explicit path specified by user),
** then OpenFile to get fully-qualified filename;
** . Added function Seek695File, so when we force file position we
** always clear the pushback char.
** 
**    Rev 1.7   21 Oct 1992 16:37:56   courtney
** Cleaned up error reporting to use string resource.
** 
**    Rev 1.6   14 Sep 1992 10:42:36   courtney
** Switch to TMalloc.
** 
**    Rev 1.5   01 Jun 1992 20:14:14   courtney
** Added SyncTo() for altlang support - skip over bytes till record
** indicated is found (or eof).
** 
**    Rev 1.4   12 May 1992 09:19:52   courtney
** Inline build flags for FASTBUF, added routines to support file
** buffering.
** 
**    Rev 1.3   07 May 1992 15:53:42   courtney
** New function Open695File for buffered file input (4K buffer allocated).
** 
**    Rev 1.2   24 Mar 1992 21:09:14   courtney
** Routine to get load item from 695 file - needed to parse start PC value.
** 
**    Rev 1.1   31 Dec 1991 10:54:30   courtney
** Changes to support ondemand loading, as well as loader 'flags'.
** 
**    Rev 1.0   12 Dec 1991 13:44:08   courtney
** Initial revision.
**
**  $Header:   S:/tbird/mt2_68k/l695/lrecord.c_v   1.3   04 Dec 1997 11:08:14   hera  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#ifndef __LDR__
#include "ldr.h"
#endif

#ifndef __LDEBUG__
#include "ldebug.h"
#endif


#include <ctype.h>
#include <io.h>
#include <limits.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

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

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

//**Hera 08/27/96**/
#ifndef _LPROFILE_
#include "lprofile.h"
#endif
//**Hera**/

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
U16 curbyte;                        /* current byte obtained from file */
STATIC U16 pushback = INITIAL_CH;   /* single character 'ungetc' pushback */
STATIC U8 FAR *lbuffer;
STATIC U8 *readPtr;
STATIC S16 charsInBuffer;
CHAR scratchBuffer[IEEE_IDNLEN];
#define LDR_BUFSIZE 4096    /* file read buffer size for 695 file */
U32 endDebugPart = 0L;
                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
extern CHAR errbuf[];
extern BOOLEAN atn9_processed;

//**Hera 08/26/96**/
extern BOOLEAN MRI45;
extern U16 toolSelect;
//**Hera**/
extern U32 typeBasis; //Hera 12/4/97
                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/
/* Attempt to match the given record type, for the given number of bytes,
** with the results of a read operation on the file at the current position.
** If this record is not found, an error is returned (and, if a required
** record, resynch forced) in caller.
** cpm:     note: currently only handles records of 1 byte in length!
** query:   should this be a read-only type operation, and unget, if fails?
**          note: what really happens on a 386 when you pass a byte as param?
**          would it be more efficient to declare as word?
*/

/*****************************************************************************
**
**  MatchRecord
**
*****************************************************************************/
RETCODE MatchRecord(HANDLE hfile, U16 rtype) {
   /* Match 1 byte form the input file */
   Get695Byte(hfile, &curbyte);
   if (curbyte != rtype)
      return (ER_NO_MATCH);
   return (GOOD);
}  /* MatchRecord */

/*****************************************************************************
**
**  Match2Record
**
*****************************************************************************/
RETCODE Match2Record(HANDLE hfile, U16 rtype) {
   U16 rbyte;

   /* Match a 2-byte record from the input file */
   Get695Byte(hfile, &rbyte);
   if (rbyte != (BYTE)((rtype & 0xff00) >> 8))
      return (ER_NO_MATCH);  /* will need resynch!! */
   Get695Byte(hfile, &rbyte);
   if (rbyte != (BYTE)(rtype & 0x00ff))
      return (ER_NO_MATCH);
   return (GOOD);
}  /* Match2Record */

                       /* Get 695 record type routines */
/* These routines first do a simple check to see if this type of record
** is found at the current file position (based on type prefix).  If not,
** then return error (which may cause a resynch, if required field).
** In general, there is a prefix byte which indicates the type of object
** which follows.  Objects are either numbers (including long numbers,
** negative numbers), names (identifiers), long names (long identifiers),
** or operators.  There is a generic _GetByte routine in case needed, and
** for getting record-type bytes from the file.
*/

/*****************************************************************************
**
**  Get695Number
**
*****************************************************************************/
/* Get695Number - handle IEEE number format (byte stream).
** Handles simple one-byte numerics, as well as the longer form,
** which sets the high bit on a byte-count field, followed by
** the bytes in the number.  Will get at most a 16-bit unsigned
**  quantity.  Use the routine Get695Offset if you need to get a
** long quantity.
*/
RETCODE Get695Number(HANDLE hfile, U16 *pn) {
   U16 prefix, nbytes, i, n;
   U32 nvalue = 0L;

   *pn = 0;  /* in case byte count is zero */
   Get695Byte(hfile, &prefix);
   /* convert long byte stream to int */
   if (prefix & NP_LONG) {
      nbytes = prefix & ~NP_LONG;
      for (i=0; i<nbytes; i++) {
         Get695Byte(hfile, &n);
         nvalue = nvalue << 8;
         nvalue |= n;
      }
      *pn = (U16)nvalue;

      //**Hera 09/23/96**/
      /* check for truncation */
      // if ((nvalue > 2) && (nvalue > USHRT_MAX)) {
      //    return(ER_INT_TOO_BIG);
      //}
      //**Hera**/

     /* get single byte int */
   } else if (prefix <= SCHAR_MAX) {
      /* NOTES: Nghia - 08/19/93
      ** Number format page 1 of the IEEE695 Spec
      ** single byte is value between 0-127 - the number is $0-$7F
      */
      *pn = prefix;
   }
   return (GOOD);
}  /* Get695Number */

/******************************************************************************
**
**  Get695Offset
**
******************************************************************************/
RETCODE Get695Offset(HANDLE hfile, U32 *lpoffset) {
   /* hfile - handle to file to read from
   ** lpoffset - pointer to long int, in which to store offset
   */
   U16 prefix, n;
   U16 nbytes;
   LOOP_VAR i;
   U32 nvalue=0;

   /* Can be called whenever the caller expects to find a long quantity
   ** (32-bit unsigned long) rather than a short quantity (16-bit int)
   ** in a file.
   ** Returns:
   **   GOOD for success or error (read error or incorrect synch)
   */
   /* number is stored in 68K byte order */
   Get695Byte(hfile, &prefix);
   if (prefix & NP_LONG) {
      nbytes = prefix & ~NP_LONG;
      for (i=0; i<nbytes; i++) {
         Get695Byte(hfile, &n);
         nvalue = nvalue << 8;
         nvalue |= n;
      }
      *lpoffset = nvalue;
   } else {
      *lpoffset = prefix;
   }
   return (GOOD);
}  /* Get695Offset */

/*****************************************************************************
**
**  Get695Idn - Get name field in IEEE 695 format
**
*****************************************************************************/
RETCODE Get695Idn(HANDLE hfile, LPSTR idn) {
   U16 len;
   LOOP_VAR i;
   CHAR buf[IEEE_IDNLEN];
   U16 cbyte;

   /* format:  byte field, followed by ASCII bytes for identifier */
   Get695Byte(hfile, &len);
   /* added by <Judy 8/20/97> */
   if (len == LONG_STR_MAX || len == LONG_STR_256) {
      Get695Number(hfile, &len);
      len = (len == 0) ? 0x80 : len;
   }
   /* eof <Judy 8/20/97> */
   /* marked by < Judy 8/20/97>
   if (len > SCHAR_MAX)
      return (ER_INVALID_IDN);
   */
   for (i = 0; i < len; i++) {
       Get695Byte(hfile, (U16 *) &cbyte);
       if (i < IEEE_IDNLEN)
          buf[i] = cbyte;
   }
   buf[i] = '\0';  /* we like C-style null-terminated strings */
   /* remember we are in a DLL, our stack is far-away */
   lstrcpy((LPSTR)idn, (LPSTR)buf);

   /* special case for 'blank' section identifier, where idn
   ** format contains an extra null byte, lets eat it.
   */
   if ((lstrlen(buf) == 1) && (buf[0] == CH_SPACE)) {
      Get695Byte(hfile, &cbyte);
      /* not always for assembly files!  (mod 11-24-92 cpm) */
      if (cbyte != 0)
         Unget695Byte(hfile, cbyte);
   }
   return (GOOD);
}  /* Get695Idn */

/*****************************************************************************
**
**  Get695Byte
**
*****************************************************************************/
RETCODE Get695Byte(HANDLE hfile, U16 *pbyte) {
   /*
   ** Lets declare as pointer to word, since most callers will convert to U16
   ** If pushback char is present, then we return it, else we read from file
   */
   if (pushback != INITIAL_CH) {
      *pbyte = pushback;
      pushback = INITIAL_CH;
      return(GOOD);
   }
   if (charsInBuffer <= 0) {
      charsInBuffer = _lread(hfile, (S8*)lbuffer, LDR_BUFSIZE);
      if (charsInBuffer <= 0)
         return(ER_BADGET);
      readPtr = lbuffer;
   }
   *pbyte = (U16)(*readPtr++);
   charsInBuffer--;
   return(GOOD);
}  /* Get695Byte */

/*****************************************************************************
**
**  Get695Bytes
**
*****************************************************************************/
RETCODE Get695Bytes(HANDLE hfile, U8 *pbyte, U16 number) {
   U16 size;
   U16 bytes=0;
   if (pushback != INITIAL_CH) {
      *pbyte++ = (U8)pushback;
      pushback = INITIAL_CH;
      number--;
      bytes++;
   }
   while (number > 0) {
      if (charsInBuffer <= 0) {
         charsInBuffer = _lread(hfile, (S8*)lbuffer, LDR_BUFSIZE);
         if (charsInBuffer <= 0) break;
         readPtr = lbuffer;
      }
      size = min(charsInBuffer, number);
      memcpy((LPSTR)pbyte,(LPSTR)readPtr,size);
      readPtr += size;
      charsInBuffer -= size;
      pbyte += size;
      number -= size;
      bytes += size;
   }
   return((bytes<number) ? ER_BAD_FILE : GOOD);
}

/*****************************************************************************
**
**  Peek695Byte
**
*****************************************************************************/
RETCODE Peek695Byte(HANDLE hfile, U16 *pbyte) {
   RETCODE err;
   if ((err = Get695Byte(hfile,pbyte)) != GOOD) return(err);
   /* we pushback so next get will retrieve */
   pushback = *pbyte;
   return (GOOD);
}  /* Peek695Byte */


/******************************************************************************
**
**  Clear695Byte
**
******************************************************************************/
VOID Clear695Byte(VOID) {
   /* clears any pushback char set
   ** (used at end of processing each Part of file)
   */
   pushback = INITIAL_CH;
   charsInBuffer = 0;  /* clear file buffer */
}  /* Clear695Byte */

/******************************************************************************
**
**  UnGet695Byte
**
******************************************************************************/
#pragma argsused
VOID Unget695Byte(HANDLE hfile, U16 c) {
   /* Unget the last character read to the local pushback value */
   pushback = c;
}  /* Unget695Byte */

/******************************************************************************
**
**  Get695STrecord
**
******************************************************************************/
RETCODE Get695STrecord(HANDLE hfile, U16 *pattr, U16 *stType) {
   U16 sprefix;
   U16 sbyte;
   U16 cbyte;

   *pattr = 0;  /* initially, no attribute */
   Get695Byte(hfile, &sprefix);
   switch (sprefix) {
      case 0xC1:
         if (MatchRecord(hfile, 0xD3) != GOOD)
            return (ER_BAD_SECREC);
         /* check for optional section modifier */
         Peek695Byte(hfile, &cbyte);
         if (IS_SEC_ATTR(cbyte))
            Get695Byte(hfile, pattr);
         *stType = ST_AS;
         break;
/* <Judy 8/12/96> */
      case 0xC2:
         /* check for optional section modifier */
         Peek695Byte(hfile, &cbyte);
         if (IS_SEC_ATTR(cbyte))
            Get695Byte(hfile, pattr);
         *stType = ST_AS;
         break;
/******/
      case 0xC3:
         Get695Byte(hfile, pattr);
         *stType = ST_C;
         break;
      case 0xC5:
         if (Get695Byte(hfile, &sbyte) == 0xDA)
           *stType = ST_EZ;
         else if (sbyte == 0xC1) {
           Get695Byte(hfile, pattr);
           *stType = ST_EA;
         }
         break;
      case 0xDA:
         if (Get695Byte(hfile, &sbyte) == 0xCD)
            *stType = ST_ZM;
         else if (sbyte == 0xC3) {
            Get695Byte(hfile, pattr);
            *stType = ST_ZC;
         }
         break;
      default:
         return (ER_BAD_SECREC);
   }
   return(GOOD);
}  /* Get695STrecord */

/******************************************************************************
**
**  Get695Srecord
**
******************************************************************************/
U16 Get695Srecord(HANDLE hfile, U16 *pindex, U32 *pvalue) {
   U16 sprefix;
   U16 sbyte;

   *pvalue = 0L;  /* initally, no value */
   Get695Byte(hfile, &sprefix);
   switch (sprefix) {
      case SR_SB:
         /* SB record = {$E5} {n1} */
         Get695Number(hfile, pindex);
         return(sprefix);
      case SR_SA:
         /* SA record = {$E7}{n1}[n2][n3] */
         Get695Number(hfile, pindex);
         Peek695Byte(hfile, &sbyte);
         if (sbyte != SR_AS_PREFIX)
            Get695Offset(hfile, pvalue);  /* alignment */
         Peek695Byte(hfile, &sbyte);
         if (sbyte != SR_AS_PREFIX)
            Get695Number(hfile, &sbyte);  /* Page size - value in MAU */
         return(sprefix);
      case RP_SECTION:
         Get695Byte(hfile, &sbyte);
         /* Note!!!  Should check validity of sbyte here.  Sometimes (like,
            at the end of the Data Part, additional records from another Part
            are read (Trail Part) and they don't fall in the range here.
            Once this processing is done, the check for INT_TOO_BIG in
            Get695Number can be enabled (use U32 and check - heed compiler
            warnings!
         */
         Get695Number(hfile, pindex);
         Get695Offset(hfile, pvalue);
         switch (sbyte) {
            case SR_ASS:   /* ASS record = {$E2}{$D3}{n1}{n2} */
            case SR_ASA:   /* ASA record = {$E2}{$C1}{n1}{n2} */
            case SR_ASB:   /* ASB record = {$E2}{$C2}{n1}{n2} */
            case SR_ASF:   /* ASF record = {$E2}{$C6}{n1}{n2} */
            case SR_ASM:   /* ASM record = {$E2}{$CD}{n1}{n2} */
            case SR_ASL:   /* ASL record = {$E2}{$CC}{n1}{n2} */
            case SR_ASP:   /* ASP record = {$E2}{$D0}{n1}{n2} */
            case SR_ASR:   /* ASR record = {$E2}{$D2}{n1}{n2} */
               return(sbyte);
         }
   }
   return (ER_BAD_SECREC);
}  /* Get695Srecord */

/******************************************************************************
**
**  Get695Nrecord - Get NameType record
**
******************************************************************************/
S16 Get695Nrecord(HANDLE hfile, U16 *pnindex, LPSTR name) {
   /* pnindex - pointer to name index
   ** name - name string
   */
   /* assumes no more than U16 names in file */
   RETCODE err;
   err = Get695Number(hfile, pnindex) ;
   err = (err == GOOD) ? Get695Idn(hfile, name) : err;
   return(err);
}  /* Get695Nrecord */

/******************************************************************************
**
**  SkipOver
**
**  Move the file pointer from blockPos for blocksize bytes.  If blockSize
**  is 0 then scan to the next BB signature.
**  Return error or GOOD
**
******************************************************************************/
RETCODE SkipOver(HANDLE hfile, U32 blockPos, U32 blockSize, U16 blockType) {
   RETCODE err;
   U16 cByte, nextBlockType;
   U32 nextBlockPos = 0L;
   LONG filePos;
   BOOLEAN endBlock = FALSE;
   
   /* If blockSize > 0 then seek to next block */
   if (blockSize) {
      nextBlockPos = blockPos + blockSize;
      /* Throw away the current read buffer and set file pointer */
      if (Seek695File(hfile, nextBlockPos, SEEK_SET) == -1L)
         return(ER_BAD_SEEK);
   } else {
      while(1) {
         // Blocksize is UNKNOWN - scan to the start of the next block
         // SyncTo() will stop at the RT_BE if first - set the endblock flag
         // then continue to scan
         if ((err = SyncTo(hfile, RT_BB, &filePos)) != GOOD)
            return(err);
         // Saved the position to restore
         nextBlockPos = Seek695File(hfile, 0L, SEEK_CUR);
         // Also check for going off the debug part -
         // Assume that ASW4 (debug) part is located before ASW5 (data)
         // endDebugPart = Hdr695.data_part and > 0
         if ((endDebugPart) && (nextBlockPos >= endDebugPart)) {
            nextBlockPos = endDebugPart;
            break;  /* out of while loop to stop */
         }
         Get695Byte(hfile, &cByte);
         if (cByte == RT_BB) {
            Get695BB(hfile, &blockSize, (LPSTR)scratchBuffer,&nextBlockType);
            if ((nextBlockType < BB_LOCAL_TYPE) ||
                (nextBlockType > BB_ASMSECTION)) { 
               break; /* Not a valid block */
            } 
            switch(blockType) {
               case BB_ASMBLOCK  :   
                  // Nested block processing
                  if (nextBlockType != BB_ASMSECTION)
                     goto DoneSkipOver;
                  break;
               case BB_MODULE :
                  if ((nextBlockType != BB_STATIC_FN) &&
                      (nextBlockType != BB_EXTERN_FN))
                     goto DoneSkipOver;
                  break;
                     
               case BB_LINE :
                  if (nextBlockType != BB_LINE) 
                     goto DoneSkipOver;
                  break;

               default :
                  if (endBlock)
                     goto DoneSkipOver;
                  break;
            }
            // Nested block processing
            if ((err != SkipOver(hfile, nextBlockPos, blockSize,
                                 nextBlockType)) != GOOD)
               return(err);
         }
         else {            
            // reach the RT_BE signature
            // Set endBlock flag & scan to beginning of the next block
            if (!endBlock) 
               endBlock = TRUE;            
            else {
               // NOTES: 02/24/94
               // When there are two consecutive BE then exit to 
               // end of the current block
               goto DoneSkipOver;
            }
         }
      } /* end of while */
      
DoneSkipOver:      
      /* Restore to the block BB maker */
      Seek695File(hfile, nextBlockPos, SEEK_SET);
   }
   return(GOOD);
}  /* SkipOver */

/******************************************************************************
**
**  SyncTo - Error recovery to the specified record.
**
******************************************************************************/
RETCODE SyncTo(HANDLE hfile, U16 rtype, LONG *pfilePos) {
   /* rtype - record type to sync to
   ** pfilePos - new file position after seek
   */
   U16 curbyte;

   /* first, set filepos for error case */
   *pfilePos = -1L;
   while (1) {
      /* check for eof */
      if (Get695Byte(hfile, &curbyte) != GOOD)
         return(ER_BADGET);
      if (curbyte == rtype) {
         /* sync successful */
         Unget695Byte(hfile, curbyte);
         if ((*pfilePos = Seek695File(hfile, 0L, SEEK_CUR)) == -1L)
            return(ER_BAD_SEEK);
         return(GOOD);
      }
      /* We've reached the end of the block, new block detected.
      ** This is an error case.  Since even local routines must return
      ** RETCODE, we indicate error by return parameter.
      */
      if ((curbyte == RT_BE) || (curbyte == RT_BB)) {
         /* put it back so parsing can continue */
         Unget695Byte(hfile, curbyte);
         *pfilePos = -1L;
         return(GOOD);
      }
   }
}  /* SyncTo */

/******************************************************************************
**
**  Get695TIndex
**
******************************************************************************/
/* Get type index from file, and fix-up before we return:
** after the first module has been processed, all successive
** modules need their type indices fixed-up, so that unique
** type indices are registered with the symbol table.  We bury
** this processing here, which keeps the rest of the code clean.
** The offset was calculated at the start of BB1 block.
*/
RETCODE Get695TIndex(HANDLE hfile, U32 *ptindex, U32 toffset) {
   /* ptindex - pointer to type index
      toffset - type fix-up value
   */
   U32 tindex;
   RETCODE err = GOOD;
   err = Get695Offset(hfile, &tindex);
   /* fix-up type */
   //**Hera 08/26/96**/
   /*The typedef in MRI4.5 or later is different than others Ex.*/
   /*BB2 -- Global Typedefs                                     */
   /*T100                                                       */
   /*T101                                                       */
   /*T102                                                       */
   /*...........................................................*/
   /*BB1 -- Local Typedefs in Module1                           */
   /*T103                                                       */
   /*T104                                                       */
   /*...........................................................*/
   /*BB1 -- Local Typedef in Module2                            */
   /*T103                                                       */
   /*T104                                                       */
   /*T105                                                       */
   /*************************************************************/
    
   if (MRI45 == TRUE && toolSelect == MRI_TOOLCHAIN) {
      if (toffset != 0 && typeBasis == 0) {
         typeBasis = toffset;
      }
      if (tindex < (0x100+typeBasis))
         *ptindex = tindex;
      else {
         tindex -= typeBasis;
         *ptindex = tindex + toffset;
      }
   }
   else 
      *ptindex = MAPTYPE(tindex, toffset);
   //**Hera**/
   return(err);
}  /* Get695TIndex */

/*****************************************************************************
**
**  ClearParseState
**
*****************************************************************************/
VOID ClearParseState(void) {
   curbyte = 0;
   Clear695Byte();
}  /* ClearParseState */


/****************************************************************************
**
**  Open695File
**
*****************************************************************************/
/* return file handle, if success (else -1) */
S16 Open695File(LPSTR file, OFSTRUCT *pof) {
   int hfile;

   /* fill in the file struct so caller has fully-qualified filename */
   if ((hfile = _lopen(file, READ)) == -1)
      return (-1);
   /* Still need to fill in ofstruct, since this is the only way to obtain
       the fully-qualified pathname (stored in symbol table). */
   OpenFile(file, pof, OF_PARSE);

   if ((lbuffer = (U8*)TMalloc(LDR_BUFSIZE)) == NULL)
      return (-1);
   readPtr = NULL;
   charsInBuffer = 0;

   return (hfile);
}  /* Open695File */

/*****************************************************************************
**
**  Seek695File
**
*****************************************************************************/
LONG Seek695File(HANDLE hfile, LONG pos, S16 seekTo) {
   LONG npos = _llseek(hfile, pos, seekTo);
   if (seekTo == SEEK_SET) {
      /* if changing position in file, clear pushback character & cache */
      Clear695Byte();
   }
   /* NOTES: Nghia - 08/17/93
   ** To return the correct virtual file position, the pushback character
   ** must be compensate appropriately.  Add 1 to number of charsInBuffer if
   ** pushback is not the INITIAL_CH.
   */
   return(npos - (charsInBuffer + (pushback != INITIAL_CH ? 1 : 0)));
}  /* Seek695File */

/*****************************************************************************
**
**  Close695File
**
*****************************************************************************/
RETCODE Close695File(HANDLE hfile) {
   /* De-allocate file buffer */
   if ((lbuffer != NULL) && (TFree((LPSTR)lbuffer) != GOOD)) {
      Warning(ER_BAD_FREE);
   }
   atn9_processed = FALSE;  /* Clear optimized code detection for next load */
   lbuffer = NULL;
   _lclose(hfile);
   return(GOOD);
}  /* Close695File */

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