// read and return descriptor area (headers + entries)
Int32
readDescArea
(fstream              &mf,          // (IN) : binary module file
 module_header_struct &latestModHdr,// (IN) : its module header
 NAHeap               &heap,        // (IN) : allocate DESC area from here
 const char *         name,       // (IN) : module name (for error msg)
 ComDiagsArea         &diags,       // (IN) : deposit any error msg here
 char                *&descArea)    // (OUT): desc headers + entries
{
  // make sure we have reasonable arguments
  if (latestModHdr.descriptor_area_offset <= 0 ||
      latestModHdr.descriptor_area_length <= 0)
    return -1;

  // allocate space for DESC headers + entries
  descArea = (char*)
    heap.allocateMemory((size_t)latestModHdr.descriptor_area_length);
	  
  // read DESC headers + entries
  mf.seekg(latestModHdr.descriptor_area_offset, ios::beg);
  mf.read(descArea, (Int32)latestModHdr.descriptor_area_length);
  if (mf.fail()) {
    diags << DgSqlCode(-CLI_READ_ERROR) << DgString0(name);
    return -1;
  }
  return 1; // all OK
}
Lng32 MXCI_RW_allocateHeap (void* sqlciEnv, Lng32 len, char* &ptr)
{

  SqlciEnv * sqlci_env = (SqlciEnv *)sqlciEnv;
  
  NAHeap *h = sqlci_env->sqlciRWEnv()->rwHeap();
  void *p = NULL;

  if (h)
    p = h->allocateMemory(len, TRUE);
 
  if (p)
  {
    ptr = (char *)p;
    return SUCCESS;
  }
  else
    return ERR;
}
// read and return a binary module file's source area
SourceBuf readSourceArea
(fstream               &mf,          // (IN) : binary module file
 module_header_struct  &latestModHdr,// (IN) : its module header
 NAHeap                &heap,        // (IN) : allocate PLT area from here
 const char *          name,         // (IN) : module name (for error msg)
 ComDiagsArea          &diags)       // (IN) : deposit any error msg here
{
  SourceBuf srcArea = NULL;
  if (latestModHdr.source_area_length > 0) {
    // allocate space for source area
    srcArea = (SourceBuf)
      heap.allocateMemory((size_t)latestModHdr.source_area_length);

    // read source area
    mf.seekg(latestModHdr.source_area_offset, ios::beg);
    mf.read(srcArea, (Int32)latestModHdr.source_area_length);
    if (mf.fail()) {
      diags << DgSqlCode(-CLI_READ_ERROR) << DgString0(name);
      return NULL;
    }
  }
  return srcArea;
}
// read and return procedure location table area (header + entries)
Int32
readPLTArea
(fstream              &mf,          // (IN) : binary module file
 module_header_struct &latestModHdr,// (IN) : its module header
 NAHeap               &heap,        // (IN) : allocate PLT area from here
 const char *     name,       // (IN) : module name (for error msg)
 ComDiagsArea         &diags,       // (IN) : deposit any error msg here
 plt_header_struct   *&pltArea)     // (OUT): plt header + entries
{
  // make sure we have reasonable arguments
  if (latestModHdr.plt_area_offset  <= 0 ||
      latestModHdr.plt_area_length  <= 0 ||
      latestModHdr.plt_hdr_length   <= 0 ||
      latestModHdr.plt_entry_length <= 0)
    return -1;

  // allocate space for PLT header
  plt_header_struct pltHdrCls, *latestPLTHdr, *plt;
  plt = (plt_header_struct *)
    heap.allocateMemory(latestModHdr.plt_hdr_length);

  // read procedure location table header
  mf.seekg(latestModHdr.plt_area_offset, ios::beg);
  mf.read((char *)plt, latestModHdr.plt_hdr_length);
  if (mf.fail()) {
    diags << DgSqlCode(-CLI_READ_ERROR) << DgString0(name);
    return -1;
  }
      
  // give versioning a chance to massage/migrate it to this version
  latestPLTHdr = (plt_header_struct*)plt->driveUnpack(plt, &pltHdrCls,NULL);
  if (!latestPLTHdr) {
    // error: version is no longer supported
    diags << DgSqlCode(-CLI_MOD_PLT_HDR_VERSION_ERROR) 
          << DgString0(name);
    return -1;
  }

  pltArea = latestPLTHdr;
  Int32 num_procs = latestPLTHdr->num_procedures;
  
  if (num_procs >= 1) {
	// allocate space for PLT header + entries
    heap.deallocateMemory(plt);
    plt = (plt_header_struct *)
      heap.allocateMemory((size_t)latestModHdr.plt_area_length);
	  
    // read procedure location table header + entries
    mf.seekg(latestModHdr.plt_area_offset, ios::beg);
    mf.read((char *)plt, (Int32)latestModHdr.plt_area_length);
    if (mf.fail()) {
      diags << DgSqlCode(-CLI_READ_ERROR) << DgString0(name);
      return -1;
    }
	  
    // give versioning a chance to massage/migrate it to this version
    latestPLTHdr = (plt_header_struct*)plt->driveUnpack(plt, &pltHdrCls, NULL);
    if (!latestPLTHdr) {
      // error: version is no longer supported
      diags << DgSqlCode(-CLI_MOD_PLT_HDR_VERSION_ERROR) 
            << DgString0(name);
      return -1;
    }
    pltArea = latestPLTHdr;
  }

  // verify its validity
  Lng32 errCode = pltArea->RtduStructIsCorrupt();
  if (errCode) {
    // the module file is corrupted or has invalid data
    diags << DgSqlCode(errCode) << DgString0(name);
    heap.deallocateMemory(plt);
    return -1;
  }
  return num_procs;
}