<commit_before>/* Birnet
 * Copyright (C) 2006 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#ifndef __BIRNET_THREAD_XX_HH__
#define __BIRNET_THREAD_XX_HH__

#include <birnet/birnetthread.h>
#include <birnet/birnetutilsxx.hh>

namespace Birnet {

class Mutex {
  BirnetMutex mutex;
  friend class Cond;
  BIRNET_PRIVATE_CLASS_COPY (Mutex);
public:
  explicit      Mutex   ()                      { birnet_thread_table.mutex_init (&mutex); }
  void          lock    ()                      { birnet_thread_table.mutex_lock (&mutex); }
  void          unlock  ()                      { birnet_thread_table.mutex_unlock (&mutex); }
  bool          trylock ()                      { return 0 == birnet_thread_table.mutex_trylock (&mutex); /* TRUE indicates success */ }
  /*Des*/       ~Mutex  ()                      { birnet_thread_table.mutex_destroy (&mutex); }
};

class RecMutex {
  BirnetRecMutex rmutex;
  BIRNET_PRIVATE_CLASS_COPY (RecMutex);
public:
  explicit      RecMutex  ()                    { birnet_thread_table.rec_mutex_init (&rmutex); }
  void          lock      ()                    { birnet_thread_table.rec_mutex_lock (&rmutex); }
  void          unlock    ()                    { birnet_thread_table.rec_mutex_unlock (&rmutex); }
  bool          trylock   ()                    { return 0 == birnet_thread_table.rec_mutex_trylock (&rmutex); /* TRUE indicates success */ }
  /*Des*/       ~RecMutex ()                    { birnet_thread_table.rec_mutex_destroy (&rmutex); }
};

class Cond {
  BirnetCond cond;
  BIRNET_PRIVATE_CLASS_COPY (Cond);
public:
  explicit      Cond          ()                { birnet_thread_table.cond_init (&cond); }
  void          signal        ()                { birnet_thread_table.cond_signal (&cond); }
  void          broadcast     ()                { birnet_thread_table.cond_broadcast (&cond); }
  void          wait          (Mutex &m)        { birnet_thread_table.cond_wait (&cond, &m.mutex); }
  void          wait_timed    (Mutex &m,
                               int64 max_usecs) { birnet_cond_wait_timed (&cond, &m.mutex, max_usecs); }
  /*Des*/       ~Cond         ()                { birnet_thread_table.cond_destroy (&cond); }
};

/**
 * The AutoLocker class locks mutex like objects on construction, and automatically
 * unlocks on destruction. So putting an AutoLocker object on the stack conveniently
 * ensures that a mutex will be automatcially locked and properly unlocked when
 * the function returns or thros an exception.
 * Objects intended to be used by an AutoLocker need to provide the public methods
 * lock() and unlock().
 */
class AutoLocker {
  struct Locker {
    virtual void lock   () const = 0;
    virtual void unlock () const = 0;
  };
  template<class Lockable>
  struct LockerImpl : public Locker {
    Lockable    *lockable;
    virtual void lock       () const      { lockable->lock(); }
    virtual void unlock     () const      { lockable->unlock(); }
    explicit     LockerImpl (Lockable *l) : lockable (l) {}
  };
  void  *space[2];
  BIRNET_PRIVATE_CLASS_COPY (AutoLocker);
  inline const Locker*          locker      () const             { return static_cast<Locker*> ((void*) &space); }
protected:
  /* assert implicit assumption of the AutoLocker implementation */
  template<class Lockable> void
  assert_impl (Lockable &lockable)
  {
    BIRNET_ASSERT (sizeof (LockerImpl<Lockable>) <= sizeof (space));
    Locker *laddr = new (space) LockerImpl<Lockable> (&lockable);
    BIRNET_ASSERT (laddr == locker());
  }
public:
  template<class Lockable>      AutoLocker  (Lockable *lockable) { new (space) LockerImpl<Lockable> (lockable); relock(); }
  template<class Lockable>      AutoLocker  (Lockable &lockable) { new (space) LockerImpl<Lockable> (&lockable); relock(); }
  void                          relock      () const             { locker()->lock(); }
  void                          unlock      () const             { locker()->unlock(); }
  /*Des*/                       ~AutoLocker ()                   { unlock(); }
};

namespace Atomic {
/* atomic integers */
inline void     int_set      (volatile int *iptr, int value)    { birnet_atomic_int_set (iptr, value); }
inline int      int_get      (volatile int *iptr)               { return birnet_atomic_int_get (iptr); }
inline bool     int_cas      (volatile int *iptr, int o, int n) { return birnet_atomic_int_compare_and_swap (iptr, o, n); }
inline void     int_add      (volatile int *iptr, int diff)     { birnet_atomic_int_add (iptr, diff); }
inline int      int_swap_add (volatile int *iptr, int diff)     { return birnet_atomic_int_swap_and_add (iptr, diff); }
/* atomic pointers */
template<class V>
inline void     ptr_set      (volatile V **ptr_addr, V *n)      { birnet_atomic_set (void*, (void**) ptr_addr, (void*) n); }
template<class V>
inline V*       ptr_get      (volatile V **ptr_addr)            { return (V*) birnet_atomic_get (void*, (void**) ptr_addr); }
template<class V>
inline V*       ptr_get      (volatile V *const *ptr_addr)      { return (V*) birnet_atomic_get (void*, (void**) ptr_addr); }
template<class V>
inline bool     ptr_cas      (volatile V **ptr_adr, V *o, V *n) { return birnet_atomic_compare_and_swap (void*, (void**) ptr_adr, (void*) o, (void*) n); }
};

class Thread : public virtual ReferenceCountImpl {
  static void           trampoline      (void                   *thread_data);
  BIRNET_PRIVATE_CLASS_COPY (Thread);
  explicit              Thread          (BirnetThread           *thread);
protected:
  BirnetThread         *bthread;
  static Thread*        thread_from_c   (BirnetThread           *bthread);
  virtual void          run             () = 0;
public:
  explicit              Thread          (const String           &name);
  void                  start           ();
  int                   pid             () const;
  String                name            () const;
  void                  queue_abort     ();
  void                  abort           ();
  bool                  aborted         ();
  void                  wakeup          ();
  bool                  running         ();
  void                  wait_for_exit   ();
  virtual               ~Thread         ();
  /* global method */
  static void           emit_wakeups    (uint64                  stamp);
  static Thread&        self            ();
  /* self thread */
  struct Self {
    static String       name            ();
    static void         name            (const String           &name);
    static bool         sleep           (long                    max_useconds);
    static bool         aborted         ();
    static int          pid             ();
    static void         awake_after     (uint64                  stamp);
    static void         set_wakeup      (BirnetThreadWakeup      wakeup_func,
                                         void                   *wakeup_data,
                                         GDestroyNotify          destroy);
  };
  /* event loop */
  void                  exec_loop       ();
  void                  quit_loop       ();
#if 0 // FIXME
  /* mimick DataListContainer */
private:
  DataList data_list;
  void     thread_lock     ();
  bool     thread_trylock  ();
  void     thread_unlock   ();
public: /* generic data API */
  template<typename Type> inline void set_data    (DataKey<Type> *key,
                                                   Type           data) { thread_lock(); data_list.set (key, data); thread_unlock(); }
  template<typename Type> inline Type get_data    (DataKey<Type> *key)  { thread_lock(); Type d = data_list.get (key); thread_unlock(); return d; }
  template<typename Type> inline Type swap_data   (DataKey<Type> *key)  { thread_lock(); Type d = data_list.swap (key); thread_unlock(); return d; }
  template<typename Type> inline Type swap_data   (DataKey<Type> *key,
                                                   Type           data) { thread_lock(); Type d = data_list.swap (key, data); thread_unlock(); return d; }
  template<typename Type> inline void delete_data (DataKey<Type> *key)  { thread_lock(); data_list.del (key); thread_unlock(); }
#endif
};

} // Birnet

#endif /* __BIRNET_THREAD_XX_HH__ */

/* vim:set ts=8 sts=2 sw=2: */
<commit_msg>const fixes<commit_after>/* Birnet
 * Copyright (C) 2006 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#ifndef __BIRNET_THREAD_XX_HH__
#define __BIRNET_THREAD_XX_HH__

#include <birnet/birnetthread.h>
#include <birnet/birnetutilsxx.hh>

namespace Birnet {

class Mutex {
  BirnetMutex mutex;
  friend class Cond;
  BIRNET_PRIVATE_CLASS_COPY (Mutex);
public:
  explicit      Mutex   ()                      { birnet_thread_table.mutex_init (&mutex); }
  void          lock    ()                      { birnet_thread_table.mutex_lock (&mutex); }
  void          unlock  ()                      { birnet_thread_table.mutex_unlock (&mutex); }
  bool          trylock ()                      { return 0 == birnet_thread_table.mutex_trylock (&mutex); /* TRUE indicates success */ }
  /*Des*/       ~Mutex  ()                      { birnet_thread_table.mutex_destroy (&mutex); }
};

class RecMutex {
  BirnetRecMutex rmutex;
  BIRNET_PRIVATE_CLASS_COPY (RecMutex);
public:
  explicit      RecMutex  ()                    { birnet_thread_table.rec_mutex_init (&rmutex); }
  void          lock      ()                    { birnet_thread_table.rec_mutex_lock (&rmutex); }
  void          unlock    ()                    { birnet_thread_table.rec_mutex_unlock (&rmutex); }
  bool          trylock   ()                    { return 0 == birnet_thread_table.rec_mutex_trylock (&rmutex); /* TRUE indicates success */ }
  /*Des*/       ~RecMutex ()                    { birnet_thread_table.rec_mutex_destroy (&rmutex); }
};

class Cond {
  BirnetCond cond;
  BIRNET_PRIVATE_CLASS_COPY (Cond);
public:
  explicit      Cond          ()                { birnet_thread_table.cond_init (&cond); }
  void          signal        ()                { birnet_thread_table.cond_signal (&cond); }
  void          broadcast     ()                { birnet_thread_table.cond_broadcast (&cond); }
  void          wait          (Mutex &m)        { birnet_thread_table.cond_wait (&cond, &m.mutex); }
  void          wait_timed    (Mutex &m,
                               int64 max_usecs) { birnet_cond_wait_timed (&cond, &m.mutex, max_usecs); }
  /*Des*/       ~Cond         ()                { birnet_thread_table.cond_destroy (&cond); }
};

/**
 * The AutoLocker class locks mutex like objects on construction, and automatically
 * unlocks on destruction. So putting an AutoLocker object on the stack conveniently
 * ensures that a mutex will be automatcially locked and properly unlocked when
 * the function returns or thros an exception.
 * Objects intended to be used by an AutoLocker need to provide the public methods
 * lock() and unlock().
 */
class AutoLocker {
  struct Locker {
    virtual void lock   () const = 0;
    virtual void unlock () const = 0;
  };
  template<class Lockable>
  struct LockerImpl : public Locker {
    Lockable    *lockable;
    virtual void lock       () const      { lockable->lock(); }
    virtual void unlock     () const      { lockable->unlock(); }
    explicit     LockerImpl (Lockable *l) : lockable (l) {}
  };
  void  *space[2];
  BIRNET_PRIVATE_CLASS_COPY (AutoLocker);
  inline const Locker*          locker      () const             { return static_cast<const Locker*> ((const void*) &space); }
protected:
  /* assert implicit assumption of the AutoLocker implementation */
  template<class Lockable> void
  assert_impl (Lockable &lockable)
  {
    BIRNET_ASSERT (sizeof (LockerImpl<Lockable>) <= sizeof (space));
    Locker *laddr = new (space) LockerImpl<Lockable> (&lockable);
    BIRNET_ASSERT (laddr == locker());
  }
public:
  template<class Lockable>      AutoLocker  (Lockable *lockable) { new (space) LockerImpl<Lockable> (lockable); relock(); }
  template<class Lockable>      AutoLocker  (Lockable &lockable) { new (space) LockerImpl<Lockable> (&lockable); relock(); }
  void                          relock      () const             { locker()->lock(); }
  void                          unlock      () const             { locker()->unlock(); }
  /*Des*/                       ~AutoLocker ()                   { unlock(); }
};

namespace Atomic {
/* atomic integers */
inline void     int_set      (volatile int *iptr, int value)    { birnet_atomic_int_set (iptr, value); }
inline int      int_get      (volatile int *iptr)               { return birnet_atomic_int_get (iptr); }
inline bool     int_cas      (volatile int *iptr, int o, int n) { return birnet_atomic_int_compare_and_swap (iptr, o, n); }
inline void     int_add      (volatile int *iptr, int diff)     { birnet_atomic_int_add (iptr, diff); }
inline int      int_swap_add (volatile int *iptr, int diff)     { return birnet_atomic_int_swap_and_add (iptr, diff); }
/* atomic pointers */
template<class V>
inline void     ptr_set      (volatile V **ptr_addr, V *n)      { birnet_atomic_set (void*, (void**) ptr_addr, (void*) n); }
template<class V>
inline V*       ptr_get      (volatile V **ptr_addr)            { return (V*) birnet_atomic_get (void*, (void**) ptr_addr); }
template<class V>
inline V*       ptr_get      (volatile V *const *ptr_addr)      { return (V*) birnet_atomic_get (void*, (void**) ptr_addr); }
template<class V>
inline bool     ptr_cas      (volatile V **ptr_adr, V *o, V *n) { return birnet_atomic_compare_and_swap (void*, (void**) ptr_adr, (void*) o, (void*) n); }
};

class Thread : public virtual ReferenceCountImpl {
  static void           trampoline      (void                   *thread_data);
  BIRNET_PRIVATE_CLASS_COPY (Thread);
  explicit              Thread          (BirnetThread           *thread);
protected:
  BirnetThread         *bthread;
  static Thread*        thread_from_c   (BirnetThread           *bthread);
  virtual void          run             () = 0;
public:
  explicit              Thread          (const String           &name);
  void                  start           ();
  int                   pid             () const;
  String                name            () const;
  void                  queue_abort     ();
  void                  abort           ();
  bool                  aborted         ();
  void                  wakeup          ();
  bool                  running         ();
  void                  wait_for_exit   ();
  virtual               ~Thread         ();
  /* global method */
  static void           emit_wakeups    (uint64                  stamp);
  static Thread&        self            ();
  /* self thread */
  struct Self {
    static String       name            ();
    static void         name            (const String           &name);
    static bool         sleep           (long                    max_useconds);
    static bool         aborted         ();
    static int          pid             ();
    static void         awake_after     (uint64                  stamp);
    static void         set_wakeup      (BirnetThreadWakeup      wakeup_func,
                                         void                   *wakeup_data,
                                         GDestroyNotify          destroy);
  };
  /* event loop */
  void                  exec_loop       ();
  void                  quit_loop       ();
#if 0 // FIXME
  /* mimick DataListContainer */
private:
  DataList data_list;
  void     thread_lock     ();
  bool     thread_trylock  ();
  void     thread_unlock   ();
public: /* generic data API */
  template<typename Type> inline void set_data    (DataKey<Type> *key,
                                                   Type           data) { thread_lock(); data_list.set (key, data); thread_unlock(); }
  template<typename Type> inline Type get_data    (DataKey<Type> *key)  { thread_lock(); Type d = data_list.get (key); thread_unlock(); return d; }
  template<typename Type> inline Type swap_data   (DataKey<Type> *key)  { thread_lock(); Type d = data_list.swap (key); thread_unlock(); return d; }
  template<typename Type> inline Type swap_data   (DataKey<Type> *key,
                                                   Type           data) { thread_lock(); Type d = data_list.swap (key, data); thread_unlock(); return d; }
  template<typename Type> inline void delete_data (DataKey<Type> *key)  { thread_lock(); data_list.del (key); thread_unlock(); }
#endif
};

} // Birnet

#endif /* __BIRNET_THREAD_XX_HH__ */

/* vim:set ts=8 sts=2 sw=2: */
<|endoftext|>


<commit_before>#include "stdsneezy.h"
#include "database.h"
#include "shop.h"
#include "shopowned.h"
#include "process.h"

// procBankInterest
procBankInterest::procBankInterest(const int &p)
{
  trigger_pulse=p;
  name="procBankInterest";
}

void procBankInterest::run(int pulse) const
{
  TDatabase db(DB_SNEEZY), in(DB_SNEEZY);
  double profit_sell;
  unsigned int shop_nr;
  int pretalens=0, posttalens=0;

  db.query("update shopownedbank set earned_interest=0 where earned_interest is null");
  db.query("update shopownedcorpbank set earned_interest=0 where earned_interest is null");
  db.query("update shopownedbank set talens=0 where talens is null");
  db.query("update shopownedcorpbank set talens=0 where talens is null");

  db.query("select shop_nr, keeper from shop");

  while(db.fetchRow()){
    if(mob_index[real_mobile(convertTo<int>(db["keeper"]))].spec==SPEC_BANKER){
      shop_nr=convertTo<int>(db["shop_nr"]);
      profit_sell=shop_index[shop_nr].profit_sell;

      if(profit_sell==1.0)
	continue;

      in.query("select sum(talens) as talens from shopownedbank where shop_nr=%i",
	       shop_nr);
      if(in.fetchRow())
	pretalens=convertTo<int>(in["talens"]);

      in.query("select sum(talens) as talens from shopownedcorpbank where shop_nr=%i",
	       shop_nr);
      if(in.fetchRow())
	pretalens+=convertTo<int>(in["talens"]);

      // calculate interest
      in.query("update shopownedbank set earned_interest=earned_interest + (talens * (%f / 365.0)) where shop_nr=%i", profit_sell, shop_nr);

      // doll out earned interest that isn't fractional
      in.query("update shopownedbank set talens=talens + truncate(earned_interest,0), earned_interest=earned_interest - truncate(earned_interest,0) where shop_nr=%i", shop_nr);

      // calculate interest
      in.query("update shopownedcorpbank set earned_interest=earned_interest + (talens * (%f / 365.0)) where shop_nr=%i", profit_sell, shop_nr);

      // doll out earned interest that isn't fractional
      in.query("update shopownedcorpbank set talens=talens + truncate(earned_interest,0), earned_interest=earned_interest - truncate(earned_interest,0) where shop_nr=%i", shop_nr);

      in.query("select sum(talens) as talens from shopownedbank where shop_nr=%i",
	       shop_nr);
      if(in.fetchRow())
	posttalens=convertTo<int>(in["talens"]);

      in.query("select sum(talens) as talens from shopownedcorpbank where shop_nr=%i",
	       shop_nr);
      if(in.fetchRow())
	posttalens+=convertTo<int>(in["talens"]);

      if((posttalens-pretalens) !=0)
	in.query("insert into shoplog values (%i, '%s', 'paying interest', 'all', %i, 0, 0, now(), 0)", shop_nr,
		 mob_index[real_mobile(convertTo<int>(db["keeper"]))].short_desc,
		 posttalens-pretalens);

    }
  }
}

int bankWithdraw(TBeing *ch, TMonster *myself, TMonster *teller, int shop_nr, int money)
{
  TDatabase db(DB_SNEEZY);
  int bankmoney;

  if (!ch->isPc() || dynamic_cast<TMonster *>(ch)) {
    teller->doTell(ch->getName(), "Stupid monster can't bank here!");
    return TRUE;
  }

  db.query("select talens from shopownedbank where shop_nr=%i and player_id=%i", shop_nr, ch->getPlayerID());

  if(!db.fetchRow()){
    teller->doTell(ch->getName(), "You don't have an account here.");
    teller->doTell(ch->getName(), "To open an account, type 'buy account'.");
    teller->doTell(ch->getName(), "The new account fee is 100 talens.");
    return FALSE;
  } else
    bankmoney = convertTo<int>(db["talens"]);

  if (money > bankmoney) {
    teller->doTell(ch->getName(), "You don't have enough in the bank for that!");
    return TRUE;
  } else if(myself->getMoney() < money){
    teller->doTell(ch->getName(), "The bank doesn't have your funds available right now!");
    return TRUE;
  } else if (money <= 0) {
    teller->doTell(ch->getName(), "Go away, you bother me.");
    return TRUE;
  }

  teller->doTell(ch->getName(), "Thank you.");
  myself->giveMoney(ch, money, GOLD_XFER);
  myself->saveItems(fmt("%s/%d") % SHOPFILE_PATH % shop_nr);

  db.query("update shopownedbank set talens=talens-%i where player_id=%i and shop_nr=%i", money, ch->getPlayerID(), shop_nr);

  shoplog(shop_nr, ch, myself, "talens", -money, "withdrawal");

  return TRUE;
}

int bankDeposit(TBeing *ch, TMonster *myself, TMonster *teller, int shop_nr, int money)
{
  TDatabase db(DB_SNEEZY);
  int bankmoney;

  if (!ch->isPc() || dynamic_cast<TMonster *>(ch)) {
    teller->doTell(ch->getName(), "Stupid monster can't bank here!");
    return TRUE;
  }

  db.query("select talens from shopownedbank where shop_nr=%i and player_id=%i", shop_nr, ch->getPlayerID());

  if(!db.fetchRow()){
    teller->doTell(ch->getName(), "You don't have an account here.");
    teller->doTell(ch->getName(), "To open an account, type 'buy account'.");
    teller->doTell(ch->getName(), "The new account fee is 100 talens.");
    return TRUE;
  }

  if (money <= 0) {
    teller->doTell(ch->getName(), "Go away, you bother me.");
    return TRUE;
  } else if (money > ch->getMoney()) {
    teller->doTell(ch->getName(), "You don't have enough for that!");
    return TRUE;
  }

  teller->doTell(ch->getName(), "Thank you.");
  ch->giveMoney(myself, money, GOLD_XFER);
  myself->saveItems(fmt("%s/%d") % SHOPFILE_PATH % shop_nr);

  db.query("update shopownedbank set talens=talens+%i where player_id=%i and shop_nr=%i", money, ch->getPlayerID(), shop_nr);

  shoplog(shop_nr, ch, myself, "talens", money, "deposit");

  db.query("select talens from shopownedbank where shop_nr=%i and player_id=%i", shop_nr, ch->getPlayerID());

  if (!db.fetchRow()) {
    teller->doTell(ch->getName(), "You really should not see me, this is an error...");
    vlogf(LOG_BUG, fmt("Banking error, was unable to retrieve balance after a deposit: %s") % ch->getName());

    return TRUE;
  } else
    bankmoney = convertTo<int>(db["talens"]);

  teller->doTell(ch->getName(), fmt("...Your new balance is %i") % bankmoney);

  return TRUE;
}

int bankBalance(TBeing *ch, TMonster *myself, TMonster *teller, int shop_nr)
{
  TDatabase db(DB_SNEEZY);
  int bankmoney;

  db.query("select talens from shopownedbank where shop_nr=%i and player_id=%i", shop_nr, ch->getPlayerID());

  if(!db.fetchRow()){
    teller->doTell(ch->getName(), "You don't have an account here.");
    teller->doTell(ch->getName(), "To open an account, type 'buy account'.");
    teller->doTell(ch->getName(), "The new account fee is 100 talens.");
    return TRUE;
  } else
    bankmoney = convertTo<int>(db["talens"]);

  teller->doTell(ch->getName(), fmt("Your balance is %i.") % bankmoney);

  return TRUE;
}

int bankBuyAccount(TBeing *ch, TMonster *myself, TMonster *teller, int shop_nr, int money)
{
  TDatabase db(DB_SNEEZY);

  if(ch->getMoney() < 100){
    teller->doTell(ch->getName(), "You don't have enough money to open an account.");
    return TRUE;
  }

  db.query("select talens from shopownedbank where player_id=%i and shop_nr=%i", ch->getPlayerID(), shop_nr);

  if(db.fetchRow()){
    teller->doTell(ch->getName(), "You already have an account.");
    return TRUE;
  }

  db.query("insert into shopownedbank (player_id, shop_nr, talens) values (%i, %i, 0)", ch->getPlayerID(), shop_nr);
  ch->giveMoney(myself, 100, GOLD_XFER);
  shoplog(shop_nr, ch, myself, "talens", 100, "new account");
  myself->saveItems(fmt("%s/%d") % SHOPFILE_PATH % shop_nr);

  teller->doTell(ch->getName(), "Your account is now open and ready for use.");

  return TRUE;
}

int banker(TBeing *ch, cmdTypeT cmd, const char *arg, TMonster *myself, TObj *)
{
  int shop_nr, money=0;
  TDatabase db(DB_SNEEZY);

  if((cmd!=CMD_WITHDRAW &&
      cmd!=CMD_DEPOSIT &&
      cmd!=CMD_BUY &&
      cmd!=CMD_LIST &&
      cmd!=CMD_BALANCE &&
      cmd!=CMD_WHISPER) ||
     !ch || !myself)
    return FALSE;

  if(!(shop_nr=find_shop_nr(myself->number)))
    return FALSE;

  if(cmd==CMD_WHISPER)
    return shopWhisper(ch, myself, shop_nr, arg);

  if(cmd==CMD_LIST){
    TShopOwned tso(shop_nr, myself, ch);

    if(!tso.hasAccess(SHOPACCESS_LOGS)){
      myself->doTell(ch->getName(), "Sorry, you don't have access to do that.");
      return FALSE;
    }

    db.query("select p.name, b.talens from player p, shopownedbank b where b.shop_nr=%i and b.player_id=p.id union select c.name, b.talens from corporation c, shopownedcorpbank b where b.shop_nr=c.bank and b.shop_nr=%i and b.corp_id=c.corp_id order by talens desc", shop_nr, shop_nr);

    sstring buf;
    int empty=0;
    while(db.fetchRow()){
      if(convertTo<int>(db["talens"]) == 0)
	empty++;
      else
	buf += fmt("<c>%s - %s talens.<1>\n\r") % db["name"] %
	  talenDisplay(convertTo<int>(db["talens"]));
    }
    buf += fmt("%i empty accounts.\n\r") % empty;

    db.query("select (sb.c+sbc.c) as c, (sb.t+sbc.t) as t from (select count(*) as c, sum(talens) as t from shopownedbank where shop_nr=%i) sb, (select count(*) as c, sum(talens) as t from shopownedcorpbank where shop_nr=%i) sbc", shop_nr, shop_nr);

    if(db.fetchRow()){
      buf += fmt("%i total accounts, %s talens.\n\r") %
	convertTo<int>(db["c"]) %
	talenDisplay(convertTo<int>(db["t"]));
    }

    ch->desc->page_string(buf);

    return TRUE;
  }

  if(cmd==CMD_BUY && sstring(arg).lower()=="account"){
    money=convertTo<int>(arg);
    return bankBuyAccount(ch, myself, myself, shop_nr, money);
  } else if(cmd==CMD_BALANCE){
    return bankBalance(ch, myself, myself, shop_nr);
  } else if(cmd==CMD_WITHDRAW){
    if(!strcmp(arg, "all"))
      money=ch->getBank();
    else
      money=convertTo<int>(arg);

    return bankWithdraw(ch, myself, myself, shop_nr, money);
  } else if(cmd==CMD_DEPOSIT){
    if(!strcmp(arg, "all"))
      money=ch->getMoney();
    else
      money=convertTo<int>(arg);
    return bankDeposit(ch, myself, myself, shop_nr, money);
  }

  return TRUE;
}

int bankRoom(TBeing *ch, cmdTypeT cmd, const char *arg, TRoom *rp)
{
  TMonster *teller, *banker;
  TBeing *t;
  int tmp=130, money, shop_nr;

  // tellers/branches can only do these commands
  if(cmd!=CMD_WITHDRAW &&
     cmd!=CMD_DEPOSIT &&
     cmd!=CMD_BALANCE &&
     cmd!=CMD_BUY)
    return FALSE;

  // find out which teller for this room
  switch(rp->number){
    case 31751:
    case 31756:
    case 2351:
      tmp=31750;
      break;
    case 1295:
      tmp=1295;
      break;
    case 3755:
      tmp=3755;
      break;
    case 8756:
      tmp=8756;
      break;
  }

  // find the teller
  for(t=character_list;t;t=t->next){
    if(t->mobVnum()==tmp)
      break;
  }

  if(!t || !(teller=dynamic_cast<TMonster *>(t)))
    return FALSE;

  // find out which banker for this room
  switch(rp->number){
    case 31751:
    case 31756:
    case 2351:
      tmp=31765;
      break;
    case 1295:
      tmp=1295;
      break;
    case 3755:
      tmp=3755;
      break;
    case 8756:
      tmp=8756;
      break;
  }

  // find the banker
  for(t=character_list;t;t=t->next){
    if(t->mobVnum()==tmp)
      break;
  }

  if(!t || !(banker=dynamic_cast<TMonster *>(t)))
    return FALSE;

  if(!(shop_nr=find_shop_nr(banker->number)))
    return FALSE;

  if(cmd==CMD_BUY && sstring(arg).lower()=="account"){
    money=convertTo<int>(arg);
    return bankBuyAccount(ch, banker, teller, shop_nr, money);
  } else if(cmd==CMD_BALANCE){
    return bankBalance(ch, banker, teller, shop_nr);
  } else if(cmd==CMD_WITHDRAW){
    if(!strcmp(arg, "all"))
      money=ch->getBank();
    else
      money=convertTo<int>(arg);
    return bankWithdraw(ch, banker, teller, shop_nr, money);
  } else if(cmd==CMD_DEPOSIT){
    if(!strcmp(arg, "all"))
      money=ch->getMoney();
    else
      money=convertTo<int>(arg);
    return bankDeposit(ch, banker, teller, shop_nr, money);
  }

  return FALSE;
}

<commit_msg>split the interest earned log up into an individual log for each account<commit_after>#include "stdsneezy.h"
#include "database.h"
#include "shop.h"
#include "shopowned.h"
#include "process.h"

// procBankInterest
procBankInterest::procBankInterest(const int &p)
{
  trigger_pulse=p;
  name="procBankInterest";
}

void procBankInterest::run(int pulse) const
{
  TDatabase db(DB_SNEEZY), in(DB_SNEEZY), out(DB_SNEEZY);
  double profit_sell;
  unsigned int shop_nr;
  map <int, int> player_gain;
  map <int, int> corp_gain;

  db.query("update shopownedbank set earned_interest=0 where earned_interest is null");
  db.query("update shopownedcorpbank set earned_interest=0 where earned_interest is null");
  db.query("update shopownedbank set talens=0 where talens is null");
  db.query("update shopownedcorpbank set talens=0 where talens is null");

  db.query("select shop_nr, keeper from shop");

  while(db.fetchRow()){
    if(mob_index[real_mobile(convertTo<int>(db["keeper"]))].spec==SPEC_BANKER){
      shop_nr=convertTo<int>(db["shop_nr"]);
      profit_sell=shop_index[shop_nr].profit_sell;

      if(profit_sell==1.0)
	continue;

      // make a list of current player talens
      in.query("select player_id, talens from shopownedbank where shop_nr=%i",
	       shop_nr);
      while(in.fetchRow())
	player_gain[convertTo<int>(in["player_id"])]=convertTo<int>(in["talens"]);

      // make a list of current corporate talens
      in.query("select corp_id, talens from shopownedcorpbank where shop_nr=%i",
	       shop_nr);
      while(in.fetchRow())
	corp_gain[convertTo<int>(in["corp_id"])]=convertTo<int>(in["talens"]);

      // calculate interest
      in.query("update shopownedbank set earned_interest=earned_interest + (talens * (%f / 365.0)) where shop_nr=%i", profit_sell, shop_nr);

      // doll out earned interest that isn't fractional
      in.query("update shopownedbank set talens=talens + truncate(earned_interest,0), earned_interest=earned_interest - truncate(earned_interest,0) where shop_nr=%i", shop_nr);

      // calculate interest
      in.query("update shopownedcorpbank set earned_interest=earned_interest + (talens * (%f / 365.0)) where shop_nr=%i", profit_sell, shop_nr);

      // doll out earned interest that isn't fractional
      in.query("update shopownedcorpbank set talens=talens + truncate(earned_interest,0), earned_interest=earned_interest - truncate(earned_interest,0) where shop_nr=%i", shop_nr);

      // log player gains
      in.query("select p.name as name, sob.player_id as player_id, sob.talens as talens from shopownedbank sob, player p where shop_nr=%i and sob.player_id=p.id",
	       shop_nr);
      while(in.fetchRow()){
	if((convertTo<int>(in["talens"]) - player_gain[convertTo<int>(in["player_id"])]) != 0){
	  out.query("insert into shoplog values (%i, '%s', 'interest', 'talens', %i, %i, 0, now(), 0)", shop_nr,
		    in["name"].c_str(),
		    convertTo<int>(in["talens"]) - player_gain[convertTo<int>(in["player_id"])],
		    convertTo<int>(in["talens"]));
	}
      }

      // log corporate gains
      in.query("select c.name, sob.corp_id, sob.talens from shopownedcorpbank sob, corporation c where c.corp_id=sob.corp_id and sob.shop_nr=%i",
	       shop_nr);
      while(in.fetchRow()){
	if((convertTo<int>(in["talens"]) - corp_gain[convertTo<int>(in["player_id"])]) != 0){
	  out.query("insert into shoplog values (%i, '%s', 'interest', 'talens', %i, %i, 0, now(), 0)", shop_nr,
		    in["name"].c_str(),
		    convertTo<int>(in["talens"]) - corp_gain[convertTo<int>(in["corp_id"])],
		    convertTo<int>(in["talens"]));
	}
      }
    }
  }
}

int bankWithdraw(TBeing *ch, TMonster *myself, TMonster *teller, int shop_nr, int money)
{
  TDatabase db(DB_SNEEZY);
  int bankmoney;

  if (!ch->isPc() || dynamic_cast<TMonster *>(ch)) {
    teller->doTell(ch->getName(), "Stupid monster can't bank here!");
    return TRUE;
  }

  db.query("select talens from shopownedbank where shop_nr=%i and player_id=%i", shop_nr, ch->getPlayerID());

  if(!db.fetchRow()){
    teller->doTell(ch->getName(), "You don't have an account here.");
    teller->doTell(ch->getName(), "To open an account, type 'buy account'.");
    teller->doTell(ch->getName(), "The new account fee is 100 talens.");
    return FALSE;
  } else
    bankmoney = convertTo<int>(db["talens"]);

  if (money > bankmoney) {
    teller->doTell(ch->getName(), "You don't have enough in the bank for that!");
    return TRUE;
  } else if(myself->getMoney() < money){
    teller->doTell(ch->getName(), "The bank doesn't have your funds available right now!");
    return TRUE;
  } else if (money <= 0) {
    teller->doTell(ch->getName(), "Go away, you bother me.");
    return TRUE;
  }

  teller->doTell(ch->getName(), "Thank you.");
  myself->giveMoney(ch, money, GOLD_XFER);
  myself->saveItems(fmt("%s/%d") % SHOPFILE_PATH % shop_nr);

  db.query("update shopownedbank set talens=talens-%i where player_id=%i and shop_nr=%i", money, ch->getPlayerID(), shop_nr);

  shoplog(shop_nr, ch, myself, "talens", -money, "withdrawal");

  return TRUE;
}

int bankDeposit(TBeing *ch, TMonster *myself, TMonster *teller, int shop_nr, int money)
{
  TDatabase db(DB_SNEEZY);
  int bankmoney;

  if (!ch->isPc() || dynamic_cast<TMonster *>(ch)) {
    teller->doTell(ch->getName(), "Stupid monster can't bank here!");
    return TRUE;
  }

  db.query("select talens from shopownedbank where shop_nr=%i and player_id=%i", shop_nr, ch->getPlayerID());

  if(!db.fetchRow()){
    teller->doTell(ch->getName(), "You don't have an account here.");
    teller->doTell(ch->getName(), "To open an account, type 'buy account'.");
    teller->doTell(ch->getName(), "The new account fee is 100 talens.");
    return TRUE;
  }

  if (money <= 0) {
    teller->doTell(ch->getName(), "Go away, you bother me.");
    return TRUE;
  } else if (money > ch->getMoney()) {
    teller->doTell(ch->getName(), "You don't have enough for that!");
    return TRUE;
  }

  teller->doTell(ch->getName(), "Thank you.");
  ch->giveMoney(myself, money, GOLD_XFER);
  myself->saveItems(fmt("%s/%d") % SHOPFILE_PATH % shop_nr);

  db.query("update shopownedbank set talens=talens+%i where player_id=%i and shop_nr=%i", money, ch->getPlayerID(), shop_nr);

  shoplog(shop_nr, ch, myself, "talens", money, "deposit");

  db.query("select talens from shopownedbank where shop_nr=%i and player_id=%i", shop_nr, ch->getPlayerID());

  if (!db.fetchRow()) {
    teller->doTell(ch->getName(), "You really should not see me, this is an error...");
    vlogf(LOG_BUG, fmt("Banking error, was unable to retrieve balance after a deposit: %s") % ch->getName());

    return TRUE;
  } else
    bankmoney = convertTo<int>(db["talens"]);

  teller->doTell(ch->getName(), fmt("...Your new balance is %i") % bankmoney);

  return TRUE;
}

int bankBalance(TBeing *ch, TMonster *myself, TMonster *teller, int shop_nr)
{
  TDatabase db(DB_SNEEZY);
  int bankmoney;

  db.query("select talens from shopownedbank where shop_nr=%i and player_id=%i", shop_nr, ch->getPlayerID());

  if(!db.fetchRow()){
    teller->doTell(ch->getName(), "You don't have an account here.");
    teller->doTell(ch->getName(), "To open an account, type 'buy account'.");
    teller->doTell(ch->getName(), "The new account fee is 100 talens.");
    return TRUE;
  } else
    bankmoney = convertTo<int>(db["talens"]);

  teller->doTell(ch->getName(), fmt("Your balance is %i.") % bankmoney);

  return TRUE;
}

int bankBuyAccount(TBeing *ch, TMonster *myself, TMonster *teller, int shop_nr, int money)
{
  TDatabase db(DB_SNEEZY);

  if(ch->getMoney() < 100){
    teller->doTell(ch->getName(), "You don't have enough money to open an account.");
    return TRUE;
  }

  db.query("select talens from shopownedbank where player_id=%i and shop_nr=%i", ch->getPlayerID(), shop_nr);

  if(db.fetchRow()){
    teller->doTell(ch->getName(), "You already have an account.");
    return TRUE;
  }

  db.query("insert into shopownedbank (player_id, shop_nr, talens) values (%i, %i, 0)", ch->getPlayerID(), shop_nr);
  ch->giveMoney(myself, 100, GOLD_XFER);
  shoplog(shop_nr, ch, myself, "talens", 100, "new account");
  myself->saveItems(fmt("%s/%d") % SHOPFILE_PATH % shop_nr);

  teller->doTell(ch->getName(), "Your account is now open and ready for use.");

  return TRUE;
}

int banker(TBeing *ch, cmdTypeT cmd, const char *arg, TMonster *myself, TObj *)
{
  int shop_nr, money=0;
  TDatabase db(DB_SNEEZY);

  if((cmd!=CMD_WITHDRAW &&
      cmd!=CMD_DEPOSIT &&
      cmd!=CMD_BUY &&
      cmd!=CMD_LIST &&
      cmd!=CMD_BALANCE &&
      cmd!=CMD_WHISPER) ||
     !ch || !myself)
    return FALSE;

  if(!(shop_nr=find_shop_nr(myself->number)))
    return FALSE;

  if(cmd==CMD_WHISPER)
    return shopWhisper(ch, myself, shop_nr, arg);

  if(cmd==CMD_LIST){
    TShopOwned tso(shop_nr, myself, ch);

    if(!tso.hasAccess(SHOPACCESS_LOGS)){
      myself->doTell(ch->getName(), "Sorry, you don't have access to do that.");
      return FALSE;
    }

    db.query("select p.name, b.talens from player p, shopownedbank b where b.shop_nr=%i and b.player_id=p.id union select c.name, b.talens from corporation c, shopownedcorpbank b where b.shop_nr=c.bank and b.shop_nr=%i and b.corp_id=c.corp_id order by talens desc", shop_nr, shop_nr);

    sstring buf;
    int empty=0;
    while(db.fetchRow()){
      if(convertTo<int>(db["talens"]) == 0)
	empty++;
      else
	buf += fmt("<c>%s - %s talens.<1>\n\r") % db["name"] %
	  talenDisplay(convertTo<int>(db["talens"]));
    }
    buf += fmt("%i empty accounts.\n\r") % empty;

    db.query("select (sb.c+sbc.c) as c, (sb.t+sbc.t) as t from (select count(*) as c, sum(talens) as t from shopownedbank where shop_nr=%i) sb, (select count(*) as c, sum(talens) as t from shopownedcorpbank where shop_nr=%i) sbc", shop_nr, shop_nr);

    if(db.fetchRow()){
      buf += fmt("%i total accounts, %s talens.\n\r") %
	convertTo<int>(db["c"]) %
	talenDisplay(convertTo<int>(db["t"]));
    }

    ch->desc->page_string(buf);

    return TRUE;
  }

  if(cmd==CMD_BUY && sstring(arg).lower()=="account"){
    money=convertTo<int>(arg);
    return bankBuyAccount(ch, myself, myself, shop_nr, money);
  } else if(cmd==CMD_BALANCE){
    return bankBalance(ch, myself, myself, shop_nr);
  } else if(cmd==CMD_WITHDRAW){
    if(!strcmp(arg, "all"))
      money=ch->getBank();
    else
      money=convertTo<int>(arg);

    return bankWithdraw(ch, myself, myself, shop_nr, money);
  } else if(cmd==CMD_DEPOSIT){
    if(!strcmp(arg, "all"))
      money=ch->getMoney();
    else
      money=convertTo<int>(arg);
    return bankDeposit(ch, myself, myself, shop_nr, money);
  }

  return TRUE;
}

int bankRoom(TBeing *ch, cmdTypeT cmd, const char *arg, TRoom *rp)
{
  TMonster *teller, *banker;
  TBeing *t;
  int tmp=130, money, shop_nr;

  // tellers/branches can only do these commands
  if(cmd!=CMD_WITHDRAW &&
     cmd!=CMD_DEPOSIT &&
     cmd!=CMD_BALANCE &&
     cmd!=CMD_BUY)
    return FALSE;

  // find out which teller for this room
  switch(rp->number){
    case 31751:
    case 31756:
    case 2351:
      tmp=31750;
      break;
    case 1295:
      tmp=1295;
      break;
    case 3755:
      tmp=3755;
      break;
    case 8756:
      tmp=8756;
      break;
  }

  // find the teller
  for(t=character_list;t;t=t->next){
    if(t->mobVnum()==tmp)
      break;
  }

  if(!t || !(teller=dynamic_cast<TMonster *>(t)))
    return FALSE;

  // find out which banker for this room
  switch(rp->number){
    case 31751:
    case 31756:
    case 2351:
      tmp=31765;
      break;
    case 1295:
      tmp=1295;
      break;
    case 3755:
      tmp=3755;
      break;
    case 8756:
      tmp=8756;
      break;
  }

  // find the banker
  for(t=character_list;t;t=t->next){
    if(t->mobVnum()==tmp)
      break;
  }

  if(!t || !(banker=dynamic_cast<TMonster *>(t)))
    return FALSE;

  if(!(shop_nr=find_shop_nr(banker->number)))
    return FALSE;

  if(cmd==CMD_BUY && sstring(arg).lower()=="account"){
    money=convertTo<int>(arg);
    return bankBuyAccount(ch, banker, teller, shop_nr, money);
  } else if(cmd==CMD_BALANCE){
    return bankBalance(ch, banker, teller, shop_nr);
  } else if(cmd==CMD_WITHDRAW){
    if(!strcmp(arg, "all"))
      money=ch->getBank();
    else
      money=convertTo<int>(arg);
    return bankWithdraw(ch, banker, teller, shop_nr, money);
  } else if(cmd==CMD_DEPOSIT){
    if(!strcmp(arg, "all"))
      money=ch->getMoney();
    else
      money=convertTo<int>(arg);
    return bankDeposit(ch, banker, teller, shop_nr, money);
  }

  return FALSE;
}

<|endoftext|>


<commit_before>#pragma once

#include <array>
#include <cstdint>
#include <limits>
#include <cstddef>

namespace coding
{
class MoveToFront
{
public:
  static size_t constexpr kNumBytes = static_cast<size_t>(std::numeric_limits<uint8_t>::max()) + 1;

  MoveToFront();

  // Returns index of the byte |b| in the current sequence of bytes,
  // then moves |b| to the first position.
  uint8_t Transform(uint8_t b);

  uint8_t operator[](uint8_t i) const { return m_order[i]; }

private:
  std::array<uint8_t, kNumBytes> m_order;
};
}  // namespace coding
<commit_msg>Sort headers.<commit_after>#pragma once

#include <array>
#include <cstddef>
#include <cstdint>
#include <limits>

namespace coding
{
class MoveToFront
{
public:
  static size_t constexpr kNumBytes = static_cast<size_t>(std::numeric_limits<uint8_t>::max()) + 1;

  MoveToFront();

  // Returns index of the byte |b| in the current sequence of bytes,
  // then moves |b| to the first position.
  uint8_t Transform(uint8_t b);

  uint8_t operator[](uint8_t i) const { return m_order[i]; }

private:
  std::array<uint8_t, kNumBytes> m_order;
};
}  // namespace coding
<|endoftext|>


<commit_before>//===--- PPLexerChange.cpp - Handle changing lexers in the preprocessor ---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements pieces of the Preprocessor interface that manage the
// current lexer stack.
//
//===----------------------------------------------------------------------===//

#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/MemoryBuffer.h"

using namespace clang;

PPCallbacks::~PPCallbacks() {}

//===----------------------------------------------------------------------===//
// Miscellaneous Methods.
//===----------------------------------------------------------------------===//

/// isInPrimaryFile - Return true if we're in the top-level file, not in a
/// #include.  This looks through macro expansions and active _Pragma lexers.
bool Preprocessor::isInPrimaryFile() const {
  if (IsFileLexer())
    return IncludeMacroStack.empty();

  // If there are any stacked lexers, we're in a #include.
  assert(IsFileLexer(IncludeMacroStack[0]) &&
         "Top level include stack isn't our primary lexer?");
  for (unsigned i = 1, e = IncludeMacroStack.size(); i != e; ++i)
    if (IsFileLexer(IncludeMacroStack[i]))
      return false;
  return true;
}

/// getCurrentLexer - Return the current file lexer being lexed from.  Note
/// that this ignores any potentially active macro expansions and _Pragma
/// expansions going on at the time.
PreprocessorLexer *Preprocessor::getCurrentFileLexer() const {
  if (IsFileLexer())
    return CurPPLexer;

  // Look for a stacked lexer.
  for (unsigned i = IncludeMacroStack.size(); i != 0; --i) {
    const IncludeStackInfo& ISI = IncludeMacroStack[i-1];
    if (IsFileLexer(ISI))
      return ISI.ThePPLexer;
  }
  return 0;
}

//===----------------------------------------------------------------------===//
// Methods for Entering and Callbacks for leaving various contexts
//===----------------------------------------------------------------------===//

/// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.  Return true
/// on failure.
void Preprocessor::EnterSourceFile(unsigned FileID,
                                   const DirectoryLookup *CurDir) {
  assert(CurTokenLexer == 0 && "Cannot #include a file inside a macro!");
  ++NumEnteredSourceFiles;

  if (MaxIncludeStackDepth < IncludeMacroStack.size())
    MaxIncludeStackDepth = IncludeMacroStack.size();

#if 0
  Lexer *TheLexer = new Lexer(SourceLocation::getFileLoc(FileID, 0), *this);
  EnterSourceFileWithLexer(TheLexer, CurDir);
#else
  const llvm::MemoryBuffer* B = getSourceManager().getBuffer(FileID);

  // Create a raw lexer.
  Lexer L(SourceLocation::getFileLoc(FileID, 0), getLangOptions(),
          B->getBufferStart(), B->getBufferEnd(), B);

  // Ignore whitespace.
  L.SetKeepWhitespaceMode(false);
  L.SetCommentRetentionState(false);

  // Lex the file, populating our data structures.
  std::vector<Token>* Tokens = new std::vector<Token>();
  Token Tok;

  do {
    L.LexFromRawLexer(Tok);

    if (Tok.is(tok::identifier)) {
      Tok.setIdentifierInfo(LookUpIdentifierInfo(Tok));
    }
    else if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
      // Special processing for #include.  Store the '#' token and lex
      // the next token.
      Tokens->push_back(Tok);
      L.LexFromRawLexer(Tok);

      // Did we see 'include'/'import'/'include_next'?
      if (!Tok.is(tok::identifier))
        continue;

      IdentifierInfo* II = LookUpIdentifierInfo(Tok);
      Tok.setIdentifierInfo(II);
      tok::PPKeywordKind K = II->getPPKeywordID();

      if (K == tok::pp_include || K == tok::pp_import ||
          K == tok::pp_include_next) {

        // Save the 'include' token.
        Tokens->push_back(Tok);

        // Lex the next token as an include string.
        L.ParsingPreprocessorDirective = true;
        L.LexIncludeFilename(Tok);
        L.ParsingPreprocessorDirective = false;

        if (Tok.is(tok::identifier))
          Tok.setIdentifierInfo(LookUpIdentifierInfo(Tok));
      }
    }
  }
  while (Tokens->push_back(Tok), Tok.isNot(tok::eof));

  if (CurPPLexer || CurTokenLexer)
    PushIncludeMacroStack();

  CurDirLookup = CurDir;
  SourceLocation Loc = SourceLocation::getFileLoc(FileID, 0);
  CurPTHLexer.reset(new PTHLexer(*this, Loc, &(*Tokens)[0], Tokens->size()));
  CurPPLexer = CurPTHLexer.get();

  // Notify the client, if desired, that we are in a new source file.
  if (Callbacks) {
    SrcMgr::CharacteristicKind FileType =
    SourceMgr.getFileCharacteristic(CurPPLexer->getFileID());
    Callbacks->FileChanged(Loc, PPCallbacks::EnterFile, FileType);
  }
#endif
}

/// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.
void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
                                            const DirectoryLookup *CurDir) {

  // Add the current lexer to the include stack.
  if (CurPPLexer || CurTokenLexer)
    PushIncludeMacroStack();

  CurLexer.reset(TheLexer);
  CurPPLexer = TheLexer;
  CurDirLookup = CurDir;

  // Notify the client, if desired, that we are in a new source file.
  if (Callbacks && !CurLexer->Is_PragmaLexer) {
    SrcMgr::CharacteristicKind FileType =
       SourceMgr.getFileCharacteristic(CurLexer->getFileLoc());

    Callbacks->FileChanged(CurLexer->getFileLoc(),
                           PPCallbacks::EnterFile, FileType);
  }
}

/// EnterMacro - Add a Macro to the top of the include stack and start lexing
/// tokens from it instead of the current buffer.
void Preprocessor::EnterMacro(Token &Tok, MacroArgs *Args) {
  PushIncludeMacroStack();
  CurDirLookup = 0;

  if (NumCachedTokenLexers == 0) {
    CurTokenLexer.reset(new TokenLexer(Tok, Args, *this));
  } else {
    CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]);
    CurTokenLexer->Init(Tok, Args);
  }
}

/// EnterTokenStream - Add a "macro" context to the top of the include stack,
/// which will cause the lexer to start returning the specified tokens.
///
/// If DisableMacroExpansion is true, tokens lexed from the token stream will
/// not be subject to further macro expansion.  Otherwise, these tokens will
/// be re-macro-expanded when/if expansion is enabled.
///
/// If OwnsTokens is false, this method assumes that the specified stream of
/// tokens has a permanent owner somewhere, so they do not need to be copied.
/// If it is true, it assumes the array of tokens is allocated with new[] and
/// must be freed.
///
void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks,
                                    bool DisableMacroExpansion,
                                    bool OwnsTokens) {
  // Save our current state.
  PushIncludeMacroStack();
  CurDirLookup = 0;

  // Create a macro expander to expand from the specified token stream.
  if (NumCachedTokenLexers == 0) {
    CurTokenLexer.reset(new TokenLexer(Toks, NumToks, DisableMacroExpansion,
                                       OwnsTokens, *this));
  } else {
    CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]);
    CurTokenLexer->Init(Toks, NumToks, DisableMacroExpansion, OwnsTokens);
  }
}

/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
/// the current file.  This either returns the EOF token or pops a level off
/// the include stack and keeps going.
bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
  assert(!CurTokenLexer &&
         "Ending a file when currently in a macro!");

  // See if this file had a controlling macro.
  if (CurPPLexer) {  // Not ending a macro, ignore it.
    if (const IdentifierInfo *ControllingMacro =
          CurPPLexer->MIOpt.GetControllingMacroAtEndOfFile()) {
      // Okay, this has a controlling macro, remember in PerFileInfo.
      if (const FileEntry *FE =
            SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))
        HeaderInfo.SetFileControllingMacro(FE, ControllingMacro);
    }
  }

  // If this is a #include'd file, pop it off the include stack and continue
  // lexing the #includer file.
  if (!IncludeMacroStack.empty()) {
    // We're done with the #included file.
    RemoveTopOfLexerStack();

    // Notify the client, if desired, that we are in a new source file.
    if (Callbacks && !isEndOfMacro && CurPPLexer) {
      SrcMgr::CharacteristicKind FileType =
        SourceMgr.getFileCharacteristic(CurPPLexer->getFileID());

      if (CurLexer) {
        Callbacks->FileChanged(CurLexer->getSourceLocation(CurLexer->BufferPtr),
                               PPCallbacks::ExitFile, FileType);
      }
      else {
        // FIXME: Is this okay to use the location of 'Result'?
        Callbacks->FileChanged(Result.getLocation(), PPCallbacks::ExitFile,
                               FileType);
      }
    }

    // Client should lex another token.
    return false;
  }

  // If the file ends with a newline, form the EOF token on the newline itself,
  // rather than "on the line following it", which doesn't exist.  This makes
  // diagnostics relating to the end of file include the last file that the user
  // actually typed, which is goodness.
  if (CurLexer) {
    const char *EndPos = CurLexer->BufferEnd;
    if (EndPos != CurLexer->BufferStart &&
        (EndPos[-1] == '\n' || EndPos[-1] == '\r')) {
      --EndPos;

      // Handle \n\r and \r\n:
      if (EndPos != CurLexer->BufferStart &&
          (EndPos[-1] == '\n' || EndPos[-1] == '\r') &&
          EndPos[-1] != EndPos[0])
        --EndPos;
    }

    Result.startToken();
    CurLexer->BufferPtr = EndPos;
    CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);

    // We're done with the #included file.
    CurLexer.reset();
  }
  else {
    CurPTHLexer->setEOF(Result);
    CurPTHLexer.reset();
  }

  CurPPLexer = 0;

  // This is the end of the top-level file.  If the diag::pp_macro_not_used
  // diagnostic is enabled, look for macros that have not been used.
  if (Diags.getDiagnosticLevel(diag::pp_macro_not_used) != Diagnostic::Ignored){
    for (llvm::DenseMap<IdentifierInfo*, MacroInfo*>::iterator I =
         Macros.begin(), E = Macros.end(); I != E; ++I) {
      if (!I->second->isUsed())
        Diag(I->second->getDefinitionLoc(), diag::pp_macro_not_used);
    }
  }
  return true;
}

/// HandleEndOfTokenLexer - This callback is invoked when the current TokenLexer
/// hits the end of its token stream.
bool Preprocessor::HandleEndOfTokenLexer(Token &Result) {
  assert(CurTokenLexer && !CurPPLexer &&
         "Ending a macro when currently in a #include file!");

  // Delete or cache the now-dead macro expander.
  if (NumCachedTokenLexers == TokenLexerCacheSize)
    CurTokenLexer.reset();
  else
    TokenLexerCache[NumCachedTokenLexers++] = CurTokenLexer.take();

  // Handle this like a #include file being popped off the stack.
  return HandleEndOfFile(Result, true);
}

/// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the
/// lexer stack.  This should only be used in situations where the current
/// state of the top-of-stack lexer is unknown.
void Preprocessor::RemoveTopOfLexerStack() {
  assert(!IncludeMacroStack.empty() && "Ran out of stack entries to load");

  if (CurTokenLexer) {
    // Delete or cache the now-dead macro expander.
    if (NumCachedTokenLexers == TokenLexerCacheSize)
      CurTokenLexer.reset();
    else
      TokenLexerCache[NumCachedTokenLexers++] = CurTokenLexer.take();
  }

  PopIncludeMacroStack();
}

/// HandleMicrosoftCommentPaste - When the macro expander pastes together a
/// comment (/##/) in microsoft mode, this method handles updating the current
/// state, returning the token on the next source line.
void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) {
  assert(CurTokenLexer && !CurPPLexer &&
         "Pasted comment can only be formed from macro");

  // We handle this by scanning for the closest real lexer, switching it to
  // raw mode and preprocessor mode.  This will cause it to return \n as an
  // explicit EOM token.
  PreprocessorLexer *FoundLexer = 0;
  bool LexerWasInPPMode = false;
  for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
    IncludeStackInfo &ISI = *(IncludeMacroStack.end()-i-1);
    if (ISI.ThePPLexer == 0) continue;  // Scan for a real lexer.

    // Once we find a real lexer, mark it as raw mode (disabling macro
    // expansions) and preprocessor mode (return EOM).  We know that the lexer
    // was *not* in raw mode before, because the macro that the comment came
    // from was expanded.  However, it could have already been in preprocessor
    // mode (#if COMMENT) in which case we have to return it to that mode and
    // return EOM.
    FoundLexer = ISI.ThePPLexer;
    FoundLexer->LexingRawMode = true;
    LexerWasInPPMode = FoundLexer->ParsingPreprocessorDirective;
    FoundLexer->ParsingPreprocessorDirective = true;
    break;
  }

  // Okay, we either found and switched over the lexer, or we didn't find a
  // lexer.  In either case, finish off the macro the comment came from, getting
  // the next token.
  if (!HandleEndOfTokenLexer(Tok)) Lex(Tok);

  // Discarding comments as long as we don't have EOF or EOM.  This 'comments
  // out' the rest of the line, including any tokens that came from other macros
  // that were active, as in:
  //  #define submacro a COMMENT b
  //    submacro c
  // which should lex to 'a' only: 'b' and 'c' should be removed.
  while (Tok.isNot(tok::eom) && Tok.isNot(tok::eof))
    Lex(Tok);

  // If we got an eom token, then we successfully found the end of the line.
  if (Tok.is(tok::eom)) {
    assert(FoundLexer && "Can't get end of line without an active lexer");
    // Restore the lexer back to normal mode instead of raw mode.
    FoundLexer->LexingRawMode = false;

    // If the lexer was already in preprocessor mode, just return the EOM token
    // to finish the preprocessor line.
    if (LexerWasInPPMode) return;

    // Otherwise, switch out of PP mode and return the next lexed token.
    FoundLexer->ParsingPreprocessorDirective = false;
    return Lex(Tok);
  }

  // If we got an EOF token, then we reached the end of the token stream but
  // didn't find an explicit \n.  This can only happen if there was no lexer
  // active (an active lexer would return EOM at EOF if there was no \n in
  // preprocessor directive mode), so just return EOF as our token.
  assert(!FoundLexer && "Lexer should return EOM before EOF in PP mode");
}
<commit_msg>Reenable the default lexer.<commit_after>//===--- PPLexerChange.cpp - Handle changing lexers in the preprocessor ---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements pieces of the Preprocessor interface that manage the
// current lexer stack.
//
//===----------------------------------------------------------------------===//

#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/MemoryBuffer.h"

using namespace clang;

PPCallbacks::~PPCallbacks() {}

//===----------------------------------------------------------------------===//
// Miscellaneous Methods.
//===----------------------------------------------------------------------===//

/// isInPrimaryFile - Return true if we're in the top-level file, not in a
/// #include.  This looks through macro expansions and active _Pragma lexers.
bool Preprocessor::isInPrimaryFile() const {
  if (IsFileLexer())
    return IncludeMacroStack.empty();

  // If there are any stacked lexers, we're in a #include.
  assert(IsFileLexer(IncludeMacroStack[0]) &&
         "Top level include stack isn't our primary lexer?");
  for (unsigned i = 1, e = IncludeMacroStack.size(); i != e; ++i)
    if (IsFileLexer(IncludeMacroStack[i]))
      return false;
  return true;
}

/// getCurrentLexer - Return the current file lexer being lexed from.  Note
/// that this ignores any potentially active macro expansions and _Pragma
/// expansions going on at the time.
PreprocessorLexer *Preprocessor::getCurrentFileLexer() const {
  if (IsFileLexer())
    return CurPPLexer;

  // Look for a stacked lexer.
  for (unsigned i = IncludeMacroStack.size(); i != 0; --i) {
    const IncludeStackInfo& ISI = IncludeMacroStack[i-1];
    if (IsFileLexer(ISI))
      return ISI.ThePPLexer;
  }
  return 0;
}

//===----------------------------------------------------------------------===//
// Methods for Entering and Callbacks for leaving various contexts
//===----------------------------------------------------------------------===//

/// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.  Return true
/// on failure.
void Preprocessor::EnterSourceFile(unsigned FileID,
                                   const DirectoryLookup *CurDir) {
  assert(CurTokenLexer == 0 && "Cannot #include a file inside a macro!");
  ++NumEnteredSourceFiles;

  if (MaxIncludeStackDepth < IncludeMacroStack.size())
    MaxIncludeStackDepth = IncludeMacroStack.size();

#if 1
  Lexer *TheLexer = new Lexer(SourceLocation::getFileLoc(FileID, 0), *this);
  EnterSourceFileWithLexer(TheLexer, CurDir);
#else
  const llvm::MemoryBuffer* B = getSourceManager().getBuffer(FileID);

  // Create a raw lexer.
  Lexer L(SourceLocation::getFileLoc(FileID, 0), getLangOptions(),
          B->getBufferStart(), B->getBufferEnd(), B);

  // Ignore whitespace.
  L.SetKeepWhitespaceMode(false);
  L.SetCommentRetentionState(false);

  // Lex the file, populating our data structures.
  std::vector<Token>* Tokens = new std::vector<Token>();
  Token Tok;

  do {
    L.LexFromRawLexer(Tok);

    if (Tok.is(tok::identifier)) {
      Tok.setIdentifierInfo(LookUpIdentifierInfo(Tok));
    }
    else if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
      // Special processing for #include.  Store the '#' token and lex
      // the next token.
      Tokens->push_back(Tok);
      L.LexFromRawLexer(Tok);

      // Did we see 'include'/'import'/'include_next'?
      if (!Tok.is(tok::identifier))
        continue;

      IdentifierInfo* II = LookUpIdentifierInfo(Tok);
      Tok.setIdentifierInfo(II);
      tok::PPKeywordKind K = II->getPPKeywordID();

      if (K == tok::pp_include || K == tok::pp_import ||
          K == tok::pp_include_next) {

        // Save the 'include' token.
        Tokens->push_back(Tok);

        // Lex the next token as an include string.
        L.ParsingPreprocessorDirective = true;
        L.LexIncludeFilename(Tok);
        L.ParsingPreprocessorDirective = false;

        if (Tok.is(tok::identifier))
          Tok.setIdentifierInfo(LookUpIdentifierInfo(Tok));
      }
    }
  }
  while (Tokens->push_back(Tok), Tok.isNot(tok::eof));

  if (CurPPLexer || CurTokenLexer)
    PushIncludeMacroStack();

  CurDirLookup = CurDir;
  SourceLocation Loc = SourceLocation::getFileLoc(FileID, 0);
  CurPTHLexer.reset(new PTHLexer(*this, Loc, &(*Tokens)[0], Tokens->size()));
  CurPPLexer = CurPTHLexer.get();

  // Notify the client, if desired, that we are in a new source file.
  if (Callbacks) {
    SrcMgr::CharacteristicKind FileType =
    SourceMgr.getFileCharacteristic(CurPPLexer->getFileID());
    Callbacks->FileChanged(Loc, PPCallbacks::EnterFile, FileType);
  }
#endif
}

/// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.
void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
                                            const DirectoryLookup *CurDir) {

  // Add the current lexer to the include stack.
  if (CurPPLexer || CurTokenLexer)
    PushIncludeMacroStack();

  CurLexer.reset(TheLexer);
  CurPPLexer = TheLexer;
  CurDirLookup = CurDir;

  // Notify the client, if desired, that we are in a new source file.
  if (Callbacks && !CurLexer->Is_PragmaLexer) {
    SrcMgr::CharacteristicKind FileType =
       SourceMgr.getFileCharacteristic(CurLexer->getFileLoc());

    Callbacks->FileChanged(CurLexer->getFileLoc(),
                           PPCallbacks::EnterFile, FileType);
  }
}

/// EnterMacro - Add a Macro to the top of the include stack and start lexing
/// tokens from it instead of the current buffer.
void Preprocessor::EnterMacro(Token &Tok, MacroArgs *Args) {
  PushIncludeMacroStack();
  CurDirLookup = 0;

  if (NumCachedTokenLexers == 0) {
    CurTokenLexer.reset(new TokenLexer(Tok, Args, *this));
  } else {
    CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]);
    CurTokenLexer->Init(Tok, Args);
  }
}

/// EnterTokenStream - Add a "macro" context to the top of the include stack,
/// which will cause the lexer to start returning the specified tokens.
///
/// If DisableMacroExpansion is true, tokens lexed from the token stream will
/// not be subject to further macro expansion.  Otherwise, these tokens will
/// be re-macro-expanded when/if expansion is enabled.
///
/// If OwnsTokens is false, this method assumes that the specified stream of
/// tokens has a permanent owner somewhere, so they do not need to be copied.
/// If it is true, it assumes the array of tokens is allocated with new[] and
/// must be freed.
///
void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks,
                                    bool DisableMacroExpansion,
                                    bool OwnsTokens) {
  // Save our current state.
  PushIncludeMacroStack();
  CurDirLookup = 0;

  // Create a macro expander to expand from the specified token stream.
  if (NumCachedTokenLexers == 0) {
    CurTokenLexer.reset(new TokenLexer(Toks, NumToks, DisableMacroExpansion,
                                       OwnsTokens, *this));
  } else {
    CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]);
    CurTokenLexer->Init(Toks, NumToks, DisableMacroExpansion, OwnsTokens);
  }
}

/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
/// the current file.  This either returns the EOF token or pops a level off
/// the include stack and keeps going.
bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
  assert(!CurTokenLexer &&
         "Ending a file when currently in a macro!");

  // See if this file had a controlling macro.
  if (CurPPLexer) {  // Not ending a macro, ignore it.
    if (const IdentifierInfo *ControllingMacro =
          CurPPLexer->MIOpt.GetControllingMacroAtEndOfFile()) {
      // Okay, this has a controlling macro, remember in PerFileInfo.
      if (const FileEntry *FE =
            SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))
        HeaderInfo.SetFileControllingMacro(FE, ControllingMacro);
    }
  }

  // If this is a #include'd file, pop it off the include stack and continue
  // lexing the #includer file.
  if (!IncludeMacroStack.empty()) {
    // We're done with the #included file.
    RemoveTopOfLexerStack();

    // Notify the client, if desired, that we are in a new source file.
    if (Callbacks && !isEndOfMacro && CurPPLexer) {
      SrcMgr::CharacteristicKind FileType =
        SourceMgr.getFileCharacteristic(CurPPLexer->getFileID());

      if (CurLexer) {
        Callbacks->FileChanged(CurLexer->getSourceLocation(CurLexer->BufferPtr),
                               PPCallbacks::ExitFile, FileType);
      }
      else {
        // FIXME: Is this okay to use the location of 'Result'?
        Callbacks->FileChanged(Result.getLocation(), PPCallbacks::ExitFile,
                               FileType);
      }
    }

    // Client should lex another token.
    return false;
  }

  // If the file ends with a newline, form the EOF token on the newline itself,
  // rather than "on the line following it", which doesn't exist.  This makes
  // diagnostics relating to the end of file include the last file that the user
  // actually typed, which is goodness.
  if (CurLexer) {
    const char *EndPos = CurLexer->BufferEnd;
    if (EndPos != CurLexer->BufferStart &&
        (EndPos[-1] == '\n' || EndPos[-1] == '\r')) {
      --EndPos;

      // Handle \n\r and \r\n:
      if (EndPos != CurLexer->BufferStart &&
          (EndPos[-1] == '\n' || EndPos[-1] == '\r') &&
          EndPos[-1] != EndPos[0])
        --EndPos;
    }

    Result.startToken();
    CurLexer->BufferPtr = EndPos;
    CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);

    // We're done with the #included file.
    CurLexer.reset();
  }
  else {
    CurPTHLexer->setEOF(Result);
    CurPTHLexer.reset();
  }

  CurPPLexer = 0;

  // This is the end of the top-level file.  If the diag::pp_macro_not_used
  // diagnostic is enabled, look for macros that have not been used.
  if (Diags.getDiagnosticLevel(diag::pp_macro_not_used) != Diagnostic::Ignored){
    for (llvm::DenseMap<IdentifierInfo*, MacroInfo*>::iterator I =
         Macros.begin(), E = Macros.end(); I != E; ++I) {
      if (!I->second->isUsed())
        Diag(I->second->getDefinitionLoc(), diag::pp_macro_not_used);
    }
  }
  return true;
}

/// HandleEndOfTokenLexer - This callback is invoked when the current TokenLexer
/// hits the end of its token stream.
bool Preprocessor::HandleEndOfTokenLexer(Token &Result) {
  assert(CurTokenLexer && !CurPPLexer &&
         "Ending a macro when currently in a #include file!");

  // Delete or cache the now-dead macro expander.
  if (NumCachedTokenLexers == TokenLexerCacheSize)
    CurTokenLexer.reset();
  else
    TokenLexerCache[NumCachedTokenLexers++] = CurTokenLexer.take();

  // Handle this like a #include file being popped off the stack.
  return HandleEndOfFile(Result, true);
}

/// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the
/// lexer stack.  This should only be used in situations where the current
/// state of the top-of-stack lexer is unknown.
void Preprocessor::RemoveTopOfLexerStack() {
  assert(!IncludeMacroStack.empty() && "Ran out of stack entries to load");

  if (CurTokenLexer) {
    // Delete or cache the now-dead macro expander.
    if (NumCachedTokenLexers == TokenLexerCacheSize)
      CurTokenLexer.reset();
    else
      TokenLexerCache[NumCachedTokenLexers++] = CurTokenLexer.take();
  }

  PopIncludeMacroStack();
}

/// HandleMicrosoftCommentPaste - When the macro expander pastes together a
/// comment (/##/) in microsoft mode, this method handles updating the current
/// state, returning the token on the next source line.
void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) {
  assert(CurTokenLexer && !CurPPLexer &&
         "Pasted comment can only be formed from macro");

  // We handle this by scanning for the closest real lexer, switching it to
  // raw mode and preprocessor mode.  This will cause it to return \n as an
  // explicit EOM token.
  PreprocessorLexer *FoundLexer = 0;
  bool LexerWasInPPMode = false;
  for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
    IncludeStackInfo &ISI = *(IncludeMacroStack.end()-i-1);
    if (ISI.ThePPLexer == 0) continue;  // Scan for a real lexer.

    // Once we find a real lexer, mark it as raw mode (disabling macro
    // expansions) and preprocessor mode (return EOM).  We know that the lexer
    // was *not* in raw mode before, because the macro that the comment came
    // from was expanded.  However, it could have already been in preprocessor
    // mode (#if COMMENT) in which case we have to return it to that mode and
    // return EOM.
    FoundLexer = ISI.ThePPLexer;
    FoundLexer->LexingRawMode = true;
    LexerWasInPPMode = FoundLexer->ParsingPreprocessorDirective;
    FoundLexer->ParsingPreprocessorDirective = true;
    break;
  }

  // Okay, we either found and switched over the lexer, or we didn't find a
  // lexer.  In either case, finish off the macro the comment came from, getting
  // the next token.
  if (!HandleEndOfTokenLexer(Tok)) Lex(Tok);

  // Discarding comments as long as we don't have EOF or EOM.  This 'comments
  // out' the rest of the line, including any tokens that came from other macros
  // that were active, as in:
  //  #define submacro a COMMENT b
  //    submacro c
  // which should lex to 'a' only: 'b' and 'c' should be removed.
  while (Tok.isNot(tok::eom) && Tok.isNot(tok::eof))
    Lex(Tok);

  // If we got an eom token, then we successfully found the end of the line.
  if (Tok.is(tok::eom)) {
    assert(FoundLexer && "Can't get end of line without an active lexer");
    // Restore the lexer back to normal mode instead of raw mode.
    FoundLexer->LexingRawMode = false;

    // If the lexer was already in preprocessor mode, just return the EOM token
    // to finish the preprocessor line.
    if (LexerWasInPPMode) return;

    // Otherwise, switch out of PP mode and return the next lexed token.
    FoundLexer->ParsingPreprocessorDirective = false;
    return Lex(Tok);
  }

  // If we got an EOF token, then we reached the end of the token stream but
  // didn't find an explicit \n.  This can only happen if there was no lexer
  // active (an active lexer would return EOM at EOF if there was no \n in
  // preprocessor directive mode), so just return EOF as our token.
  assert(!FoundLexer && "Lexer should return EOM before EOF in PP mode");
}
<|endoftext|>


<commit_before>#include <Internal/CharacterControlManagerImpl.hpp>
#include <Internal/PhysicsModuleImplementation.hpp>
#include <cstdint>
namespace DoremiEngine
{
    namespace Physics
    {
        CharacterControlManagerImpl::CharacterControlManagerImpl(InternalPhysicsUtils& p_utils) : m_utils(p_utils)
        {
            m_manager = PxCreateControllerManager(*m_utils.m_worldScene);
        }
        CharacterControlManagerImpl::~CharacterControlManagerImpl() {}

        int CharacterControlManagerImpl::AddController(int p_id, int p_matID, XMFLOAT3 p_position, XMFLOAT2 p_dimensions)
        {
            // Set start attributes of the controller
            PxCapsuleControllerDesc desc;
            desc.setToDefault();
            desc.position = PxExtendedVec3(p_position.x, p_position.y, p_position.z);
            desc.height = p_dimensions.x;
            desc.radius = p_dimensions.y;
            desc.material = m_utils.m_physicsMaterialManager->GetMaterial(p_matID); // DANGER! Assumes it already has material
            if(desc.material == NULL)
            {
                throw std::runtime_error("No physics material exists with that ID");
            }
            desc.stepOffset = 0.1;
            desc.reportCallback = m_controllerCallback;
            desc.behaviorCallback = this;

            // Hard coded up vector
            desc.upDirection = PxVec3(0, 1, 0);

            m_controllers[p_id] = m_manager->createController(desc);
            m_IDsByControllers[m_controllers[p_id]] = p_id;

            SetCallback(p_id, (1 << 0), (1 << 0));

            // Redundant return?
            return p_id;
        }

        int CharacterControlManagerImpl::MoveController(int p_id, XMFLOAT3 p_discplacement, float p_dt)
        {
            /*
            Some variable that apperas to define when the controller stops moving
            Tweak as necessary. Possibly could be moved to some other place.*/
            float m_minDistTraveled = 0;
            // EMPTY FILTERS!
            PxControllerFilters filters;
            // Check if controller exists
            if(m_controllers.find(p_id) == m_controllers.end())
            {
                // Controller did not exist
                throw std::runtime_error("No controller exists with id: " + to_string(p_id));
            }
            m_controllers[p_id]->move(PxVec3(p_discplacement.x, p_discplacement.y, p_discplacement.z), 0, p_dt, filters);
            // Redundant return?
            return p_id;
        }

        XMFLOAT3 CharacterControlManagerImpl::GetPosition(int p_id)
        {
            // Check if controller exists
            if(m_controllers.find(p_id) == m_controllers.end())
            {
                // Controller did not exist
                throw std::runtime_error("No controller exists with id: " + to_string(p_id));
            }
            PxExtendedVec3 p = m_controllers[p_id]->getPosition();
            return XMFLOAT3(p.x, p.y, p.z);
        }

        XMFLOAT4 CharacterControlManagerImpl::GetOrientation(int p_id)
        {
            // Check if controller exists
            if(m_controllers.find(p_id) == m_controllers.end())
            {
                // Controller did not exist
                throw std::runtime_error("No controller exists with id: " + to_string(p_id));
            }
            PxQuat q = m_controllers[p_id]->getActor()->getGlobalPose().q;
            return XMFLOAT4(q.x, q.y, q.z, q.w);
        }

        void CharacterControlManagerImpl::SetPosition(int p_id, XMFLOAT3 p_position)
        {
            // Check if controller exists
            if(m_controllers.find(p_id) == m_controllers.end())
            {
                // Controller did not exist
                throw std::runtime_error("No controller exists with id: " + to_string(p_id));
            }

            m_controllers[p_id]->setPosition(PxExtendedVec3(p_position.x, p_position.y, p_position.z));
        }

        void CharacterControlManagerImpl::SetCallback(int p_bodyID, int p_filterGroup, int p_filterMask)
        {
            // Check if controller exists
            if(m_controllers.find(p_bodyID) == m_controllers.end())
            {
                // Controller did not exist
                throw std::runtime_error("No controller exists with id: " + to_string(p_bodyID));
            }
            PxFilterData filterData;
            filterData.word0 = p_filterGroup; // Own ID
            filterData.word1 = p_filterMask; // ID mask to filter pairs that trigger contact callback
            PxRigidActor* actor = m_controllers[p_bodyID]->getActor();
            uint32_t numShapes = actor->getNbShapes();
            // Magic allocation of memory (i think)
            PxShape** shapes = (PxShape**)m_utils.m_allocator.allocate(sizeof(PxShape*) * numShapes, 0, __FILE__, __LINE__);
            actor->getShapes(shapes, numShapes);
            for(uint32_t i = 0; i < numShapes; i++)
            {
                PxShape* shape = shapes[i];
                shape->setSimulationFilterData(filterData);
            }
            if(shapes)
            {
                m_utils.m_allocator.deallocate(shapes);
                shapes = NULL;
            }
        }

        void CharacterControlManagerImpl::SetCallbackClass(PxUserControllerHitReport* p_callback) { m_controllerCallback = p_callback; }

        unordered_map<PxController*, int> CharacterControlManagerImpl::GetIdsByControllers() { return m_IDsByControllers; }

        PxControllerBehaviorFlags CharacterControlManagerImpl::getBehaviorFlags(const PxShape& shape, const PxActor& actor)
        {
            return PxControllerBehaviorFlag::eCCT_CAN_RIDE_ON_OBJECT;
        }
        PxControllerBehaviorFlags CharacterControlManagerImpl::getBehaviorFlags(const PxController& controller)
        {
            return PxControllerBehaviorFlags(0);
        }
        PxControllerBehaviorFlags CharacterControlManagerImpl::getBehaviorFlags(const PxObstacle& obstacle) { return PxControllerBehaviorFlags(0); }
    }
}<commit_msg>Fixed float warning in CharacterControlManagerImpl<commit_after>#include <Internal/CharacterControlManagerImpl.hpp>
#include <Internal/PhysicsModuleImplementation.hpp>
#include <cstdint>
namespace DoremiEngine
{
    namespace Physics
    {
        CharacterControlManagerImpl::CharacterControlManagerImpl(InternalPhysicsUtils& p_utils) : m_utils(p_utils)
        {
            m_manager = PxCreateControllerManager(*m_utils.m_worldScene);
        }
        CharacterControlManagerImpl::~CharacterControlManagerImpl() {}

        int CharacterControlManagerImpl::AddController(int p_id, int p_matID, XMFLOAT3 p_position, XMFLOAT2 p_dimensions)
        {
            // Set start attributes of the controller
            PxCapsuleControllerDesc desc;
            desc.setToDefault();
            desc.position = PxExtendedVec3(p_position.x, p_position.y, p_position.z);
            desc.height = p_dimensions.x;
            desc.radius = p_dimensions.y;
            desc.material = m_utils.m_physicsMaterialManager->GetMaterial(p_matID); // DANGER! Assumes it already has material
            if(desc.material == NULL)
            {
                throw std::runtime_error("No physics material exists with that ID");
            }
            desc.stepOffset = 0.1f;
            desc.reportCallback = m_controllerCallback;
            desc.behaviorCallback = this;

            // Hard coded up vector
            desc.upDirection = PxVec3(0, 1, 0);

            m_controllers[p_id] = m_manager->createController(desc);
            m_IDsByControllers[m_controllers[p_id]] = p_id;

            SetCallback(p_id, (1 << 0), (1 << 0));

            // Redundant return?
            return p_id;
        }

        int CharacterControlManagerImpl::MoveController(int p_id, XMFLOAT3 p_discplacement, float p_dt)
        {
            /*
            Some variable that apperas to define when the controller stops moving
            Tweak as necessary. Possibly could be moved to some other place.*/
            float m_minDistTraveled = 0;
            // EMPTY FILTERS!
            PxControllerFilters filters;
            // Check if controller exists
            if(m_controllers.find(p_id) == m_controllers.end())
            {
                // Controller did not exist
                throw std::runtime_error("No controller exists with id: " + to_string(p_id));
            }
            m_controllers[p_id]->move(PxVec3(p_discplacement.x, p_discplacement.y, p_discplacement.z), 0, p_dt, filters);
            // Redundant return?
            return p_id;
        }

        XMFLOAT3 CharacterControlManagerImpl::GetPosition(int p_id)
        {
            // Check if controller exists
            if(m_controllers.find(p_id) == m_controllers.end())
            {
                // Controller did not exist
                throw std::runtime_error("No controller exists with id: " + to_string(p_id));
            }
            PxExtendedVec3 p = m_controllers[p_id]->getPosition();
            return XMFLOAT3(p.x, p.y, p.z);
        }

        XMFLOAT4 CharacterControlManagerImpl::GetOrientation(int p_id)
        {
            // Check if controller exists
            if(m_controllers.find(p_id) == m_controllers.end())
            {
                // Controller did not exist
                throw std::runtime_error("No controller exists with id: " + to_string(p_id));
            }
            PxQuat q = m_controllers[p_id]->getActor()->getGlobalPose().q;
            return XMFLOAT4(q.x, q.y, q.z, q.w);
        }

        void CharacterControlManagerImpl::SetPosition(int p_id, XMFLOAT3 p_position)
        {
            // Check if controller exists
            if(m_controllers.find(p_id) == m_controllers.end())
            {
                // Controller did not exist
                throw std::runtime_error("No controller exists with id: " + to_string(p_id));
            }

            m_controllers[p_id]->setPosition(PxExtendedVec3(p_position.x, p_position.y, p_position.z));
        }

        void CharacterControlManagerImpl::SetCallback(int p_bodyID, int p_filterGroup, int p_filterMask)
        {
            // Check if controller exists
            if(m_controllers.find(p_bodyID) == m_controllers.end())
            {
                // Controller did not exist
                throw std::runtime_error("No controller exists with id: " + to_string(p_bodyID));
            }
            PxFilterData filterData;
            filterData.word0 = p_filterGroup; // Own ID
            filterData.word1 = p_filterMask; // ID mask to filter pairs that trigger contact callback
            PxRigidActor* actor = m_controllers[p_bodyID]->getActor();
            uint32_t numShapes = actor->getNbShapes();
            // Magic allocation of memory (i think)
            PxShape** shapes = (PxShape**)m_utils.m_allocator.allocate(sizeof(PxShape*) * numShapes, 0, __FILE__, __LINE__);
            actor->getShapes(shapes, numShapes);
            for(uint32_t i = 0; i < numShapes; i++)
            {
                PxShape* shape = shapes[i];
                shape->setSimulationFilterData(filterData);
            }
            if(shapes)
            {
                m_utils.m_allocator.deallocate(shapes);
                shapes = NULL;
            }
        }

        void CharacterControlManagerImpl::SetCallbackClass(PxUserControllerHitReport* p_callback) { m_controllerCallback = p_callback; }

        unordered_map<PxController*, int> CharacterControlManagerImpl::GetIdsByControllers() { return m_IDsByControllers; }

        PxControllerBehaviorFlags CharacterControlManagerImpl::getBehaviorFlags(const PxShape& shape, const PxActor& actor)
        {
            return PxControllerBehaviorFlag::eCCT_CAN_RIDE_ON_OBJECT;
        }
        PxControllerBehaviorFlags CharacterControlManagerImpl::getBehaviorFlags(const PxController& controller)
        {
            return PxControllerBehaviorFlags(0);
        }
        PxControllerBehaviorFlags CharacterControlManagerImpl::getBehaviorFlags(const PxObstacle& obstacle) { return PxControllerBehaviorFlags(0); }
    }
}<|endoftext|>