<commit_before>/*
  This file is part of KOrganizer.
  Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
  Copyright (c) 2009 Allen Winter <winter@kde.org>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program 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 General Public License for more details.

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

  As a special exception, permission is given to link this program
  with any edition of Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

// TODO: validate hand-entered email addresses
// TODO: don't allow duplicates; at least remove dupes when passing back
// TODO: the list in PublishDialog::addresses()

#include "publishdialog.h"

#include <kabc/addresseedialog.h>
#include <kcal/attendee.h>
#include <kcal/person.h>
#include <kpimutils/email.h>

#include <klineedit.h>
#include <klocale.h>

PublishDialog::PublishDialog( QWidget *parent )
  : KDialog( parent )
{
  setCaption( i18n( "Select Addresses" ) );
  setButtons( Ok|Cancel|Help );
  setHelp( "group-scheduling", "korganizer" );
  QWidget *widget = new QWidget( this );
  widget->setObjectName( "PublishFreeBusy" );
  mUI.setupUi( widget );
  setMainWidget( widget );
  mUI.mListWidget->setSelectionMode( QAbstractItemView::SingleSelection );
  mUI.mNameLineEdit->setEnabled( false );
  mUI.mEmailLineEdit->setEnabled( false );

  setButtonToolTip( Ok, i18n( "Send email to these recipients" ) );
  setButtonWhatsThis( Ok, i18n( "Clicking the Ok button will cause "
                                "an email to be sent to the recipients you "
                                "have entered." ) );
  setButtonToolTip( Cancel, i18n( "Cancel recipient selection and the email" ) );
  setButtonWhatsThis( Cancel, i18n( "Clicking the Cancel button will "
                                    "cause the email operation to be terminated." ) );

  setButtonWhatsThis( Help, i18n( "Click the Help button to read "
                                  "more information about Group Scheduling." ) );

  mUI.mNew->setIcon( KIcon( "list-add" ) );
  mUI.mRemove->setIcon( KIcon( "list-remove" ) );
  mUI.mRemove->setEnabled( false );
  mUI.mSelectAddressee->setIcon( KIcon( "view-pim-contacts" ) );

  connect( mUI.mListWidget, SIGNAL(itemSelectionChanged()),
           SLOT(updateInput()) );
  connect( mUI.mNew, SIGNAL(clicked()),
           SLOT(addItem()) );
  connect( mUI.mRemove, SIGNAL(clicked()),
           SLOT(removeItem()) );
  connect( mUI.mSelectAddressee, SIGNAL(clicked()),
           SLOT(openAddressbook()) );
  connect( mUI.mNameLineEdit, SIGNAL(textChanged(const QString &)),
           SLOT(updateItem()) );
  connect( mUI.mEmailLineEdit, SIGNAL(textChanged(const QString &)),
           SLOT(updateItem()) );
}

PublishDialog::~PublishDialog()
{
}

void PublishDialog::addAttendee( Attendee *attendee )
{
  mUI.mNameLineEdit->setEnabled( true );
  mUI.mEmailLineEdit->setEnabled( true );
  QListWidgetItem *item = new QListWidgetItem( mUI.mListWidget );
  Person person( attendee->name(), attendee->email() );
  item->setText( person.fullName() );
  mUI.mListWidget->addItem( item );
  mUI.mRemove->setEnabled( true );
}

QString PublishDialog::addresses()
{
  QString to = "";
  QListWidgetItem *item;
  int i, count;
  count = mUI.mListWidget->count();
  for ( i=0; i<count; i++ ) {
    item = mUI.mListWidget->takeItem( i );
    to += item->text();
    if ( i < count-1 ) {
      to += ", ";
    }
  }
  return to;
}

void PublishDialog::addItem()
{
  mUI.mNameLineEdit->setEnabled( true );
  mUI.mEmailLineEdit->setEnabled( true );
  QListWidgetItem *item = new QListWidgetItem( mUI.mListWidget );
  mUI.mListWidget->addItem( item );
  mUI.mListWidget->setItemSelected( item, true );
  mUI.mNameLineEdit->setText( i18n( "(EmptyName)" ) );
  mUI.mEmailLineEdit->setText( i18n( "(EmptyEmail)" ) );

  mUI.mRemove->setEnabled( true );
}

void PublishDialog::removeItem()
{
  QListWidgetItem *item;
  item = mUI.mListWidget->selectedItems().first();
  if ( !item ) {
    return;
  }

  int row = mUI.mListWidget->row( item );
  mUI.mListWidget->takeItem( row );

  if ( !mUI.mListWidget->count() ) {
    mUI.mNameLineEdit->setText( QString() );
    mUI.mNameLineEdit->setEnabled( false );
    mUI.mEmailLineEdit->setText( QString() );
    mUI.mEmailLineEdit->setEnabled( false );
    mUI.mRemove->setEnabled( false );
    return;
  }
  if ( row > 0 ) {
    row--;
  }

  mUI.mListWidget->setCurrentRow( row );
}

void PublishDialog::openAddressbook()
{
  KABC::Addressee::List addressList = KABC::AddresseeDialog::getAddressees( this );
  if( addressList.isEmpty() ) {
     return;
  }

  KABC::Addressee a = addressList.first();
  if ( !a.isEmpty() ) {
    int i;
    for ( i=0; i<addressList.size(); i++ ) {
      a = addressList[i];
      mUI.mNameLineEdit->setEnabled( true );
      mUI.mEmailLineEdit->setEnabled( true );
      QListWidgetItem *item = new QListWidgetItem( mUI.mListWidget );
      mUI.mListWidget->setItemSelected( item, true );
      mUI.mNameLineEdit->setText( a.realName() );
      mUI.mEmailLineEdit->setText( a.preferredEmail() );
      mUI.mListWidget->addItem( item );
    }
    mUI.mRemove->setEnabled( true );
  }
}

void PublishDialog::updateItem()
{
  if ( !mUI.mListWidget->selectedItems().count() ) {
    return;
  }

  Person person( mUI.mNameLineEdit->text(), mUI.mEmailLineEdit->text() );
  QListWidgetItem *item = mUI.mListWidget->selectedItems().first();
  item->setText( person.fullName() );
}

void PublishDialog::updateInput()
{
  if ( !mUI.mListWidget->selectedItems().count() ) {
    return;
  }

  mUI.mNameLineEdit->setEnabled( true );
  mUI.mEmailLineEdit->setEnabled( true );

  QListWidgetItem *item = mUI.mListWidget->selectedItems().first();
  QString mail, name;
  KPIMUtils::extractEmailAddressAndName( item->text(), mail, name );
  mUI.mNameLineEdit->setText( name );
  mUI.mEmailLineEdit->setText( mail );
}

#include "publishdialog.moc"
<commit_msg>Fix crash<commit_after>/*
  This file is part of KOrganizer.
  Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
  Copyright (c) 2009 Allen Winter <winter@kde.org>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program 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 General Public License for more details.

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

  As a special exception, permission is given to link this program
  with any edition of Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

// TODO: validate hand-entered email addresses
// TODO: don't allow duplicates; at least remove dupes when passing back
// TODO: the list in PublishDialog::addresses()

#include "publishdialog.h"

#include <kabc/addresseedialog.h>
#include <kcal/attendee.h>
#include <kcal/person.h>
#include <kpimutils/email.h>

#include <klineedit.h>
#include <klocale.h>

PublishDialog::PublishDialog( QWidget *parent )
  : KDialog( parent )
{
  setCaption( i18n( "Select Addresses" ) );
  setButtons( Ok|Cancel|Help );
  setHelp( "group-scheduling", "korganizer" );
  QWidget *widget = new QWidget( this );
  widget->setObjectName( "PublishFreeBusy" );
  mUI.setupUi( widget );
  setMainWidget( widget );
  mUI.mListWidget->setSelectionMode( QAbstractItemView::SingleSelection );
  mUI.mNameLineEdit->setEnabled( false );
  mUI.mEmailLineEdit->setEnabled( false );

  setButtonToolTip( Ok, i18n( "Send email to these recipients" ) );
  setButtonWhatsThis( Ok, i18n( "Clicking the Ok button will cause "
                                "an email to be sent to the recipients you "
                                "have entered." ) );
  setButtonToolTip( Cancel, i18n( "Cancel recipient selection and the email" ) );
  setButtonWhatsThis( Cancel, i18n( "Clicking the Cancel button will "
                                    "cause the email operation to be terminated." ) );

  setButtonWhatsThis( Help, i18n( "Click the Help button to read "
                                  "more information about Group Scheduling." ) );

  mUI.mNew->setIcon( KIcon( "list-add" ) );
  mUI.mRemove->setIcon( KIcon( "list-remove" ) );
  mUI.mRemove->setEnabled( false );
  mUI.mSelectAddressee->setIcon( KIcon( "view-pim-contacts" ) );

  connect( mUI.mListWidget, SIGNAL(itemSelectionChanged()),
           SLOT(updateInput()) );
  connect( mUI.mNew, SIGNAL(clicked()),
           SLOT(addItem()) );
  connect( mUI.mRemove, SIGNAL(clicked()),
           SLOT(removeItem()) );
  connect( mUI.mSelectAddressee, SIGNAL(clicked()),
           SLOT(openAddressbook()) );
  connect( mUI.mNameLineEdit, SIGNAL(textChanged(const QString &)),
           SLOT(updateItem()) );
  connect( mUI.mEmailLineEdit, SIGNAL(textChanged(const QString &)),
           SLOT(updateItem()) );
}

PublishDialog::~PublishDialog()
{
}

void PublishDialog::addAttendee( Attendee *attendee )
{
  mUI.mNameLineEdit->setEnabled( true );
  mUI.mEmailLineEdit->setEnabled( true );
  QListWidgetItem *item = new QListWidgetItem( mUI.mListWidget );
  Person person( attendee->name(), attendee->email() );
  item->setText( person.fullName() );
  mUI.mListWidget->addItem( item );
  mUI.mRemove->setEnabled( true );
}

QString PublishDialog::addresses()
{
  QString to = "";
  QListWidgetItem *item;
  int i, count;
  count = mUI.mListWidget->count();
  for ( i=0; i<count; ++i ) {
    item = mUI.mListWidget->item( i );
    to += item->text();
    if ( i < count-1 ) {
      to += ", ";
    }
  }
  return to;
}

void PublishDialog::addItem()
{
  mUI.mNameLineEdit->setEnabled( true );
  mUI.mEmailLineEdit->setEnabled( true );
  QListWidgetItem *item = new QListWidgetItem( mUI.mListWidget );
  mUI.mListWidget->addItem( item );
  mUI.mListWidget->setItemSelected( item, true );
  mUI.mNameLineEdit->setText( i18n( "(EmptyName)" ) );
  mUI.mEmailLineEdit->setText( i18n( "(EmptyEmail)" ) );

  mUI.mRemove->setEnabled( true );
}

void PublishDialog::removeItem()
{
  QListWidgetItem *item;
  item = mUI.mListWidget->selectedItems().first();
  if ( !item ) {
    return;
  }

  int row = mUI.mListWidget->row( item );
  mUI.mListWidget->takeItem( row );

  if ( !mUI.mListWidget->count() ) {
    mUI.mNameLineEdit->setText( QString() );
    mUI.mNameLineEdit->setEnabled( false );
    mUI.mEmailLineEdit->setText( QString() );
    mUI.mEmailLineEdit->setEnabled( false );
    mUI.mRemove->setEnabled( false );
    return;
  }
  if ( row > 0 ) {
    row--;
  }

  mUI.mListWidget->setCurrentRow( row );
}

void PublishDialog::openAddressbook()
{
  KABC::Addressee::List addressList = KABC::AddresseeDialog::getAddressees( this );
  if( addressList.isEmpty() ) {
     return;
  }

  KABC::Addressee a = addressList.first();
  if ( !a.isEmpty() ) {
    int i;
    for ( i=0; i<addressList.size(); i++ ) {
      a = addressList[i];
      mUI.mNameLineEdit->setEnabled( true );
      mUI.mEmailLineEdit->setEnabled( true );
      QListWidgetItem *item = new QListWidgetItem( mUI.mListWidget );
      mUI.mListWidget->setItemSelected( item, true );
      mUI.mNameLineEdit->setText( a.realName() );
      mUI.mEmailLineEdit->setText( a.preferredEmail() );
      mUI.mListWidget->addItem( item );
    }
    mUI.mRemove->setEnabled( true );
  }
}

void PublishDialog::updateItem()
{
  if ( !mUI.mListWidget->selectedItems().count() ) {
    return;
  }

  Person person( mUI.mNameLineEdit->text(), mUI.mEmailLineEdit->text() );
  QListWidgetItem *item = mUI.mListWidget->selectedItems().first();
  item->setText( person.fullName() );
}

void PublishDialog::updateInput()
{
  if ( !mUI.mListWidget->selectedItems().count() ) {
    return;
  }

  mUI.mNameLineEdit->setEnabled( true );
  mUI.mEmailLineEdit->setEnabled( true );

  QListWidgetItem *item = mUI.mListWidget->selectedItems().first();
  QString mail, name;
  KPIMUtils::extractEmailAddressAndName( item->text(), mail, name );
  mUI.mNameLineEdit->setText( name );
  mUI.mEmailLineEdit->setText( mail );
}

#include "publishdialog.moc"
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: urp_dispatch.cxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 16:00:48 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_bridges.hxx"
#include <sal/alloca.h>
#include <osl/mutex.hxx>
#include <osl/diagnose.h>

#include <rtl/alloc.h>
#include <rtl/ustrbuf.hxx>

#include <uno/mapping.hxx>
#include <uno/threadpool.h>

#include <bridges/remote/remote.h>
#include <bridges/remote/stub.hxx>
#include <bridges/remote/proxy.hxx>
#include <bridges/remote/remote.hxx>

#include "urp_bridgeimpl.hxx"
#include "urp_marshal.hxx"
#include "urp_dispatch.hxx"
#include "urp_job.hxx"
#include "urp_writer.hxx"
#include "urp_log.hxx"

using namespace ::rtl;
using namespace ::osl;
using namespace ::com::sun::star::uno;

namespace bridges_urp
{

void SAL_CALL urp_sendCloseConnection( uno_Environment *pEnvRemote )
{
    remote_Context *pContext = (remote_Context *) pEnvRemote->pContext;
    urp_BridgeImpl *pImpl = (urp_BridgeImpl*) ( pContext->m_pBridgeImpl );

    {
        MutexGuard guard( pImpl->m_marshalingMutex );

        // send immediately
        if( ! pImpl->m_blockMarshaler.empty() )
        {
            pImpl->m_pWriter->touch( sal_True );
        }

        pImpl->m_pWriter->sendEmptyMessage();
        // no more data via this connection !
        pImpl->m_pWriter->abort();
    }
}
extern "C" void SAL_CALL urp_sendRequest(
    uno_Environment *pEnvRemote,
    typelib_TypeDescription const * pMemberType,
    rtl_uString *pOid,
    typelib_InterfaceTypeDescription *pInterfaceType,
    void *pReturn,
    void *ppArgs[],
    uno_Any **ppException )
{
    remote_Context *pContext = (remote_Context *) pEnvRemote->pContext;
    urp_BridgeImpl *pImpl = (urp_BridgeImpl*) ( pContext->m_pBridgeImpl );

    ClientJob job(pEnvRemote, pImpl, pOid, pMemberType, pInterfaceType, pReturn, ppArgs, ppException);

    if( job.pack() && ! job.isOneway() )
    {
        job.wait();
    }
}

}

<commit_msg>INTEGRATION: CWS sb23 (1.12.38); FILE MERGED 2006/11/07 08:30:32 sb 1.12.38.5: RESYNC: (1.14-1.15); FILE MERGED 2006/08/21 07:36:41 sb 1.12.38.4: #88601# Made code warning-free. 2006/08/18 16:01:06 sb 1.12.38.3: RESYNC: (1.12-1.14); FILE MERGED 2005/03/23 14:44:29 sb 1.12.38.2: #88601# Ensure that negotiating current context support is finished before any requests are sent. 2005/03/23 14:21:44 sb 1.12.38.1: #88601# Support for current context in binary UNO URP bridge.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: urp_dispatch.cxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: rt $ $Date: 2006-12-01 14:47:22 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_bridges.hxx"
#include <sal/alloca.h>
#include <osl/mutex.hxx>
#include <osl/diagnose.h>

#include <rtl/alloc.h>
#include <rtl/ustrbuf.hxx>

#include <uno/mapping.hxx>
#include <uno/threadpool.h>

#include <bridges/remote/remote.h>
#include <bridges/remote/stub.hxx>
#include <bridges/remote/proxy.hxx>
#include <bridges/remote/remote.hxx>

#include "urp_bridgeimpl.hxx"
#include "urp_marshal.hxx"
#include "urp_dispatch.hxx"
#include "urp_job.hxx"
#include "urp_writer.hxx"
#include "urp_log.hxx"

using namespace ::rtl;
using namespace ::osl;
using namespace ::com::sun::star::uno;

namespace bridges_urp
{

void SAL_CALL urp_sendCloseConnection( uno_Environment *pEnvRemote )
{
    remote_Context *pContext = (remote_Context *) pEnvRemote->pContext;
    urp_BridgeImpl *pImpl = (urp_BridgeImpl*) ( pContext->m_pBridgeImpl );

    {
        MutexGuard guard( pImpl->m_marshalingMutex );

        // send immediately
        if( ! pImpl->m_blockMarshaler.empty() )
        {
            pImpl->m_pWriter->touch( sal_True );
        }

        pImpl->m_pWriter->sendEmptyMessage();
        // no more data via this connection !
        pImpl->m_pWriter->abort();
    }
}
extern "C" void SAL_CALL urp_sendRequest(
    uno_Environment *pEnvRemote,
    typelib_TypeDescription const * pMemberType,
    rtl_uString *pOid,
    typelib_InterfaceTypeDescription *pInterfaceType,
    void *pReturn,
    void *ppArgs[],
    uno_Any **ppException )
{
    remote_Context *pContext = (remote_Context *) pEnvRemote->pContext;
    urp_BridgeImpl *pImpl = (urp_BridgeImpl*) ( pContext->m_pBridgeImpl );
    pImpl->m_initialized.wait();
    urp_sendRequest_internal(
        pEnvRemote, pMemberType, pOid, pInterfaceType, pReturn, ppArgs,
        ppException );
}
void SAL_CALL urp_sendRequest_internal(
    uno_Environment *pEnvRemote,
    typelib_TypeDescription const * pMemberType,
    rtl_uString *pOid,
    typelib_InterfaceTypeDescription *pInterfaceType,
    void *pReturn,
    void *ppArgs[],
    uno_Any **ppException )
{
    remote_Context *pContext = (remote_Context *) pEnvRemote->pContext;
    urp_BridgeImpl *pImpl = (urp_BridgeImpl*) ( pContext->m_pBridgeImpl );

    ClientJob job(
        pEnvRemote, pContext, pImpl, pOid, pMemberType, pInterfaceType, pReturn,
        ppArgs, ppException);

    if( job.pack() && ! job.isOneway() )
    {
        job.wait();
    }
}

}

<|endoftext|>


<commit_before>#include "SDL.h"
#include "SDL_image.h"
#include <iostream>
#include <assert.h>
#include "shared/path_creator.hpp"
#include "shared/tdmap.hpp"
#include "shared/sizes.h"
#include <map>
#include <cmath>
#include <set>
#include <boost/foreach.hpp>
#include "graphics/graphics_path.hpp"

using namespace std;

class GUI
{
    private:
        void logSDLError(std::ostream &os, const std::string &msg)
        {
            os << msg << " error: " << SDL_GetError() << std::endl;
        }

        std::map<std::string, SDL_Texture *> loaded_textures;
        std::string resPath;

        SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren)
        {
            SDL_Texture *texture;

            if(loaded_textures.find(file) != loaded_textures.end())
            {
                texture = loaded_textures[file];
            }
            else
            {
                texture = IMG_LoadTexture(ren, (resPath + file).c_str());
                if (texture == nullptr)
                {
                    logSDLError(std::cout, "LoadTexture");
                }
                loaded_textures[file] = texture;
            }
            return texture;
        }

        /**
         * Draw an SDL_Texture to an SDL_Renderer at position x, y, preserving
         * the texture's width and height
         * @param tex The source texture we want to draw
         * @param ren The renderer we want to draw to
         * @param x The x Coordinate to draw to
         * @param y The y Coordinate to draw to
         */

        void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, int rw, int rh)
        {
            //Setup the destination rectangle to be at the position we want
            SDL_Rect dst;
            dst.x = x;
            dst.y = y;
            dst.w = rw;
            dst.h = rh;
            SDL_RenderCopy(ren, tex, NULL, &dst);
        }

        int row_width;
        int row_height;
        SDL_Renderer * ren;
        Path * main_path;
        int numrows;
        int numcols;

        Coordinate screen_to_game_coord(Coordinate c)
        {
            return Coordinate(c.x / row_width, c.y / row_height);
        }

        void re_render()
        {
            std::set<Coordinate> s( diff_coords.begin(), diff_coords.end() );
            diff_coords.assign( diff_coords.begin(), diff_coords.end() );

            BOOST_FOREACH(Coordinate &screen_cord, diff_coords)
            {

                Coordinate game_coord = screen_to_game_coord(screen_cord);
                renderTexture(background, ren, screen_cord.x, screen_cord.y, row_width, row_height);
                if(main_path->in(game_coord.x, game_coord.y))
                {
                    renderTexture(tile, ren, screen_cord.x, screen_cord.y, row_width, row_height);
                }
                Tower * tower = map->get_tower_at(game_coord);
                if(tower != nullptr)
                {
                    SDL_Texture * texture = loadTexture(tower->get_image_string(), ren);
                    if(texture != nullptr)
                    {
                        renderTexture(texture, ren, screen_cord.x, screen_cord.y, row_width, row_height);
                    }
                }
            }
        }

        void fill_screen_tiles()
        {
            for(int i = 0; i < numrows; i++)
            {
                for(int j = 0; j < numcols; j++)
                {

                    Coordinate screen_cord = game_to_screen_coord(Coordinate(i, j));
                    renderTexture(background, ren, screen_cord.x, screen_cord.y, row_width, row_height);
                    if(main_path->in(i, j))
                    {
                        renderTexture(tile, ren, screen_cord.x, screen_cord.y, row_width, row_height);
                    }
                    Tower * tower = map->get_tower_at(i, j);
                    if(tower != nullptr)
                    {
                        SDL_Texture * texture = loadTexture(tower->get_image_string(), ren);
                        Coordinate current_cord = game_to_screen_coord(Coordinate(i, j));
                        if(texture != nullptr)
                        {
                            renderTexture(texture, ren, current_cord.x, current_cord.y, row_width, row_height);
                        }
                    }
                }
            }
        }

        TDMap * map;
        int current_anim_frame;
        SDL_Texture * tile;
        SDL_Texture * background;

    public:
        GUI(int rows, int columns, Path * path, TDMap * map)
        {
            assert(rows > 0 && columns > 0 && path != nullptr && map != nullptr);
            current_anim_frame = 0;
            row_width = DEFAULT_WIDTH/rows;
            row_height = DEFAULT_HEIGHT/columns;
            resPath = GRAPHICS_PATH;
            numrows = rows;
            numcols = columns;
            this->map = map;
            SDL_Window *win;
            main_path = path;

            if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
            {
                logSDLError(std::cout, "SDL_Init");
                exit(1);
            }

            win = SDL_CreateWindow("Tower Defense",
                    SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DEFAULT_WIDTH, DEFAULT_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);

            if (win == nullptr)
            {
                logSDLError(std::cout, "CreateWindow");
                SDL_Quit();
                exit(1);
            }

            ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

            if (ren == nullptr)
            {
                logSDLError(std::cout, "CreateRenderer");
                //TODO free window
                SDL_Quit();
                exit(1);
            }

            background = loadTexture("grass.png", ren);
            tile = loadTexture("tile.png", ren);

            if (background == nullptr || tile == nullptr)
            {
                logSDLError(std::cout, "Getting Images");
                //TODO cleanup
                SDL_Quit();
                exit(1);
            }

            fill_screen_tiles();
            SDL_RenderPresent(ren);
            SDL_Delay(1000);
        }

        typedef std::pair<std::pair<SDL_Texture *, Coordinate> , std::pair<Coordinate, Coordinate>> anim_type;
        std::vector<anim_type> animations;
        std::vector<Coordinate> diff_coords;
        // takes pixel coords.
        // pls take care while using.

        void set_up_animation(SDL_Texture * texture, Coordinate from, Coordinate to, bool addToDiff)
        {
            animations.push_back(anim_type(std::make_pair(texture, from), std::make_pair(from, to)));
            diff_coords.push_back(from);
            diff_coords.push_back(to);
        }

        void clear_attack_animations()
        {
            animations.clear();
        }

        bool show_animations()
        {
            re_render();
            BOOST_FOREACH(anim_type & animation, animations)
            {
                SDL_Texture * tex = animation.first.first;
                auto from_to = animation.second;
                int hdiff = from_to.second.x - from_to.first.x;
                int vdiff = from_to.second.y - from_to.first.y;
                hdiff = hdiff/ANIMATION_CONSTANT;
                vdiff = vdiff/ANIMATION_CONSTANT;
                int extra_x = hdiff == 0 ? 0 : hdiff/std::abs(hdiff);
                int extra_y = vdiff == 0 ? 0 : vdiff/std::abs(vdiff);
                Coordinate game_coord = screen_to_game_coord(animation.first.second);
                Coordinate new_game_coord = Coordinate(game_coord.x + extra_x, game_coord.y + extra_y);
                Coordinate new_game_coord2 = Coordinate(game_coord.x, game_coord.y + extra_y);
                Coordinate new_game_coord3 = Coordinate(game_coord.x + extra_x, game_coord.y);
                diff_coords.push_back(game_to_screen_coord(new_game_coord));
                diff_coords.push_back(game_to_screen_coord(new_game_coord2));
                diff_coords.push_back(game_to_screen_coord(new_game_coord3));
                animation.first.second.x += hdiff;
                animation.first.second.y += vdiff;
                renderTexture(tex, ren, animation.first.second.x, animation.first.second.y, row_width, row_height);
            }
            if(++current_anim_frame < ANIMATION_CONSTANT)
            {
                SDL_Delay(10);
                return false;
            }
            return true;
        }

        void Update()
        {
            current_anim_frame = 0;
            for(int i = 0; i < NUM_ROWS; i++)
            {
                for(int j = 0; j < NUM_COLS; j++)
                {
                    Tower * tower = map->get_tower_at(i, j);
                    if(tower != nullptr)
                    {
                        Coordinate current_cord = game_to_screen_coord(Coordinate(i, j));
                        SDL_Texture * attack_texture = loadTexture(tower->get_attack_image_string(), ren);
                        BOOST_FOREACH(Coordinate c, tower->get_attack_tiles())
                        {
                            Coordinate screen_cord = game_to_screen_coord(c);
                            set_up_animation(attack_texture, current_cord, screen_cord, true);
                        }
                    }
                    BOOST_FOREACH(Sprite * s, map->get_sprites_at(i,j))
                    {

                        SDL_Texture * sprite_texture = loadTexture(s->image_string, ren);
                        Coordinate previous_cord = game_to_screen_coord(s->get_previous_position());
                        set_up_animation(sprite_texture, previous_cord, game_to_screen_coord(s->get_coordinate()), true);
                    }
                }
            }
            while(!show_animations())
            {
                SDL_RenderPresent(ren);
            }
            re_render();
            SDL_Delay(300);
            SDL_RenderPresent(ren);
            clear_attack_animations();
        }

        Coordinate game_to_screen_coord(Coordinate game_coord)
        {
            return Coordinate(game_coord.x * row_width, game_coord.y * row_height);
        }

        Coordinate game_to_screen_coord(int x, int y)
        {
            return game_to_screen_coord(Coordinate(x, y));
        }
};
<commit_msg>fixing indents<commit_after>#include "SDL.h"
#include "SDL_image.h"
#include <iostream>
#include <assert.h>
#include "shared/path_creator.hpp"
#include "shared/tdmap.hpp"
#include "shared/sizes.h"
#include <map>
#include <cmath>
#include <set>
#include <boost/foreach.hpp>
#include "graphics/graphics_path.hpp"

using namespace std;

class GUI
{
    private:
        void logSDLError(std::ostream &os, const std::string &msg)
        {
            os << msg << " error: " << SDL_GetError() << std::endl;
        }

        std::map<std::string, SDL_Texture *> loaded_textures;
        std::string resPath;

        SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren)
        {
            SDL_Texture *texture;
            if(loaded_textures.find(file) != loaded_textures.end())
            {
                texture = loaded_textures[file];
            }
            else
            {
                texture = IMG_LoadTexture(ren, (resPath + file).c_str());
                if (texture == nullptr)
                {
                    logSDLError(std::cout, "LoadTexture");
                }
                loaded_textures[file] = texture;
            }
            return texture;
        }

        /**
         * Draw an SDL_Texture to an SDL_Renderer at position x, y, preserving
         * the texture's width and height
         * @param tex The source texture we want to draw
         * @param ren The renderer we want to draw to
         * @param x The x Coordinate to draw to
         * @param y The y Coordinate to draw to
         */

        void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, int rw, int rh)
        {
            //Setup the destination rectangle to be at the position we want
            SDL_Rect dst;
            dst.x = x;
            dst.y = y;
            dst.w = rw;
            dst.h = rh;
            SDL_RenderCopy(ren, tex, NULL, &dst);
        }

        int row_width;
        int row_height;
        SDL_Renderer * ren;
        Path * main_path;
        int numrows;
        int numcols;

        Coordinate screen_to_game_coord(Coordinate c)
        {
            return Coordinate(c.x / row_width, c.y / row_height);
        }

        void re_render()
        {
            std::set<Coordinate> s( diff_coords.begin(), diff_coords.end() );
            diff_coords.assign( diff_coords.begin(), diff_coords.end() );

            BOOST_FOREACH(Coordinate &screen_cord, diff_coords)
            {

                Coordinate game_coord = screen_to_game_coord(screen_cord);
                renderTexture(background, ren, screen_cord.x, screen_cord.y, row_width, row_height);
                if(main_path->in(game_coord.x, game_coord.y))
                {
                    renderTexture(tile, ren, screen_cord.x, screen_cord.y, row_width, row_height);
                }
                Tower * tower = map->get_tower_at(game_coord);
                if(tower != nullptr)
                {
                    SDL_Texture * texture = loadTexture(tower->get_image_string(), ren);
                    if(texture != nullptr)
                    {
                        renderTexture(texture, ren, screen_cord.x, screen_cord.y, row_width, row_height);
                    }
                }
            }
        }

        void fill_screen_tiles()
        {
            for(int i = 0; i < numrows; i++)
            {
                for(int j = 0; j < numcols; j++)
                {

                    Coordinate screen_cord = game_to_screen_coord(Coordinate(i, j));
                    renderTexture(background, ren, screen_cord.x, screen_cord.y, row_width, row_height);
                    if(main_path->in(i, j))
                    {
                        renderTexture(tile, ren, screen_cord.x, screen_cord.y, row_width, row_height);
                    }
                    Tower * tower = map->get_tower_at(i, j);
                    if(tower != nullptr)
                    {
                        SDL_Texture * texture = loadTexture(tower->get_image_string(), ren);
                        Coordinate current_cord = game_to_screen_coord(Coordinate(i, j));
                        if(texture != nullptr)
                        {
                            renderTexture(texture, ren, current_cord.x, current_cord.y, row_width, row_height);
                        }
                    }
                }
            }
        }

        TDMap * map;
        int current_anim_frame;
        SDL_Texture * tile;
        SDL_Texture * background;

    public:
        GUI(int rows, int columns, Path * path, TDMap * map)
        {
            assert(rows > 0 && columns > 0 && path != nullptr && map != nullptr);
            current_anim_frame = 0;
            row_width = DEFAULT_WIDTH/rows;
            row_height = DEFAULT_HEIGHT/columns;
            resPath = GRAPHICS_PATH;
            numrows = rows;
            numcols = columns;
            this->map = map;
            SDL_Window *win;
            main_path = path;

            if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
            {
                logSDLError(std::cout, "SDL_Init");
                exit(1);
            }

            win = SDL_CreateWindow("Tower Defense",
                    SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DEFAULT_WIDTH, DEFAULT_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);

            if (win == nullptr)
            {
                logSDLError(std::cout, "CreateWindow");
                SDL_Quit();
                exit(1);
            }

            ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

            if (ren == nullptr)
            {
                logSDLError(std::cout, "CreateRenderer");
                //TODO free window
                SDL_Quit();
                exit(1);
            }

            background = loadTexture("grass.png", ren);
            tile = loadTexture("tile.png", ren);

            if (background == nullptr || tile == nullptr)
            {
                logSDLError(std::cout, "Getting Images");
                //TODO cleanup
                SDL_Quit();
                exit(1);
            }

            fill_screen_tiles();
            SDL_RenderPresent(ren);
            SDL_Delay(1000);
        }

        typedef std::pair<std::pair<SDL_Texture *, Coordinate> , std::pair<Coordinate, Coordinate>> anim_type;
        std::vector<anim_type> animations;
        std::vector<Coordinate> diff_coords;
        // takes pixel coords.
        // pls take care while using.

        void set_up_animation(SDL_Texture * texture, Coordinate from, Coordinate to, bool addToDiff)
        {
            animations.push_back(anim_type(std::make_pair(texture, from), std::make_pair(from, to)));
            diff_coords.push_back(from);
            diff_coords.push_back(to);
        }

        void clear_attack_animations()
        {
            animations.clear();
        }

        bool show_animations()
        {
            re_render();
            BOOST_FOREACH(anim_type & animation, animations)
            {
                SDL_Texture * tex = animation.first.first;
                auto from_to = animation.second;
                int hdiff = from_to.second.x - from_to.first.x;
                int vdiff = from_to.second.y - from_to.first.y;
                hdiff = hdiff/ANIMATION_CONSTANT;
                vdiff = vdiff/ANIMATION_CONSTANT;
                int extra_x = hdiff == 0 ? 0 : hdiff/std::abs(hdiff);
                int extra_y = vdiff == 0 ? 0 : vdiff/std::abs(vdiff);
                Coordinate game_coord = screen_to_game_coord(animation.first.second);
                Coordinate new_game_coord = Coordinate(game_coord.x + extra_x, game_coord.y + extra_y);
                Coordinate new_game_coord2 = Coordinate(game_coord.x, game_coord.y + extra_y);
                Coordinate new_game_coord3 = Coordinate(game_coord.x + extra_x, game_coord.y);
                diff_coords.push_back(game_to_screen_coord(new_game_coord));
                diff_coords.push_back(game_to_screen_coord(new_game_coord2));
                diff_coords.push_back(game_to_screen_coord(new_game_coord3));
                animation.first.second.x += hdiff;
                animation.first.second.y += vdiff;
                renderTexture(tex, ren, animation.first.second.x, animation.first.second.y, row_width, row_height);
            }
            if(++current_anim_frame < ANIMATION_CONSTANT)
            {
                SDL_Delay(10);
                return false;
            }
            return true;
        }

        void Update()
        {
            current_anim_frame = 0;
            for(int i = 0; i < NUM_ROWS; i++)
            {
                for(int j = 0; j < NUM_COLS; j++)
                {
                    Tower * tower = map->get_tower_at(i, j);
                    if(tower != nullptr)
                    {
                        Coordinate current_cord = game_to_screen_coord(Coordinate(i, j));
                        SDL_Texture * attack_texture = loadTexture(tower->get_attack_image_string(), ren);
                        BOOST_FOREACH(Coordinate c, tower->get_attack_tiles())
                        {
                            Coordinate screen_cord = game_to_screen_coord(c);
                            set_up_animation(attack_texture, current_cord, screen_cord, true);
                        }
                    }
                    BOOST_FOREACH(Sprite * s, map->get_sprites_at(i,j))
                    {

                        SDL_Texture * sprite_texture = loadTexture(s->image_string, ren);
                        Coordinate previous_cord = game_to_screen_coord(s->get_previous_position());
                        set_up_animation(sprite_texture, previous_cord, game_to_screen_coord(s->get_coordinate()), true);
                    }
                }
            }
            while(!show_animations())
            {
                SDL_RenderPresent(ren);
            }
            re_render();
            SDL_Delay(300);
            SDL_RenderPresent(ren);
            clear_attack_animations();
        }

        Coordinate game_to_screen_coord(Coordinate game_coord)
        {
            return Coordinate(game_coord.x * row_width, game_coord.y * row_height);
        }

        Coordinate game_to_screen_coord(int x, int y)
        {
            return game_to_screen_coord(Coordinate(x, y));
        }
};
<|endoftext|>


<commit_before>/*
 *  Copyright 2008-2010 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*! \file scan.inl
 *  \brief Inline file for scan.h.
 */

#include <thrust/detail/config.h>
#include <thrust/detail/device/cuda/dispatch/scan.h>
#include <thrust/detail/static_assert.h>

namespace thrust
{
namespace detail
{
namespace device
{
namespace cuda
{

template<typename InputIterator,
         typename OutputIterator,
         typename AssociativeOperator>
  OutputIterator inclusive_scan(InputIterator first,
                                InputIterator last,
                                OutputIterator result,
                                AssociativeOperator binary_op)
{
    // we're attempting to launch a kernel, assert we're compiling with nvcc
    // ========================================================================
    // X Note to the user: If you've found this line due to a compiler error, X
    // X you need to compile your code using nvcc, rather than g++ or cl.exe  X
    // ========================================================================
    THRUST_STATIC_ASSERT( (depend_on_instantiation<InputIterator, THRUST_DEVICE_COMPILER == THRUST_DEVICE_COMPILER_NVCC>::value) );

    typedef typename thrust::iterator_value<OutputIterator>::type OutputType;

    // whether to use fast_scan or safe_scan
    // TODO profile this threshold
#if THRUST_DEVICE_COMPILER == THRUST_DEVICE_COMPILER_NVCC && CUDA_VERSION >= 3010
    // CUDA 3.1 and higher support non-pod types in statically-allocated __shared__ memory
    static const bool use_fast_scan = sizeof(OutputType) <= 16;
#else
    // CUDA 3.0 and earlier must use safe_scan for non-pod types
    static const bool use_fast_scan = sizeof(OutputType) <= 16 && thrust::detail::is_pod<OutputType>::value;
#endif

    // XXX WAR nvcc unused variable warning
    (void) use_fast_scan;

    return thrust::detail::device::cuda::dispatch::inclusive_scan
        (first, last, result, binary_op,
         thrust::detail::integral_constant<bool, use_fast_scan>());
}

template<typename InputIterator,
         typename OutputIterator,
         typename T,
         typename AssociativeOperator>
  OutputIterator exclusive_scan(InputIterator first,
                                InputIterator last,
                                OutputIterator result,
                                T init,
                                AssociativeOperator binary_op)
{
    // we're attempting to launch a kernel, assert we're compiling with nvcc
    // ========================================================================
    // X Note to the user: If you've found this line due to a compiler error, X
    // X you need to compile your code using nvcc, rather than g++ or cl.exe  X
    // ========================================================================
    THRUST_STATIC_ASSERT( (depend_on_instantiation<InputIterator, THRUST_DEVICE_COMPILER == THRUST_DEVICE_COMPILER_NVCC>::value) );

    typedef typename thrust::iterator_value<OutputIterator>::type OutputType;

    // whether to use fast_scan or safe_scan
    // TODO profile this threshold
#if THRUST_DEVICE_COMPILER == THRUST_DEVICE_COMPILER_NVCC && CUDA_VERSION >= 3010
    // CUDA 3.1 and higher support non-pod types in statically-allocated __shared__ memory
    static const bool use_fast_scan = sizeof(OutputType) <= 16;
#else
    // CUDA 3.0 and earlier must use safe_scan for non-pod types
    static const bool use_fast_scan = sizeof(OutputType) <= 16 && thrust::detail::is_pod<OutputType>::value;
#endif

    // XXX WAR nvcc 3.0 unused variable warning
    (void) use_fast_scan;

    return thrust::detail::device::cuda::dispatch::exclusive_scan
        (first, last, result, init, binary_op,
         thrust::detail::integral_constant<bool, use_fast_scan>());
}

} // end namespace cuda
} // end namespace device
} // end namespace detail
} // end namespace thrust

<commit_msg>revert to Thrust v1.2 fast_scan/safe_scan dispatch<commit_after>/*
 *  Copyright 2008-2010 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*! \file scan.inl
 *  \brief Inline file for scan.h.
 */

#include <thrust/detail/config.h>
#include <thrust/detail/device/cuda/dispatch/scan.h>
#include <thrust/detail/static_assert.h>

namespace thrust
{
namespace detail
{
namespace device
{
namespace cuda
{

template<typename InputIterator,
         typename OutputIterator,
         typename AssociativeOperator>
  OutputIterator inclusive_scan(InputIterator first,
                                InputIterator last,
                                OutputIterator result,
                                AssociativeOperator binary_op)
{
    // we're attempting to launch a kernel, assert we're compiling with nvcc
    // ========================================================================
    // X Note to the user: If you've found this line due to a compiler error, X
    // X you need to compile your code using nvcc, rather than g++ or cl.exe  X
    // ========================================================================
    THRUST_STATIC_ASSERT( (depend_on_instantiation<InputIterator, THRUST_DEVICE_COMPILER == THRUST_DEVICE_COMPILER_NVCC>::value) );

    typedef typename thrust::iterator_value<OutputIterator>::type OutputType;

    // whether to use fast_scan or safe_scan
    // TODO profile this threshold
//#if THRUST_DEVICE_COMPILER == THRUST_DEVICE_COMPILER_NVCC && CUDA_VERSION >= 3010
//    // CUDA 3.1 and higher support non-pod types in statically-allocated __shared__ memory
//    static const bool use_fast_scan = sizeof(OutputType) <= 16;
//#else
//    // CUDA 3.0 and earlier must use safe_scan for non-pod types
    static const bool use_fast_scan = sizeof(OutputType) <= 16 && thrust::detail::is_pod<OutputType>::value;
//#endif

    // XXX WAR nvcc unused variable warning
    (void) use_fast_scan;

    return thrust::detail::device::cuda::dispatch::inclusive_scan
        (first, last, result, binary_op,
         thrust::detail::integral_constant<bool, use_fast_scan>());
}

template<typename InputIterator,
         typename OutputIterator,
         typename T,
         typename AssociativeOperator>
  OutputIterator exclusive_scan(InputIterator first,
                                InputIterator last,
                                OutputIterator result,
                                T init,
                                AssociativeOperator binary_op)
{
    // we're attempting to launch a kernel, assert we're compiling with nvcc
    // ========================================================================
    // X Note to the user: If you've found this line due to a compiler error, X
    // X you need to compile your code using nvcc, rather than g++ or cl.exe  X
    // ========================================================================
    THRUST_STATIC_ASSERT( (depend_on_instantiation<InputIterator, THRUST_DEVICE_COMPILER == THRUST_DEVICE_COMPILER_NVCC>::value) );

    typedef typename thrust::iterator_value<OutputIterator>::type OutputType;

    // whether to use fast_scan or safe_scan
    // TODO profile this threshold
//#if THRUST_DEVICE_COMPILER == THRUST_DEVICE_COMPILER_NVCC && CUDA_VERSION >= 3010
//    // CUDA 3.1 and higher support non-pod types in statically-allocated __shared__ memory
//    static const bool use_fast_scan = sizeof(OutputType) <= 16;
//#else
//    // CUDA 3.0 and earlier must use safe_scan for non-pod types
    static const bool use_fast_scan = sizeof(OutputType) <= 16 && thrust::detail::is_pod<OutputType>::value;
//#endif

    // XXX WAR nvcc 3.0 unused variable warning
    (void) use_fast_scan;

    return thrust::detail::device::cuda::dispatch::exclusive_scan
        (first, last, result, init, binary_op,
         thrust::detail::integral_constant<bool, use_fast_scan>());
}

} // end namespace cuda
} // end namespace device
} // end namespace detail
} // end namespace thrust

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2006 Tommi Maekitalo
 *
 * 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.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "tnt/poller.h"
#include "tnt/pollerimpl.h"
#include "tnt/tntnet.h"
#include <cxxtools/syserror.h>
#include <cxxtools/log.h>
#include <ios>
#include <unistd.h>
#include <fcntl.h>
#ifdef WITH_EPOLL
#include <sys/epoll.h>
#include <errno.h>
#endif

log_define("tntnet.poller")

namespace tnt
{
  PollerIf::~PollerIf()
  { }

  Poller::Poller(Jobqueue& q)
    : impl(new PollerImpl(q))
  { }

  void Poller::run()
  {
    impl->run();
  }

#ifdef WITH_EPOLL

  PollerImpl::PollerImpl(Jobqueue& q)
    : queue(q),
      pollFd(-1)
  {
    pollFd = ::epoll_create(256);
    if (pollFd < 0)
      throw cxxtools::SystemError("epoll_create");

    fcntl(notify_pipe.getReadFd(), F_SETFL, O_NONBLOCK);
    addFd(notify_pipe.getReadFd());
  }

  PollerImpl::~PollerImpl()
  {
    close(pollFd);
  }

  void PollerImpl::addFd(int fd)
  {
    log_debug("addFd(" << fd << ')');

    epoll_event e;
    e.events = EPOLLIN;
    e.data.fd = fd;
    int ret = ::epoll_ctl(pollFd, EPOLL_CTL_ADD, fd, &e);
    if (ret < 0)
      throw cxxtools::SystemError("epoll_ctl(EPOLL_CTL_ADD)");
  }

  bool PollerImpl::removeFd(int fd)
  {
    log_debug("removeFd(" << fd << ')');

    epoll_event e;
    e.data.fd = fd;
    int ret = ::epoll_ctl(pollFd, EPOLL_CTL_DEL, fd, &e);
    if (ret < 0)
    {
      if (errno == EBADF || errno == ENOENT)
      {
        log_debug("fd " << fd << " couldn't be removed");
        return false;
      }
      else
        throw cxxtools::SystemError("epoll_ctl(EPOLL_CTL_DEL)");
    }

    return true;
  }

  void PollerImpl::doStop()
  {
    log_debug("notify stop");
    notify_pipe.write('A');
  }

  void PollerImpl::addIdleJob(Jobqueue::JobPtr job)
  {
    log_debug("addIdleJob " << job->getFd());

    {
      cxxtools::MutexLock lock(mutex);
      new_jobs.insert(job);
      notify_pipe.write('A');
    }

    log_debug("addIdleJob ready");
  }

  void PollerImpl::append_new_jobs()
  {
    cxxtools::MutexLock lock(mutex);
    if (!new_jobs.empty())
    {
      // append new jobs to current
      log_debug("add " << new_jobs.size() << " new jobs to poll-list");

      time_t currentTime;
      time(&currentTime);
      for (new_jobs_type::iterator it = new_jobs.begin();
           it != new_jobs.end(); ++it)
      {
        addFd((*it)->getFd());
        jobs[(*it)->getFd()] = *it;

        int msec;
        if (poll_timeout < 0)
          poll_timeout = (*it)->msecToTimeout(currentTime);
        else if ((msec = (*it)->msecToTimeout(currentTime)) < poll_timeout)
          poll_timeout = msec;

      }

      new_jobs.clear();
    }
  }

  void PollerImpl::run()
  {
    epoll_event events[16];

    time_t pollTime;
    time(&pollTime);
    while (!Tntnet::shouldStop())
    {
      usleep(100);

      append_new_jobs();

      if (jobs.size() == 0)
        poll_timeout = -1;

      log_debug("epoll_wait with timeout " << poll_timeout << " ms");
      int ret = ::epoll_wait(pollFd, events, 16, poll_timeout);

      if (ret < 0)
      {
        if (errno != EINTR)
          throw cxxtools::SystemError("epoll_wait");
      }
      else if (ret == 0)
      {
        // timeout reached - check for timed out requests and get next timeout

        log_debug("timeout reached");

        poll_timeout = -1;
        time_t currentTime;
        time(&currentTime);
        for (jobs_type::iterator it = jobs.begin(); it != jobs.end(); )
        {
          int msec = it->second->msecToTimeout(currentTime);
          if (msec <= 0)
          {
            log_debug("keep-alive-timeout reached");
            jobs_type::iterator it2 = it++;
            jobs.erase(it2);
          }
          else
          {
            if (poll_timeout < 0 || msec < poll_timeout)
              poll_timeout = msec;
            ++it;
          }
        }
      }
      else
      {
        time_t currentTime;
        time(&currentTime);
        poll_timeout -= (currentTime - pollTime) * 1000;
        if (poll_timeout <= 0)
          poll_timeout = 100;

        pollTime = currentTime;

        // no timeout - process events
        log_debug(ret << " events occured");

        bool rebuildPollFd = false;

        for (int i = 0; i < ret; ++i)
        {
          if (events[i].data.fd == notify_pipe.getReadFd())
          {
            if (Tntnet::shouldStop())
            {
              log_info("stop poller");
              break;
            }

            log_debug("read notify-pipe");
            char buffer[64];
            ssize_t n = notify_pipe.read(buffer, sizeof(buffer));
            log_debug("read returns " << n);
          }
          else
          {
            jobs_type::iterator it = jobs.find(events[i].data.fd);
            if (it == jobs.end())
            {
              log_fatal("internal error: job for fd " << events[i].data.fd << " not found in jobs-list");
              ::close(events[i].data.fd);
              rebuildPollFd = true;
            }
            else
            {
              Jobqueue::JobPtr j = it->second;
              int ev = events[i].events;
              jobs.erase(it);

              if (!removeFd(events[i].data.fd))
                rebuildPollFd = true;

              if (ev & EPOLLIN)
              {
                log_debug("put fd " << it->first << " back in queue");
                queue.put(j);
              }
              else
              {
                log_debug("remove fd " << it->first << " from queue");
              }
            }
          }
        }

        if (rebuildPollFd)
        {
          // rebuild poll-structure
          log_warn("need to rebuild poll structure");
          close(pollFd);
          pollFd = ::epoll_create(256);
          if (pollFd < 0)
            throw cxxtools::SystemError("epoll_create");

          int ret = fcntl(notify_pipe.getReadFd(), F_SETFL, O_NONBLOCK);
          if (ret < 0)
            throw cxxtools::SystemError("fcntl");

          addFd(notify_pipe.getReadFd());
          for (jobs_type::iterator it = jobs.begin(); it != jobs.end(); ++it)
            addFd(it->first);
        }
      }
    }
  }

#else

  PollerImpl::PollerImpl(Jobqueue& q)
    : queue(q),
      poll_timeout(-1)
  {
    fcntl(notify_pipe.getReadFd(), F_SETFL, O_NONBLOCK);

    pollfds.reserve(16);
    pollfds[0].fd = notify_pipe.getReadFd();
    pollfds[0].events = POLLIN;
    pollfds[0].revents = 0;
  }

  void PollerImpl::append_new_jobs()
  {
    cxxtools::MutexLock lock(mutex);
    if (!new_jobs.empty())
    {
      // append new jobs to current
      log_debug("add " << new_jobs.size() << " new jobs to poll-list");

      pollfds.reserve(current_jobs.size() + new_jobs.size() + 1);

      time_t currentTime;
      time(&currentTime);
      for (jobs_type::iterator it = new_jobs.begin();
           it != new_jobs.end(); ++it)
      {
        append(*it);
        int msec;
        if (poll_timeout < 0)
          poll_timeout = (*it)->msecToTimeout(currentTime);
        else if ((msec = (*it)->msecToTimeout(currentTime)) < poll_timeout)
          poll_timeout = msec;
      }

      new_jobs.clear();
    }
  }

  void PollerImpl::append(Jobqueue::JobPtr& job)
  {
    current_jobs.push_back(job);

    pollfd& p = *(pollfds.data() + current_jobs.size());
    p.fd = job->getFd();
    p.events = POLLIN;
  }

  void PollerImpl::run()
  {
    while (!Tntnet::shouldStop())
    {
      usleep(100);
      append_new_jobs();

      try
      {
        log_debug("poll timeout=" << poll_timeout);
        ::poll(pollfds.data(), current_jobs.size() + 1, poll_timeout);
        poll_timeout = -1;

        if (pollfds[0].revents != 0)
        {
          if (Tntnet::shouldStop())
          {
            log_info("stop poller");
            break;
          }

          log_debug("read notify-pipe");
          char buffer[64];
          ssize_t n = notify_pipe.read(&buffer, sizeof(buffer));
          log_debug("read returns " << n);
          pollfds[0].revents = 0;
        }

        if (current_jobs.size() > 0)
          dispatch();
      }
      catch (const std::exception& e)
      {
        log_error("error in poll-loop: " << e.what());
      }
    }
  }

  void PollerImpl::doStop()
  {
    log_debug("notify stop");
    notify_pipe.write('A');
  }

  void PollerImpl::dispatch()
  {
    log_debug("dispatch " << current_jobs.size() << " jobs");

    time_t currentTime;
    time(&currentTime);
    for (unsigned i = 0; i < current_jobs.size(); )
    {
      if (pollfds[i + 1].revents & POLLIN)
      {
        log_debug("job found " << pollfds[i + 1].fd);

        // put job into work-queue
        queue.put(current_jobs[i]);
        remove(i);
      }
      else if (pollfds[i + 1].revents != 0)
      {
        log_debug("pollevent " << std::hex << pollfds[i + 1].revents << " on fd "  << pollfds[i + 1].fd);
        remove(i);
      }
      else
      {
        // check timeout
        int msec = current_jobs[i]->msecToTimeout(currentTime);
        if (msec <= 0)
        {
          log_debug("keep-alive-timeout reached");
          remove(i);
        }
        else if (poll_timeout < 0 || msec < poll_timeout)
          poll_timeout = msec;

        ++i;
      }
    }
  }

  void PollerImpl::remove(jobs_type::size_type n)
  {
    // replace job with last job in poller-list
    jobs_type::size_type last = current_jobs.size() - 1;

    if (n != last)
    {
      pollfds[n + 1] = pollfds[last + 1];
      current_jobs[n] = current_jobs[last];
    }

    current_jobs.pop_back();
  }

  void PollerImpl::addIdleJob(Jobqueue::JobPtr job)
  {
    log_debug("addIdleJob " << job->getFd());

    {
      cxxtools::MutexLock lock(mutex);
      new_jobs.push_back(job);
    }

    log_debug("notify " << job->getFd());

    notify_pipe.write('A');

    log_debug("addIdleJob ready");
  }
#endif // #else HAVE_EPOLL

}
<commit_msg>bugfix: wrong buffer for notification of poller was used, which may lead to a buffer overflow in very rare cases<commit_after>/*
 * Copyright (C) 2005-2006 Tommi Maekitalo
 *
 * 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.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "tnt/poller.h"
#include "tnt/pollerimpl.h"
#include "tnt/tntnet.h"
#include <cxxtools/syserror.h>
#include <cxxtools/log.h>
#include <ios>
#include <unistd.h>
#include <fcntl.h>
#ifdef WITH_EPOLL
#include <sys/epoll.h>
#include <errno.h>
#endif

log_define("tntnet.poller")

namespace tnt
{
  PollerIf::~PollerIf()
  { }

  Poller::Poller(Jobqueue& q)
    : impl(new PollerImpl(q))
  { }

  void Poller::run()
  {
    impl->run();
  }

#ifdef WITH_EPOLL

  PollerImpl::PollerImpl(Jobqueue& q)
    : queue(q),
      pollFd(-1)
  {
    pollFd = ::epoll_create(256);
    if (pollFd < 0)
      throw cxxtools::SystemError("epoll_create");

    fcntl(notify_pipe.getReadFd(), F_SETFL, O_NONBLOCK);
    addFd(notify_pipe.getReadFd());
  }

  PollerImpl::~PollerImpl()
  {
    close(pollFd);
  }

  void PollerImpl::addFd(int fd)
  {
    log_debug("addFd(" << fd << ')');

    epoll_event e;
    e.events = EPOLLIN;
    e.data.fd = fd;
    int ret = ::epoll_ctl(pollFd, EPOLL_CTL_ADD, fd, &e);
    if (ret < 0)
      throw cxxtools::SystemError("epoll_ctl(EPOLL_CTL_ADD)");
  }

  bool PollerImpl::removeFd(int fd)
  {
    log_debug("removeFd(" << fd << ')');

    epoll_event e;
    e.data.fd = fd;
    int ret = ::epoll_ctl(pollFd, EPOLL_CTL_DEL, fd, &e);
    if (ret < 0)
    {
      if (errno == EBADF || errno == ENOENT)
      {
        log_debug("fd " << fd << " couldn't be removed");
        return false;
      }
      else
        throw cxxtools::SystemError("epoll_ctl(EPOLL_CTL_DEL)");
    }

    return true;
  }

  void PollerImpl::doStop()
  {
    log_debug("notify stop");
    notify_pipe.write('A');
  }

  void PollerImpl::addIdleJob(Jobqueue::JobPtr job)
  {
    log_debug("addIdleJob " << job->getFd());

    {
      cxxtools::MutexLock lock(mutex);
      new_jobs.insert(job);
      notify_pipe.write('A');
    }

    log_debug("addIdleJob ready");
  }

  void PollerImpl::append_new_jobs()
  {
    cxxtools::MutexLock lock(mutex);
    if (!new_jobs.empty())
    {
      // append new jobs to current
      log_debug("add " << new_jobs.size() << " new jobs to poll-list");

      time_t currentTime;
      time(&currentTime);
      for (new_jobs_type::iterator it = new_jobs.begin();
           it != new_jobs.end(); ++it)
      {
        addFd((*it)->getFd());
        jobs[(*it)->getFd()] = *it;

        int msec;
        if (poll_timeout < 0)
          poll_timeout = (*it)->msecToTimeout(currentTime);
        else if ((msec = (*it)->msecToTimeout(currentTime)) < poll_timeout)
          poll_timeout = msec;

      }

      new_jobs.clear();
    }
  }

  void PollerImpl::run()
  {
    epoll_event events[16];

    time_t pollTime;
    time(&pollTime);
    while (!Tntnet::shouldStop())
    {
      usleep(100);

      append_new_jobs();

      if (jobs.size() == 0)
        poll_timeout = -1;

      log_debug("epoll_wait with timeout " << poll_timeout << " ms");
      int ret = ::epoll_wait(pollFd, events, 16, poll_timeout);

      if (ret < 0)
      {
        if (errno != EINTR)
          throw cxxtools::SystemError("epoll_wait");
      }
      else if (ret == 0)
      {
        // timeout reached - check for timed out requests and get next timeout

        log_debug("timeout reached");

        poll_timeout = -1;
        time_t currentTime;
        time(&currentTime);
        for (jobs_type::iterator it = jobs.begin(); it != jobs.end(); )
        {
          int msec = it->second->msecToTimeout(currentTime);
          if (msec <= 0)
          {
            log_debug("keep-alive-timeout reached");
            jobs_type::iterator it2 = it++;
            jobs.erase(it2);
          }
          else
          {
            if (poll_timeout < 0 || msec < poll_timeout)
              poll_timeout = msec;
            ++it;
          }
        }
      }
      else
      {
        time_t currentTime;
        time(&currentTime);
        poll_timeout -= (currentTime - pollTime) * 1000;
        if (poll_timeout <= 0)
          poll_timeout = 100;

        pollTime = currentTime;

        // no timeout - process events
        log_debug(ret << " events occured");

        bool rebuildPollFd = false;

        for (int i = 0; i < ret; ++i)
        {
          if (events[i].data.fd == notify_pipe.getReadFd())
          {
            if (Tntnet::shouldStop())
            {
              log_info("stop poller");
              break;
            }

            log_debug("read notify-pipe");
            char buffer[64];
            ssize_t n = notify_pipe.read(buffer, sizeof(buffer));
            log_debug("read returns " << n);
          }
          else
          {
            jobs_type::iterator it = jobs.find(events[i].data.fd);
            if (it == jobs.end())
            {
              log_fatal("internal error: job for fd " << events[i].data.fd << " not found in jobs-list");
              ::close(events[i].data.fd);
              rebuildPollFd = true;
            }
            else
            {
              Jobqueue::JobPtr j = it->second;
              int ev = events[i].events;
              jobs.erase(it);

              if (!removeFd(events[i].data.fd))
                rebuildPollFd = true;

              if (ev & EPOLLIN)
              {
                log_debug("put fd " << it->first << " back in queue");
                queue.put(j);
              }
              else
              {
                log_debug("remove fd " << it->first << " from queue");
              }
            }
          }
        }

        if (rebuildPollFd)
        {
          // rebuild poll-structure
          log_warn("need to rebuild poll structure");
          close(pollFd);
          pollFd = ::epoll_create(256);
          if (pollFd < 0)
            throw cxxtools::SystemError("epoll_create");

          int ret = fcntl(notify_pipe.getReadFd(), F_SETFL, O_NONBLOCK);
          if (ret < 0)
            throw cxxtools::SystemError("fcntl");

          addFd(notify_pipe.getReadFd());
          for (jobs_type::iterator it = jobs.begin(); it != jobs.end(); ++it)
            addFd(it->first);
        }
      }
    }
  }

#else

  PollerImpl::PollerImpl(Jobqueue& q)
    : queue(q),
      poll_timeout(-1)
  {
    fcntl(notify_pipe.getReadFd(), F_SETFL, O_NONBLOCK);

    pollfds.reserve(16);
    pollfds[0].fd = notify_pipe.getReadFd();
    pollfds[0].events = POLLIN;
    pollfds[0].revents = 0;
  }

  void PollerImpl::append_new_jobs()
  {
    cxxtools::MutexLock lock(mutex);
    if (!new_jobs.empty())
    {
      // append new jobs to current
      log_debug("add " << new_jobs.size() << " new jobs to poll-list");

      pollfds.reserve(current_jobs.size() + new_jobs.size() + 1);

      time_t currentTime;
      time(&currentTime);
      for (jobs_type::iterator it = new_jobs.begin();
           it != new_jobs.end(); ++it)
      {
        append(*it);
        int msec;
        if (poll_timeout < 0)
          poll_timeout = (*it)->msecToTimeout(currentTime);
        else if ((msec = (*it)->msecToTimeout(currentTime)) < poll_timeout)
          poll_timeout = msec;
      }

      new_jobs.clear();
    }
  }

  void PollerImpl::append(Jobqueue::JobPtr& job)
  {
    current_jobs.push_back(job);

    pollfd& p = *(pollfds.data() + current_jobs.size());
    p.fd = job->getFd();
    p.events = POLLIN;
  }

  void PollerImpl::run()
  {
    while (!Tntnet::shouldStop())
    {
      usleep(100);
      append_new_jobs();

      try
      {
        log_debug("poll timeout=" << poll_timeout);
        ::poll(pollfds.data(), current_jobs.size() + 1, poll_timeout);
        poll_timeout = -1;

        if (pollfds[0].revents != 0)
        {
          if (Tntnet::shouldStop())
          {
            log_info("stop poller");
            break;
          }

          log_debug("read notify-pipe");
          char buffer[64];
          ssize_t n = notify_pipe.read(buffer, sizeof(buffer));
          log_debug("read returns " << n);
          pollfds[0].revents = 0;
        }

        if (current_jobs.size() > 0)
          dispatch();
      }
      catch (const std::exception& e)
      {
        log_error("error in poll-loop: " << e.what());
      }
    }
  }

  void PollerImpl::doStop()
  {
    log_debug("notify stop");
    notify_pipe.write('A');
  }

  void PollerImpl::dispatch()
  {
    log_debug("dispatch " << current_jobs.size() << " jobs");

    time_t currentTime;
    time(&currentTime);
    for (unsigned i = 0; i < current_jobs.size(); )
    {
      if (pollfds[i + 1].revents & POLLIN)
      {
        log_debug("job found " << pollfds[i + 1].fd);

        // put job into work-queue
        queue.put(current_jobs[i]);
        remove(i);
      }
      else if (pollfds[i + 1].revents != 0)
      {
        log_debug("pollevent " << std::hex << pollfds[i + 1].revents << " on fd "  << pollfds[i + 1].fd);
        remove(i);
      }
      else
      {
        // check timeout
        int msec = current_jobs[i]->msecToTimeout(currentTime);
        if (msec <= 0)
        {
          log_debug("keep-alive-timeout reached");
          remove(i);
        }
        else if (poll_timeout < 0 || msec < poll_timeout)
          poll_timeout = msec;

        ++i;
      }
    }
  }

  void PollerImpl::remove(jobs_type::size_type n)
  {
    // replace job with last job in poller-list
    jobs_type::size_type last = current_jobs.size() - 1;

    if (n != last)
    {
      pollfds[n + 1] = pollfds[last + 1];
      current_jobs[n] = current_jobs[last];
    }

    current_jobs.pop_back();
  }

  void PollerImpl::addIdleJob(Jobqueue::JobPtr job)
  {
    log_debug("addIdleJob " << job->getFd());

    {
      cxxtools::MutexLock lock(mutex);
      new_jobs.push_back(job);
    }

    log_debug("notify " << job->getFd());

    notify_pipe.write('A');

    log_debug("addIdleJob ready");
  }
#endif // #else HAVE_EPOLL

}
<|endoftext|>


<commit_before>//===- OptimizerDriver.cpp - Allow BugPoint to run passes safely ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an interface that allows bugpoint to run various passes
// without the threat of a buggy pass corrupting bugpoint (of course, bugpoint
// may have its own bugs, but that's another story...).  It achieves this by
// forking a copy of itself and having the child process do the optimizations.
// If this client dies, we can always fork a new one.  :)
//
//===----------------------------------------------------------------------===//

#include "BugDriver.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"

#define DONT_GET_PLUGIN_LOADER_OPTION
#include "llvm/Support/PluginLoader.h"

#include <fstream>
using namespace llvm;

namespace llvm {
  extern cl::opt<std::string> OutputPrefix;
}

namespace {
  // ChildOutput - This option captures the name of the child output file that
  // is set up by the parent bugpoint process
  cl::opt<std::string> ChildOutput("child-output", cl::ReallyHidden);
}

/// writeProgramToFile - This writes the current "Program" to the named bitcode
/// file.  If an error occurs, true is returned.
///
bool BugDriver::writeProgramToFile(const std::string &Filename,
                                   const Module *M) const {
  std::string ErrInfo;
  tool_output_file Out(Filename.c_str(), ErrInfo,
                       raw_fd_ostream::F_Binary);
  if (ErrInfo.empty()) {
    WriteBitcodeToFile(M, Out.os());
    Out.os().close();
    if (!Out.os().has_error()) {
      Out.keep();
      return false;
    }
  }
  Out.os().clear_error();
  return true;
}

/// EmitProgressBitcode - This function is used to output the current Program
/// to a file named "bugpoint-ID.bc".
///
void BugDriver::EmitProgressBitcode(const Module *M,
                                    const std::string &ID,
                                    bool NoFlyer)  const {
  // Output the input to the current pass to a bitcode file, emit a message
  // telling the user how to reproduce it: opt -foo blah.bc
  //
  std::string Filename = OutputPrefix + "-" + ID + ".bc";
  if (writeProgramToFile(Filename, M)) {
    errs() <<  "Error opening file '" << Filename << "' for writing!\n";
    return;
  }

  outs() << "Emitted bitcode to '" << Filename << "'\n";
  if (NoFlyer || PassesToRun.empty()) return;
  outs() << "\n*** You can reproduce the problem with: ";
  if (UseValgrind) outs() << "valgrind ";
  outs() << "opt " << Filename << " ";
  outs() << getPassesString(PassesToRun) << "\n";
}

cl::opt<bool> SilencePasses("silence-passes", cl::desc("Suppress output of running passes (both stdout and stderr)"));

static cl::list<std::string> OptArgs("opt-args", cl::Positional,
                                     cl::desc("<opt arguments>..."),
                                     cl::ZeroOrMore, cl::PositionalEatsArgs);

/// runPasses - Run the specified passes on Program, outputting a bitcode file
/// and writing the filename into OutputFile if successful.  If the
/// optimizations fail for some reason (optimizer crashes), return true,
/// otherwise return false.  If DeleteOutput is set to true, the bitcode is
/// deleted on success, and the filename string is undefined.  This prints to
/// outs() a single line message indicating whether compilation was successful
/// or failed.
///
bool BugDriver::runPasses(Module *Program,
                          const std::vector<std::string> &Passes,
                          std::string &OutputFilename, bool DeleteOutput,
                          bool Quiet, unsigned NumExtraArgs,
                          const char * const *ExtraArgs) const {
  // setup the output file name
  outs().flush();
  sys::Path uniqueFilename(OutputPrefix + "-output.bc");
  std::string ErrMsg;
  if (uniqueFilename.makeUnique(true, &ErrMsg)) {
    errs() << getToolName() << ": Error making unique filename: "
           << ErrMsg << "\n";
    return(1);
  }
  OutputFilename = uniqueFilename.str();

  // set up the input file name
  sys::Path inputFilename(OutputPrefix + "-input.bc");
  if (inputFilename.makeUnique(true, &ErrMsg)) {
    errs() << getToolName() << ": Error making unique filename: "
           << ErrMsg << "\n";
    return(1);
  }

  std::string ErrInfo;
  tool_output_file InFile(inputFilename.c_str(), ErrInfo,
                          raw_fd_ostream::F_Binary);

  if (!ErrInfo.empty()) {
    errs() << "Error opening bitcode file: " << inputFilename.str() << "\n";
    return 1;
  }
  WriteBitcodeToFile(Program, InFile.os());
  InFile.os().close();
  if (InFile.os().has_error()) {
    errs() << "Error writing bitcode file: " << inputFilename.str() << "\n";
    InFile.os().clear_error();
    return 1;
  }

  sys::Path tool = PrependMainExecutablePath("opt", getToolName(),
                                             (void*)"opt");
  if (tool.empty()) {
    errs() << "Cannot find `opt' in executable directory!\n";
    return 1;
  }

  // Ok, everything that could go wrong before running opt is done.
  InFile.keep();

  // setup the child process' arguments
  SmallVector<const char*, 8> Args;
  std::string Opt = tool.str();
  if (UseValgrind) {
    Args.push_back("valgrind");
    Args.push_back("--error-exitcode=1");
    Args.push_back("-q");
    Args.push_back(tool.c_str());
  } else
    Args.push_back(Opt.c_str());

  Args.push_back("-o");
  Args.push_back(OutputFilename.c_str());
  for (unsigned i = 0, e = OptArgs.size(); i != e; ++i)
    Args.push_back(OptArgs[i].c_str());
  std::vector<std::string> pass_args;
  for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) {
    pass_args.push_back( std::string("-load"));
    pass_args.push_back( PluginLoader::getPlugin(i));
  }
  for (std::vector<std::string>::const_iterator I = Passes.begin(),
       E = Passes.end(); I != E; ++I )
    pass_args.push_back( std::string("-") + (*I) );
  for (std::vector<std::string>::const_iterator I = pass_args.begin(),
       E = pass_args.end(); I != E; ++I )
    Args.push_back(I->c_str());
  Args.push_back(inputFilename.c_str());
  for (unsigned i = 0; i < NumExtraArgs; ++i)
    Args.push_back(*ExtraArgs);
  Args.push_back(0);

  DEBUG(errs() << "\nAbout to run:\t";
        for (unsigned i = 0, e = Args.size()-1; i != e; ++i)
          errs() << " " << Args[i];
        errs() << "\n";
        );

  sys::Path prog;
  if (UseValgrind)
    prog = sys::Program::FindProgramByName("valgrind");
  else
    prog = tool;

  // Redirect stdout and stderr to nowhere if SilencePasses is given
  sys::Path Nowhere;
  const sys::Path *Redirects[3] = {0, &Nowhere, &Nowhere};

  int result = sys::Program::ExecuteAndWait(prog, Args.data(), 0,
                                            (SilencePasses ? Redirects : 0),
                                            Timeout, MemoryLimit, &ErrMsg);

  // If we are supposed to delete the bitcode file or if the passes crashed,
  // remove it now.  This may fail if the file was never created, but that's ok.
  if (DeleteOutput || result != 0)
    sys::Path(OutputFilename).eraseFromDisk();

  // Remove the temporary input file as well
  inputFilename.eraseFromDisk();

  if (!Quiet) {
    if (result == 0)
      outs() << "Success!\n";
    else if (result > 0)
      outs() << "Exited with error code '" << result << "'\n";
    else if (result < 0) {
      if (result == -1)
        outs() << "Execute failed: " << ErrMsg << "\n";
      else
        outs() << "Crashed with signal #" << abs(result) << "\n";
    }
    if (result & 0x01000000)
      outs() << "Dumped core\n";
  }

  // Was the child successful?
  return result != 0;
}

/// runPassesOn - Carefully run the specified set of pass on the specified
/// module, returning the transformed module on success, or a null pointer on
/// failure.
Module *BugDriver::runPassesOn(Module *M,
                               const std::vector<std::string> &Passes,
                               bool AutoDebugCrashes, unsigned NumExtraArgs,
                               const char * const *ExtraArgs) {
  std::string BitcodeResult;
  if (runPasses(M, Passes, BitcodeResult, false/*delete*/, true/*quiet*/,
                NumExtraArgs, ExtraArgs)) {
    if (AutoDebugCrashes) {
      errs() << " Error running this sequence of passes"
             << " on the input program!\n";
      delete swapProgramIn(M);
      EmitProgressBitcode(M, "pass-error",  false);
      exit(debugOptimizerCrash());
    }
    return 0;
  }

  Module *Ret = ParseInputFile(BitcodeResult, Context);
  if (Ret == 0) {
    errs() << getToolName() << ": Error reading bitcode file '"
           << BitcodeResult << "'!\n";
    exit(1);
  }
  sys::Path(BitcodeResult).eraseFromDisk();  // No longer need the file on disk
  return Ret;
}
<commit_msg>fit in 80 cols.<commit_after>//===- OptimizerDriver.cpp - Allow BugPoint to run passes safely ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an interface that allows bugpoint to run various passes
// without the threat of a buggy pass corrupting bugpoint (of course, bugpoint
// may have its own bugs, but that's another story...).  It achieves this by
// forking a copy of itself and having the child process do the optimizations.
// If this client dies, we can always fork a new one.  :)
//
//===----------------------------------------------------------------------===//

#include "BugDriver.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"

#define DONT_GET_PLUGIN_LOADER_OPTION
#include "llvm/Support/PluginLoader.h"

#include <fstream>
using namespace llvm;

namespace llvm {
  extern cl::opt<std::string> OutputPrefix;
}

namespace {
  // ChildOutput - This option captures the name of the child output file that
  // is set up by the parent bugpoint process
  cl::opt<std::string> ChildOutput("child-output", cl::ReallyHidden);
}

/// writeProgramToFile - This writes the current "Program" to the named bitcode
/// file.  If an error occurs, true is returned.
///
bool BugDriver::writeProgramToFile(const std::string &Filename,
                                   const Module *M) const {
  std::string ErrInfo;
  tool_output_file Out(Filename.c_str(), ErrInfo,
                       raw_fd_ostream::F_Binary);
  if (ErrInfo.empty()) {
    WriteBitcodeToFile(M, Out.os());
    Out.os().close();
    if (!Out.os().has_error()) {
      Out.keep();
      return false;
    }
  }
  Out.os().clear_error();
  return true;
}

/// EmitProgressBitcode - This function is used to output the current Program
/// to a file named "bugpoint-ID.bc".
///
void BugDriver::EmitProgressBitcode(const Module *M,
                                    const std::string &ID,
                                    bool NoFlyer)  const {
  // Output the input to the current pass to a bitcode file, emit a message
  // telling the user how to reproduce it: opt -foo blah.bc
  //
  std::string Filename = OutputPrefix + "-" + ID + ".bc";
  if (writeProgramToFile(Filename, M)) {
    errs() <<  "Error opening file '" << Filename << "' for writing!\n";
    return;
  }

  outs() << "Emitted bitcode to '" << Filename << "'\n";
  if (NoFlyer || PassesToRun.empty()) return;
  outs() << "\n*** You can reproduce the problem with: ";
  if (UseValgrind) outs() << "valgrind ";
  outs() << "opt " << Filename << " ";
  outs() << getPassesString(PassesToRun) << "\n";
}

cl::opt<bool> SilencePasses("silence-passes",
        cl::desc("Suppress output of running passes (both stdout and stderr)"));

static cl::list<std::string> OptArgs("opt-args", cl::Positional,
                                     cl::desc("<opt arguments>..."),
                                     cl::ZeroOrMore, cl::PositionalEatsArgs);

/// runPasses - Run the specified passes on Program, outputting a bitcode file
/// and writing the filename into OutputFile if successful.  If the
/// optimizations fail for some reason (optimizer crashes), return true,
/// otherwise return false.  If DeleteOutput is set to true, the bitcode is
/// deleted on success, and the filename string is undefined.  This prints to
/// outs() a single line message indicating whether compilation was successful
/// or failed.
///
bool BugDriver::runPasses(Module *Program,
                          const std::vector<std::string> &Passes,
                          std::string &OutputFilename, bool DeleteOutput,
                          bool Quiet, unsigned NumExtraArgs,
                          const char * const *ExtraArgs) const {
  // setup the output file name
  outs().flush();
  sys::Path uniqueFilename(OutputPrefix + "-output.bc");
  std::string ErrMsg;
  if (uniqueFilename.makeUnique(true, &ErrMsg)) {
    errs() << getToolName() << ": Error making unique filename: "
           << ErrMsg << "\n";
    return(1);
  }
  OutputFilename = uniqueFilename.str();

  // set up the input file name
  sys::Path inputFilename(OutputPrefix + "-input.bc");
  if (inputFilename.makeUnique(true, &ErrMsg)) {
    errs() << getToolName() << ": Error making unique filename: "
           << ErrMsg << "\n";
    return(1);
  }

  std::string ErrInfo;
  tool_output_file InFile(inputFilename.c_str(), ErrInfo,
                          raw_fd_ostream::F_Binary);

  if (!ErrInfo.empty()) {
    errs() << "Error opening bitcode file: " << inputFilename.str() << "\n";
    return 1;
  }
  WriteBitcodeToFile(Program, InFile.os());
  InFile.os().close();
  if (InFile.os().has_error()) {
    errs() << "Error writing bitcode file: " << inputFilename.str() << "\n";
    InFile.os().clear_error();
    return 1;
  }

  sys::Path tool = PrependMainExecutablePath("opt", getToolName(),
                                             (void*)"opt");
  if (tool.empty()) {
    errs() << "Cannot find `opt' in executable directory!\n";
    return 1;
  }

  // Ok, everything that could go wrong before running opt is done.
  InFile.keep();

  // setup the child process' arguments
  SmallVector<const char*, 8> Args;
  std::string Opt = tool.str();
  if (UseValgrind) {
    Args.push_back("valgrind");
    Args.push_back("--error-exitcode=1");
    Args.push_back("-q");
    Args.push_back(tool.c_str());
  } else
    Args.push_back(Opt.c_str());

  Args.push_back("-o");
  Args.push_back(OutputFilename.c_str());
  for (unsigned i = 0, e = OptArgs.size(); i != e; ++i)
    Args.push_back(OptArgs[i].c_str());
  std::vector<std::string> pass_args;
  for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) {
    pass_args.push_back( std::string("-load"));
    pass_args.push_back( PluginLoader::getPlugin(i));
  }
  for (std::vector<std::string>::const_iterator I = Passes.begin(),
       E = Passes.end(); I != E; ++I )
    pass_args.push_back( std::string("-") + (*I) );
  for (std::vector<std::string>::const_iterator I = pass_args.begin(),
       E = pass_args.end(); I != E; ++I )
    Args.push_back(I->c_str());
  Args.push_back(inputFilename.c_str());
  for (unsigned i = 0; i < NumExtraArgs; ++i)
    Args.push_back(*ExtraArgs);
  Args.push_back(0);

  DEBUG(errs() << "\nAbout to run:\t";
        for (unsigned i = 0, e = Args.size()-1; i != e; ++i)
          errs() << " " << Args[i];
        errs() << "\n";
        );

  sys::Path prog;
  if (UseValgrind)
    prog = sys::Program::FindProgramByName("valgrind");
  else
    prog = tool;

  // Redirect stdout and stderr to nowhere if SilencePasses is given
  sys::Path Nowhere;
  const sys::Path *Redirects[3] = {0, &Nowhere, &Nowhere};

  int result = sys::Program::ExecuteAndWait(prog, Args.data(), 0,
                                            (SilencePasses ? Redirects : 0),
                                            Timeout, MemoryLimit, &ErrMsg);

  // If we are supposed to delete the bitcode file or if the passes crashed,
  // remove it now.  This may fail if the file was never created, but that's ok.
  if (DeleteOutput || result != 0)
    sys::Path(OutputFilename).eraseFromDisk();

  // Remove the temporary input file as well
  inputFilename.eraseFromDisk();

  if (!Quiet) {
    if (result == 0)
      outs() << "Success!\n";
    else if (result > 0)
      outs() << "Exited with error code '" << result << "'\n";
    else if (result < 0) {
      if (result == -1)
        outs() << "Execute failed: " << ErrMsg << "\n";
      else
        outs() << "Crashed with signal #" << abs(result) << "\n";
    }
    if (result & 0x01000000)
      outs() << "Dumped core\n";
  }

  // Was the child successful?
  return result != 0;
}

/// runPassesOn - Carefully run the specified set of pass on the specified
/// module, returning the transformed module on success, or a null pointer on
/// failure.
Module *BugDriver::runPassesOn(Module *M,
                               const std::vector<std::string> &Passes,
                               bool AutoDebugCrashes, unsigned NumExtraArgs,
                               const char * const *ExtraArgs) {
  std::string BitcodeResult;
  if (runPasses(M, Passes, BitcodeResult, false/*delete*/, true/*quiet*/,
                NumExtraArgs, ExtraArgs)) {
    if (AutoDebugCrashes) {
      errs() << " Error running this sequence of passes"
             << " on the input program!\n";
      delete swapProgramIn(M);
      EmitProgressBitcode(M, "pass-error",  false);
      exit(debugOptimizerCrash());
    }
    return 0;
  }

  Module *Ret = ParseInputFile(BitcodeResult, Context);
  if (Ret == 0) {
    errs() << getToolName() << ": Error reading bitcode file '"
           << BitcodeResult << "'!\n";
    exit(1);
  }
  sys::Path(BitcodeResult).eraseFromDisk();  // No longer need the file on disk
  return Ret;
}
<|endoftext|>