コード例 #1
0
ファイル: search.c プロジェクト: 309972460/software
/* binary_search():
   An array of data structures is in memory, as above. However, the
   structs must be stored in forward order of their keys (taking each key
   to be a multibyte unsigned integer.) There can be no duplicate keys. 
   numstructs must indicate the exact length of the array; it cannot
   be -1.

   The KeyIndirect and ReturnIndex options may be used.
*/
glui32 binary_search(glui32 key, glui32 keysize, 
  glui32 start, glui32 structsize, glui32 numstructs, 
  glui32 keyoffset, glui32 options)
{
  unsigned char keybuf[4];
  unsigned char byte, byte2;
  glui32 top, bot, val, addr;
  int ix;
  int retindex = ((options & serop_ReturnIndex) != 0);

  fetchkey(keybuf, key, keysize, options);
  
  bot = 0;
  top = numstructs;
  while (bot < top) {
    int cmp = 0;
    val = (top+bot) / 2;
    addr = start + val * structsize;

    if (keysize <= 4) {
      for (ix=0; (!cmp) && ix<keysize; ix++) {
        byte = Mem1(addr + keyoffset + ix);
        byte2 = keybuf[ix];
        if (byte < byte2)
          cmp = -1;
        else if (byte > byte2)
          cmp = 1;
      }
    }
    else {
      for (ix=0; (!cmp) && ix<keysize; ix++) {
        byte = Mem1(addr + keyoffset + ix);
        byte2 = Mem1(key + ix);
        if (byte < byte2)
          cmp = -1;
        else if (byte > byte2)
          cmp = 1;
      }
    }

    if (!cmp) {
      if (retindex)
        return val;
      else
        return addr;
    }

    if (cmp < 0) {
      bot = val+1;
    }
    else {
      top = val;
    }
  }

  if (retindex)
    return -1;
  else
    return 0;
}
コード例 #2
0
ファイル: search.c プロジェクト: 309972460/software
/* linear_search():
   An array of data structures is stored in memory, beginning at start,
   each structure being structsize bytes. Within each struct, there is
   a key value keysize bytes long, starting at position keyoffset (from
   the start of the structure.) Search through these in order. If one
   is found whose key matches, return it. If numstructs are searched
   with no result, return NULL.
   
   numstructs may be -1 (0xFFFFFFFF) to indicate no upper limit to the
   number of structures to search. The search will continue until a match
   is found, or (if ZeroKeyTerminates is set) a zero key.

   The KeyIndirect, ZeroKeyTerminates, and ReturnIndex options may be
   used.
*/
glui32 linear_search(glui32 key, glui32 keysize, 
  glui32 start, glui32 structsize, glui32 numstructs, 
  glui32 keyoffset, glui32 options)
{
  unsigned char keybuf[4];
  glui32 count;
  int ix;
  int retindex = ((options & serop_ReturnIndex) != 0);
  int zeroterm = ((options & serop_ZeroKeyTerminates) != 0);

  fetchkey(keybuf, key, keysize, options);

  for (count=0; count<numstructs; count++, start+=structsize) {
    int match = TRUE;
    if (keysize <= 4) {
      for (ix=0; match && ix<keysize; ix++) {
        if (Mem1(start + keyoffset + ix) != keybuf[ix])
          match = FALSE;
      }
    }
    else {
      for (ix=0; match && ix<keysize; ix++) {
        if (Mem1(start + keyoffset + ix) != Mem1(key + ix))
          match = FALSE;
      }
    }

    if (match) {
      if (retindex)
        return count;
      else
        return start;
    }

    if (zeroterm) {
      match = TRUE;
      for (ix=0; match && ix<keysize; ix++) {
        if (Mem1(start + keyoffset + ix) != 0)
          match = FALSE;
      }
      if (match) {
        break;
      }
    }
  }
  
  if (retindex)
    return -1;
  else
    return 0;
}
コード例 #3
0
ファイル: glkop.cpp プロジェクト: fingolfin/scummvm
char *Glulxe::grab_temp_c_array(uint addr, uint len, int passin) {
	arrayref_t *arref = nullptr;
	char *arr = nullptr;
	uint ix, addr2;

	if (len) {
		arr = (char *)glulx_malloc(len * sizeof(char));
		arref = (arrayref_t *)glulx_malloc(sizeof(arrayref_t));
		if (!arr || !arref)
			error("Unable to allocate space for array argument to Glk call.");

		arref->array = arr;
		arref->addr = addr;
		arref->elemsize = 1;
		arref->retained = false;
		arref->len = len;
		arref->next = arrays;
		arrays = arref;

		if (passin) {
			for (ix = 0, addr2 = addr; ix < len; ix++, addr2 += 1) {
				arr[ix] = Mem1(addr2);
			}
		}
	}

	return arr;
}
コード例 #4
0
ファイル: search.c プロジェクト: 309972460/software
/* fetchkey():
   This massages the key into a form that's easier to handle. When it
   returns, the key will be stored in keybuf if keysize <= 4; otherwise,
   it will be in memory.
*/
static void fetchkey(unsigned char *keybuf, glui32 key, glui32 keysize, 
  glui32 options)
{
  int ix;

  if (options & serop_KeyIndirect) {
    if (keysize <= 4) {
      for (ix=0; ix<keysize; ix++)
        keybuf[ix] = Mem1(key+ix);
    }
  }
  else {
    switch (keysize) {
    case 4:
      Write4(keybuf, key);
      break;
    case 2:
      Write2(keybuf, key);
      break;
    case 1:
      Write1(keybuf, key);
      break;
    default:
      fatal_error("Direct search key must hold one, two, or four bytes.");
    }
  }
}
コード例 #5
0
ファイル: search.c プロジェクト: 309972460/software
/* linked_search():
   The structures may be anywhere in memory, in any order. They are
   linked by a four-byte address field, which is found in each struct
   at position nextoffset. If this field contains zero, it indicates
   the end of the linked list.

   The KeyIndirect and ZeroKeyTerminates options may be used.
*/
glui32 linked_search(glui32 key, glui32 keysize, 
  glui32 start, glui32 keyoffset, glui32 nextoffset, glui32 options)
{
  unsigned char keybuf[4];
  int ix;
  glui32 val;
  int zeroterm = ((options & serop_ZeroKeyTerminates) != 0);

  fetchkey(keybuf, key, keysize, options);

  while (start != 0) {
    int match = TRUE;
    if (keysize <= 4) {
      for (ix=0; match && ix<keysize; ix++) {
        if (Mem1(start + keyoffset + ix) != keybuf[ix])
          match = FALSE;
      }
    }
    else {
      for (ix=0; match && ix<keysize; ix++) {
        if (Mem1(start + keyoffset + ix) != Mem1(key + ix))
          match = FALSE;
      }
    }

    if (match) {
      return start;
    }

    if (zeroterm) {
      match = TRUE;
      for (ix=0; match && ix<keysize; ix++) {
        if (Mem1(start + keyoffset + ix) != 0)
          match = FALSE;
      }
      if (match) {
        break;
      }
    }
    
    val = start + nextoffset;
    start = Mem4(val);
  }

  return 0;
}
コード例 #6
0
ファイル: serial.c プロジェクト: 309972460/software
static glui32 write_memstate(dest_t *dest)
{
  glui32 res, pos;
  int val;
  int runlen;
  unsigned char ch;

  res = write_long(dest, endmem);
  if (res)
    return res;

  runlen = 0;
  glk_stream_set_position(gamefile, gamefile_start+ramstart, seekmode_Start);

  for (pos=ramstart; pos<endmem; pos++) {
    ch = Mem1(pos);
    if (pos < endgamefile) {
      val = glk_get_char_stream(gamefile);
      if (val == -1) {
        fatal_error("The game file ended unexpectedly while saving.");
      }
      ch ^= (unsigned char)val;
    }
    if (ch == 0) {
      runlen++;
    }
    else {
      /* Write any run we've got. */
      while (runlen) {
        if (runlen >= 0x100)
          val = 0x100;
        else
          val = runlen;
        res = write_byte(dest, 0);
        if (res)
          return res;
        res = write_byte(dest, (val-1));
        if (res)
          return res;
        runlen -= val;
      }
      /* Write the byte we got. */
      res = write_byte(dest, ch);
      if (res)
        return res;
    }
  }
  /* It's possible we've got a run left over, but we don't write it. */

  return 0;
}
コード例 #7
0
ファイル: accel.c プロジェクト: erkyrath/glulxe
void accel_set_func(glui32 index, glui32 addr)
{
    int bucknum;
    accelentry_t *ptr;
    int functype;
    acceleration_func new_func = NULL;

    /* Check the Glulx type identifier byte. */
    functype = Mem1(addr);
    if (functype != 0xC0 && functype != 0xC1) {
        fatal_error_i("Attempt to accelerate non-function.", addr);
    }

    if (!accelentries) {
        accelentries = (accelentry_t **)glulx_malloc(ACCEL_HASH_SIZE
                       * sizeof(accelentry_t *));
        if (!accelentries)
            fatal_error("Cannot malloc acceleration table.");
        for (bucknum=0; bucknum<ACCEL_HASH_SIZE; bucknum++)
            accelentries[bucknum] = NULL;
    }

    new_func = accel_find_func(index);
    /* Might be NULL, if the index is zero or not recognized. */

    bucknum = (addr % ACCEL_HASH_SIZE);
    for (ptr = accelentries[bucknum]; ptr; ptr = ptr->next) {
        if (ptr->addr == addr)
            break;
    }
    if (!ptr) {
        if (!new_func) {
            return; /* no need for a new entry */
        }
        ptr = (accelentry_t *)glulx_malloc(sizeof(accelentry_t));
        if (!ptr)
            fatal_error("Cannot malloc acceleration entry.");
        ptr->addr = addr;
        ptr->index = 0;
        ptr->func = NULL;
        ptr->next = accelentries[bucknum];
        accelentries[bucknum] = ptr;
    }

    ptr->index = index;
    ptr->func = new_func;
}
コード例 #8
0
ファイル: serial.c プロジェクト: MikulasZelinka/glulxe
/* perform_restore():
   Pull a state pointer from a stream. This returns 0 on success,
   1 on failure. Note that if it succeeds, the frameptr, localsbase,
   and valstackbase registers are invalid; they must be rebuilt from
   the stack.
 
   If fromshell is true, the restore is being invoked by the library
   shell (an autorestore of some kind). This currently happens only in
   iosglk.
*/
glui32 perform_restore(strid_t str, int fromshell)
{
  dest_t dest;
  int ix;
  glui32 lx, res, val;
  glui32 filestart, filelen;
  glui32 heapsumlen = 0;
  glui32 *heapsumarr = NULL;

  /* If profiling is enabled and active then fail. */
  #if VM_PROFILING
  if (profile_profiling_active())
    return 1;
  #endif /* VM_PROFILING */

  stream_get_iosys(&val, &lx);
  if (val != 2 && !fromshell) {
    /* Not using the Glk I/O system, so bail. This function only
       knows how to read from a Glk stream. (But in the autorestore
       case, iosys hasn't been set yet, so ignore this test.) */
    fatal_error("Streams are only available in Glk I/O system.");
  }

  if (str == 0)
    return 1;

  dest.ismem = FALSE;
  dest.size = 0;
  dest.pos = 0;
  dest.ptr = NULL;
  dest.str = str;

  res = 0;

  /* ### the format errors checked below should send error messages to
     the current stream. */

  if (res == 0) {
    res = read_long(&dest, &val);
  }
  if (res == 0 && val != IFFID('F', 'O', 'R', 'M')) {
    /* ### bad header */
    return 1;
  }
  if (res == 0) {
    res = read_long(&dest, &filelen);
  }
  filestart = dest.pos;

  if (res == 0) {
    res = read_long(&dest, &val);
  }
  if (res == 0 && val != IFFID('I', 'F', 'Z', 'S')) { /* ### ? */
    /* ### bad header */
    return 1;
  }

  while (res == 0 && dest.pos < filestart+filelen) {
    /* Read a chunk and deal with it. */
    glui32 chunktype=0, chunkstart=0, chunklen=0;
    unsigned char dummy;

    if (res == 0) {
      res = read_long(&dest, &chunktype);
    }
    if (res == 0) {
      res = read_long(&dest, &chunklen);
    }
    chunkstart = dest.pos;

    if (chunktype == IFFID('I', 'F', 'h', 'd')) {
      for (ix=0; res==0 && ix<128; ix++) {
        res = read_byte(&dest, &dummy);
        if (res == 0 && Mem1(ix) != dummy) {
          /* ### non-matching header */
          return 1;
        }
      }
    }
    else if (chunktype == IFFID('C', 'M', 'e', 'm')) {
      res = read_memstate(&dest, chunklen);
    }
    else if (chunktype == IFFID('M', 'A', 'l', 'l')) {
      res = read_heapstate(&dest, chunklen, TRUE, &heapsumlen, &heapsumarr);
    }
    else if (chunktype == IFFID('S', 't', 'k', 's')) {
      res = read_stackstate(&dest, chunklen, TRUE);
    }
    else {
      /* Unknown chunk type. Skip it. */
      for (lx=0; res==0 && lx<chunklen; lx++) {
        res = read_byte(&dest, &dummy);
      }
    }

    if (chunkstart+chunklen != dest.pos) {
      /* ### funny chunk length */
      return 1;
    }

    if ((chunklen & 1) != 0) {
      if (res == 0) {
        res = read_byte(&dest, &dummy);
      }
    }
  }

  if (res == 0) {
    if (heapsumarr) {
      /* The summary might have come from any interpreter, so it could
         be out of order. We'll sort it. */
      glulx_sort(heapsumarr+2, (heapsumlen-2)/2, 2*sizeof(glui32),
        &sort_heap_summary);
      res = heap_apply_summary(heapsumlen, heapsumarr);
    }
  }

  if (res)
    return 1;

  return 0;
}
コード例 #9
0
ファイル: serial.c プロジェクト: MikulasZelinka/glulxe
/* perform_save():
   Write the state to the output stream. This returns 0 on success,
   1 on failure.
*/
glui32 perform_save(strid_t str)
{
  dest_t dest;
  int ix;
  glui32 res, lx, val;
  glui32 memstart, memlen, stackstart, stacklen, heapstart, heaplen;
  glui32 filestart=0, filelen;

  stream_get_iosys(&val, &lx);
  if (val != 2) {
    /* Not using the Glk I/O system, so bail. This function only
       knows how to write to a Glk stream. */
    fatal_error("Streams are only available in Glk I/O system.");
  }

  if (str == 0)
    return 1;

  dest.ismem = FALSE;
  dest.size = 0;
  dest.pos = 0;
  dest.ptr = NULL;
  dest.str = str;

  res = 0;

  /* Quetzal header. */
  if (res == 0) {
    res = write_long(&dest, IFFID('F', 'O', 'R', 'M'));
  }
  if (res == 0) {
    res = write_long(&dest, 0); /* space for file length */
    filestart = dest.pos;
  }

  if (res == 0) {
    res = write_long(&dest, IFFID('I', 'F', 'Z', 'S')); /* ### ? */
  }

  /* Header chunk. This is the first 128 bytes of memory. */
  if (res == 0) {
    res = write_long(&dest, IFFID('I', 'F', 'h', 'd'));
  }
  if (res == 0) {
    res = write_long(&dest, 128);
  }
  for (ix=0; res==0 && ix<128; ix++) {
    res = write_byte(&dest, Mem1(ix));
  }
  /* Always even, so no padding necessary. */
  
  /* Memory chunk. */
  if (res == 0) {
    res = write_long(&dest, IFFID('C', 'M', 'e', 'm'));
  }
  if (res == 0) {
    res = write_long(&dest, 0); /* space for chunk length */
  }
  if (res == 0) {
    memstart = dest.pos;
    res = write_memstate(&dest);
    memlen = dest.pos - memstart;
  }
  if (res == 0 && (memlen & 1) != 0) {
    res = write_byte(&dest, 0);
  }

  /* Heap chunk. */
  if (res == 0) {
    res = write_long(&dest, IFFID('M', 'A', 'l', 'l'));
  }
  if (res == 0) {
    res = write_long(&dest, 0); /* space for chunk length */
  }
  if (res == 0) {
    heapstart = dest.pos;
    res = write_heapstate(&dest, TRUE);
    heaplen = dest.pos - heapstart;
  }
  /* Always even, so no padding necessary. */

  /* Stack chunk. */
  if (res == 0) {
    res = write_long(&dest, IFFID('S', 't', 'k', 's'));
  }
  if (res == 0) {
    res = write_long(&dest, 0); /* space for chunk length */
  }
  if (res == 0) {
    stackstart = dest.pos;
    res = write_stackstate(&dest, TRUE);
    stacklen = dest.pos - stackstart;
  }
  if (res == 0 && (stacklen & 1) != 0) {
    res = write_byte(&dest, 0);
  }

  filelen = dest.pos - filestart;

  /* Okay, fill in all the lengths. */
  if (res == 0) {
    res = reposition_write(&dest, memstart-4);
  }
  if (res == 0) {
    res = write_long(&dest, memlen);
  }
  if (res == 0) {
    res = reposition_write(&dest, heapstart-4);
  }
  if (res == 0) {
    res = write_long(&dest, heaplen);
  }
  if (res == 0) {
    res = reposition_write(&dest, stackstart-4);
  }
  if (res == 0) {
    res = write_long(&dest, stacklen);
  }
  if (res == 0) {
    res = reposition_write(&dest, filestart-4);
  }
  if (res == 0) {
    res = write_long(&dest, filelen);
  }

  /* All done. */
    
  return res;
}