<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef UTILITY_HXX
#define UTILITY_HXX

#include <sfx2/minarray.hxx>
#include <vcl/font.hxx>
#include <vcl/fixed.hxx>
#include <vcl/combobox.hxx>
#include <vcl/lstbox.hxx>
#include <tools/fract.hxx>

class SmRect;
class String;

#define C2S(cChar) String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(cChar))

/////////////////////////////////////////////////////////////////

const ByteString    ExportString( const String& rString );
const String        ImportString( const ByteString& rByteString );

/////////////////////////////////////////////////////////////////

inline long SmPtsTo100th_mm(long nNumPts)
    // returns the length (in 100th of mm) that corresponds to the length
    // 'nNumPts' (in units points).
    // 72.27 [pt] = 1 [inch] = 2,54 [cm] = 2540 [100th of mm].
    // result is being rounded to the nearest integer.
{
    DBG_ASSERT(nNumPts >= 0, "Sm : Ooops...");
    // broken into multiple and fraction of 'nNumPts' to reduce chance
    // of overflow
    // (7227 / 2) is added in order to round to the nearest integer
    return 35 * nNumPts + (nNumPts * 1055L + (7227 / 2)) / 7227L;
}

inline long SmPtsTo100th_mm(const Fraction &rNumPts)
    // as above but with argument 'rNumPts' as 'Fraction'
{
    Fraction  aTmp (254000L, 7227L);
    return aTmp *= rNumPts;
}

inline Fraction Sm100th_mmToPts(long nNum100th_mm)
    // returns the length (in points) that corresponds to the length
    // 'nNum100th_mm' (in 100th of mm).
{
    DBG_ASSERT(nNum100th_mm >= 0, "Sm : Ooops...");
    Fraction  aTmp (7227L, 254000L);
    return aTmp *= Fraction(nNum100th_mm);
}

inline long SmRoundFraction(const Fraction &rFrac)
{
    DBG_ASSERT(rFrac > Fraction(), "Sm : Ooops...");
    return (rFrac.GetNumerator() + rFrac.GetDenominator() / 2) / rFrac.GetDenominator();
}

class SmViewShell;
SmViewShell * SmGetActiveView();

////////////////////////////////////////////////////////////
//
// SmFace
//

bool    IsItalic( const Font &rFont );
bool    IsBold( const Font &rFont );

class SmFace : public Font
{
    long    nBorderWidth;

    void    Impl_Init();

public:
    SmFace() :
        Font(), nBorderWidth(-1) { Impl_Init(); }
    SmFace(const Font& rFont) :
        Font(rFont), nBorderWidth(-1) { Impl_Init(); }
    SmFace(const String& rName, const Size& rSize) :
        Font(rName, rSize), nBorderWidth(-1) { Impl_Init(); }
    SmFace( FontFamily eFamily, const Size& rSize) :
        Font(eFamily, rSize), nBorderWidth(-1) { Impl_Init(); }

    SmFace(const SmFace &rFace) :
        Font(rFace), nBorderWidth(-1) { Impl_Init(); }

    // overloaded version in order to supply a min value
    // for font size (height). (Also used in ctor's to do so.)
    void    SetSize(const Size& rSize);

    void    SetBorderWidth(long nWidth)     { nBorderWidth = nWidth; }
    long    GetBorderWidth() const;
    long    GetDefaultBorderWidth() const   { return GetSize().Height() / 20 ; }
    void    FreezeBorderWidth()     { nBorderWidth = GetDefaultBorderWidth(); }

    SmFace & operator = (const SmFace &rFace);
};

SmFace & operator *= (SmFace &rFace, const Fraction &rFrac);

#ifdef NEVER
////////////////////////////////////////////////////////////
//
// SmInfoText
//

class SmInfoText : public FixedText
{
protected:
    USHORT  nMaxLen;
    String  aText;

public:
    SmInfoText(Window* pParent, WinBits nWinStyle = 0, USHORT nMax = 128);
    SmInfoText(Window* pParent, const ResId& rResId, USHORT nMax = 128);

    void    SetText(const String& rStr);

    XubString GetText() const { return (aText); }
};
#endif

////////////////////////////////////////////////////////////
//
// SmPickList
//

class SmPickList : public SfxPtrArr
{
protected:
    USHORT  nSize;

    virtual void   *CreateItem(const String& rString) = 0;
    virtual void   *CreateItem(const void *pItem) = 0;
    virtual void    DestroyItem(void *pItem) = 0;

    virtual bool    CompareItem(const void *pFirstItem, const void *pSecondItem) const = 0;

    virtual String  GetStringItem(void *pItem) = 0;

    void       *GetPtr(USHORT nPos) const { return SfxPtrArr::GetObject(nPos); }
    void      *&GetPtr(USHORT nPos) { return SfxPtrArr::GetObject(nPos); }
    void        InsertPtr(USHORT nPos, void *pItem) { SfxPtrArr::Insert(nPos, pItem); }
    void        RemovePtr(USHORT nPos, USHORT nCount = 1) { SfxPtrArr::Remove(nPos, nCount); }

public:
    SmPickList(USHORT nInitSize = 0, USHORT nMaxSize = 5);
    virtual ~SmPickList();

    SmPickList&   operator = (const SmPickList& rList);

    void       *Get(USHORT nPos = 0) const { return GetPtr(nPos); }
    using   SfxPtrArr::Insert;
    void        Insert(const void* pItem);
    void        Update(const void* pItem, const void *pNewItem);
    using   SfxPtrArr::Remove;
    void        Remove(const void* pItem);

    using   SfxPtrArr::operator [];
    void       *operator [] (USHORT nPos) const { return GetPtr(nPos); }

    USHORT      GetSize() const { return nSize; }
    USHORT      Count() const { return SfxPtrArr::Count(); }

    void        Clear();
};

////////////////////////////////////////////////////////////
//
// SmStringPickList
//
#ifdef NEVER
class SmStringPickList : public SmPickList
{
protected:
    virtual void   *CreateItem(const String& rString);
    virtual void   *CreateItem(const void *pItem);
    virtual void    DestroyItem(void *pItem);

    virtual bool    CompareItem(const void *pFirstItem, const void *pSecondItem) const;

    virtual String  GetStringItem(void *pItem);

public:
    SmStringPickList()
        : SmPickList(0, 5) {}
    SmStringPickList(USHORT nInitSize, USHORT nMaxSize)
        : SmPickList(nInitSize, nMaxSize) {}
    SmStringPickList(const SmPickList& rOrig )
        : SmPickList(rOrig) {}
    virtual ~SmStringPickList() { Clear(); }

    virtual void    Insert(const String &rString);
    virtual void    Update(const String &rString, const String &rNewString);
    virtual void    Remove(const String &rString);

    inline bool     Contains(const String &rString) const;
    inline String   Get(USHORT nPos = 0) const;

    inline SmStringPickList& operator = (const SmStringPickList& rList);
    inline String            operator [] (USHORT nPos) const;
};

inline SmStringPickList& SmStringPickList::operator = (const SmStringPickList& rList)
{
    *(SmPickList *)this = *(SmPickList *)&rList; return *this;
}

inline String SmStringPickList::operator [] (USHORT nPos) const
{
    return *((String *)SmPickList::operator[](nPos));
}

inline String SmStringPickList::Get(USHORT nPos) const
{
    return nPos < Count() ? *((String *)SmPickList::Get(nPos)) : String();
}

inline bool SmStringPickList::Contains(const String &rString) const
{
    return SmPickList::Contains((void *)&rString);
}
#endif

////////////////////////////////////////////////////////////
//
// SmFontPickList
//

class SmFontDialog;

class SmFontPickList : public SmPickList
{
protected:
    virtual void   *CreateItem(const String& rString);
    virtual void   *CreateItem(const void *pItem);
    virtual void    DestroyItem(void *pItem);

    virtual bool    CompareItem(const void *pFirstItem, const void *pSecondItem) const;

    virtual String  GetStringItem(void *pItem);

public:
    SmFontPickList()
        : SmPickList(0, 5) {}
    SmFontPickList(USHORT nInitSize, USHORT nMaxSize)
        : SmPickList(nInitSize, nMaxSize) {}
    SmFontPickList(const SmPickList& rOrig )
        : SmPickList(rOrig) {}
    virtual ~SmFontPickList() { Clear(); }

    using   SfxPtrArr::Insert;
    virtual void    Insert(const Font &rFont);
    using   SmPickList::Update;
    virtual void    Update(const Font &rFont, const Font &rNewFont);
    using   SfxPtrArr::Remove;
    virtual void    Remove(const Font &rFont);

    using   SmPickList::Contains;
    inline bool     Contains(const Font &rFont) const;
    inline Font     Get(USHORT nPos = 0) const;

    inline SmFontPickList&  operator = (const SmFontPickList& rList);
    using   SfxPtrArr::operator [];
    inline Font             operator [] (USHORT nPos) const;

    void            ReadFrom(const SmFontDialog& rDialog);
    void            WriteTo(SmFontDialog& rDialog) const;
};

inline SmFontPickList& SmFontPickList::operator = (const SmFontPickList& rList)
{
    *(SmPickList *)this = *(SmPickList *)&rList; return *this;
}

inline Font SmFontPickList::operator [] (USHORT nPos) const
{
    return *((Font *)SmPickList::operator[](nPos));
}

inline Font SmFontPickList::Get(USHORT nPos) const
{
    return nPos < Count() ? *((Font *)SmPickList::Get(nPos)) : Font();
}

inline bool SmFontPickList::Contains(const Font &rFont) const
{
    return SmPickList::Contains((void *)&rFont);
}

////////////////////////////////////////////////////////////
//
// SmStringPickComboBox
//
#ifdef NEVER
class SmStringPickComboBox : public SmStringPickList, public ComboBox
{
protected:
    virtual void LoseFocus();

    DECL_LINK(SelectHdl, ComboBox *);

public:
    SmStringPickComboBox(Window* pParent, WinBits nWinStyle = 0, USHORT nMax = 4);
    SmStringPickComboBox(Window* pParent, const ResId& rResId, USHORT nMax = 4);

    SmStringPickComboBox& operator = (const SmStringPickList& rList);

    void            SetText(const String& rStr);

    virtual void    Insert(const String &rString);
    virtual void    Update(const String &rString, const String &rNewString);
    virtual void    Remove(const String &rString);
};
#endif

////////////////////////////////////////////////////////////
//
//  SmFontPickListBox
//

class SmFontPickListBox : public SmFontPickList, public ListBox
{
protected:
    DECL_LINK(SelectHdl, ListBox *);

public:
    SmFontPickListBox(Window* pParent, const ResId& rResId, USHORT nMax = 4);

    SmFontPickListBox& operator = (const SmFontPickList& rList);

    using   SfxPtrArr::Insert;
    virtual void    Insert(const Font &rFont);
    using   Window::Update;
    virtual void    Update(const Font &rFont, const Font &rNewFont);
    using   SfxPtrArr::Remove;
    virtual void    Remove(const Font &rFont);
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Remove NEVER<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef UTILITY_HXX
#define UTILITY_HXX

#include <sfx2/minarray.hxx>
#include <vcl/font.hxx>
#include <vcl/fixed.hxx>
#include <vcl/combobox.hxx>
#include <vcl/lstbox.hxx>
#include <tools/fract.hxx>

class SmRect;
class String;

#define C2S(cChar) String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(cChar))

/////////////////////////////////////////////////////////////////

const ByteString    ExportString( const String& rString );
const String        ImportString( const ByteString& rByteString );

/////////////////////////////////////////////////////////////////

inline long SmPtsTo100th_mm(long nNumPts)
    // returns the length (in 100th of mm) that corresponds to the length
    // 'nNumPts' (in units points).
    // 72.27 [pt] = 1 [inch] = 2,54 [cm] = 2540 [100th of mm].
    // result is being rounded to the nearest integer.
{
    DBG_ASSERT(nNumPts >= 0, "Sm : Ooops...");
    // broken into multiple and fraction of 'nNumPts' to reduce chance
    // of overflow
    // (7227 / 2) is added in order to round to the nearest integer
    return 35 * nNumPts + (nNumPts * 1055L + (7227 / 2)) / 7227L;
}

inline long SmPtsTo100th_mm(const Fraction &rNumPts)
    // as above but with argument 'rNumPts' as 'Fraction'
{
    Fraction  aTmp (254000L, 7227L);
    return aTmp *= rNumPts;
}

inline Fraction Sm100th_mmToPts(long nNum100th_mm)
    // returns the length (in points) that corresponds to the length
    // 'nNum100th_mm' (in 100th of mm).
{
    DBG_ASSERT(nNum100th_mm >= 0, "Sm : Ooops...");
    Fraction  aTmp (7227L, 254000L);
    return aTmp *= Fraction(nNum100th_mm);
}

inline long SmRoundFraction(const Fraction &rFrac)
{
    DBG_ASSERT(rFrac > Fraction(), "Sm : Ooops...");
    return (rFrac.GetNumerator() + rFrac.GetDenominator() / 2) / rFrac.GetDenominator();
}

class SmViewShell;
SmViewShell * SmGetActiveView();

////////////////////////////////////////////////////////////
//
// SmFace
//

bool    IsItalic( const Font &rFont );
bool    IsBold( const Font &rFont );

class SmFace : public Font
{
    long    nBorderWidth;

    void    Impl_Init();

public:
    SmFace() :
        Font(), nBorderWidth(-1) { Impl_Init(); }
    SmFace(const Font& rFont) :
        Font(rFont), nBorderWidth(-1) { Impl_Init(); }
    SmFace(const String& rName, const Size& rSize) :
        Font(rName, rSize), nBorderWidth(-1) { Impl_Init(); }
    SmFace( FontFamily eFamily, const Size& rSize) :
        Font(eFamily, rSize), nBorderWidth(-1) { Impl_Init(); }

    SmFace(const SmFace &rFace) :
        Font(rFace), nBorderWidth(-1) { Impl_Init(); }

    // overloaded version in order to supply a min value
    // for font size (height). (Also used in ctor's to do so.)
    void    SetSize(const Size& rSize);

    void    SetBorderWidth(long nWidth)     { nBorderWidth = nWidth; }
    long    GetBorderWidth() const;
    long    GetDefaultBorderWidth() const   { return GetSize().Height() / 20 ; }
    void    FreezeBorderWidth()     { nBorderWidth = GetDefaultBorderWidth(); }

    SmFace & operator = (const SmFace &rFace);
};

SmFace & operator *= (SmFace &rFace, const Fraction &rFrac);

////////////////////////////////////////////////////////////
//
// SmPickList
//

class SmPickList : public SfxPtrArr
{
protected:
    USHORT  nSize;

    virtual void   *CreateItem(const String& rString) = 0;
    virtual void   *CreateItem(const void *pItem) = 0;
    virtual void    DestroyItem(void *pItem) = 0;

    virtual bool    CompareItem(const void *pFirstItem, const void *pSecondItem) const = 0;

    virtual String  GetStringItem(void *pItem) = 0;

    void       *GetPtr(USHORT nPos) const { return SfxPtrArr::GetObject(nPos); }
    void      *&GetPtr(USHORT nPos) { return SfxPtrArr::GetObject(nPos); }
    void        InsertPtr(USHORT nPos, void *pItem) { SfxPtrArr::Insert(nPos, pItem); }
    void        RemovePtr(USHORT nPos, USHORT nCount = 1) { SfxPtrArr::Remove(nPos, nCount); }

public:
    SmPickList(USHORT nInitSize = 0, USHORT nMaxSize = 5);
    virtual ~SmPickList();

    SmPickList&   operator = (const SmPickList& rList);

    void       *Get(USHORT nPos = 0) const { return GetPtr(nPos); }
    using   SfxPtrArr::Insert;
    void        Insert(const void* pItem);
    void        Update(const void* pItem, const void *pNewItem);
    using   SfxPtrArr::Remove;
    void        Remove(const void* pItem);

    using   SfxPtrArr::operator [];
    void       *operator [] (USHORT nPos) const { return GetPtr(nPos); }

    USHORT      GetSize() const { return nSize; }
    USHORT      Count() const { return SfxPtrArr::Count(); }

    void        Clear();
};

////////////////////////////////////////////////////////////
//
// SmFontPickList
//

class SmFontDialog;

class SmFontPickList : public SmPickList
{
protected:
    virtual void   *CreateItem(const String& rString);
    virtual void   *CreateItem(const void *pItem);
    virtual void    DestroyItem(void *pItem);

    virtual bool    CompareItem(const void *pFirstItem, const void *pSecondItem) const;

    virtual String  GetStringItem(void *pItem);

public:
    SmFontPickList()
        : SmPickList(0, 5) {}
    SmFontPickList(USHORT nInitSize, USHORT nMaxSize)
        : SmPickList(nInitSize, nMaxSize) {}
    SmFontPickList(const SmPickList& rOrig )
        : SmPickList(rOrig) {}
    virtual ~SmFontPickList() { Clear(); }

    using   SfxPtrArr::Insert;
    virtual void    Insert(const Font &rFont);
    using   SmPickList::Update;
    virtual void    Update(const Font &rFont, const Font &rNewFont);
    using   SfxPtrArr::Remove;
    virtual void    Remove(const Font &rFont);

    using   SmPickList::Contains;
    inline bool     Contains(const Font &rFont) const;
    inline Font     Get(USHORT nPos = 0) const;

    inline SmFontPickList&  operator = (const SmFontPickList& rList);
    using   SfxPtrArr::operator [];
    inline Font             operator [] (USHORT nPos) const;

    void            ReadFrom(const SmFontDialog& rDialog);
    void            WriteTo(SmFontDialog& rDialog) const;
};

inline SmFontPickList& SmFontPickList::operator = (const SmFontPickList& rList)
{
    *(SmPickList *)this = *(SmPickList *)&rList; return *this;
}

inline Font SmFontPickList::operator [] (USHORT nPos) const
{
    return *((Font *)SmPickList::operator[](nPos));
}

inline Font SmFontPickList::Get(USHORT nPos) const
{
    return nPos < Count() ? *((Font *)SmPickList::Get(nPos)) : Font();
}

inline bool SmFontPickList::Contains(const Font &rFont) const
{
    return SmPickList::Contains((void *)&rFont);
}

////////////////////////////////////////////////////////////
//
//  SmFontPickListBox
//

class SmFontPickListBox : public SmFontPickList, public ListBox
{
protected:
    DECL_LINK(SelectHdl, ListBox *);

public:
    SmFontPickListBox(Window* pParent, const ResId& rResId, USHORT nMax = 4);

    SmFontPickListBox& operator = (const SmFontPickList& rList);

    using   SfxPtrArr::Insert;
    virtual void    Insert(const Font &rFont);
    using   Window::Update;
    virtual void    Update(const Font &rFont, const Font &rNewFont);
    using   SfxPtrArr::Remove;
    virtual void    Remove(const Font &rFont);
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>// Copyright (c) 2010 Chris Pickel <sfiera@gmail.com>
//
// This file is part of libsfz, a free software project.  You can redistribute it and/or modify it
// under the terms of the MIT License.

#include "sfz/Os.hpp"

#include <fcntl.h>
#include <fts.h>
#include "sfz/Encoding.hpp"
#include "sfz/Exception.hpp"
#include "sfz/Format.hpp"
#include "sfz/PosixFormatter.hpp"

namespace sfz {

namespace path {

bool exists(const StringPiece& path) {
    CString c_str(path);
    Stat st;
    return (stat(c_str.data(), &st) == 0);
}

bool isdir(const StringPiece& path) {
    CString c_str(path);
    Stat st;
    return (stat(c_str.data(), &st) == 0) && ((st.st_mode & S_IFMT) == S_IFDIR);
}

bool isfile(const StringPiece& path) {
    CString c_str(path);
    Stat st;
    return (stat(c_str.data(), &st) == 0) && ((st.st_mode & S_IFMT) == S_IFREG);
}

bool islink(const StringPiece& path) {
    CString c_str(path);
    Stat st;
    return (lstat(c_str.data(), &st) == 0) && ((st.st_mode & S_IFMT) == S_IFLNK);
}

StringPiece basename(const StringPiece& path) {
    if (path == "/") {
        return path;
    }
    size_t pos = path.rfind('/', path.size() - 1);
    if (pos == StringPiece::npos) {
        return path;
    } else if (pos == path.size() - 1) {
        return basename(path.substr(0, path.size() - 1));
    } else {
        return path.substr(pos + 1);
    }
}

StringPiece dirname(const StringPiece& path) {
    size_t pos = path.rfind('/', path.size() - 1);
    if (pos == 0) {
        return "/";
    } else if (pos == StringPiece::npos) {
        return ".";
    } else if (pos == path.size() - 1) {
        return dirname(path.substr(0, path.size() - 1));
    } else {
        return path.substr(0, pos);
    }
}

}  // namespace path

void chdir(const StringPiece& path) {
    CString c_str(path);
    if (::chdir(c_str.data()) < 0) {
        throw Exception(format("chdir: {0}", posix_strerror()));
    }
}

void symlink(const StringPiece& content, const StringPiece& container) {
    CString content_c_str(content);
    CString container_c_str(container);
    if (::symlink(content_c_str.data(), container_c_str.data()) < 0) {
        throw Exception(format("symlink: {0}", posix_strerror()));
    }
}

int open(const StringPiece& path, int oflag, mode_t mode) {
    CString c_str(path);
    int fd = ::open(c_str.data(), oflag, mode);
    if (fd < 0) {
        throw Exception(format("open: {0}", posix_strerror()));
    }
    return fd;
}

void mkdir(const StringPiece& path, mode_t mode) {
    CString c_str(path);
    if (::mkdir(c_str.data(), mode) != 0) {
        throw Exception(format("mkdir: {0}", posix_strerror()));
    }
}

void mkfifo(const StringPiece& path, mode_t mode) {
    CString c_str(path);
    if (::mkfifo(c_str.data(), mode) != 0) {
        throw Exception(format("mkfifo: {0}", posix_strerror()));
    }
}

void makedirs(const StringPiece& path, mode_t mode) {
    if (!path::isdir(path)) {
        makedirs(path::dirname(path), mode);
        mkdir(path, mode);
    }
}

void unlink(const StringPiece& path) {
    CString c_str(path);
    if (::unlink(c_str.data()) < 0) {
        throw Exception(format("unlink: {0}", posix_strerror()));
    }
}

void rmdir(const StringPiece& path) {
    CString c_str(path);
    if (::rmdir(c_str.data()) < 0) {
        throw Exception(format("rmdir: {0}", posix_strerror()));
    }
}

void rmtree(const StringPiece& path) {
    if (path::exists(path)) {
        class RmtreeVisitor : public TreeWalker {
          public:
            void pre_directory(    const StringPiece& path, const Stat&) { }
            void cycle_directory(  const StringPiece& path, const Stat&) { }

            void post_directory(   const StringPiece& path, const Stat&) { rmdir(path); }

            void file(             const StringPiece& path, const Stat&) { unlink(path); }
            void symlink(          const StringPiece& path, const Stat&) { unlink(path); }
            void broken_symlink(   const StringPiece& path, const Stat&) { unlink(path); }
            void other(            const StringPiece& path, const Stat&) { unlink(path); }
        };
        RmtreeVisitor visitor;
        walk(path, WALK_PHYSICAL, &visitor);
    }
}

TemporaryDirectory::TemporaryDirectory(const StringPiece& prefix) {
    String str(format("/tmp/{0}XXXXXX", prefix));
    CString c_str(str);
    mkdtemp(c_str.mutable_data());
    _path.assign(utf8::decode(c_str.data()));
}

TemporaryDirectory::~TemporaryDirectory() {
    rmtree(_path);
}

const String& TemporaryDirectory::path() const {
    return _path;
}

namespace {

class FtsCloser {
  public:
    FtsCloser(FTS* fts) : _fts(fts) { }
    ~FtsCloser() { fts_close(_fts); }
  private:
    FTS* _fts;
    DISALLOW_COPY_AND_ASSIGN(FtsCloser);
};

int compare_ftsent(const FTSENT** lhs, const FTSENT** rhs) {
    return strcmp((*lhs)->fts_name, (*rhs)->fts_name);
}

}  // namespace

void walk(const StringPiece& root, WalkType type, TreeWalker* visitor) {
    CString c_str(root);
    char* const pathv[] = { c_str.mutable_data(), NULL };
    int options = FTS_NOCHDIR;
    if (type == WALK_PHYSICAL) {
        options |= FTS_PHYSICAL;
    } else {
        options |= FTS_LOGICAL;
    }

    FTS* fts = fts_open(pathv, options, compare_ftsent);
    if (fts == NULL) {
        throw Exception(format("fts_open: {0}", posix_strerror()));
    }
    FtsCloser deleter(fts);
    while (FTSENT* ent = fts_read(fts)) {
        String path(utf8::decode(ent->fts_path));
        const Stat& st = *ent->fts_statp;
        switch (ent->fts_info) {
          case FTS_D:        visitor->pre_directory(    path, st); break;
          case FTS_DC:       visitor->cycle_directory(  path, st); break;
          case FTS_DEFAULT:  visitor->other(            path, st); break;
          case FTS_DP:       visitor->post_directory(   path, st); break;
          case FTS_F:        visitor->file(             path, st); break;
          case FTS_SL:       visitor->symlink(          path, st); break;
          case FTS_SLNONE:   visitor->broken_symlink(   path, st); break;

          case FTS_DNR:
          case FTS_ERR:
          case FTS_NS:
            throw Exception(format("fts_read: {0}", posix_strerror(ent->fts_errno)));

          case FTS_DOT:
          case FTS_NSOK:
          default:
            throw Exception(format("walk: got invalid type {0}", ent->fts_info));
        }
    }
}

TreeWalker::~TreeWalker() { }

}  // namespace sfz
<commit_msg>Include path in Os.cpp exceptions.<commit_after>// Copyright (c) 2010 Chris Pickel <sfiera@gmail.com>
//
// This file is part of libsfz, a free software project.  You can redistribute it and/or modify it
// under the terms of the MIT License.

#include "sfz/Os.hpp"

#include <fcntl.h>
#include <fts.h>
#include "sfz/Encoding.hpp"
#include "sfz/Exception.hpp"
#include "sfz/Format.hpp"
#include "sfz/PosixFormatter.hpp"

namespace sfz {

namespace path {

bool exists(const StringPiece& path) {
    CString c_str(path);
    Stat st;
    return (stat(c_str.data(), &st) == 0);
}

bool isdir(const StringPiece& path) {
    CString c_str(path);
    Stat st;
    return (stat(c_str.data(), &st) == 0) && ((st.st_mode & S_IFMT) == S_IFDIR);
}

bool isfile(const StringPiece& path) {
    CString c_str(path);
    Stat st;
    return (stat(c_str.data(), &st) == 0) && ((st.st_mode & S_IFMT) == S_IFREG);
}

bool islink(const StringPiece& path) {
    CString c_str(path);
    Stat st;
    return (lstat(c_str.data(), &st) == 0) && ((st.st_mode & S_IFMT) == S_IFLNK);
}

StringPiece basename(const StringPiece& path) {
    if (path == "/") {
        return path;
    }
    size_t pos = path.rfind('/', path.size() - 1);
    if (pos == StringPiece::npos) {
        return path;
    } else if (pos == path.size() - 1) {
        return basename(path.substr(0, path.size() - 1));
    } else {
        return path.substr(pos + 1);
    }
}

StringPiece dirname(const StringPiece& path) {
    size_t pos = path.rfind('/', path.size() - 1);
    if (pos == 0) {
        return "/";
    } else if (pos == StringPiece::npos) {
        return ".";
    } else if (pos == path.size() - 1) {
        return dirname(path.substr(0, path.size() - 1));
    } else {
        return path.substr(0, pos);
    }
}

}  // namespace path

void chdir(const StringPiece& path) {
    CString c_str(path);
    if (::chdir(c_str.data()) < 0) {
        throw Exception(format("chdir: {0}: {1}", path, posix_strerror()));
    }
}

void symlink(const StringPiece& content, const StringPiece& container) {
    CString content_c_str(content);
    CString container_c_str(container);
    if (::symlink(content_c_str.data(), container_c_str.data()) < 0) {
        throw Exception(format("symlink: {0}: {1}", container, posix_strerror()));
    }
}

int open(const StringPiece& path, int oflag, mode_t mode) {
    CString c_str(path);
    int fd = ::open(c_str.data(), oflag, mode);
    if (fd < 0) {
        throw Exception(format("open: {0}: {1}", path, posix_strerror()));
    }
    return fd;
}

void mkdir(const StringPiece& path, mode_t mode) {
    CString c_str(path);
    if (::mkdir(c_str.data(), mode) != 0) {
        throw Exception(format("mkdir: {0}: {1}", path, posix_strerror()));
    }
}

void mkfifo(const StringPiece& path, mode_t mode) {
    CString c_str(path);
    if (::mkfifo(c_str.data(), mode) != 0) {
        throw Exception(format("mkfifo: {0}: {1}", path, posix_strerror()));
    }
}

void makedirs(const StringPiece& path, mode_t mode) {
    if (!path::isdir(path)) {
        makedirs(path::dirname(path), mode);
        mkdir(path, mode);
    }
}

void unlink(const StringPiece& path) {
    CString c_str(path);
    if (::unlink(c_str.data()) < 0) {
        throw Exception(format("unlink: {0}: {1}", path, posix_strerror()));
    }
}

void rmdir(const StringPiece& path) {
    CString c_str(path);
    if (::rmdir(c_str.data()) < 0) {
        throw Exception(format("rmdir: {0}: {1}", path, posix_strerror()));
    }
}

void rmtree(const StringPiece& path) {
    if (path::exists(path)) {
        class RmtreeVisitor : public TreeWalker {
          public:
            void pre_directory(    const StringPiece& path, const Stat&) { }
            void cycle_directory(  const StringPiece& path, const Stat&) { }

            void post_directory(   const StringPiece& path, const Stat&) { rmdir(path); }

            void file(             const StringPiece& path, const Stat&) { unlink(path); }
            void symlink(          const StringPiece& path, const Stat&) { unlink(path); }
            void broken_symlink(   const StringPiece& path, const Stat&) { unlink(path); }
            void other(            const StringPiece& path, const Stat&) { unlink(path); }
        };
        RmtreeVisitor visitor;
        walk(path, WALK_PHYSICAL, &visitor);
    }
}

TemporaryDirectory::TemporaryDirectory(const StringPiece& prefix) {
    String str(format("/tmp/{0}XXXXXX", prefix));
    CString c_str(str);
    mkdtemp(c_str.mutable_data());
    _path.assign(utf8::decode(c_str.data()));
}

TemporaryDirectory::~TemporaryDirectory() {
    rmtree(_path);
}

const String& TemporaryDirectory::path() const {
    return _path;
}

namespace {

class FtsCloser {
  public:
    FtsCloser(FTS* fts) : _fts(fts) { }
    ~FtsCloser() { fts_close(_fts); }
  private:
    FTS* _fts;
    DISALLOW_COPY_AND_ASSIGN(FtsCloser);
};

int compare_ftsent(const FTSENT** lhs, const FTSENT** rhs) {
    return strcmp((*lhs)->fts_name, (*rhs)->fts_name);
}

}  // namespace

void walk(const StringPiece& root, WalkType type, TreeWalker* visitor) {
    CString c_str(root);
    char* const pathv[] = { c_str.mutable_data(), NULL };
    int options = FTS_NOCHDIR;
    if (type == WALK_PHYSICAL) {
        options |= FTS_PHYSICAL;
    } else {
        options |= FTS_LOGICAL;
    }

    FTS* fts = fts_open(pathv, options, compare_ftsent);
    if (fts == NULL) {
        throw Exception(format("fts_open: {0}: {1}", root, posix_strerror()));
    }
    FtsCloser deleter(fts);
    while (FTSENT* ent = fts_read(fts)) {
        String path(utf8::decode(ent->fts_path));
        const Stat& st = *ent->fts_statp;
        switch (ent->fts_info) {
          case FTS_D:        visitor->pre_directory(    path, st); break;
          case FTS_DC:       visitor->cycle_directory(  path, st); break;
          case FTS_DEFAULT:  visitor->other(            path, st); break;
          case FTS_DP:       visitor->post_directory(   path, st); break;
          case FTS_F:        visitor->file(             path, st); break;
          case FTS_SL:       visitor->symlink(          path, st); break;
          case FTS_SLNONE:   visitor->broken_symlink(   path, st); break;

          case FTS_DNR:
          case FTS_ERR:
          case FTS_NS:
            throw Exception(format("fts_read: {0}: {1}", path, posix_strerror(ent->fts_errno)));

          case FTS_DOT:
          case FTS_NSOK:
          default:
            throw Exception(format("walk: got invalid type {0}", ent->fts_info));
        }
    }
}

TreeWalker::~TreeWalker() { }

}  // namespace sfz
<|endoftext|>


<commit_before>/*
 * PrimeSieveGUI.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2011 Kim Walisch, <kim.walisch@gmail.com>
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>
 */

#include "PrimeSieveGUI.h"
#include "ui_PrimeSieveGUI.h"
#include "PrimeSieveProcess.h"
#include "../soe/ParallelPrimeSieve.h"
#include "../expr/ExpressionParser.h"

#include <QtGlobal>
#include <QCoreApplication>
#include <QByteArray>
#include <QTextStream>
#include <QFile>
#include <QSize>
#include <QMessageBox>
#include <QTextCursor>
#include <stdexcept>

PrimeSieveGUI::PrimeSieveGUI(QWidget *parent) :
  QMainWindow(parent), ui(new Ui::PrimeSieveGUI), validator_(0),
  primeSieveProcess_(0), saveAct_(0), quitAct_(0), aboutAct_(0),
  alignmentGroup_(0) {
  ui->setupUi(this);
  primeText_.push_back("Prime numbers");
  primeText_.push_back("Twin primes");
  primeText_.push_back("Prime triplets");
  primeText_.push_back("Prime quadruplets");
  primeText_.push_back("Prime quintuplets");
  primeText_.push_back("Prime sextuplets");
  primeText_.push_back("Prime septuplets");
  this->initGUI();
  this->initConnections();
}

PrimeSieveGUI::~PrimeSieveGUI() {
  this->cleanUp();
  delete validator_;
  delete saveAct_;
  delete quitAct_;
  delete aboutAct_;
  delete alignmentGroup_;
  for (; !countAct_.isEmpty(); countAct_.pop_back())
    delete countAct_.back();
  for (; !printAct_.isEmpty(); printAct_.pop_back())
    delete printAct_.back();
  // Qt code
  delete ui;
}

void PrimeSieveGUI::changeEvent(QEvent *e) {
  QMainWindow::changeEvent(e);
  switch (e->type()) {
  case QEvent::LanguageChange:
    ui->retranslateUi(this);
    break;
  default:
    break;
  }
}

void PrimeSieveGUI::initGUI() {
  this->setWindowTitle(APPLICATION_NAME + " " + APPLICATION_VERSION);
  this->createMenu(primeText_);

  // fill the sieveSizeComboBox with power of 2 values <= "8192 KB"
  for (int i = MINIMUM_SIEVE_SIZE; i <= MAXIMUM_SIEVE_SIZE; i *= 2)
    ui->sieveSizeComboBox->addItem(QString::number(i) + " KB");
  this->setTo(ui->sieveSizeComboBox, DEFAULT_SIEVE_SIZE);

  // fill the threadsComboBox with power of 2 values <= maxThreads_
  maxThreads_ = ParallelPrimeSieve::getMaxThreads();
  for (int i = 1; i < maxThreads_; i *= 2)
    ui->threadsComboBox->addItem(QString::number(i));
  ui->threadsComboBox->addItem(QString::number(maxThreads_));
  this->setTo(ui->threadsComboBox, "1");

  // set an ideal ComboBox width
  int width = ui->sieveSizeComboBox->minimumSizeHint().width();
  ui->sieveSizeComboBox->setFixedWidth(width);
  ui->threadsComboBox->setFixedWidth(width);

  // set a nice GUI size
  QSize size = this->sizeHint();
  size.setWidth(this->minimumSizeHint().width());
#if defined(Q_OS_WIN)
  size.setHeight(size.height() - size.height() / 10);
#endif
  this->resize(size);

  // limit input for arithmetic expressions
  QRegExp rx("[0-9\\+\\-\\*\\/\\%\\^\\(\\)\\e\\E]*");
  validator_ = new QRegExpValidator(rx, this);
  ui->lowerBoundLineEdit->setValidator(validator_);
  ui->upperBoundLineEdit->setValidator(validator_);
}

void PrimeSieveGUI::initConnections() {
  connect(&progressBarTimer_,     SIGNAL(timeout()),                    this, SLOT(advanceProgressBar()));
  connect(ui->lowerBoundLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(autoSetThreads()));
  connect(ui->upperBoundLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(autoSetThreads()));
  connect(ui->autoSetCheckBox,    SIGNAL(toggled(bool)),                this, SLOT(autoSetThreads()));
  connect(saveAct_,               SIGNAL(triggered()),                  this, SLOT(saveToFile()));
  connect(quitAct_,               SIGNAL(triggered()),                  qApp, SLOT(closeAllWindows()));
  connect(alignmentGroup_,        SIGNAL(triggered(QAction*)),          this, SLOT(printMenuClicked(QAction*)));
  connect(aboutAct_,              SIGNAL(triggered()),                  this, SLOT(showAboutDialog()));
}

/**
 * Get the sieve size in kilobytes from the sieveSizeComboBox.
 * @post sieveSize >= 1 && sieveSize <= 8192.
 */
int PrimeSieveGUI::getSieveSize() {
  QString sieveSize(ui->sieveSizeComboBox->currentText());
  // remove " KB"
  sieveSize.chop(3);
  return sieveSize.toInt();
}

/**
 * Get the number of threads from the threadsComboBox.
 */
int PrimeSieveGUI::getThreads() {
  return ui->threadsComboBox->currentText().toInt();
}

quint64 PrimeSieveGUI::getNumber(const QString& str) {
  if (str.isEmpty())
    throw std::invalid_argument("Please enter a lower and upper bound for prime sieving.");

  ExpressionParser<quint64> parser;
  if (!parser.eval(str.toAscii().data()))
    throw std::invalid_argument(parser.getErrorMessage());

  int digits = str.count(QRegExp("[0-9]"));
  if (parser.getResult() >= UPPER_BOUND_LIMIT || (
      digits == str.size() && (
      digits >  UPPER_BOUND_STR.size() || (
      digits == UPPER_BOUND_STR.size() &&
      str    >= UPPER_BOUND_STR))))
    throw std::invalid_argument("Please use positive integers < 2^64 - 2^32*10.");

  return parser.getResult();
}

void PrimeSieveGUI::setTo(QComboBox* comboBox, const QString& text) {
  comboBox->setCurrentIndex(comboBox->findText(text));
}

/**
 * If "Auto set" is enabled set an ideal number of threads for the
 * current lower bound, upper bound in the threadsComboBox.
 */
void PrimeSieveGUI::autoSetThreads() {
  if (ui->autoSetCheckBox->isEnabled() && ui->autoSetCheckBox->isChecked()) {
    try {
      quint64 lowerBound = this->getNumber(ui->lowerBoundLineEdit->text());
      quint64 upperBound = this->getNumber(ui->upperBoundLineEdit->text());
      ParallelPrimeSieve pps;
      pps.setStartNumber(lowerBound);
      pps.setStopNumber(upperBound);
      int idealNumThreads = pps.getNumThreads();
      if (idealNumThreads < maxThreads_) {
        // floor to the next power of 2 value
        int p = 1;
        for (; p <= idealNumThreads; p *= 2)
          ;
        idealNumThreads = p / 2;
      }
      this->setTo(ui->threadsComboBox, QString::number(idealNumThreads));
    } catch (...) {
      this->setTo(ui->threadsComboBox, "1");
    }
  }
}

/**
 * The user has chosen a custom number of threads, disable "Auto set".
 */
void PrimeSieveGUI::on_threadsComboBox_activated() {
  ui->autoSetCheckBox->setChecked(false);
}

/**
 * Start sieving primes.
 */
void PrimeSieveGUI::on_sieveButton_clicked() {
  // invert buttons, reset upon cleanUp()
  ui->sieveButton->setDisabled(true);
  ui->cancelButton->setEnabled(true);
  try {
    flags_ = this->getMenuSettings();
    if ((flags_ & (ParallelPrimeSieve::COUNT_FLAGS | ParallelPrimeSieve::PRINT_FLAGS)) == 0)
      throw std::invalid_argument("Nothing to do, no count or print options selected.");

    quint64 lowerBound = this->getNumber(ui->lowerBoundLineEdit->text());
    quint64 upperBound = this->getNumber(ui->upperBoundLineEdit->text());
    if (lowerBound > upperBound)
      throw std::invalid_argument("The lower bound must not be greater than the upper bound.");

    // reset the GUI widgets
    ui->progressBar->setValue(ui->progressBar->minimum());
    ui->textEdit->clear();
    progressBarTimer_.start(25);

    // start a new process for sieving (avoids cancel
    // trouble with multiple threads)
    primeSieveProcess_ = new PrimeSieveProcess(this);
    if (flags_ & ParallelPrimeSieve::PRINT_FLAGS)
      connect(primeSieveProcess_, SIGNAL(readyReadStandardOutput()),
          this, SLOT(printProcessOutput()));
    connect(primeSieveProcess_, SIGNAL(finished(int, QProcess::ExitStatus)),
        this, SLOT(processFinished(int, QProcess::ExitStatus)));
    primeSieveProcess_->start(lowerBound, upperBound, this->getSieveSize(),
        flags_, this->getThreads());

  } catch (std::invalid_argument& ex) {
    this->cleanUp();
    QMessageBox::warning(this, APPLICATION_NAME, ex.what());
  } catch (std::exception& ex) {
    this->cleanUp();
    QMessageBox::critical(this, APPLICATION_NAME, ex.what());
  }
}

void PrimeSieveGUI::advanceProgressBar() {
  int permil = static_cast<int> (primeSieveProcess_->getStatus() * 10.0);
  ui->progressBar->setValue(permil);
}

/**
 * Redirects the standard output (prime numbers or prime k-tuplets) of
 * the primeSieveProcess_ to the TextEdit.
 */
void PrimeSieveGUI::printProcessOutput() {
  QByteArray buffer;
  buffer.reserve(PRINT_BUFFER_SIZE + 256);
  while (ui->cancelButton->isEnabled() && primeSieveProcess_->canReadLine()) {
    buffer.clear();
    while (primeSieveProcess_->canReadLine() && buffer.size() < PRINT_BUFFER_SIZE)
      buffer.append(primeSieveProcess_->readLine(256));
    // remove "\r\n" or '\n', '\r' at the back
    while (buffer.endsWith('\n') ||
           buffer.endsWith('\r'))
      buffer.chop(1);
    if (!buffer.isEmpty())
      ui->textEdit->appendPlainText(buffer);
/// Keep the GUI responsive.
/// @warning QApplication::processEvents() must not be used on
///          operating systems that use signal recursion (like Linux
///          X11) otherwise the stack will explode!
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
    QApplication::processEvents();
#else
    ui->textEdit->repaint();
#endif
  }
}

/**
 * Is executed when the primeSieveProcess_ finishes, checks for
 * process errors and calls this->printResults().
 */
void PrimeSieveGUI::processFinished(int exitCode,
    QProcess::ExitStatus exitStatus) {
  // the process did not exit normally, i.e. threw and exception
  if (exitCode != 0) {
    // Qt uses '/' internally, even for Windows
    QString path = QCoreApplication::applicationDirPath() + "/" + APPLICATION_NAME + "_error.txt";
    QFile error_log(path);
    if (error_log.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
      QTextStream out(&error_log);
      out << primeSieveProcess_->readAllStandardError();
      error_log.close();
    }
    this->cleanUp();
    QMessageBox::critical(this, APPLICATION_NAME,
        "The PrimeSieveProcess reported an error (see primesieve_error.txt), sieving has been aborted.");
  }
  // the PrimeSieveProcess has been interrupted by a signal (SIGTERM,
  // SIGKILL, ...) or a segmentation fault
  else if (exitStatus == QProcess::CrashExit) {
    this->cleanUp();
    QMessageBox::critical(this, APPLICATION_NAME, "The PrimeSieveProcess crashed, sieving has been aborted.");
  }
  // the PrimeSieveProcess has finished correctly
  else {
    ui->progressBar->setValue(ui->progressBar->maximum());
    // print results if not canceled lately
    if (ui->cancelButton->isEnabled())
      this->printResults();
    this->cleanUp();
  }
}

/**
 * Print the sieving results.
 */
void PrimeSieveGUI::printResults() {
  if (!ui->textEdit->toPlainText().isEmpty())
    ui->textEdit->appendPlainText("");

  // hack to get the count results aligned using tabs
  QString maxSizeText;
  for (int i = 0; i < ParallelPrimeSieve::COUNTS_SIZE; i++) {
    if ((flags_ & (ParallelPrimeSieve::COUNT_PRIMES << i)) &&
        maxSizeText.size() < primeText_[i].size())
      maxSizeText = primeText_[i];
  }
  ui->textEdit->insertPlainText(maxSizeText + ": ");
  int maxWidth = ui->textEdit->cursorRect().left();
  ui->textEdit->moveCursor(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
  ui->textEdit->textCursor().removeSelectedText();
  ui->textEdit->setTabStopWidth(maxWidth);

  // print prime counts & time elapsed
  for (int i = 0; i < ParallelPrimeSieve::COUNTS_SIZE; i++) {
    if (flags_ & (ParallelPrimeSieve::COUNT_PRIMES << i))
      ui->textEdit->appendPlainText(primeText_[i] + ":\t" + QString::number(primeSieveProcess_->getCounts(i)));
  }
  if (flags_ & ParallelPrimeSieve::COUNT_KTUPLETS)
    ui->textEdit->appendPlainText("");
  QString time("Elapsed time:\t" + QString::number(primeSieveProcess_->getTimeElapsed(), 'f', 2) + " sec");
  ui->textEdit->appendPlainText(time);
}

/**
 * Cancel sieving.
 */
void PrimeSieveGUI::on_cancelButton_clicked() {
  ui->cancelButton->setDisabled(true);
  ui->progressBar->setValue(0);
  // too late to abort
  if ((flags_ & ParallelPrimeSieve::PRINT_FLAGS) && primeSieveProcess_->isFinished())
    return;
  this->cleanUp();
}

/**
 * Clean up after sieving is finished or canceled (abort the
 * PrimeSieveProcess if still running).
 */
void PrimeSieveGUI::cleanUp() {
  progressBarTimer_.stop();
  if (primeSieveProcess_ != 0)
    delete primeSieveProcess_;
  primeSieveProcess_ = 0;
  // invert buttons
  ui->cancelButton->setDisabled(true);
  ui->sieveButton->setEnabled(true);
  // force repainting widgets
  this->repaint();
}
<commit_msg>removed ambiguous PrimeSieve::PRINT_FLAGS<commit_after>/*
 * PrimeSieveGUI.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2011 Kim Walisch, <kim.walisch@gmail.com>
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>
 */

#include "PrimeSieveGUI.h"
#include "ui_PrimeSieveGUI.h"
#include "PrimeSieveProcess.h"
#include "../soe/ParallelPrimeSieve.h"
#include "../expr/ExpressionParser.h"

#include <QtGlobal>
#include <QCoreApplication>
#include <QByteArray>
#include <QTextStream>
#include <QFile>
#include <QSize>
#include <QMessageBox>
#include <QTextCursor>
#include <stdexcept>

PrimeSieveGUI::PrimeSieveGUI(QWidget *parent) :
  QMainWindow(parent), ui(new Ui::PrimeSieveGUI), validator_(0),
  primeSieveProcess_(0), saveAct_(0), quitAct_(0), aboutAct_(0),
  alignmentGroup_(0) {
  ui->setupUi(this);
  primeText_.push_back("Prime numbers");
  primeText_.push_back("Twin primes");
  primeText_.push_back("Prime triplets");
  primeText_.push_back("Prime quadruplets");
  primeText_.push_back("Prime quintuplets");
  primeText_.push_back("Prime sextuplets");
  primeText_.push_back("Prime septuplets");
  this->initGUI();
  this->initConnections();
}

PrimeSieveGUI::~PrimeSieveGUI() {
  this->cleanUp();
  delete validator_;
  delete saveAct_;
  delete quitAct_;
  delete aboutAct_;
  delete alignmentGroup_;
  for (; !countAct_.isEmpty(); countAct_.pop_back())
    delete countAct_.back();
  for (; !printAct_.isEmpty(); printAct_.pop_back())
    delete printAct_.back();
  // Qt code
  delete ui;
}

void PrimeSieveGUI::changeEvent(QEvent *e) {
  QMainWindow::changeEvent(e);
  switch (e->type()) {
  case QEvent::LanguageChange:
    ui->retranslateUi(this);
    break;
  default:
    break;
  }
}

void PrimeSieveGUI::initGUI() {
  this->setWindowTitle(APPLICATION_NAME + " " + APPLICATION_VERSION);
  this->createMenu(primeText_);

  // fill the sieveSizeComboBox with power of 2 values <= "8192 KB"
  for (int i = MINIMUM_SIEVE_SIZE; i <= MAXIMUM_SIEVE_SIZE; i *= 2)
    ui->sieveSizeComboBox->addItem(QString::number(i) + " KB");
  this->setTo(ui->sieveSizeComboBox, DEFAULT_SIEVE_SIZE);

  // fill the threadsComboBox with power of 2 values <= maxThreads_
  maxThreads_ = ParallelPrimeSieve::getMaxThreads();
  for (int i = 1; i < maxThreads_; i *= 2)
    ui->threadsComboBox->addItem(QString::number(i));
  ui->threadsComboBox->addItem(QString::number(maxThreads_));
  this->setTo(ui->threadsComboBox, "1");

  // set an ideal ComboBox width
  int width = ui->sieveSizeComboBox->minimumSizeHint().width();
  ui->sieveSizeComboBox->setFixedWidth(width);
  ui->threadsComboBox->setFixedWidth(width);

  // set a nice GUI size
  QSize size = this->sizeHint();
  size.setWidth(this->minimumSizeHint().width());
#if defined(Q_OS_WIN)
  size.setHeight(size.height() - size.height() / 10);
#endif
  this->resize(size);

  // limit input for arithmetic expressions
  QRegExp rx("[0-9\\+\\-\\*\\/\\%\\^\\(\\)\\e\\E]*");
  validator_ = new QRegExpValidator(rx, this);
  ui->lowerBoundLineEdit->setValidator(validator_);
  ui->upperBoundLineEdit->setValidator(validator_);
}

void PrimeSieveGUI::initConnections() {
  connect(&progressBarTimer_,     SIGNAL(timeout()),                    this, SLOT(advanceProgressBar()));
  connect(ui->lowerBoundLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(autoSetThreads()));
  connect(ui->upperBoundLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(autoSetThreads()));
  connect(ui->autoSetCheckBox,    SIGNAL(toggled(bool)),                this, SLOT(autoSetThreads()));
  connect(saveAct_,               SIGNAL(triggered()),                  this, SLOT(saveToFile()));
  connect(quitAct_,               SIGNAL(triggered()),                  qApp, SLOT(closeAllWindows()));
  connect(alignmentGroup_,        SIGNAL(triggered(QAction*)),          this, SLOT(printMenuClicked(QAction*)));
  connect(aboutAct_,              SIGNAL(triggered()),                  this, SLOT(showAboutDialog()));
}

/**
 * Get the sieve size in kilobytes from the sieveSizeComboBox.
 * @post sieveSize >= 1 && sieveSize <= 8192.
 */
int PrimeSieveGUI::getSieveSize() {
  QString sieveSize(ui->sieveSizeComboBox->currentText());
  // remove " KB"
  sieveSize.chop(3);
  return sieveSize.toInt();
}

/**
 * Get the number of threads from the threadsComboBox.
 */
int PrimeSieveGUI::getThreads() {
  return ui->threadsComboBox->currentText().toInt();
}

quint64 PrimeSieveGUI::getNumber(const QString& str) {
  if (str.isEmpty())
    throw std::invalid_argument("Please enter a lower and upper bound for prime sieving.");

  ExpressionParser<quint64> parser;
  if (!parser.eval(str.toAscii().data()))
    throw std::invalid_argument(parser.getErrorMessage());

  int digits = str.count(QRegExp("[0-9]"));
  if (parser.getResult() >= UPPER_BOUND_LIMIT || (
      digits == str.size() && (
      digits >  UPPER_BOUND_STR.size() || (
      digits == UPPER_BOUND_STR.size() &&
      str    >= UPPER_BOUND_STR))))
    throw std::invalid_argument("Please use positive integers < 2^64 - 2^32*10.");

  return parser.getResult();
}

void PrimeSieveGUI::setTo(QComboBox* comboBox, const QString& text) {
  comboBox->setCurrentIndex(comboBox->findText(text));
}

/**
 * If "Auto set" is enabled set an ideal number of threads for the
 * current lower bound, upper bound in the threadsComboBox.
 */
void PrimeSieveGUI::autoSetThreads() {
  if (ui->autoSetCheckBox->isEnabled() && ui->autoSetCheckBox->isChecked()) {
    try {
      quint64 lowerBound = this->getNumber(ui->lowerBoundLineEdit->text());
      quint64 upperBound = this->getNumber(ui->upperBoundLineEdit->text());
      ParallelPrimeSieve pps;
      pps.setStartNumber(lowerBound);
      pps.setStopNumber(upperBound);
      int idealNumThreads = pps.getNumThreads();
      if (idealNumThreads < maxThreads_) {
        // floor to the next power of 2 value
        int p = 1;
        for (; p <= idealNumThreads; p *= 2)
          ;
        idealNumThreads = p / 2;
      }
      this->setTo(ui->threadsComboBox, QString::number(idealNumThreads));
    } catch (...) {
      this->setTo(ui->threadsComboBox, "1");
    }
  }
}

/**
 * The user has chosen a custom number of threads, disable "Auto set".
 */
void PrimeSieveGUI::on_threadsComboBox_activated() {
  ui->autoSetCheckBox->setChecked(false);
}

/**
 * Start sieving primes.
 */
void PrimeSieveGUI::on_sieveButton_clicked() {
  // invert buttons, reset upon cleanUp()
  ui->sieveButton->setDisabled(true);
  ui->cancelButton->setEnabled(true);
  try {
    flags_ = this->getMenuSettings();
    if ((flags_ & (ParallelPrimeSieve::COUNT_FLAGS |
                   ParallelPrimeSieve::PRINT_PRIMES |
                   ParallelPrimeSieve::PRINT_KTUPLETS)) == 0)
      throw std::invalid_argument("Nothing to do, no count or print options selected.");

    quint64 lowerBound = this->getNumber(ui->lowerBoundLineEdit->text());
    quint64 upperBound = this->getNumber(ui->upperBoundLineEdit->text());
    if (lowerBound > upperBound)
      throw std::invalid_argument("The lower bound must not be greater than the upper bound.");

    // reset the GUI widgets
    ui->progressBar->setValue(ui->progressBar->minimum());
    ui->textEdit->clear();
    progressBarTimer_.start(25);

    // start a new process for sieving (avoids cancel
    // trouble with multiple threads)
    primeSieveProcess_ = new PrimeSieveProcess(this);
    if (flags_ & (ParallelPrimeSieve::PRINT_PRIMES | ParallelPrimeSieve::PRINT_KTUPLETS))
      connect(primeSieveProcess_, SIGNAL(readyReadStandardOutput()),
          this, SLOT(printProcessOutput()));
    connect(primeSieveProcess_, SIGNAL(finished(int, QProcess::ExitStatus)),
        this, SLOT(processFinished(int, QProcess::ExitStatus)));
    primeSieveProcess_->start(lowerBound, upperBound, this->getSieveSize(),
        flags_, this->getThreads());

  } catch (std::invalid_argument& ex) {
    this->cleanUp();
    QMessageBox::warning(this, APPLICATION_NAME, ex.what());
  } catch (std::exception& ex) {
    this->cleanUp();
    QMessageBox::critical(this, APPLICATION_NAME, ex.what());
  }
}

void PrimeSieveGUI::advanceProgressBar() {
  int permil = static_cast<int> (primeSieveProcess_->getStatus() * 10.0);
  ui->progressBar->setValue(permil);
}

/**
 * Redirects the standard output (prime numbers or prime k-tuplets) of
 * the primeSieveProcess_ to the TextEdit.
 */
void PrimeSieveGUI::printProcessOutput() {
  QByteArray buffer;
  buffer.reserve(PRINT_BUFFER_SIZE + 256);
  while (ui->cancelButton->isEnabled() && primeSieveProcess_->canReadLine()) {
    buffer.clear();
    while (primeSieveProcess_->canReadLine() && buffer.size() < PRINT_BUFFER_SIZE)
      buffer.append(primeSieveProcess_->readLine(256));
    // remove "\r\n" or '\n', '\r' at the back
    while (buffer.endsWith('\n') ||
           buffer.endsWith('\r'))
      buffer.chop(1);
    if (!buffer.isEmpty())
      ui->textEdit->appendPlainText(buffer);
/// Keep the GUI responsive.
/// @warning QApplication::processEvents() must not be used on
///          operating systems that use signal recursion (like Linux
///          X11) otherwise the stack will explode!
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
    QApplication::processEvents();
#else
    ui->textEdit->repaint();
#endif
  }
}

/**
 * Is executed when the primeSieveProcess_ finishes, checks for
 * process errors and calls this->printResults().
 */
void PrimeSieveGUI::processFinished(int exitCode,
    QProcess::ExitStatus exitStatus) {
  // the process did not exit normally, i.e. threw and exception
  if (exitCode != 0) {
    // Qt uses '/' internally, even for Windows
    QString path = QCoreApplication::applicationDirPath() + "/" + APPLICATION_NAME + "_error.txt";
    QFile error_log(path);
    if (error_log.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
      QTextStream out(&error_log);
      out << primeSieveProcess_->readAllStandardError();
      error_log.close();
    }
    this->cleanUp();
    QMessageBox::critical(this, APPLICATION_NAME,
        "The PrimeSieveProcess reported an error (see primesieve_error.txt), sieving has been aborted.");
  }
  // the PrimeSieveProcess has been interrupted by a signal (SIGTERM,
  // SIGKILL, ...) or a segmentation fault
  else if (exitStatus == QProcess::CrashExit) {
    this->cleanUp();
    QMessageBox::critical(this, APPLICATION_NAME, "The PrimeSieveProcess crashed, sieving has been aborted.");
  }
  // the PrimeSieveProcess has finished correctly
  else {
    ui->progressBar->setValue(ui->progressBar->maximum());
    // print results if not canceled lately
    if (ui->cancelButton->isEnabled())
      this->printResults();
    this->cleanUp();
  }
}

/**
 * Print the sieving results.
 */
void PrimeSieveGUI::printResults() {
  if (!ui->textEdit->toPlainText().isEmpty())
    ui->textEdit->appendPlainText("");

  // hack to get the count results aligned using tabs
  QString maxSizeText;
  for (int i = 0; i < ParallelPrimeSieve::COUNTS_SIZE; i++) {
    if ((flags_ & (ParallelPrimeSieve::COUNT_PRIMES << i)) &&
        maxSizeText.size() < primeText_[i].size())
      maxSizeText = primeText_[i];
  }
  ui->textEdit->insertPlainText(maxSizeText + ": ");
  int maxWidth = ui->textEdit->cursorRect().left();
  ui->textEdit->moveCursor(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
  ui->textEdit->textCursor().removeSelectedText();
  ui->textEdit->setTabStopWidth(maxWidth);

  // print prime counts & time elapsed
  for (int i = 0; i < ParallelPrimeSieve::COUNTS_SIZE; i++) {
    if (flags_ & (ParallelPrimeSieve::COUNT_PRIMES << i))
      ui->textEdit->appendPlainText(primeText_[i] + ":\t" + QString::number(primeSieveProcess_->getCounts(i)));
  }
  if (flags_ & ParallelPrimeSieve::COUNT_KTUPLETS)
    ui->textEdit->appendPlainText("");
  QString time("Elapsed time:\t" + QString::number(primeSieveProcess_->getTimeElapsed(), 'f', 2) + " sec");
  ui->textEdit->appendPlainText(time);
}

/**
 * Cancel sieving.
 */
void PrimeSieveGUI::on_cancelButton_clicked() {
  ui->cancelButton->setDisabled(true);
  ui->progressBar->setValue(0);
  // too late to abort
  if ((flags_ & (ParallelPrimeSieve::PRINT_PRIMES |
                 ParallelPrimeSieve::PRINT_KTUPLETS))
       && primeSieveProcess_->isFinished())
    return;
  this->cleanUp();
}

/**
 * Clean up after sieving is finished or canceled (abort the
 * PrimeSieveProcess if still running).
 */
void PrimeSieveGUI::cleanUp() {
  progressBarTimer_.stop();
  if (primeSieveProcess_ != 0)
    delete primeSieveProcess_;
  primeSieveProcess_ = 0;
  // invert buttons
  ui->cancelButton->setDisabled(true);
  ui->sieveButton->setEnabled(true);
  // force repainting widgets
  this->repaint();
}
<|endoftext|>


<commit_before>#ifndef SPECIFIC_H
#define SPECIFIC_H

#include <stdio.h>
#include "STYPES.H"

#if PSXPC_VERSION
#define UNIMPLEMENTED() __asm("nop");
#else
#ifdef _MSC_VER
#define FUNCNAME __FUNCTION__
#else
#define FUNCNAME __func__
#endif

#if defined(__EMSCRIPTEN__)
#define UNIMPLEMENTED()
#else
#define UNIMPLEMENTED() S_Warn("[%s] - Unimplemented!\n", FUNCNAME);
#endif

#endif

extern unsigned short AnimComp;
extern short AnimatingTexturesVOffset;
extern struct REQUESTER SettingsReq;
extern struct REQUESTER ConfigReq;
extern unsigned char SoundFXVolume;
extern unsigned short nAnimTextureRanges;
extern unsigned short* AnimTextureRanges;
extern unsigned short nAnimUVRanges;
extern int GtSFXEnabled;
extern short AnimatingTexturesV[16][8][3];

extern void S_control_screen_position();
extern long S_DumpScreen();
extern void S_ExitSystem(char* exit_message);
extern void DisplayConfig(int x, int y);
extern int DoPauseMenu();
extern void gInit();
extern short S_Death();
extern void DisplayStatsUCunt();
//extern void S_Warn(const char* warning_message);

#define S_Warn printf

#endif<commit_msg>[Specific-PSXPC_N] Fix compile.<commit_after>#ifndef SPECIFIC_H
#define SPECIFIC_H

#include <stdio.h>
#include "STYPES.H"

#define WARN_HACK(x) printf("%s\n", x);

#if PSXPC_VERSION
#define UNIMPLEMENTED() __asm("nop");
#else
#ifdef _MSC_VER
#define FUNCNAME __FUNCTION__
#else
#define FUNCNAME __func__
#endif

#if defined(__EMSCRIPTEN__)
#define UNIMPLEMENTED()
#else
#define UNIMPLEMENTED() S_Warn("[%s] - Unimplemented!\n", FUNCNAME);
#endif

#endif

extern unsigned short AnimComp;
extern short AnimatingTexturesVOffset;
extern struct REQUESTER SettingsReq;
extern struct REQUESTER ConfigReq;
extern unsigned char SoundFXVolume;
extern unsigned short nAnimTextureRanges;
extern unsigned short* AnimTextureRanges;
extern unsigned short nAnimUVRanges;
extern int GtSFXEnabled;
extern short AnimatingTexturesV[16][8][3];

extern void S_control_screen_position();
extern long S_DumpScreen();
extern void S_ExitSystem(char* exit_message);
extern void DisplayConfig(int x, int y);
extern int DoPauseMenu();
extern void gInit();
extern short S_Death();
extern void DisplayStatsUCunt();
//extern void S_Warn(const char* warning_message);
extern int sub_62190();

#define S_Warn printf

#endif<|endoftext|>


<commit_before>#include "Sampler.hpp"

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include <iterator>
#include <complex>

#ifdef PAPI_ENABLED
#include <papi.h>
#endif

#include CFG_H
#include "sample.h"

using namespace std;

void Sampler::set_counters(const vector<string> &tokens) {
#ifdef PAPI_ENABLED
    // ignore excess counters
    const int maxcounters = PAPI_num_counters();
    size_t ncounters = tokens.size() - 1;
    if (ncounters > maxcounters) {
        cerr << "Too many counters specified: given " << ncounters;
        cerr << " maximum " << maxcounters << " (truncating counter list)" << endl;
        ncounters = maxcounters;
    }

    // clear old counters
    counters.clear();

    // register new counters individually
    for (size_t i = 0; i < ncounters; i++) {

        // convert string to code
        int code;
        char str[PAPI_MAX_STR_LEN];  // need to pass a non-const *
        strcpy(str, tokens[i + 1].c_str());
        const int check = PAPI_event_name_to_code(str, &code);

        // check for errors
        if (check == PAPI_OK)
            counters.push_back(code);
        else if (check == PAPI_ENOTPRESET)
            cerr << "Counter unknown: " << tokens[i + 1] << " (counter ignored)" << endl;
        else if (check == PAPI_ENOEVNT)
            cerr << "Counter unavailable: " << tokens[i + 1] << " (counter ignored)" << endl;

        // check if combination is valid
        if (PAPI_start_counters(&counters[0], counters.size()) == PAPI_OK) {
            long long counts[counters.size()];
            PAPI_stop_counters(counts, counters.size());
        } else {
            counters.pop_back();
            cerr << "Could not add " << tokens[i + 1] << " (counter ignored)" << endl;
        }
    }
#else
    cerr << "PAPI support not enabled (command ignored)" << endl;
#endif
}

void Sampler::omp_start(const vector<string>&tokens) {
#ifdef OPENMP_ENABLED
    if (tokens.size() > 1)
        cerr << "Ignoring arguments for " << tokens[0] << endl;
    if (omp_active) {
        cerr << "Implicitly ending last parallel region, starting a new one" << endl;
        omp_end(vector<string>());
    }
    omp_active = true;
#else
    cerr << "OpenMP support not enabled (command ignored)" << endl;
#endif
}

void Sampler::omp_end(const vector<string>&tokens) {
#ifdef OPENMP_ENABLED
    if (tokens.size() > 1)
        cerr << "Ignoring arguments for " << tokens[0] << endl;
    if (!omp_active) {
        cerr << "Not in parallel region (comand ignored)" << endl;
        return;
    }
    omp_active = false;
    if (!callparsers.empty())
        callparsers.back().omp_active = true;
#else
    cerr << "OpenMP support not enabled (command ignored)" << endl;
#endif
}

template <typename T>
void Sampler::named_malloc(const vector<string> &tokens) {
    // require 2 arguments: name, size
    if (tokens.size() < 3) {
        cerr << "Too few arguments for " << tokens[0] << " (command ignored)" << endl;
        cerr << "usage (example): " << tokens[0] << " A 10000" << endl;
        return;
    }
    if (tokens.size() > 3) {
        cerr << "Ignoring excess arguments for " << tokens[0] << endl;
        cerr << "usage (example): " << tokens[0] << " A 10000" << endl;
    }

    // parse arguments
    const string &name = tokens[1];
    const ssize_t size = atol(tokens[2].c_str());

    // variable must not exist yet
    if (mem.named_exists(name)) {
        cerr << "Variable already exists: " << name << " (command ignored)" << endl;
        return;
    }
    // name must beginn with letter
    if (!isalpha(name[0])) {
        cerr << "Variable name must begin with a letter: " << name << " (command ignored)" << endl;
        return;
    }

    //TODO: check size conversion error
    // size must be > 0
    if (size < 0) {
        cerr << "Cannot allocate variable of negative size " << size << " (command ignored)" << endl;
        return;
    }

    // malloc the variabel
    mem.named_malloc<T>(name, size);
}

template <typename T>
void Sampler::named_offset(const vector<string> &tokens) {
    // require 3 arguments: oldname, offset, newname
    if (tokens.size() < 4) {
        cerr << "Too few arguments for " << tokens[0] << " (command ignored)" << endl;
        cerr << "usage (example): " << tokens[0] << " Old 10000 New" << endl;
        return;
    }
    if (tokens.size() > 4) {
        cerr << "Ignoring excess arguments for " << tokens[0] << endl;
        cerr << "usage (example): " << tokens[0] << " Old 10000 New" << endl;
    }

    // parse arguments
    const string &oldname = tokens[1];
    const ssize_t offset = atol(tokens[2].c_str());
    const string &newname = tokens[3];

    // oldname must exist
    if (!mem.named_exists(oldname)) {
        cerr << "Unknown variable: " << oldname << " (command ignored)" << endl;
        return;
    }
    // TODO: check offset conversion errors
    // newname must not exist yet
    if (mem.named_exists(newname)) {
        cerr << "Variable already exists: " << newname << " (command ignored)" << endl;
        return;
    }

    // alias a new offset
    mem.named_offset<T>(oldname, offset, newname);
}

void Sampler::named_free(const vector<string> &tokens) {
    // require 1 argument: name
    if (tokens.size() < 2) {
        cerr << "Too few arguments for " << tokens[0] << " (command ignored)" << endl;
        cerr << "usage (example): " << tokens[0] << " A" << endl;
        return;
    }
    if (tokens.size() > 2) {
        cerr << "Ignoring excess arguments for " << tokens[0] << endl;
        cerr << "usage (example): " << tokens[0] << " A" << endl;
    }

    // parse arguments
    const string &name = tokens[1];

    // check existence
    if (!mem.named_exists(name)) {
        cerr << "Unknown variable: " << name << " (command ignored)" << endl;
        return;
    }

    // free the variable
    mem.named_free(name);
}

void Sampler::add_call(const vector<string> &tokens) {
    const string &routine = tokens[0];

    // catch unknown routines
    if (signatures.find(routine) == signatures.end()) {
        cerr << "Uknown kernel: " << routine << " (call ignored)" << endl;
        return;
    }

    // (try to) set up a call parser for the kernel
    const Signature &signature = signatures[routine];
    try {
        CallParser callparser(tokens, signature, mem);
#ifdef OPENMP_ENABLED
        callparser.omp_active = omp_active;
#endif
        callparsers.push_back(callparser);
    } catch (CallParser::CallParserException &e) {
        // the call could not be parsed
        // (failure already reported)
    }
}

void Sampler::go(const vector<string> &tokens) {
    // end parallel region if active
#ifdef OPENMP_ENABLED
    if (omp_active) {
        cerr << "Implicitly ending last parallel region" << endl;
        omp_end(vector<string>());
    }
#endif

    size_t ncalls = callparsers.size();
    KernelCall *calls = new KernelCall[ncalls];

    // construct KernelCalls (C structs)
    for (size_t i = 0; i < ncalls; i++)
        calls[i] = callparsers[i].get_call();

    // run measurements
#ifdef PAPI_ENABLED
    sample(calls, ncalls, &counters[0], counters.size());
#else
    sample(calls, ncalls);
#endif

    // print results
    for (size_t i = 0; i < ncalls; i++) {
        CallParser &callparser = callparsers[i];

#ifdef OPENMP_ENABLED
        if (callparser.omp_active)
            // part of a parallel region
            continue;
#endif

        // cycle counter
        cout << calls[i].cycles;

#ifdef PAPI_ENABLED
        // papi counters
        for (size_t j = 0; j < counters.size(); j++)
            cout << "\t" << calls[i].counters[j];
#endif

        cout << endl;
    }

    // clean up
    delete [] calls;
    callparsers.clear();
    mem.static_reset();
}

void Sampler::print(const vector<string> &tokens) {
    ostringstream text;
    copy(tokens.begin() + 1, tokens.end(), ostream_iterator<string>(text, " "));
    cout << text.str() << endl;
}

void Sampler::info(const vector<string> &tokens) {
    // require 1 argument: kernel name
    if (tokens.size() < 2) {
        cerr << "No argument for " << tokens[0] << " (command ignored)" << endl;
        cerr << "usage (exmaple): " << tokens[0] << " dgemm" << endl;
        return;
    }
    if (tokens.size() > 2) {
        cerr << "Ignoring excess arguments for " << tokens[0] << endl;
        cerr << "usage (example): " << tokens[0] << " dgemm" << endl;
    }

    const string &routine = tokens[1];

    // catch unknown routines
    if (signatures.find(routine) == signatures.end()) {
        cerr << "Uknown kernel: " << routine << " (command ignored)" << endl;
        return;
    }

    // print <routine name>(
    cerr << routine << "(";

    // print the signatue for the routine
    const Signature &signature = signatures[routine];
    const size_t argc = signature.arguments.size();
    for (unsigned char i = 1; i < argc; i++) {
        switch (signature.arguments[i]) {
            case CHARP:
                cerr << "char *";
                break;
            case INTP:
                cerr << "int *";
                break;
            case FLOATP:
                cerr << "float *";
                break;
            case DOUBLEP:
                cerr << "double *";
                break;
            case VOIDP:
                cerr << "void *";
                break;
            default:
                break;
        }
        if (i + 1 < argc)
            cerr << ", ";
    }

    // print );
    cerr << ");" << endl;
}

void Sampler::add_signature(const Signature &signature) {
    signatures[signature.name] = signature;
}

void Sampler::start() {
    // special commands
    map<string, void (Sampler:: *)(const vector<string> &)> commands;
    commands["set_counters"] = &Sampler::set_counters;
    commands["{omp"] = &Sampler::omp_start;
    commands["}"] = &Sampler::omp_end;
    commands["malloc"] = &Sampler::named_malloc<char>;
    commands["imalloc"] = &Sampler::named_malloc<int>;
    commands["smalloc"] = &Sampler::named_malloc<float>;
    commands["dmalloc"] = &Sampler::named_malloc<double>;
    commands["cmalloc"] = &Sampler::named_malloc<complex<float> >;
    commands["zmalloc"] = &Sampler::named_malloc<complex<double> >;
    commands["offset"] = &Sampler::named_offset<char>;
    commands["ioffset"] = &Sampler::named_offset<int>;
    commands["soffset"] = &Sampler::named_offset<float>;
    commands["doffset"] = &Sampler::named_offset<double>;
    commands["coffset"] = &Sampler::named_offset<complex<float> >;
    commands["zoffset"] = &Sampler::named_offset<complex<double> >;
    commands["free"] = &Sampler::named_free;
    commands["go"] = &Sampler::go;
    commands["info"] = &Sampler::info;
    commands["print"] = &Sampler::print;

    // default: not parallel
#ifdef OPENMP_ENABLED
    omp_active = false;
#endif

    // read stdin by lines
    string line;
    while (getline(cin, line)) {

        // clear comments
        line = line.substr(0, line.find_first_of("#"));

        // ignore empty lines
        if (line.size() == 0)
            continue;

        // remove leading spaces
        line = line.substr(line.find_first_not_of(" \t\n\v\f\r"));

        // ignore empty lines
        if (line.size() == 0)
            continue;

        // tokenize line
        vector<string> tokens;
        istringstream iss(line);
        copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter(tokens));

        // check for commands
        map<string, void (Sampler:: *)(const vector<string> &)>::iterator command = commands.find(tokens[0]);
        if (command != commands.end())
            (this->*(command->second))(tokens);
        else
            add_call(tokens);
    }

    // process remaining calls
    go(vector<string>());
}
<commit_msg>omp end fix<commit_after>#include "Sampler.hpp"

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include <iterator>
#include <complex>

#ifdef PAPI_ENABLED
#include <papi.h>
#endif

#include CFG_H
#include "sample.h"

using namespace std;

void Sampler::set_counters(const vector<string> &tokens) {
#ifdef PAPI_ENABLED
    // ignore excess counters
    const int maxcounters = PAPI_num_counters();
    size_t ncounters = tokens.size() - 1;
    if (ncounters > maxcounters) {
        cerr << "Too many counters specified: given " << ncounters;
        cerr << " maximum " << maxcounters << " (truncating counter list)" << endl;
        ncounters = maxcounters;
    }

    // clear old counters
    counters.clear();

    // register new counters individually
    for (size_t i = 0; i < ncounters; i++) {

        // convert string to code
        int code;
        char str[PAPI_MAX_STR_LEN];  // need to pass a non-const *
        strcpy(str, tokens[i + 1].c_str());
        const int check = PAPI_event_name_to_code(str, &code);

        // check for errors
        if (check == PAPI_OK)
            counters.push_back(code);
        else if (check == PAPI_ENOTPRESET)
            cerr << "Counter unknown: " << tokens[i + 1] << " (counter ignored)" << endl;
        else if (check == PAPI_ENOEVNT)
            cerr << "Counter unavailable: " << tokens[i + 1] << " (counter ignored)" << endl;

        // check if combination is valid
        if (PAPI_start_counters(&counters[0], counters.size()) == PAPI_OK) {
            long long counts[counters.size()];
            PAPI_stop_counters(counts, counters.size());
        } else {
            counters.pop_back();
            cerr << "Could not add " << tokens[i + 1] << " (counter ignored)" << endl;
        }
    }
#else
    cerr << "PAPI support not enabled (command ignored)" << endl;
#endif
}

void Sampler::omp_start(const vector<string>&tokens) {
#ifdef OPENMP_ENABLED
    if (tokens.size() > 1)
        cerr << "Ignoring arguments for " << tokens[0] << endl;
    if (omp_active) {
        cerr << "Implicitly ending last parallel region, starting a new one" << endl;
        omp_end(vector<string>());
    }
    omp_active = true;
#else
    cerr << "OpenMP support not enabled (command ignored)" << endl;
#endif
}

void Sampler::omp_end(const vector<string>&tokens) {
#ifdef OPENMP_ENABLED
    if (tokens.size() > 1)
        cerr << "Ignoring arguments for " << tokens[0] << endl;
    if (!omp_active) {
        cerr << "Not in parallel region (comand ignored)" << endl;
        return;
    }
    omp_active = false;
    if (!callparsers.empty())
        callparsers.back().omp_active = false;
#else
    cerr << "OpenMP support not enabled (command ignored)" << endl;
#endif
}

template <typename T>
void Sampler::named_malloc(const vector<string> &tokens) {
    // require 2 arguments: name, size
    if (tokens.size() < 3) {
        cerr << "Too few arguments for " << tokens[0] << " (command ignored)" << endl;
        cerr << "usage (example): " << tokens[0] << " A 10000" << endl;
        return;
    }
    if (tokens.size() > 3) {
        cerr << "Ignoring excess arguments for " << tokens[0] << endl;
        cerr << "usage (example): " << tokens[0] << " A 10000" << endl;
    }

    // parse arguments
    const string &name = tokens[1];
    const ssize_t size = atol(tokens[2].c_str());

    // variable must not exist yet
    if (mem.named_exists(name)) {
        cerr << "Variable already exists: " << name << " (command ignored)" << endl;
        return;
    }
    // name must beginn with letter
    if (!isalpha(name[0])) {
        cerr << "Variable name must begin with a letter: " << name << " (command ignored)" << endl;
        return;
    }

    //TODO: check size conversion error
    // size must be > 0
    if (size < 0) {
        cerr << "Cannot allocate variable of negative size " << size << " (command ignored)" << endl;
        return;
    }

    // malloc the variabel
    mem.named_malloc<T>(name, size);
}

template <typename T>
void Sampler::named_offset(const vector<string> &tokens) {
    // require 3 arguments: oldname, offset, newname
    if (tokens.size() < 4) {
        cerr << "Too few arguments for " << tokens[0] << " (command ignored)" << endl;
        cerr << "usage (example): " << tokens[0] << " Old 10000 New" << endl;
        return;
    }
    if (tokens.size() > 4) {
        cerr << "Ignoring excess arguments for " << tokens[0] << endl;
        cerr << "usage (example): " << tokens[0] << " Old 10000 New" << endl;
    }

    // parse arguments
    const string &oldname = tokens[1];
    const ssize_t offset = atol(tokens[2].c_str());
    const string &newname = tokens[3];

    // oldname must exist
    if (!mem.named_exists(oldname)) {
        cerr << "Unknown variable: " << oldname << " (command ignored)" << endl;
        return;
    }
    // TODO: check offset conversion errors
    // newname must not exist yet
    if (mem.named_exists(newname)) {
        cerr << "Variable already exists: " << newname << " (command ignored)" << endl;
        return;
    }

    // alias a new offset
    mem.named_offset<T>(oldname, offset, newname);
}

void Sampler::named_free(const vector<string> &tokens) {
    // require 1 argument: name
    if (tokens.size() < 2) {
        cerr << "Too few arguments for " << tokens[0] << " (command ignored)" << endl;
        cerr << "usage (example): " << tokens[0] << " A" << endl;
        return;
    }
    if (tokens.size() > 2) {
        cerr << "Ignoring excess arguments for " << tokens[0] << endl;
        cerr << "usage (example): " << tokens[0] << " A" << endl;
    }

    // parse arguments
    const string &name = tokens[1];

    // check existence
    if (!mem.named_exists(name)) {
        cerr << "Unknown variable: " << name << " (command ignored)" << endl;
        return;
    }

    // free the variable
    mem.named_free(name);
}

void Sampler::add_call(const vector<string> &tokens) {
    const string &routine = tokens[0];

    // catch unknown routines
    if (signatures.find(routine) == signatures.end()) {
        cerr << "Uknown kernel: " << routine << " (call ignored)" << endl;
        return;
    }

    // (try to) set up a call parser for the kernel
    const Signature &signature = signatures[routine];
    try {
        CallParser callparser(tokens, signature, mem);
#ifdef OPENMP_ENABLED
        callparser.omp_active = omp_active;
#endif
        callparsers.push_back(callparser);
    } catch (CallParser::CallParserException &e) {
        // the call could not be parsed
        // (failure already reported)
    }
}

void Sampler::go(const vector<string> &tokens) {
    // end parallel region if active
#ifdef OPENMP_ENABLED
    if (omp_active) {
        cerr << "Implicitly ending last parallel region" << endl;
        omp_end(vector<string>());
    }
#endif

    size_t ncalls = callparsers.size();
    KernelCall *calls = new KernelCall[ncalls];

    // construct KernelCalls (C structs)
    for (size_t i = 0; i < ncalls; i++)
        calls[i] = callparsers[i].get_call();

    // run measurements
#ifdef PAPI_ENABLED
    sample(calls, ncalls, &counters[0], counters.size());
#else
    sample(calls, ncalls);
#endif

    // print results
    for (size_t i = 0; i < ncalls; i++) {
        CallParser &callparser = callparsers[i];

#ifdef OPENMP_ENABLED
        if (callparser.omp_active)
            // part of a parallel region
            continue;
#endif

        // cycle counter
        cout << calls[i].cycles;

#ifdef PAPI_ENABLED
        // papi counters
        for (size_t j = 0; j < counters.size(); j++)
            cout << "\t" << calls[i].counters[j];
#endif

        cout << endl;
    }

    // clean up
    delete [] calls;
    callparsers.clear();
    mem.static_reset();
}

void Sampler::print(const vector<string> &tokens) {
    ostringstream text;
    copy(tokens.begin() + 1, tokens.end(), ostream_iterator<string>(text, " "));
    cout << text.str() << endl;
}

void Sampler::info(const vector<string> &tokens) {
    // require 1 argument: kernel name
    if (tokens.size() < 2) {
        cerr << "No argument for " << tokens[0] << " (command ignored)" << endl;
        cerr << "usage (exmaple): " << tokens[0] << " dgemm" << endl;
        return;
    }
    if (tokens.size() > 2) {
        cerr << "Ignoring excess arguments for " << tokens[0] << endl;
        cerr << "usage (example): " << tokens[0] << " dgemm" << endl;
    }

    const string &routine = tokens[1];

    // catch unknown routines
    if (signatures.find(routine) == signatures.end()) {
        cerr << "Uknown kernel: " << routine << " (command ignored)" << endl;
        return;
    }

    // print <routine name>(
    cerr << routine << "(";

    // print the signatue for the routine
    const Signature &signature = signatures[routine];
    const size_t argc = signature.arguments.size();
    for (unsigned char i = 1; i < argc; i++) {
        switch (signature.arguments[i]) {
            case CHARP:
                cerr << "char *";
                break;
            case INTP:
                cerr << "int *";
                break;
            case FLOATP:
                cerr << "float *";
                break;
            case DOUBLEP:
                cerr << "double *";
                break;
            case VOIDP:
                cerr << "void *";
                break;
            default:
                break;
        }
        if (i + 1 < argc)
            cerr << ", ";
    }

    // print );
    cerr << ");" << endl;
}

void Sampler::add_signature(const Signature &signature) {
    signatures[signature.name] = signature;
}

void Sampler::start() {
    // special commands
    map<string, void (Sampler:: *)(const vector<string> &)> commands;
    commands["set_counters"] = &Sampler::set_counters;
    commands["{omp"] = &Sampler::omp_start;
    commands["}"] = &Sampler::omp_end;
    commands["malloc"] = &Sampler::named_malloc<char>;
    commands["imalloc"] = &Sampler::named_malloc<int>;
    commands["smalloc"] = &Sampler::named_malloc<float>;
    commands["dmalloc"] = &Sampler::named_malloc<double>;
    commands["cmalloc"] = &Sampler::named_malloc<complex<float> >;
    commands["zmalloc"] = &Sampler::named_malloc<complex<double> >;
    commands["offset"] = &Sampler::named_offset<char>;
    commands["ioffset"] = &Sampler::named_offset<int>;
    commands["soffset"] = &Sampler::named_offset<float>;
    commands["doffset"] = &Sampler::named_offset<double>;
    commands["coffset"] = &Sampler::named_offset<complex<float> >;
    commands["zoffset"] = &Sampler::named_offset<complex<double> >;
    commands["free"] = &Sampler::named_free;
    commands["go"] = &Sampler::go;
    commands["info"] = &Sampler::info;
    commands["print"] = &Sampler::print;

    // default: not parallel
#ifdef OPENMP_ENABLED
    omp_active = false;
#endif

    // read stdin by lines
    string line;
    while (getline(cin, line)) {

        // clear comments
        line = line.substr(0, line.find_first_of("#"));

        // ignore empty lines
        if (line.size() == 0)
            continue;

        // remove leading spaces
        line = line.substr(line.find_first_not_of(" \t\n\v\f\r"));

        // ignore empty lines
        if (line.size() == 0)
            continue;

        // tokenize line
        vector<string> tokens;
        istringstream iss(line);
        copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter(tokens));

        // check for commands
        map<string, void (Sampler:: *)(const vector<string> &)>::iterator command = commands.find(tokens[0]);
        if (command != commands.end())
            (this->*(command->second))(tokens);
        else
            add_call(tokens);
    }

    // process remaining calls
    go(vector<string>());
}
<|endoftext|>