#define CHRIS_FILE_C
#include "file.h"

#include "standard.h"
#include "dosmem.h"
#include "error.h"

#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#include <fcntl.h>
#include <ctype.h>
#include <dos.h>
#include <i86.h>
#include <io.h>
#undef CHRIS_FILE_C

T_INT c_handler=0;
T_CHAR c_error=0;
#ifdef ISB_WATCOM
extern void _harderr(register int (__far *__func)(unsigned __deverr,
            unsigned __errcode,unsigned __far *__devhdr));
#endif

T_INT __far critical_error_handler(T_UINT deverr, T_UINT errcode, T_UINT __far *devhdr)
{
 c_error=1;
 return( _HARDERR_IGNORE );
}


/* Modul globale Variablen */

/* Modul globale Funktionen */
T_INT vergleich_dir(const T_PVOID test1, const T_PVOID test2);

/* Globale Variablen */
T_INT file_error = T_OK;

/*************************************************************************/

/* diese funktion sollte vor change_drive() aufgerufen werden */
/* sie erwartet die gleiche eingabe und gibt */
/* T_OK zurueck, falls das laufwerk in ordnung ist, */
/* T_NOT_OK sonst */
/* ob die funktion alle laufwerktypen korrekt erkennt ist noch unbekannt */
T_INT drive_check(T_BYTE drive)
{
 T_PCHAR current_path=NULL;
 T_PCHAR Drive="A:\\";
 T_DEBUG_ENTRY("drive_check",5)
 if (c_handler==0)
 {
  _harderr( critical_error_handler );
  c_handler=1;
  c_error=0;
 }
 Drive[0]=drive+'A';
 if (change_directory(Drive)!=T_OK)
 {
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return T_NOT_OK;
 }
 current_path=get_current_path();
 if (current_path==NULL)
 {
  T_DEBUG_FUNCTION_POSITION(2)
  T_DEBUG_LEAVE
  return T_NOT_OK;
 }
 change_drive((toupper((T_INT)*current_path))-'A');
 if (c_error==1)
 {
  c_error=0;
  free(current_path);
  T_DEBUG_FUNCTION_POSITION(3)
  T_DEBUG_LEAVE
  return T_NOT_OK;
 }
 free(current_path);
 c_error=0;
 T_DEBUG_LEAVE
 return T_OK;
}

/*************************************************************************/

/* gibt den aktuellen pfad zurueck */
/* einen zeiger auf ein T_CHAR feld */
/* dieses muss dann 'per hand' freigegeben werden */
T_PCHAR get_current_path(T_VOID)
{
 T_PCHAR directory=NULL;
 T_PCHAR dire=NULL;
 T_DEBUG_ENTRY("get_current_path",5)
 directory=(T_PCHAR) malloc((T_PATH_MAX+1)*sizeof(T_CHAR));
 if (directory==NULL)
 {
  file_error = GENERIC_MEMORY_NOT_AVAILABLE;
  T_DEBUG_SET_THIS_FUNCTION_ERROR(GENERIC_MEMORY_NOT_AVAILABLE)
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return NULL;
 }
 dire=getcwd(NULL,0);
 if (/*(errno)||*/(dire==NULL)) // errno ist auch gesetzt bei erfolg (1)
 {
  file_error = FILE_DIRECTORY_ERROR;
  T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_DIRECTORY_ERROR)
  T_DEBUG_FUNCTION_POSITION(2)
  free(directory);
  T_DEBUG_LEAVE
  return NULL;
 }
 strncpy(directory,dire,T_PATH_MAX);
 free(dire);
 T_DEBUG_LEAVE
 return directory;
}

/*************************************************************************/

/* erwartet ein feld von 26 ('z'-'a') char eintraegen */
/* traegt in dieses feld eine 1 ein, wenn das laufwerk vorhanden ist */
/* eine 0 sonst */
T_VOID check_drives(T_PCHAR drives)
{
 union REGS regs;
 struct SREGS sregs;
 T_BYTE zaehler;
 T_WORD status;
 T_DEBUG_ENTRY("check_drives",5)
 sregs.ds = sregs.es = sregs.fs = sregs.gs = FP_SEG( &sregs );
 for (zaehler=0;zaehler<(T_BYTE)('Z'-'A'+1);zaehler++)
 {
  regs.h.bl=zaehler+1;
  regs.h.ah=IOCTL;
  regs.h.al=MEDIUM_WECHSELBAR;
  intdosx(&regs, &regs, &sregs);
  if (regs.w.ax!=15)
   drives[zaehler]=1;
  else
   drives[zaehler]=0;
 }
 regs.h.ah=LAUFWERKTYP;
 regs.h.al=0;
 int386x(0x13,&regs,&regs,&sregs);
 status=(T_INT) regs.h.ah;
 if (status!=0)
  drives[0]=1;
 else
  drives[0]=0;
 regs.h.ah=LAUFWERKTYP;
 regs.h.dl=1;
 int386x(0x13,&regs,&regs,&sregs);
 status=(T_INT)regs.h.ah;
 if (status!=0)
  drives[1]=1;
 else
  drives[1]=0;
 T_DEBUG_LEAVE
}

/*************************************************************************/

/* aendert den aktuellen pfad in den angegeben pfad */
/* die ueblichen dos-beschraenkungen gelten (128 zeichen...) */
T_INT change_directory(T_PCHAR path)
{
 T_DEBUG_ENTRY("change_directory",5)
 if ((path==NULL)||(path[0]==0))
 {
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return T_NOT_OK;
 }
 if (path[1]==':')
 {
  change_drive((T_BYTE) (toupper((T_INT) path[0])-'A'));
  path+=2;
 }
 if (path[0]==0)
 {
  T_DEBUG_FUNCTION_POSITION(2)
  T_DEBUG_LEAVE
  return T_NOT_OK;
 }
 if (!chdir(path))
 {
  T_DEBUG_FUNCTION_POSITION(3)
  T_DEBUG_LEAVE
  return T_OK;
 }
 T_DEBUG_LEAVE
 return T_NOT_OK;
}

/*************************************************************************/

/* andert das aktuelle laufwerk */
/* uebergabe 0=a, 1=b ... */
/* vorsicht, wenn laufwerk nicht ansprechbar ist */
/* wird von dos ein 'critical error' erzeugt */
T_BYTE change_drive(T_BYTE drive)
{
 union REGS regs;
 struct SREGS sregs;
 T_DEBUG_ENTRY("change_drive",5)
 sregs.ds = sregs.es = sregs.fs = sregs.gs = FP_SEG( &sregs );
 regs.h.ah=LAUFWERK_WECHSELN;
 regs.h.dl=drive;
 intdosx(&regs, &regs, &sregs);
 T_DEBUG_LEAVE
 return regs.h.al;
}

/*************************************************************************/

/* funktion, die zum sortieren der verzeichniseintraege */
/* verwendet wird, wird von der standard 'c' funktion */
/* qsort() verwendet */
T_INT vergleich_dir(const T_PVOID test1, const T_PVOID test2)
{
 T_INT t1=0,t2=0;
 T_DEBUG_ENTRY("vergleich_dir",5)
 if ( (((DIR *)test1)->d_attr&8)&&(((DIR *)test2)->d_attr&8) )
 {
  /* beides volumen (geht gar nicht!!!) */
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return (strcmp(((DIR *)test1)->d_name,((DIR *)test2)->d_name));
 }
 if ( (!(((DIR *)test1)->d_attr&8))&&(((DIR *)test2)->d_attr&8) )
 {
  /* erstes irgendwas, zweites VOL */
  T_DEBUG_FUNCTION_POSITION(2)
  T_DEBUG_LEAVE
  return 1;
 }
 if ( (((DIR *)test1)->d_attr&8)&& (!(((DIR *)test2)->d_attr&8)) )
 {
  /* erstes VOL, zweites irgendwas */
  T_DEBUG_FUNCTION_POSITION(3)
  T_DEBUG_LEAVE
  return -1;
 }
 if ( (((DIR *)test1)->d_attr&16)&&(((DIR *)test2)->d_attr&16) )
 {
  /* beides DIR */
  T_DEBUG_FUNCTION_POSITION(4)
  T_DEBUG_LEAVE
  return (strcmp(((DIR *)test1)->d_name,((DIR *)test2)->d_name));
 }
 if ( (!(((DIR *)test1)->d_attr&16))&&(((DIR *)test2)->d_attr&16) )
 {
  /* erstes irgendwas, zweites DIR */
  T_DEBUG_FUNCTION_POSITION(5)
  T_DEBUG_LEAVE
  return 1;
 }
 if ( (((DIR *)test1)->d_attr&16)&& (!(((DIR *)test2)->d_attr&16)) )
 {
  /* erstes DIR, zweites irgendwas */
  T_DEBUG_FUNCTION_POSITION(6)
  T_DEBUG_LEAVE
  return -1;
 }
 /* ab hier, beides programme */
 while ( (((DIR *)test1)->d_name[t1]!=0)&&(((DIR *)test1)->d_name[t1]!='.'))
  t1++;
 while ( (((DIR *)test2)->d_name[t2]!=0)&&(((DIR *)test2)->d_name[t2]!='.'))
  t2++;
 if ((strcmp(((DIR *)test1)->d_name+t1,((DIR *)test2)->d_name+t2))==0)
 {
  /* endungen gleich */
  T_DEBUG_FUNCTION_POSITION(7)
  T_DEBUG_LEAVE
  return (strcmp(((DIR *)test1)->d_name,((DIR *)test2)->d_name));
 }
 /* endungen ungleich */
 T_DEBUG_LEAVE
 return (strcmp(((DIR *)test1)->d_name+t1,((DIR *)test2)->d_name+t2));
}

/*************************************************************************/

/* diese funktion liefert ein array von directory eintraegen von den */
/* durch 'pfad' angegebenen pfad == maske */
/* beschreibung des arrays siehe doc */
DIR_ARRAY *file_get_dir(T_PCHAR pfad)
{
 DIR *dirp;
 DIR *direntp;
 DATEI_LISTE *datei_liste;
 DATEI_LISTE *datei_liste1;
 DIR_ARRAY *dir;
 T_INT anzahl=0,i;
 T_DEBUG_ENTRY("file_get_dir",5)

 datei_liste=(DATEI_LISTE *) malloc(sizeof(DATEI_LISTE));
 if (datei_liste==NULL)
 {
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return NULL;
 }
 datei_liste1=datei_liste;
 datei_liste->naechste_datei=NULL;
 datei_liste->letzte_datei=NULL;

 dirp =(DIR *) opendir(pfad);
 if ( dirp == NULL )
 {
  free(datei_liste);
  T_DEBUG_FUNCTION_POSITION(2)
  T_DEBUG_LEAVE
  return NULL;
 }
 else
 {
  for(;;)
  {
   DATEI_LISTE *datei_liste_help;
   direntp = (DIR *)readdir( (DIR *)dirp );
   if (direntp == NULL)
    break;
   anzahl++;
   datei_liste_help=(DATEI_LISTE *) malloc(sizeof(DATEI_LISTE));
   if (datei_liste_help==NULL)
   {
    printf("datei_liste_help out of memory");
    T_DEBUG_FUNCTION_POSITION(3)
    T_DEBUG_LEAVE
    tool_exit(GENERIC_MEMORY_NOT_AVAILABLE);
   }
   memcpy(&(datei_liste->datei),direntp,sizeof(DIR));
   datei_liste->naechste_datei=datei_liste_help;
   datei_liste_help->letzte_datei=datei_liste;
   datei_liste=datei_liste_help;
   datei_liste->naechste_datei=NULL;
  }
  closedir((DIR *) dirp );
 }
 dir=(DIR_ARRAY *)malloc(sizeof(T_INT)+sizeof(DIR)*anzahl);
 if (dir==NULL)
 {
  printf("dir array out of memory");
  T_DEBUG_FUNCTION_POSITION(4)
  T_DEBUG_LEAVE
  tool_exit(GENERIC_MEMORY_NOT_AVAILABLE);
 }
 dir->anzahl_eintraege=anzahl;
 datei_liste=datei_liste1;
 for (i=0;i<dir->anzahl_eintraege;i++)
 {
  memcpy(&dir->file[i],&datei_liste->datei,sizeof(DIR));
  datei_liste1=datei_liste;
  datei_liste=(DATEI_LISTE  *)datei_liste->naechste_datei;
  free(datei_liste1);
 }
 /* directory sortieren */
 if (dir->anzahl_eintraege)
  qsort((T_PVOID) dir->file, (size_t) dir->anzahl_eintraege,(size_t) sizeof(DIR), vergleich_dir);
 T_DEBUG_LEAVE
 return dir;
}

/*************************************************************************/
/*********************************************************************/
/* Eigene Routinen zum lowlevel file handling.                       */
/* Eigentlich die normal open/close/read/write Funktionen, nur noch  */
/* ein Buffer dazwischengeschaltet.                                  */
/* Bringt Geschwindigkeitsvorteile, bei haeufigeren                  */
/* lesen kleiner Datenmengen.                                        */
/* Statt des ueblichen handles wird ein Zeiger auf eine Struktur     */
/* zurueckgegeben (file.h), diese braucht den Aufrufer aber          */
/* aber genausowenig zu interessieren wie der 'normale'              */
/* Dateideskriptor, er muss nur immer uebergeben werden...           */
F_FILE *f_open(T_PCHAR filename, T_INT modus)
{
 F_FILE *file;
 T_INT handle;
 T_DEBUG_ENTRY("f_open",5)
 if ( modus & O_CREAT )
 {
  T_SINT sec_modus = 0;
  if ( ( modus & O_WRONLY ) || (modus & O_RDWR) )
   sec_modus |= S_IWRITE;
  if ( ( modus & O_RDONLY ) || (modus & O_RDWR) )
   sec_modus |= S_IREAD;
  handle = open( filename, modus, sec_modus );
 }
 else
 {
  handle = open( filename, modus );
 }
 if ( handle == -1 )
 {
  file_error = FILE_OPEN_ERROR;
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_OPEN_ERROR)
  T_DEBUG_LEAVE
  return NULL;
 }
 file = ( F_FILE * ) malloc( sizeof( F_FILE ) );
 if ( file == NULL )
 {
  file_error = GENERIC_MEMORY_NOT_AVAILABLE;
  T_DEBUG_FUNCTION_POSITION(2)
  T_DEBUG_SET_THIS_FUNCTION_ERROR(GENERIC_MEMORY_NOT_AVAILABLE)
  T_DEBUG_LEAVE
  return NULL;
 }
 file->handle = handle;
 file->position = 0;
 file->ende_erreicht = T_FALSE;
 file->anzahl_in_buffer = 0;
 file->modus = modus;
 file_error = T_OK;
 T_DEBUG_LEAVE
 return file;
}

/*********************************************************************/

T_INT f_close( F_FILE *file )
{
 T_DEBUG_ENTRY("f_close",5)
 if ( file == NULL )
 {
  file_error = T_OK;
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return T_OK;
 }
 f_write_buffer( file );
 close( file->handle );
 free( file );
 file_error = T_OK;
 T_DEBUG_LEAVE
 return T_OK;
}

/*********************************************************************/

T_INT f_write_buffer(F_FILE *file)
{
 T_DEBUG_ENTRY("f_write_buffer",5)
 if ( (file != NULL) && ( ( file->modus & O_WRONLY ) || ( file->modus & O_RDWR ) ) )
 {
  write( file->handle, file->buffer, file->anzahl_in_buffer );
 }
 T_DEBUG_LEAVE
 return T_OK;
}

/*********************************************************************/
/* Bischen bloede gemacht, viel zu kompliziert, aber zu faul zum     */
/* aendern.                                                          */
T_INT f_read( F_FILE *file, T_PCHAR out_buffer, T_INT anzahl_zu_lesen )
{
 T_INT anzahl_gelesen;
 T_INT neu_gelesen;
 T_DEBUG_ENTRY("f_read",5)
 if ( file->position + anzahl_zu_lesen > file->anzahl_in_buffer )
 {
  if ( file->anzahl_in_buffer - file->position > 0 )
  {
   memcpy( out_buffer, file->buffer + file->position, file->anzahl_in_buffer - file->position );
  }
  anzahl_gelesen = file->anzahl_in_buffer - file->position;
  neu_gelesen = read( file->handle, out_buffer + anzahl_gelesen, anzahl_zu_lesen - anzahl_gelesen );
  anzahl_gelesen += neu_gelesen;
  file->anzahl_in_buffer = read( file->handle, file->buffer, F_FILE_BUFFER_GROESSE );
  if ( file->anzahl_in_buffer < F_FILE_BUFFER_GROESSE )
  {
   file->ende_erreicht = T_TRUE;
  }
  file->position = 0;
 }
 else
 {
  memcpy( out_buffer, file->buffer + file->position, anzahl_zu_lesen );
  anzahl_gelesen = anzahl_zu_lesen;
  file->position += anzahl_gelesen;
 }
 file_error = T_OK;
 T_DEBUG_LEAVE
 return anzahl_gelesen;
}

/*********************************************************************/

T_INT f_write( F_FILE *file, T_PCHAR buffer, T_INT anzahl )
{
 T_INT anzahl_geschrieben;
 T_DEBUG_ENTRY("f_write",5)
 if ( anzahl > F_FILE_BUFFER_GROESSE - file->anzahl_in_buffer )
 {
/* leere buffer und schreibe */
  anzahl_geschrieben = write( file->handle,file->buffer, file->anzahl_in_buffer );
  anzahl_geschrieben += write( file->handle,buffer, anzahl );
  file->anzahl_in_buffer = 0;
 }
 else
 {
  memcpy( file->buffer+file->anzahl_in_buffer, buffer, anzahl );
  file->anzahl_in_buffer += anzahl;
  anzahl_geschrieben = anzahl;
 }
 if ( anzahl_geschrieben < anzahl )
 {
  anzahl = anzahl_geschrieben;
 }
 file_error = T_OK;
 T_DEBUG_LEAVE
 return anzahl;
}

/*********************************************************************/
/* liefert den Wert T_TRUE, falls eine Datei mit dem Namen           */
/* 'filename' existiert, sonst T_FALSE.                              */
/* Es wird NICHT geprueft, ob die Datei eine DATEI oder VERZEICHNIS  */
/* ist!!!                                                            */
T_INT f_file_exist( T_PCHAR filename )
{
 T_INT handle;
 T_DEBUG_ENTRY("f_file_exist",5)
 handle = open( filename, O_RDONLY );
 if ( handle != -1 )
 {
  close( handle );
  file_error = T_OK;
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return T_TRUE;
 }
 file_error = T_OK;
 T_DEBUG_LEAVE
 return T_FALSE;
}

/*********************************************************************/

T_LONG f_rewind( F_FILE *file, T_LONG offset )
{
 T_LONG status = -1;
 T_DEBUG_ENTRY("f_rewind",5)
 if ( file != NULL )
 {
  status = offset;
  if ( ( T_LONG ) file->position >= offset )
  {
   file->position -= ( T_INT ) offset;
  }
  else
  {
   T_LONG current_pos;
   T_LONG new_pos;
   f_write_buffer( file );
   current_pos = tell( file->handle ) - ( F_FILE_BUFFER_GROESSE - file->position );
   new_pos = current_pos - offset;
   status = lseek( file->handle, new_pos, SEEK_SET );
   file->position = 0;
   file->ende_erreicht = T_FALSE;
   file->anzahl_in_buffer = 0;
   if ( status == -1L )
   {
    file_error = FILE_REWIND_ERROR;
    T_DEBUG_FUNCTION_POSITION(1)
    T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_REWIND_ERROR)
    T_DEBUG_LEAVE
    return status;
   }
   file->position = 0;
   file->ende_erreicht = T_FALSE;
   file->anzahl_in_buffer = 0;
   file_error = T_OK;
  }
  T_DEBUG_FUNCTION_POSITION(2)
  T_DEBUG_LEAVE
  return status;
 }
 file_error = FILE_NO_HANDLE;
 T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_NO_HANDLE)
 T_DEBUG_LEAVE
 return status;
}

/*********************************************************************/

T_LONG f_forward( F_FILE *file, T_LONG offset )
{
 T_LONG status = -1;
 T_DEBUG_ENTRY("f_forward",5)
 if ( file != NULL )
 {
  status = offset;
  if ( ( T_LONG ) ( F_FILE_BUFFER_GROESSE - file->position ) > offset )
  {
   file->position += ( T_INT ) offset;
  }
  else
  {
   T_LONG current_pos;
   T_LONG new_pos;
   f_write_buffer( file );
   current_pos = tell( file->handle ) - ( F_FILE_BUFFER_GROESSE - file->position );
   new_pos = current_pos + offset;
   status = lseek( file->handle, new_pos, SEEK_SET );
   file->position = 0;
   file->ende_erreicht = T_FALSE;
   file->anzahl_in_buffer = 0;
   if ( status == -1L )
   {
    file_error = FILE_FORWARD_ERROR;
    T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_FORWARD_ERROR)
    T_DEBUG_FUNCTION_POSITION(1)
    T_DEBUG_LEAVE
    return status;
   }
   file->position = 0;
   file->ende_erreicht = T_FALSE;
   file->anzahl_in_buffer = 0;
   file_error = T_OK;
  }
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return status;
 }
 file_error = FILE_NO_HANDLE;
 T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_NO_HANDLE)
 T_DEBUG_LEAVE
 return status;
}

/*********************************************************************/

T_INT f_begin( F_FILE *file )
{
 T_DEBUG_ENTRY("f_begin",5)
 if ( file != NULL )
 {
  f_write_buffer( file );
  lseek( file->handle, 0L, SEEK_SET );
  file->position = 0;
  file->ende_erreicht = T_FALSE;
  file->anzahl_in_buffer = 0;
  file_error = T_OK;
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return T_OK;
 }
 file_error = FILE_NO_HANDLE;
 T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_NO_HANDLE)
 T_DEBUG_LEAVE
 return T_NOT_OK;
}

/*********************************************************************/

T_INT f_end( F_FILE *file )
{
 T_DEBUG_ENTRY("f_end",5)
 if ( file != NULL )
 {
  f_write_buffer( file );
  lseek( file->handle, 0L, SEEK_END );
  file->position = 0;
  file->ende_erreicht = T_TRUE;
  file->anzahl_in_buffer = 0;
  file_error = T_OK;
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return T_OK;
 }
 file_error = FILE_NO_HANDLE;
 T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_NO_HANDLE)
 T_DEBUG_LEAVE
 return T_NOT_OK;
}

T_INT m_read(M_PFILE mfile, T_PCHAR dest, T_INT d_size)
{
 T_DEBUG_ENTRY("m_read",5)
 if (mfile->position+d_size>mfile->size)
 {
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return 0;
 }
 memmove(dest,mfile->mem+mfile->position,d_size);
 mfile->position+=d_size;
 T_DEBUG_LEAVE
 return d_size;
}

T_SINT m_rewind(M_PFILE mfile, T_INT offset )
{
 T_DEBUG_ENTRY("m_read",5)
 if (mfile==NULL)
 {
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return -1;
 }
 if (mfile->position>offset)
 {
  mfile->position-=offset;
 }
 else
 {
  T_DEBUG_FUNCTION_POSITION(2)
  T_DEBUG_LEAVE
  return -1;
 }
 T_DEBUG_LEAVE
 return offset;
}

/*********************************************************************/


