Пример #1
0
/***************************************************************************
  Clear all bits.
***************************************************************************/
void dbv_clr_all(struct dbv *pdbv)
{
  fc_assert_ret(pdbv != NULL);
  fc_assert_ret(pdbv->vec != NULL);

  memset(pdbv->vec, 0, _BV_BYTES(pdbv->bits));
}
Пример #2
0
/**************************************************************************
  Assign a guard to a city.
**************************************************************************/
void aiguard_assign_guard_city(struct city *charge, struct unit *guard)
{
  struct unit_ai *guard_data = def_ai_unit_data(guard);

  fc_assert_ret(charge != NULL);
  fc_assert_ret(guard != NULL);
  /*
   * Usually, but not always, city_owner(charge) == unit_owner(guard).
   */

  if (0 < guard_data->charge
      && guard_data->charge != charge->id) {
    /* Remove previous assignment: */
    aiguard_clear_charge(guard);
  }

  guard_data->charge = charge->id;
  if (city_owner(charge) != unit_owner(guard)) {
    /* Peculiar, but not always an error */
    BODYGUARD_LOG(LOGLEVEL_BODYGUARD, guard, "assigned foreign charge");
  } else {
    BODYGUARD_LOG(LOGLEVEL_BODYGUARD, guard, "assigned charge");
  }

  CHECK_GUARD(guard);
}
Пример #3
0
/*****************************************************************************
  Called when the return key is pressed.
*****************************************************************************/
static void luaconsole_input_return(GtkEntry *w, gpointer data)
{
  const char *theinput;
  struct luaconsole_data *pdialog = luaconsole_dialog_get();

  fc_assert_ret(pdialog);
  fc_assert_ret(pdialog->history_list);

  theinput = gtk_entry_get_text(w);

  if (*theinput) {
    luaconsole_printf(ftc_luaconsole_input, "(input)> %s", theinput);
    script_client_do_string(theinput);

    if (genlist_size(pdialog->history_list) >= MAX_LUACONSOLE_HISTORY) {
      void *data;

      data = genlist_get(pdialog->history_list, -1);
      genlist_remove(pdialog->history_list, data);
      free(data);
    }

    genlist_prepend(pdialog->history_list, fc_strdup(theinput));
    pdialog->history_pos = -1;
  }

  gtk_entry_set_text(w, "");
}
Пример #4
0
/**************************************************************************
  Do sanity checks on a guard, reporting error messages to the log
  if necessary.

  Inconsistent references do not always indicate an error, because units
  can change owners (for example, because of civil war) outside the control
  the the AI code.
**************************************************************************/
void aiguard_check_guard(const struct unit *guard)
{
  struct unit_ai *guard_data = def_ai_unit_data(guard);
  const struct unit *charge_unit = game_unit_by_number(guard_data->charge);
  const struct city *charge_city = game_city_by_number(guard_data->charge);
  const struct player *guard_owner = unit_owner(guard);
  const struct player *charge_owner = NULL;
  struct unit_ai *charge_data = NULL;

  fc_assert_ret(BODYGUARD_NONE <= guard_data->charge);
  /* IDs always distinct */
  fc_assert_ret(charge_unit == NULL || charge_city == NULL);

  if (charge_unit) {
    charge_owner = unit_owner(charge_unit);
    charge_data = def_ai_unit_data(charge_unit);
  } else if (charge_city) {
    charge_owner = city_owner(charge_city);
  }

  if (charge_unit && charge_data->bodyguard != guard->id) {
    BODYGUARD_LOG(LOG_DEBUG, guard, "inconsistent guard references");
  } else if (!charge_unit && !charge_city && 0 < guard_data->charge) {
    BODYGUARD_LOG(LOG_DEBUG, guard, "dangling guard reference");
  }
  if (charge_owner && pplayers_at_war(charge_owner, guard_owner)) {
    /* Probably due to civil war */
    BODYGUARD_LOG(LOG_DEBUG, guard, "enemy charge");
  } else if (charge_owner && charge_owner != guard_owner) {
    /* Probably sold a city with its supported units. */
    BODYGUARD_LOG(LOG_DEBUG, guard, "foreign charge");
  }
}
Пример #5
0
/**************************************************************************
  Check whether the assignment of a guard is still sane, and fix and problems.
  It was once sane, but might have been destroyed or become an enemy since.
**************************************************************************/
void aiguard_update_charge(struct unit *guard)
{
  struct unit_ai *guard_data = def_ai_unit_data(guard);
  const struct unit *charge_unit = game_unit_by_number(guard_data->charge);
  const struct city *charge_city = game_city_by_number(guard_data->charge);
  const struct player *guard_owner = unit_owner(guard);
  const struct player *charge_owner = NULL;

  fc_assert_ret(BODYGUARD_NONE <= guard_data->charge);
  /* IDs always distinct */
  fc_assert_ret(charge_unit == NULL || charge_city == NULL);

  if (charge_unit) {
    charge_owner = unit_owner(charge_unit);
  } else if (charge_city) {
    charge_owner = city_owner(charge_city);
  }

  if (!charge_unit && !charge_city && 0 < guard_data->charge) {
    guard_data->charge = BODYGUARD_NONE;
    BODYGUARD_LOG(LOGLEVEL_BODYGUARD, guard, "charge was destroyed");
  }
  if (charge_owner && charge_owner != guard_owner) {
    BODYGUARD_LOG(LOGLEVEL_BODYGUARD, guard, "charge transferred, dismiss");
    aiguard_clear_charge(guard);
  }

  CHECK_GUARD(guard);
}
Пример #6
0
/***************************************************************************
  Clear the bit given by 'bit'.
***************************************************************************/
void dbv_clr(struct dbv *pdbv, int bit)
{
  fc_assert_ret(pdbv != NULL);
  fc_assert_ret(pdbv->vec != NULL);
  fc_assert_ret(bit < pdbv->bits);

  pdbv->vec[_BV_BYTE_INDEX(bit)] &= ~_BV_BITMASK(bit);
}
Пример #7
0
/*****************************************************************************
  Push arguments into the Lua stack.
*****************************************************************************/
void luascript_push_args(struct fc_lua *fcl, int nargs,
                         enum api_types *parg_types, va_list args)
{
  int i;

  fc_assert_ret(fcl);
  fc_assert_ret(fcl->state);

  for (i = 0; i < nargs; i++) {
    int type;

    type = va_arg(args, int);
    fc_assert_ret(api_types_is_valid(type));
    fc_assert_ret(type == *(parg_types + i));

    switch (type) {
      case API_TYPE_INT:
        {
          int arg;

          arg = va_arg(args, int);
          tolua_pushnumber(fcl->state, (lua_Number)arg);
        }
        break;
      case API_TYPE_BOOL:
        {
          int arg;

          arg = va_arg(args, int);
          tolua_pushboolean(fcl->state, (bool)arg);
        }
        break;
      case API_TYPE_STRING:
        {
          const char *arg;

          arg = va_arg(args, const char*);
          tolua_pushstring(fcl->state, arg);
        }
        break;
      default:
        {
          const char *name;
          void *arg;

          name = api_types_name(type);

          arg = va_arg(args, void*);
          tolua_pushusertype(fcl->state, arg, name);
        }
        break;
    }
  }
}
Пример #8
0
/*****************************************************************************
  Load lua variables from file.
*****************************************************************************/
void luascript_vars_load(struct fc_lua *fcl, struct section_file *file,
                         const char *section)
{
  const char *vars;

  fc_assert_ret(file);
  fc_assert_ret(fcl);
  fc_assert_ret(fcl->state);

  vars = secfile_lookup_str_default(file, "", "%s", section);
  luascript_do_string(fcl, vars, section);
}
Пример #9
0
/***************************************************************************
  Initialize a dynamic bitvector of size 'bits'. 'bits' must be greater
  than 0 and lower than the maximal size given by MAX_DBV_LENGTH. The
  bitvector is set to all clear.
***************************************************************************/
void dbv_init(struct dbv *pdbv, int bits)
{
  fc_assert_ret(pdbv->vec == NULL);
  fc_assert_ret(pdbv->bits == 0);

  fc_assert_ret(bits > 0 && bits < MAX_DBV_LENGTH);

  pdbv->bits = bits;
  pdbv->vec = fc_calloc(1, _BV_BYTES(pdbv->bits) * sizeof(*pdbv->vec));

  dbv_clr_all(pdbv);
}
Пример #10
0
/*****************************************************************************
  Mark any, if exported, full userdata representing 'object' in
  the current script state as 'Nonexistent'.
  This changes the type of the lua variable.
*****************************************************************************/
void luascript_remove_exported_object(struct fc_lua *fcl, void *object)
{
  if (fcl && fcl->state) {
    fc_assert_ret(object != NULL);

    /* The following is similar to tolua_release(..) in src/lib/tolua_map.c */
    /* Find the userdata representing 'object' */
    lua_pushstring(fcl->state,"tolua_ubox");
    /* stack: ubox */
    lua_rawget(fcl->state, LUA_REGISTRYINDEX);
    /* stack: ubox u */
    lua_pushlightuserdata(fcl->state, object);
    /* stack: ubox ubox[u] */
    lua_rawget(fcl->state, -2);

    if (!lua_isnil(fcl->state, -1)) {
      fc_assert(object == tolua_tousertype(fcl->state, -1, NULL));
      /* Change API type to 'Nonexistent' */
      /* stack: ubox ubox[u] mt */
      tolua_getmetatable(fcl->state, "Nonexistent");
      lua_setmetatable(fcl->state, -2);
      /* Set the userdata payload to NULL */
      *((void **)lua_touserdata(fcl->state, -1)) = NULL;
      /* Remove from ubox */
      /* stack: ubox ubox[u] u */
      lua_pushlightuserdata(fcl->state, object);
      /* stack: ubox ubox[u] u nil */
      lua_pushnil(fcl->state);
      lua_rawset(fcl->state, -4);
    }
    lua_pop(fcl->state, 2);
  }
}
Пример #11
0
/*****************************************************************************
  Print a message to the selected output handle.
*****************************************************************************/
void luascript_log_vargs(struct fc_lua *fcl, enum log_level level,
                         const char *format, va_list args)
{
  char buf[1024];

  fc_assert_ret(fcl);
  fc_assert_ret(0 <= level && level <= LOG_DEBUG);

  fc_vsnprintf(buf, sizeof(buf), format, args);

  if (fcl->output_fct) {
    fcl->output_fct(fcl, level, "%s", buf);
  } else {
    log_base(level, "%s", buf);
  }
}
Пример #12
0
/**********************************************************************
  Reset accumulated time to zero, and stop timer if going.
  That is, this may be called whether t is started or stopped;
  in either case the timer is in the stopped state after this function.
***********************************************************************/
void timer_clear(struct timer *t)
{
    fc_assert_ret(NULL != t);
    t->state = TIMER_STOPPED;
    t->sec = 0.0;
    t->usec = 0;
}
Пример #13
0
/********************************************************************
  Insert an item into the queue.
*********************************************************************/
void pq_insert(struct pqueue *q, pq_data_t datum, int datum_priority)
{
  int i;

  fc_assert_ret(NULL != q);

  /* allocate more memory if necessary */
  if (q->size >= q->avail) {
    int newsize = q->size + q->step;

    q->cells = fc_realloc(q->cells, sizeof(pq_data_t) * newsize);
    q->priorities = fc_realloc(q->priorities, sizeof(int) * newsize);
    q->avail = newsize;
  }

  /* insert item */
  i = q->size++;
  while (i > 1 && q->priorities[i / 2] < datum_priority) {
    q->cells[i] = q->cells[i / 2];
    q->priorities[i] = q->priorities[i / 2];
    i /= 2;
  }
  q->cells[i] = datum;
  q->priorities[i] = datum_priority;
}
Пример #14
0
/********************************************************************
  Destructor for queue structure.
********************************************************************/
void pq_destroy(struct pqueue *q)
{
  fc_assert_ret(NULL != q);
  free(q->cells);
  free(q->priorities);
  free(q);
}
Пример #15
0
/**************************************************************************
  Alert the user to an important event.
**************************************************************************/
void gui_dialog_alert(struct gui_dialog *dlg)
{
  fc_assert_ret(NULL != dlg);

  switch (dlg->type) {
  case GUI_DIALOG_WINDOW:
    break;
  case GUI_DIALOG_TAB:
    {
      GtkNotebook *notebook = GTK_NOTEBOOK(dlg->v.tab.notebook);
      gint current, n;

      current = gtk_notebook_get_current_page(notebook);
      n = gtk_notebook_page_num(notebook, dlg->vbox);

      if (current != n) {
        GtkWidget *label = dlg->v.tab.label;
        GdkColormap *cmap = gtk_widget_get_default_colormap();
        GdkColor color = {.red = 0, .green = 0, .blue = 255 << 8};

        gdk_rgb_find_color(cmap, &color);
        gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, &color);
      }
    }
    break;
  }
}
Пример #16
0
/****************************************************************************
  Wrapper for load_theme. It's is used by local options dialog
****************************************************************************/
void theme_reread_callback(struct option *poption)
{
  const char *theme_name = option_str_get(poption);

  fc_assert_ret(NULL != theme_name && theme_name[0] != '\0');
  load_theme(theme_name);
}
Пример #17
0
/**************************************************************************
 This function is called when the client received a new input from the
 server.
**************************************************************************/
void input_from_server(int fd)
{
  int nb;

  fc_assert_ret(fd == client.conn.sock);

  nb = read_from_connection(&client.conn, FALSE);
  if (0 <= nb) {
    enum packet_type type;

    agents_freeze_hint();
    while (client.conn.used) {
      bool result;
      void *packet = get_packet_from_connection(&client.conn,
						&type, &result);

      if (result) {
        fc_assert_action(packet != NULL, break);
	client_packet_input(packet, type);
	free(packet);
      } else {
        fc_assert(packet == NULL);
	break;
      }
    }
    if (client.conn.used) {
      agents_thaw_hint();
    }
  } else if (-2 == nb) {
Пример #18
0
/**************************************************************************
  Alert the user to an important event.
**************************************************************************/
void gui_dialog_alert(struct gui_dialog *dlg)
{
  fc_assert_ret(NULL != dlg);

  switch (dlg->type) {
  case GUI_DIALOG_WINDOW:
    break;
  case GUI_DIALOG_TAB:
    {
      GtkNotebook *notebook = GTK_NOTEBOOK(dlg->v.tab.notebook);
      gint current, n;

      current = gtk_notebook_get_current_page(notebook);
      n = gtk_notebook_page_num(notebook, dlg->vbox);

      if (current != n) {
        GtkWidget *label = dlg->v.tab.label;
        GdkRGBA color = {.red = 0, .green = 0, .blue =1.0, .alpha = 1.0};

        gtk_widget_override_color(label, GTK_STATE_FLAG_NORMAL, &color);
      }
    }
    break;
  }
}
Пример #19
0
/*****************************************************************************
  Initilialize a lua console.
*****************************************************************************/
static void luaconsole_dialog_create(struct luaconsole_data *pdialog)
{
  GtkWidget *entry, *box, *vbox, *sw, *text, *notebook;

  fc_assert_ret(NULL != pdialog);

  if (gui_gtk2_message_chat_location == GUI_GTK_MSGCHAT_SPLIT) {
    notebook = right_notebook;
  } else {
    notebook = bottom_notebook;
  }

  gui_dialog_new(&pdialog->shell, GTK_NOTEBOOK(notebook), pdialog, TRUE);
  gui_dialog_set_title(pdialog->shell, _("Client Lua Console"));

  box = GTK_WIDGET(pdialog->shell->vbox);

  vbox = gtk_vbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(box), vbox, TRUE, TRUE, 0);

  sw = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
                                      GTK_SHADOW_ETCHED_IN);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
  gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);

  text = gtk_text_view_new_with_buffer(pdialog->message_buffer);
  set_message_buffer_view_link_handlers(text);
  gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
  gtk_container_add(GTK_CONTAINER(sw), text);
  g_signal_connect(text, "size-allocate",
                   G_CALLBACK(luaconsole_dialog_area_size_allocate), NULL);

  gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
  gtk_widget_realize(text);
  gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 5);

  pdialog->message_area = GTK_TEXT_VIEW(text);

  /* The lua console input line. */
  entry = gtk_entry_new();
  gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, TRUE, 2);
  g_signal_connect(entry, "activate", G_CALLBACK(luaconsole_input_return),
                   NULL);
  g_signal_connect(entry, "key_press_event",
                   G_CALLBACK(luaconsole_input_handler), NULL);
  pdialog->entry = entry;

  /* Load lua script command button. */
  gui_dialog_add_stockbutton(pdialog->shell, GTK_STOCK_OPEN,
                             _("Load Lua Script"), LUACONSOLE_RES_OPEN);

  gui_dialog_add_button(pdialog->shell, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
  gui_dialog_response_set_callback(pdialog->shell,
                                   luaconsole_response_callback);

  luaconsole_dialog_refresh(pdialog);
  gui_dialog_show_all(pdialog->shell);
}
Пример #20
0
/*****************************************************************************
  Appends the string to the chat output window.  The string should be
  inserted on its own line, although it will have no newline.
*****************************************************************************/
void real_luaconsole_append(const char *astring,
                            const struct text_tag_list *tags)
{
  GtkTextBuffer *buf;
  GtkTextIter iter;
  GtkTextMark *mark;
  ft_offset_t text_start_offset;
  struct luaconsole_data *pdialog = luaconsole_dialog_get();

  fc_assert_ret(pdialog);

  buf = pdialog->message_buffer;
  gtk_text_buffer_get_end_iter(buf, &iter);
  gtk_text_buffer_insert(buf, &iter, "\n", -1);
  mark = gtk_text_buffer_create_mark(buf, NULL, &iter, TRUE);

  if (gui_gtk2_show_chat_message_time) {
    char timebuf[64];
    time_t now;
    struct tm *now_tm;

    now = time(NULL);
    now_tm = localtime(&now);
    strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", now_tm);
    gtk_text_buffer_insert(buf, &iter, timebuf, -1);
  }

  text_start_offset = gtk_text_iter_get_offset(&iter);
  gtk_text_buffer_insert(buf, &iter, astring, -1);
  text_tag_list_iterate(tags, ptag) {
    apply_text_tag(ptag, buf, text_start_offset, astring);
  } text_tag_list_iterate_end;
Пример #21
0
/*****************************************************************************
  Scrolls the luaconsole all the way to the bottom.
  If delayed is TRUE, it will be done in a idle_callback.

  Modified copy of chatline_scroll_to_bottom().
*****************************************************************************/
static void luaconsole_dialog_scroll_to_bottom(void)
{
  struct luaconsole_data *pdialog = luaconsole_dialog_get();

  fc_assert_ret(pdialog);

  if (pdialog->shell) {
    GtkTextIter end;

    fc_assert_ret(NULL != pdialog->message_buffer);
    fc_assert_ret(NULL != pdialog->message_area);

    gtk_text_buffer_get_end_iter(pdialog->message_buffer, &end);
    gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(pdialog->message_area),
                                 &end, 0.0, TRUE, 1.0, 0.0);
  }
}
Пример #22
0
/****************************************************************************
  Save an RGB color definition (<colorpath>.red, <colorpath>.green and
  <colorpath>.blue).
****************************************************************************/
void rgbcolor_save(struct section_file *file,
                   const struct rgbcolor *prgbcolor, char *path, ...)
{
  char colorpath[256];
  va_list args;

  fc_assert_ret(file != NULL);
  fc_assert_ret(prgbcolor != NULL);

  va_start(args, path);
  fc_vsnprintf(colorpath, sizeof(colorpath), path, args);
  va_end(args);

  secfile_insert_int(file, prgbcolor->r, "%s.r", colorpath);
  secfile_insert_int(file, prgbcolor->g, "%s.g", colorpath);
  secfile_insert_int(file, prgbcolor->b, "%s.b", colorpath);
}
Пример #23
0
/**************************************************************************
  Assign a bodyguard to a unit.

  Assumes that a unit can have at most one guard.
**************************************************************************/
void aiguard_assign_guard_unit(struct unit *charge, struct unit *guard)
{
  fc_assert_ret(NULL != charge);
  fc_assert_ret(NULL != guard);
  fc_assert_ret(charge != guard);
  fc_assert_ret(unit_owner(charge) == unit_owner(guard));

  /* Remove previous assignment: */
  aiguard_clear_charge(guard);
  aiguard_clear_guard(charge);

  def_ai_unit_data(guard)->charge = charge->id;
  def_ai_unit_data(charge)->bodyguard = guard->id;

  BODYGUARD_LOG(LOGLEVEL_BODYGUARD, guard, "assigned charge");
  CHECK_GUARD(guard);
  CHECK_CHARGE_UNIT(charge);
}
Пример #24
0
/*****************************************************************************
  Closes the lua console; the content is saved till the client is done.
*****************************************************************************/
void luaconsole_dialog_popdown(void)
{
  struct luaconsole_data *pdialog = luaconsole_dialog_get();

  fc_assert_ret(pdialog);
  if (pdialog->shell == NULL) {
    luaconsole_dialog_destroy(pdialog);
  }
}
Пример #25
0
/**************************************************************************
  Unloads the sprite. Decrease the reference counter. If the last
  reference is removed the sprite is freed.
**************************************************************************/
static void unload_sprite(struct theme *t, const char *tag_name)
{
  struct small_sprite *ss;

  small_sprite_hash_lookup(t->sprite_hash, tag_name, &ss);
  fc_assert_ret(ss);
  fc_assert_ret(ss->ref_count >= 1);
  fc_assert_ret(ss->sprite);

  ss->ref_count--;

  if (ss->ref_count == 0) {
    /* Nobody's using the sprite anymore, so we should free it.  We know
     * where to find it if we need it again. */
    log_debug("freeing sprite '%s'.", tag_name);
    free_sprite(ss->sprite);
    ss->sprite = NULL;
  }
}
Пример #26
0
/*****************************************************************************
  Closes a lua console.
*****************************************************************************/
static void luaconsole_dialog_destroy(struct luaconsole_data *pdialog)
{
  fc_assert_ret(NULL != pdialog);

  if (pdialog->shell) {
    gui_dialog_destroy(pdialog->shell);
    fc_assert(NULL == pdialog->shell);
  }
  fc_assert(NULL == pdialog->message_area);
}
Пример #27
0
/*****************************************************************************
  Update the lua console.
*****************************************************************************/
void real_luaconsole_dialog_update(void)
{
  struct luaconsole_data *pdialog = luaconsole_dialog_get();

  fc_assert_ret(pdialog);

  if (NULL != pdialog->shell) {
    luaconsole_dialog_refresh(pdialog);
  }
}
Пример #28
0
/****************************************************************************
  Call the conn_close_callback.
****************************************************************************/
void connection_close(struct connection *pconn, const char *reason)
{
  fc_assert_ret(NULL != pconn);

  if (NULL != reason && NULL == pconn->closing_reason) {
    /* NB: we don't overwrite the original reason. */
    pconn->closing_reason = fc_strdup(reason);
  }

  (*conn_close_callback) (pconn);
}
Пример #29
0
/***************************************************************************
  Debug a dynamic bitvector.
***************************************************************************/
void dbv_debug(struct dbv *pdbv)
{
  char test_str[51];
  int i, j, bit;

  fc_assert_ret(pdbv != NULL);
  fc_assert_ret(pdbv->vec != NULL);

  for (i = 0; i < (pdbv->bits - 1) / 50 + 1; i++) {
    for (j = 0; j < 50; j++) {
      bit = i * 50 + j;
      if (bit >= pdbv->bits) {
        break;
      }
      test_str[j] = dbv_isset(pdbv, bit) ? '1' : '0';
    }
    test_str[j] = '\0';
    log_error("[%5d] %s", i, test_str);
  }
}
Пример #30
0
/***************************************************************************
  Resize a dynamic bitvector. Create it if needed.
***************************************************************************/
void dbv_resize(struct dbv *pdbv, int bits)
{
  fc_assert_ret(bits > 0 && bits < MAX_DBV_LENGTH);

  if (pdbv->vec == NULL) {
    /* Initialise a new dbv. */
    dbv_init(pdbv, bits);
  } else {
    /* Resize an existing dbv. */
    fc_assert_ret(pdbv->bits != 0);

    if (bits != pdbv->bits) {
      pdbv->bits = bits;
      pdbv->vec = fc_realloc(pdbv->vec,
                             _BV_BYTES(pdbv->bits) * sizeof(*pdbv->vec));
    }

    dbv_clr_all(pdbv);
  }
}