<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2011-2012 Florian Eßer <f.esser@rwth-aachen.de>
// Copyright 2012      Bernhard Beschow <bbeschow@cs.tu-berlin.de>
// Copyright 2013      Roman Karlstetter <roman.karlstetter@googlemail.com>
//
#include "ElevationProfileDataSource.h"
#include "ElevationModel.h"
#include "GeoDataDocument.h"
#include "GeoDataTreeModel.h"
#include "GeoDataObject.h"
#include "GeoDataPlacemark.h"
#include "MarbleDebug.h"
#include "MarbleMath.h"
#include "routing/Route.h"
#include "routing/RoutingModel.h"
#include "routing/RoutingManager.h"
#include <QFileInfo>

namespace Marble
{

/*
 * ElevationProfileDataSource
 */
MarbleModel *ElevationProfileDataSource::marbleModel() const
{
    return m_marbleModel;
}

ElevationProfileDataSource::ElevationProfileDataSource(MarbleModel *marbleModel, QObject *parent):
    QObject(parent),
    m_marbleModel(marbleModel)
{
    // nothing to do
}

QList<QPointF> ElevationProfileDataSource::calculateElevationData( const GeoDataLineString &lineString ) const
{
    // TODO: Don't re-calculate the whole route if only a small part of it was changed
    QList<QPointF> result;
    qreal distance = 0;

    //GeoDataLineString path;
    for ( int i = 0; i < lineString.size(); i++ ) {
        qreal ele = getElevation( lineString[i] );

        if ( i ) {
            distance += EARTH_RADIUS * distanceSphere( lineString[i-1], lineString[i] );
        }

        if ( ele != invalidElevationData ) { // skip no data
            result.append( QPointF( distance, ele ) );
        }
    }

    return result;
}
// end of impl of ElevationProfileDataSource

/*
 * ElevationProfileTrackDataSource
 */
ElevationProfileTrackDataSource::ElevationProfileTrackDataSource(MarbleModel *marbleModel, QObject *parent):
    ElevationProfileDataSource(marbleModel, parent)
{
    if ( marbleModel ) {
        connect( marbleModel->treeModel(), SIGNAL(added(GeoDataObject*)), this, SLOT(handleObjectAdded(GeoDataObject*)) );
        connect( marbleModel->treeModel(), SIGNAL(removed(GeoDataObject*)), this, SLOT(handleObjectRemoved(GeoDataObject*)) );
    }
}

QStringList ElevationProfileTrackDataSource::sourceDescriptions() const
{
    return m_trackChooserList;
}

void ElevationProfileTrackDataSource::setSourceIndex(int index)
{
    if(m_currentSourceIndex != index){
        m_currentSourceIndex = index;
        requestUpdate();
    }
}

int ElevationProfileTrackDataSource::currentSourceIndex() const
{
    return m_currentSourceIndex;
}

void ElevationProfileTrackDataSource::requestUpdate()
{
    const GeoDataLineString *routePoints = m_trackList[m_currentSourceIndex]->lineString();

    emit dataUpdated(*routePoints, calculateElevationData(*routePoints));
}

bool ElevationProfileTrackDataSource::isDataAvailable() const
{
    return !m_trackHash.isEmpty();
}

qreal ElevationProfileTrackDataSource::getElevation(GeoDataCoordinates coord) const
{
    return coord.altitude();
}

void ElevationProfileTrackDataSource::handleObjectAdded(GeoDataObject *obj)
{
    GeoDataDocument *doc = dynamic_cast<GeoDataDocument*>(obj);
    if(!doc){
        return;// don't know what to do if not a document
    }
    QList<const GeoDataTrack *> trackList;

    for(int i = 0; i<doc->size(); ++i){
        const GeoDataFeature * c = doc->child(i);
        const GeoDataPlacemark *placemark = dynamic_cast<const GeoDataPlacemark*>(c);
        if(!placemark) {
            continue;
        }
        const GeoDataMultiGeometry *multi = dynamic_cast<const GeoDataMultiGeometry *>(placemark->geometry());
        if(!multi){
            continue;
        }
        for(int i = 0; i<multi->size(); i++){
            const GeoDataTrack *track = dynamic_cast<const GeoDataTrack *>(multi->child(i));
            if (track){
                mDebug() << "new GeoDataTrack for ElevationProfile detected";
                trackList.append(track);
            }
        }
    }

    if(trackList.isEmpty()){
        return;
    }

    // update internal datastructures
    m_trackHash.insert(doc->fileName(), trackList);

    const GeoDataTrack *selectedTrack = 0;
    if(m_currentSourceIndex < m_trackList.size()){
        selectedTrack = m_trackList[m_currentSourceIndex];
    }

    m_trackChooserList.clear();
    m_trackList.clear();
    QHashIterator<QString,   QList<const GeoDataTrack *> > i(m_trackHash);
    while (i.hasNext()) {
        i.next();
        mDebug() << i.key() << ": " << i.value() << endl;
        QFileInfo info(i.key());
        QString filename = info.fileName();
        QList<const GeoDataTrack *> list = i.value();
        for(int i = 0; i<list.size(); ++i){
            m_trackList << list[i];
            m_trackChooserList << QString(filename + ": " + QString::number(i));
        }
    }
    if(selectedTrack){
        m_currentSourceIndex = m_trackList.indexOf(selectedTrack);
    }

    emit sourceCountChanged();
}

void ElevationProfileTrackDataSource::handleObjectRemoved(GeoDataObject *obj)
{
    if(m_trackList.size() == 0){
        // no track loaded, nothing to remove
        return;
    }
    GeoDataDocument *topLevelDoc = dynamic_cast<GeoDataDocument*>(obj);
    if(!topLevelDoc){
        return;// don't know what to do if not a document
    }

    QString key = topLevelDoc->fileName();
    QList<const GeoDataTrack *> list = m_trackHash.value(key);
    const GeoDataTrack *selectedTrack = m_trackList[m_currentSourceIndex];
    for(int i = 0; i<list.size(); i++){
        int idx = m_trackList.indexOf(list[i]);
        m_trackList.removeAt(idx);
        m_trackChooserList.removeAt(idx);
    }
    m_trackHash.remove(key);

    m_currentSourceIndex = m_trackList.indexOf(selectedTrack);
    if(m_currentSourceIndex == -1){
        m_currentSourceIndex = 0;
    }
    emit sourceCountChanged();
    requestUpdate();
}

// end of impl of ElevationProfileTrackDataSource

 /*
  * ElevationProfileRouteDataSource
  */
ElevationProfileRouteDataSource::ElevationProfileRouteDataSource(MarbleModel *marbleModel, QObject *parent):
    ElevationProfileDataSource(marbleModel, parent),
    m_routingModel( 0 )
{
    if ( marbleModel ) {
        connect( marbleModel->elevationModel(), SIGNAL(updateAvailable()), SLOT(requestUpdate()) );

        m_routingModel = marbleModel->routingManager()->routingModel();
        connect( m_routingModel, SIGNAL(currentRouteChanged()), this, SLOT(requestUpdate()) );
    }

    m_routeAvailable = isDataAvailable();
}

void ElevationProfileRouteDataSource::requestUpdate()
{
    if(m_routeAvailable != isDataAvailable()){
        // availability of route changed
        emit sourceCountChanged();
        m_routeAvailable = isDataAvailable();
    }
    if(!isDataAvailable()){
        emit dataUpdated(GeoDataLineString(), QList<QPointF>());
    }
    GeoDataLineString routePoints = m_routingModel->route().path();

    emit dataUpdated(routePoints, calculateElevationData(routePoints));
}

bool ElevationProfileRouteDataSource::isDataAvailable() const
{
    return m_routingModel && m_routingModel->rowCount() > 0;
}

qreal ElevationProfileRouteDataSource::getElevation(GeoDataCoordinates coord) const
{
    const qreal lat = coord.latitude ( GeoDataCoordinates::Degree );
    const qreal lon = coord.longitude( GeoDataCoordinates::Degree );
    qreal ele = marbleModel()->elevationModel()->height( lon, lat );
    if ( ele == invalidElevationData ) { // no data
        ele = 0;
    }
    return ele;
}
// end of impl of ElevationProfileRouteDataSource

}

<commit_msg>don't emit signal twice<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2011-2012 Florian Eßer <f.esser@rwth-aachen.de>
// Copyright 2012      Bernhard Beschow <bbeschow@cs.tu-berlin.de>
// Copyright 2013      Roman Karlstetter <roman.karlstetter@googlemail.com>
//
#include "ElevationProfileDataSource.h"
#include "ElevationModel.h"
#include "GeoDataDocument.h"
#include "GeoDataTreeModel.h"
#include "GeoDataObject.h"
#include "GeoDataPlacemark.h"
#include "MarbleDebug.h"
#include "MarbleMath.h"
#include "routing/Route.h"
#include "routing/RoutingModel.h"
#include "routing/RoutingManager.h"
#include <QFileInfo>

namespace Marble
{

/*
 * ElevationProfileDataSource
 */
MarbleModel *ElevationProfileDataSource::marbleModel() const
{
    return m_marbleModel;
}

ElevationProfileDataSource::ElevationProfileDataSource(MarbleModel *marbleModel, QObject *parent):
    QObject(parent),
    m_marbleModel(marbleModel)
{
    // nothing to do
}

QList<QPointF> ElevationProfileDataSource::calculateElevationData( const GeoDataLineString &lineString ) const
{
    // TODO: Don't re-calculate the whole route if only a small part of it was changed
    QList<QPointF> result;
    qreal distance = 0;

    //GeoDataLineString path;
    for ( int i = 0; i < lineString.size(); i++ ) {
        const qreal ele = getElevation( lineString[i] );

        if ( i ) {
            distance += EARTH_RADIUS * distanceSphere( lineString[i-1], lineString[i] );
        }

        if ( ele != invalidElevationData ) { // skip no data
            result.append( QPointF( distance, ele ) );
        }
    }

    return result;
}
// end of impl of ElevationProfileDataSource

/*
 * ElevationProfileTrackDataSource
 */
ElevationProfileTrackDataSource::ElevationProfileTrackDataSource(MarbleModel *marbleModel, QObject *parent):
    ElevationProfileDataSource(marbleModel, parent)
{
    if ( marbleModel ) {
        connect( marbleModel->treeModel(), SIGNAL(added(GeoDataObject*)), this, SLOT(handleObjectAdded(GeoDataObject*)) );
        connect( marbleModel->treeModel(), SIGNAL(removed(GeoDataObject*)), this, SLOT(handleObjectRemoved(GeoDataObject*)) );
    }
}

QStringList ElevationProfileTrackDataSource::sourceDescriptions() const
{
    return m_trackChooserList;
}

void ElevationProfileTrackDataSource::setSourceIndex(int index)
{
    if(m_currentSourceIndex != index){
        m_currentSourceIndex = index;
        requestUpdate();
    }
}

int ElevationProfileTrackDataSource::currentSourceIndex() const
{
    return m_currentSourceIndex;
}

void ElevationProfileTrackDataSource::requestUpdate()
{
    const GeoDataLineString *routePoints = m_trackList[m_currentSourceIndex]->lineString();

    emit dataUpdated(*routePoints, calculateElevationData(*routePoints));
}

bool ElevationProfileTrackDataSource::isDataAvailable() const
{
    return !m_trackHash.isEmpty();
}

qreal ElevationProfileTrackDataSource::getElevation(GeoDataCoordinates coord) const
{
    return coord.altitude();
}

void ElevationProfileTrackDataSource::handleObjectAdded(GeoDataObject *obj)
{
    GeoDataDocument *doc = dynamic_cast<GeoDataDocument*>(obj);
    if(!doc){
        return;// don't know what to do if not a document
    }
    QList<const GeoDataTrack *> trackList;

    for(int i = 0; i<doc->size(); ++i){
        const GeoDataFeature * c = doc->child(i);
        const GeoDataPlacemark *placemark = dynamic_cast<const GeoDataPlacemark*>(c);
        if(!placemark) {
            continue;
        }
        const GeoDataMultiGeometry *multi = dynamic_cast<const GeoDataMultiGeometry *>(placemark->geometry());
        if(!multi){
            continue;
        }
        for(int i = 0; i<multi->size(); i++){
            const GeoDataTrack *track = dynamic_cast<const GeoDataTrack *>(multi->child(i));
            if (track){
                mDebug() << "new GeoDataTrack for ElevationProfile detected";
                trackList.append(track);
            }
        }
    }

    if(trackList.isEmpty()){
        return;
    }

    // update internal datastructures
    m_trackHash.insert(doc->fileName(), trackList);

    const GeoDataTrack *selectedTrack = 0;
    if(m_currentSourceIndex < m_trackList.size()){
        selectedTrack = m_trackList[m_currentSourceIndex];
    }

    m_trackChooserList.clear();
    m_trackList.clear();
    QHashIterator<QString,   QList<const GeoDataTrack *> > i(m_trackHash);
    while (i.hasNext()) {
        i.next();
        mDebug() << i.key() << ": " << i.value() << endl;
        QFileInfo info(i.key());
        QString filename = info.fileName();
        QList<const GeoDataTrack *> list = i.value();
        for(int i = 0; i<list.size(); ++i){
            m_trackList << list[i];
            m_trackChooserList << QString(filename + ": " + QString::number(i));
        }
    }
    if(selectedTrack){
        m_currentSourceIndex = m_trackList.indexOf(selectedTrack);
    }

    emit sourceCountChanged();
}

void ElevationProfileTrackDataSource::handleObjectRemoved(GeoDataObject *obj)
{
    if(m_trackList.size() == 0){
        // no track loaded, nothing to remove
        return;
    }
    GeoDataDocument *topLevelDoc = dynamic_cast<GeoDataDocument*>(obj);
    if(!topLevelDoc){
        return;// don't know what to do if not a document
    }

    QString key = topLevelDoc->fileName();
    QList<const GeoDataTrack *> list = m_trackHash.value(key);
    const GeoDataTrack *selectedTrack = m_trackList[m_currentSourceIndex];
    for(int i = 0; i<list.size(); i++){
        int idx = m_trackList.indexOf(list[i]);
        m_trackList.removeAt(idx);
        m_trackChooserList.removeAt(idx);
    }
    m_trackHash.remove(key);

    m_currentSourceIndex = m_trackList.indexOf(selectedTrack);
    if(m_currentSourceIndex == -1){
        m_currentSourceIndex = 0;
    }
    emit sourceCountChanged();
    requestUpdate();
}

// end of impl of ElevationProfileTrackDataSource

 /*
  * ElevationProfileRouteDataSource
  */
ElevationProfileRouteDataSource::ElevationProfileRouteDataSource(MarbleModel *marbleModel, QObject *parent):
    ElevationProfileDataSource(marbleModel, parent),
    m_routingModel( 0 )
{
    if ( marbleModel ) {
        connect( marbleModel->elevationModel(), SIGNAL(updateAvailable()), SLOT(requestUpdate()) );

        m_routingModel = marbleModel->routingManager()->routingModel();
        connect( m_routingModel, SIGNAL(currentRouteChanged()), this, SLOT(requestUpdate()) );
    }

    m_routeAvailable = isDataAvailable();
}

void ElevationProfileRouteDataSource::requestUpdate()
{
    if(m_routeAvailable != isDataAvailable()){
        // availability of route changed
        emit sourceCountChanged();
        m_routeAvailable = isDataAvailable();
    }

    GeoDataLineString routePoints = m_routingModel->route().path();

    emit dataUpdated(routePoints, calculateElevationData(routePoints));
}

bool ElevationProfileRouteDataSource::isDataAvailable() const
{
    return m_routingModel && m_routingModel->rowCount() > 0;
}

qreal ElevationProfileRouteDataSource::getElevation(GeoDataCoordinates coord) const
{
    const qreal lat = coord.latitude ( GeoDataCoordinates::Degree );
    const qreal lon = coord.longitude( GeoDataCoordinates::Degree );
    qreal ele = marbleModel()->elevationModel()->height( lon, lat );
    if ( ele == invalidElevationData ) { // no data
        ele = 0;
    }
    return ele;
}
// end of impl of ElevationProfileRouteDataSource

}

<|endoftext|>


<commit_before>// Copyright 2021 The Wuffs Authors.
//
// 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
//
//    https://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.

// ----------------

/*
sdl-imageviewer is a simple GUI program for viewing an image. To run:

$CXX sdl-imageviewer.cc -lSDL2 -lSDL2_image && \
  ./a.out ../../test/data/bricks-color.png; rm -f a.out

for a C++ compiler $CXX, such as clang++ or g++.

The Tab key switches between decoding the image via Wuffs or via SDL2_image.
There should be no difference unless you uncomment the § line of code below.

The Escape key quits.

----

This program (in Wuffs' example directory) is like example/imageviewer but with
fewer features. It focuses on showing how to integrate the Wuffs image decoders
with SDL (as an alternative to the SDL_image extension).

While SDL is cross-platform, this program is not as good as example/imageviewer
for general use. SDL (which is designed for full-screen games) uses a noticable
amount of CPU (and therefore power) polling for events even when the program
isn't otherwise doing anything.
*/

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>

// Wuffs ships as a "single file C library" or "header file library" as per
// https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
//
// To use that single file as a "foo.c"-like implementation, instead of a
// "foo.h"-like header, #define WUFFS_IMPLEMENTATION before #include'ing or
// compiling it.
#define WUFFS_IMPLEMENTATION

// Defining the WUFFS_CONFIG__MODULE* macros are optional, but it lets users of
// release/c/etc.c choose which parts of Wuffs to build. That file contains the
// entire Wuffs standard library, implementing a variety of codecs and file
// formats. Without this macro definition, an optimizing compiler or linker may
// very well discard Wuffs code for unused codecs, but listing the Wuffs
// modules we use makes that process explicit. Preprocessing means that such
// code simply isn't compiled.
#define WUFFS_CONFIG__MODULES
#define WUFFS_CONFIG__MODULE__ADLER32
#define WUFFS_CONFIG__MODULE__AUX__BASE
#define WUFFS_CONFIG__MODULE__AUX__IMAGE
#define WUFFS_CONFIG__MODULE__BASE
#define WUFFS_CONFIG__MODULE__BMP
#define WUFFS_CONFIG__MODULE__CRC32
#define WUFFS_CONFIG__MODULE__DEFLATE
#define WUFFS_CONFIG__MODULE__GIF
#define WUFFS_CONFIG__MODULE__LZW
#define WUFFS_CONFIG__MODULE__PNG
#define WUFFS_CONFIG__MODULE__ZLIB

// If building this program in an environment that doesn't easily accommodate
// relative includes, you can use the script/inline-c-relative-includes.go
// program to generate a stand-alone C file.
#include "../../release/c/wuffs-unsupported-snapshot.c"

// ----------------

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

// --------

class Wuffs_Load_RW_Callbacks : public wuffs_aux::DecodeImageCallbacks {
 public:
  Wuffs_Load_RW_Callbacks() : m_surface(NULL) {}

  ~Wuffs_Load_RW_Callbacks() {
    if (m_surface) {
      SDL_UnlockSurface(m_surface);
      SDL_FreeSurface(m_surface);
      m_surface = NULL;
    }
  }

  SDL_Surface*  //
  TakeSurface() {
    if (!m_surface) {
      return NULL;
    }
    SDL_UnlockSurface(m_surface);
    SDL_Surface* ret = m_surface;
    m_surface = NULL;
    return ret;
  }

 private:
  wuffs_base__pixel_format  //
  SelectPixfmt(const wuffs_base__image_config& image_config) override {
    // Regardless of endianness, SDL_PIXELFORMAT_BGRA32 (from a few lines
    // below) is equivalent to WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL.
    return wuffs_base__make_pixel_format(
        WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL);
  }

  AllocPixbufResult  //
  AllocPixbuf(const wuffs_base__image_config& image_config,
              bool allow_uninitialized_memory) override {
    if (m_surface) {
      SDL_UnlockSurface(m_surface);
      SDL_FreeSurface(m_surface);
      m_surface = NULL;
    }
    uint32_t w = image_config.pixcfg.width();
    uint32_t h = image_config.pixcfg.height();
    if ((w > 0xFFFFFF) || (h > 0xFFFFFF)) {
      return AllocPixbufResult("Wuffs_Load_RW_Callbacks: image is too large");
    }
    uint32_t sdl_pixelformat = SDL_PIXELFORMAT_BGRA32;

    // (§) Uncomment this line of code to invert the BGRA/RGBA color order.
    // This isn't a generally useful feature for an image viewer, but it should
    // make it obvious, when pressing the TAB key, whether you're using the
    // Wuffs (inverted) or SDL_image (correct) decoder.
    //
    // sdl_pixelformat = SDL_PIXELFORMAT_RGBA32;

    m_surface = SDL_CreateRGBSurfaceWithFormat(
        0, static_cast<int>(w), static_cast<int>(h), 32, sdl_pixelformat);
    if (!m_surface) {
      return AllocPixbufResult(
          "Wuffs_Load_RW_Callbacks: SDL_CreateRGBSurface failed");
    }
    SDL_LockSurface(m_surface);
    wuffs_base__pixel_buffer pixbuf;
    wuffs_base__status status = pixbuf.set_interleaved(
        &image_config.pixcfg,
        wuffs_base__make_table_u8(static_cast<uint8_t*>(m_surface->pixels),
                                  m_surface->w * 4, m_surface->h,
                                  m_surface->pitch),
        wuffs_base__empty_slice_u8());
    if (!status.is_ok()) {
      SDL_UnlockSurface(m_surface);
      SDL_FreeSurface(m_surface);
      m_surface = NULL;
      return AllocPixbufResult(status.message());
    }
    return AllocPixbufResult(wuffs_aux::MemOwner(NULL, &free), pixbuf);
  }

  SDL_Surface* m_surface;
};

// --------

class Wuffs_Load_RW_Input : public wuffs_aux::sync_io::Input {
 public:
  Wuffs_Load_RW_Input(SDL_RWops* rw, bool take_ownership_of_rw)
      : m_rw(rw), m_ownership(take_ownership_of_rw) {}

  ~Wuffs_Load_RW_Input() {
    if (m_rw && m_ownership) {
      m_rw->close(m_rw);
    }
  }

 private:
  std::string  //
  CopyIn(wuffs_aux::IOBuffer* dst) override {
    if (!m_rw) {
      return "Wuffs_Load_RW_Input: NULL SDL_RWops";
    } else if (!dst) {
      return "Wuffs_Load_RW_Input: NULL IOBuffer";
    } else if (dst->meta.closed) {
      return "Wuffs_Load_RW_Input: end of file";
    }
    dst->compact();
    if (dst->writer_length() == 0) {
      return "Wuffs_Load_RW_Input: full IOBuffer";
    }
    size_t n = m_rw->read(m_rw, dst->writer_pointer(), 1, dst->writer_length());
    dst->meta.wi += n;
    return std::string();
  }

  SDL_RWops* m_rw;
  const bool m_ownership;
};

// --------

// Wuffs_Load_RW loads the image from the input rw. It is like SDL_image's
// IMG_Load_RW function but it returns any error in-band (as a std::string)
// instead of separately (global state accessible via SDL_GetError).
//
// On success, the SDL_Surface* returned will be non-NULL and the caller owns
// it. Ownership means that they are responsible for calling SDL_FreeSurface on
// it when done.
std::pair<SDL_Surface*, std::string>  //
Wuffs_Load_RW(SDL_RWops* rw, bool take_ownership_of_rw) {
  Wuffs_Load_RW_Callbacks callbacks;
  Wuffs_Load_RW_Input input(rw, take_ownership_of_rw);
  wuffs_aux::DecodeImageResult res = wuffs_aux::DecodeImage(callbacks, input);
  if (!res.error_message.empty()) {
    return std::make_pair<SDL_Surface*, std::string>(
        NULL, std::move(res.error_message));
  }
  return std::make_pair<SDL_Surface*, std::string>(callbacks.TakeSurface(),
                                                   std::string());
}

// ----------------

SDL_Surface* g_image = NULL;
bool g_load_via_sdl_image = false;

bool  //
draw(SDL_Window* window) {
  SDL_Surface* ws = SDL_GetWindowSurface(window);
  SDL_FillRect(ws, NULL, SDL_MapRGB(ws->format, 0x00, 0x00, 0x00));
  if (g_image) {
    SDL_BlitSurface(g_image, NULL, ws, NULL);
  }
  SDL_UpdateWindowSurface(window);
  return true;
}

bool  //
load_image(const char* filename) {
  if (g_image) {
    SDL_FreeSurface(g_image);
    g_image = NULL;
  }

  SDL_RWops* rw = SDL_RWFromFile(filename, "rb");
  if (!rw) {
    fprintf(stderr, "main: SDL_RWFromFile(\"%s\"): %s\n", filename,
            SDL_GetError());
    return false;
  }

  constexpr bool take_ownership_of_rw = true;
  if (g_load_via_sdl_image) {
    g_image = IMG_Load_RW(rw, take_ownership_of_rw);
    if (!g_image) {
      fprintf(stderr, "main: IMG_Load_RW(\"%s\"): %s\n", filename,
              SDL_GetError());
      return false;
    }
  } else {
    std::pair<SDL_Surface*, std::string> p =
        Wuffs_Load_RW(rw, take_ownership_of_rw);
    if (!p.second.empty()) {
      fprintf(stderr, "main: Wuffs_Load_RW(\"%s\"): %s\n", filename,
              p.second.c_str());
      return false;
    }
    g_image = p.first;
  }

  return true;
}

int  //
main(int argc, char** argv) {
  if (argc != 2) {
    fprintf(stderr, "usage: %s filename\n", argv[0]);
    return 1;
  }
  if (SDL_Init(SDL_INIT_VIDEO) < 0) {
    fprintf(stderr, "main: SDL_Init: %s\n", SDL_GetError());
    return 1;
  }
  SDL_Window* window =
      SDL_CreateWindow("sdl-imageviewer", SDL_WINDOWPOS_UNDEFINED,
                       SDL_WINDOWPOS_UNDEFINED, 1024, 768, SDL_WINDOW_SHOWN);
  if (!window) {
    fprintf(stderr, "main: SDL_CreateWindow: %s\n", SDL_GetError());
    return 1;
  }

  if (!load_image(argv[1])) {
    return 1;
  }

  while (true) {
    SDL_Event event;
    if (!SDL_WaitEvent(&event)) {
      fprintf(stderr, "main: SDL_WaitEvent: %s\n", SDL_GetError());
      return 1;
    }

    switch (event.type) {
      case SDL_QUIT:
        goto cleanup;

      case SDL_WINDOWEVENT:
        switch (event.window.event) {
          case SDL_WINDOWEVENT_EXPOSED:
            if (!draw(window)) {
              return 1;
            }
            break;
        }
        break;

      case SDL_KEYDOWN:
        switch (event.key.keysym.sym) {
          case SDLK_ESCAPE:
            goto cleanup;
          case SDLK_TAB:
            g_load_via_sdl_image = !g_load_via_sdl_image;
            printf("Switched to %s.\n",
                   g_load_via_sdl_image ? "SDL_image" : "Wuffs");
            if (!load_image(argv[1]) || !draw(window)) {
              return 1;
            }
            break;
        }
        break;
    }
  }

cleanup:
  if (g_image) {
    SDL_FreeSurface(g_image);
    g_image = NULL;
  }
  SDL_DestroyWindow(window);
  SDL_Quit();
  return 0;
}
<commit_msg>Fix the sdl-imageviewer demo on DefaultDepth 30<commit_after>// Copyright 2021 The Wuffs Authors.
//
// 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
//
//    https://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.

// ----------------

/*
sdl-imageviewer is a simple GUI program for viewing an image. To run:

$CXX sdl-imageviewer.cc -lSDL2 -lSDL2_image && \
  ./a.out ../../test/data/bricks-color.png; rm -f a.out

for a C++ compiler $CXX, such as clang++ or g++.

The Tab key switches between decoding the image via Wuffs or via SDL2_image.
There should be no difference unless you uncomment the § line of code below.

The Escape key quits.

----

This program (in Wuffs' example directory) is like example/imageviewer but with
fewer features. It focuses on showing how to integrate the Wuffs image decoders
with SDL (as an alternative to the SDL_image extension).

While SDL is cross-platform, this program is not as good as example/imageviewer
for general use. SDL (which is designed for full-screen games) uses a noticable
amount of CPU (and therefore power) polling for events even when the program
isn't otherwise doing anything.
*/

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>

// Wuffs ships as a "single file C library" or "header file library" as per
// https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
//
// To use that single file as a "foo.c"-like implementation, instead of a
// "foo.h"-like header, #define WUFFS_IMPLEMENTATION before #include'ing or
// compiling it.
#define WUFFS_IMPLEMENTATION

// Defining the WUFFS_CONFIG__MODULE* macros are optional, but it lets users of
// release/c/etc.c choose which parts of Wuffs to build. That file contains the
// entire Wuffs standard library, implementing a variety of codecs and file
// formats. Without this macro definition, an optimizing compiler or linker may
// very well discard Wuffs code for unused codecs, but listing the Wuffs
// modules we use makes that process explicit. Preprocessing means that such
// code simply isn't compiled.
#define WUFFS_CONFIG__MODULES
#define WUFFS_CONFIG__MODULE__ADLER32
#define WUFFS_CONFIG__MODULE__AUX__BASE
#define WUFFS_CONFIG__MODULE__AUX__IMAGE
#define WUFFS_CONFIG__MODULE__BASE
#define WUFFS_CONFIG__MODULE__BMP
#define WUFFS_CONFIG__MODULE__CRC32
#define WUFFS_CONFIG__MODULE__DEFLATE
#define WUFFS_CONFIG__MODULE__GIF
#define WUFFS_CONFIG__MODULE__LZW
#define WUFFS_CONFIG__MODULE__PNG
#define WUFFS_CONFIG__MODULE__ZLIB

// If building this program in an environment that doesn't easily accommodate
// relative includes, you can use the script/inline-c-relative-includes.go
// program to generate a stand-alone C file.
#include "../../release/c/wuffs-unsupported-snapshot.c"

// ----------------

#include <SDL2/SDL.h>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_image.h>

// --------

class Wuffs_Load_RW_Callbacks : public wuffs_aux::DecodeImageCallbacks {
 public:
  Wuffs_Load_RW_Callbacks() : m_surface(NULL) {}

  ~Wuffs_Load_RW_Callbacks() {
    if (m_surface) {
      SDL_UnlockSurface(m_surface);
      SDL_FreeSurface(m_surface);
      m_surface = NULL;
    }
  }

  SDL_Surface*  //
  TakeSurface() {
    if (!m_surface) {
      return NULL;
    }
    SDL_UnlockSurface(m_surface);
    SDL_Surface* ret = m_surface;
    m_surface = NULL;
    return ret;
  }

 private:
  wuffs_base__pixel_format  //
  SelectPixfmt(const wuffs_base__image_config& image_config) override {
    // Regardless of endianness, SDL_PIXELFORMAT_BGRA32 (from a few lines
    // below) is equivalent to WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL.
    return wuffs_base__make_pixel_format(
        WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL);
  }

  AllocPixbufResult  //
  AllocPixbuf(const wuffs_base__image_config& image_config,
              bool allow_uninitialized_memory) override {
    if (m_surface) {
      SDL_UnlockSurface(m_surface);
      SDL_FreeSurface(m_surface);
      m_surface = NULL;
    }
    uint32_t w = image_config.pixcfg.width();
    uint32_t h = image_config.pixcfg.height();
    if ((w > 0xFFFFFF) || (h > 0xFFFFFF)) {
      return AllocPixbufResult("Wuffs_Load_RW_Callbacks: image is too large");
    }
    uint32_t sdl_pixelformat = SDL_PIXELFORMAT_BGRA32;

    // (§) Uncomment this line of code to invert the BGRA/RGBA color order.
    // This isn't a generally useful feature for an image viewer, but it should
    // make it obvious, when pressing the TAB key, whether you're using the
    // Wuffs (inverted) or SDL_image (correct) decoder.
    //
    // sdl_pixelformat = SDL_PIXELFORMAT_RGBA32;

    m_surface = SDL_CreateRGBSurfaceWithFormat(
        0, static_cast<int>(w), static_cast<int>(h), 32, sdl_pixelformat);
    if (!m_surface) {
      return AllocPixbufResult(
          "Wuffs_Load_RW_Callbacks: SDL_CreateRGBSurface failed");
    }
    SDL_LockSurface(m_surface);
    wuffs_base__pixel_buffer pixbuf;
    wuffs_base__status status = pixbuf.set_interleaved(
        &image_config.pixcfg,
        wuffs_base__make_table_u8(static_cast<uint8_t*>(m_surface->pixels),
                                  m_surface->w * 4, m_surface->h,
                                  m_surface->pitch),
        wuffs_base__empty_slice_u8());
    if (!status.is_ok()) {
      SDL_UnlockSurface(m_surface);
      SDL_FreeSurface(m_surface);
      m_surface = NULL;
      return AllocPixbufResult(status.message());
    }
    return AllocPixbufResult(wuffs_aux::MemOwner(NULL, &free), pixbuf);
  }

  SDL_Surface* m_surface;
};

// --------

class Wuffs_Load_RW_Input : public wuffs_aux::sync_io::Input {
 public:
  Wuffs_Load_RW_Input(SDL_RWops* rw, bool take_ownership_of_rw)
      : m_rw(rw), m_ownership(take_ownership_of_rw) {}

  ~Wuffs_Load_RW_Input() {
    if (m_rw && m_ownership) {
      m_rw->close(m_rw);
    }
  }

 private:
  std::string  //
  CopyIn(wuffs_aux::IOBuffer* dst) override {
    if (!m_rw) {
      return "Wuffs_Load_RW_Input: NULL SDL_RWops";
    } else if (!dst) {
      return "Wuffs_Load_RW_Input: NULL IOBuffer";
    } else if (dst->meta.closed) {
      return "Wuffs_Load_RW_Input: end of file";
    }
    dst->compact();
    if (dst->writer_length() == 0) {
      return "Wuffs_Load_RW_Input: full IOBuffer";
    }
    size_t n = m_rw->read(m_rw, dst->writer_pointer(), 1, dst->writer_length());
    dst->meta.wi += n;
    return std::string();
  }

  SDL_RWops* m_rw;
  const bool m_ownership;
};

// --------

// Wuffs_Load_RW loads the image from the input rw. It is like SDL_image's
// IMG_Load_RW function but it returns any error in-band (as a std::string)
// instead of separately (global state accessible via SDL_GetError).
//
// On success, the SDL_Surface* returned will be non-NULL and the caller owns
// it. Ownership means that they are responsible for calling SDL_FreeSurface on
// it when done.
std::pair<SDL_Surface*, std::string>  //
Wuffs_Load_RW(SDL_RWops* rw, bool take_ownership_of_rw) {
  Wuffs_Load_RW_Callbacks callbacks;
  Wuffs_Load_RW_Input input(rw, take_ownership_of_rw);
  wuffs_aux::DecodeImageResult res = wuffs_aux::DecodeImage(callbacks, input);
  if (!res.error_message.empty()) {
    return std::make_pair<SDL_Surface*, std::string>(
        NULL, std::move(res.error_message));
  }
  return std::make_pair<SDL_Surface*, std::string>(callbacks.TakeSurface(),
                                                   std::string());
}

// ----------------

SDL_Surface* g_image = NULL;
bool g_load_via_sdl_image = false;

bool  //
draw(SDL_Window* window) {
  SDL_Surface* ws = SDL_GetWindowSurface(window);
  if (!ws) {
    // This resolves DefaultDepth 30 X.org, in a slightly inefficient manner.
    SDL_Renderer* r = SDL_CreateRenderer(window, -1, 0);
    SDL_RenderClear(r);
    if (g_image) {
      SDL_Texture* texture = SDL_CreateTextureFromSurface(r, g_image);
      SDL_RenderCopy(r, texture, NULL, &g_image->clip_rect);
      SDL_DestroyTexture(texture);
    }
    SDL_RenderPresent(r);
    SDL_DestroyRenderer(r);
    return true;
  }
  SDL_FillRect(ws, NULL, SDL_MapRGB(ws->format, 0x00, 0x00, 0x00));
  if (g_image) {
    SDL_BlitSurface(g_image, NULL, ws, NULL);
  }
  SDL_UpdateWindowSurface(window);
  return true;
}

bool  //
load_image(const char* filename) {
  if (g_image) {
    SDL_FreeSurface(g_image);
    g_image = NULL;
  }

  SDL_RWops* rw = SDL_RWFromFile(filename, "rb");
  if (!rw) {
    fprintf(stderr, "main: SDL_RWFromFile(\"%s\"): %s\n", filename,
            SDL_GetError());
    return false;
  }

  constexpr bool take_ownership_of_rw = true;
  if (g_load_via_sdl_image) {
    g_image = IMG_Load_RW(rw, take_ownership_of_rw);
    if (!g_image) {
      fprintf(stderr, "main: IMG_Load_RW(\"%s\"): %s\n", filename,
              SDL_GetError());
      return false;
    }
  } else {
    std::pair<SDL_Surface*, std::string> p =
        Wuffs_Load_RW(rw, take_ownership_of_rw);
    if (!p.second.empty()) {
      fprintf(stderr, "main: Wuffs_Load_RW(\"%s\"): %s\n", filename,
              p.second.c_str());
      return false;
    }
    g_image = p.first;
  }

  return true;
}

int  //
main(int argc, char** argv) {
  if (argc != 2) {
    fprintf(stderr, "usage: %s filename\n", argv[0]);
    return 1;
  }
  if (SDL_Init(SDL_INIT_VIDEO) < 0) {
    fprintf(stderr, "main: SDL_Init: %s\n", SDL_GetError());
    return 1;
  }
  SDL_Window* window =
      SDL_CreateWindow("sdl-imageviewer", SDL_WINDOWPOS_UNDEFINED,
                       SDL_WINDOWPOS_UNDEFINED, 1024, 768, SDL_WINDOW_SHOWN);
  if (!window) {
    fprintf(stderr, "main: SDL_CreateWindow: %s\n", SDL_GetError());
    return 1;
  }

  if (!load_image(argv[1])) {
    return 1;
  }

  while (true) {
    SDL_Event event;
    if (!SDL_WaitEvent(&event)) {
      fprintf(stderr, "main: SDL_WaitEvent: %s\n", SDL_GetError());
      return 1;
    }

    switch (event.type) {
      case SDL_QUIT:
        goto cleanup;

      case SDL_WINDOWEVENT:
        switch (event.window.event) {
          case SDL_WINDOWEVENT_EXPOSED:
            if (!draw(window)) {
              return 1;
            }
            break;
        }
        break;

      case SDL_KEYDOWN:
        switch (event.key.keysym.sym) {
          case SDLK_ESCAPE:
            goto cleanup;
          case SDLK_TAB:
            g_load_via_sdl_image = !g_load_via_sdl_image;
            printf("Switched to %s.\n",
                   g_load_via_sdl_image ? "SDL_image" : "Wuffs");
            if (!load_image(argv[1]) || !draw(window)) {
              return 1;
            }
            break;
        }
        break;
    }
  }

cleanup:
  if (g_image) {
    SDL_FreeSurface(g_image);
    g_image = NULL;
  }
  SDL_DestroyWindow(window);
  SDL_Quit();
  return 0;
}
<|endoftext|>


<commit_before>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/

#include<fstream>
#include<iostream>
#include<mutex>

#include"ork/memory.hpp"
#include ORK_FILE_INCLUDE

#include"boost/core/null_deleter.hpp"
#include"boost/log/expressions.hpp"
#include"boost/log/sinks/sync_frontend.hpp"
#include"boost/log/sinks/text_ostream_backend.hpp"

namespace ork {

const ork::string debug_trace(ORK("debug_trace"));
const ork::string output_data(ORK("output_data"));

const ork::string&to_string(const log_channel val) {
	switch(val) {
	case log_channel::debug_trace:
		return debug_trace;
	case log_channel::output_data:
		return output_data;
	};
	ORK_UNREACHABLE
}
log_channel string2log_channel(const ork::string&str) {
	if(str == output_data) {
		return log_channel::output_data;
	}
	if(str == output_data) {
		return log_channel::output_data;
	}
	ORK_THROW(ORK("Invalid log_channel: ") << str);
}

const ork::string trace(ORK("trace"));
const ork::string debug(ORK("debug"));
const ork::string info(ORK("info"));
const ork::string warning(ORK("warning"));
const ork::string error(ORK("error"));
const ork::string fatal(ORK("fatal"));

const ork::string&to_string(const severity_level val) {
	switch(val) {
	case severity_level::trace:
		return trace;
	case severity_level::debug:
		return debug;
	case severity_level::info:
		return info;
	case severity_level::warning:
		return warning;
	case severity_level::error:
		return error;
	case severity_level::fatal:
		return fatal;
	};
	ORK_UNREACHABLE
}
severity_level string2severity_level(const ork::string&str) {
	if(str == trace) {
		return severity_level::trace;
	}
	if(str == debug) {
		return severity_level::debug;
	}
	if(str == info) {
		return severity_level::info;
	}
	if(str == warning) {
		return severity_level::warning;
	}
	if(str == error) {
		return severity_level::error;
	}
	if(str == fatal) {
		return severity_level::fatal;
	}
	ORK_THROW(ORK("Invalid severity_level: ") << str);
}

//This is little more than a synchronous wrapper for an ostream
template<class D>
class log_sink {
public:
	using stream_ptr = std::unique_ptr<o_stream, D>;
private:
	std::unique_ptr<o_stream, D>_stream;
	std::mutex _mutex;
public:
	log_sink(std::unique_ptr<o_stream, D>&&stream_) : _stream{ std::move(stream_) }, _mutex{ } {}
	ORK_MOVE_ONLY(log_sink)
public:
	void log(const string&message) {
		std::lock_guard<std::mutex>lock(_mutex);
		*_stream << message;
	}
};

struct log_stream::impl {
public:
	std::unique_ptr<o_stream>stream;
public:
	impl(std::unique_ptr<o_stream>&&stream_) :stream{ std::move(stream_) } {}
};

log_stream::log_stream(std::unique_ptr<o_stream>&&stream) : _pimpl{ new impl{ std::move(stream) } } {}
log_stream::~log_stream() {}

#define LOG_STREAM_OPERATOR(TYPE) \
log_stream& log_stream::operator<< (const TYPE val) {\
	*(_pimpl->stream) << val;\
	return *this;\
}
LOG_STREAM_OPERATOR(bool)
LOG_STREAM_OPERATOR(short)
LOG_STREAM_OPERATOR(unsigned short)
LOG_STREAM_OPERATOR(int)
LOG_STREAM_OPERATOR(unsigned)
LOG_STREAM_OPERATOR(long)
LOG_STREAM_OPERATOR(unsigned long)
LOG_STREAM_OPERATOR(long long)
LOG_STREAM_OPERATOR(unsigned long long)
LOG_STREAM_OPERATOR(float)
LOG_STREAM_OPERATOR(double)
LOG_STREAM_OPERATOR(long double)

#undef LOG_STREAM_OPERATOR
#define LOG_STREAM_OPERATOR(TYPE) \
log_stream& log_stream::operator<< (const TYPE val) {\
	*(_pimpl->stream) << ORK_BYTE_2_STR(val);\
	return *this;\
}

LOG_STREAM_OPERATOR(char)
LOG_STREAM_OPERATOR(char*)
LOG_STREAM_OPERATOR(bstring&)

#undef LOG_STREAM_OPERATOR
#define LOG_STREAM_OPERATOR(TYPE) \
log_stream& log_stream::operator<< (const TYPE val) {\
	*(_pimpl->stream) << ORK_WIDE_2_STR(val);\
	return *this;\
}

LOG_STREAM_OPERATOR(wchar_t)
LOG_STREAM_OPERATOR(wchar_t*)
LOG_STREAM_OPERATOR(wstring&)

log_stream& log_stream::operator<< (const void* val) {
	*(_pimpl->stream) << val;
	return *this;
}
log_stream& log_stream::operator<< (const std::streambuf* sb) {
	*(_pimpl->stream) << sb;
	return *this;
}
log_stream& log_stream::operator<< (std::ostream& (*pf)(std::ostream&)) {
	*(_pimpl->stream) << pf;
	return *this;
}
log_stream& log_stream::operator<< (std::ios& (*pf)(std::ios&)) {
	*(_pimpl->stream) << pf;
	return *this;
}
log_stream& log_stream::operator<< (std::ios_base& (*pf)(std::ios_base&)) {
	*(_pimpl->stream) << pf;
	return *this;
}

o_stream&operator<<(o_stream&strm, log_channel chan) {
	static const char_t* strings[] = {
		  ORK("Debug/Trace")
		, ORK("Output/Data")
	};

	const size_t index = static_cast<size_t>(chan);
	if(index < sizeof(strings) / sizeof(*strings)) strm << strings[index];
	else strm << index;

	return strm;
}

o_stream&operator<<(o_stream&strm, severity_level sev) {
	static const char_t* strings[] = {
		//These are fixed width, maybe this should be done in formatting instead
		  ORK("TRACE")
		, ORK("DEBUG")
		, ORK("INFO ")
		, ORK("WARN ")
		, ORK("ERROR")
		, ORK("FATAL")
	};

	const size_t index = static_cast<size_t>(sev);
	if(index < sizeof(strings) / sizeof(*strings)) strm << strings[index];
	else strm << index;

	return strm;
}

BOOST_LOG_ATTRIBUTE_KEYWORD(severity, BORK("Severity"), severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(channel, BORK("Channel"), log_channel)

namespace sources = boost::log::sources;
namespace sinks = boost::log::sinks;
namespace expr = boost::log::expressions;

#if ORK_UNICODE
typedef boost::log::wformatting_ostream formatting_ostream;
#else
typedef boost::log::formatting_ostream formatting_ostream;
#endif

boost::shared_ptr<o_stream>open_log(const file::path&file_name) {
	if(!file::ensure_directory(file_name))ORK_THROW(ORK("Could not create directory : ") << file_name)
		of_stream* p_stream = new of_stream();
	p_stream->open(file_name);//std::ios::app | std::ios::ate
	if(p_stream->fail())ORK_THROW(ORK("Error opening log : ") << file_name)
		//p_stream->rdbuf()->pubsetbuf(0, 0);//Less performance, more likely to catch error messages
		return boost::shared_ptr<o_stream>(p_stream);
}

void trace_formatter(const boost::log::record_view& rec, formatting_ostream& strm) {
	//Extract the Line attribute value that is added by the macro and put it into the stream
	const boost::log::value_ref<string> fullname = boost::log::extract<string>(BORK("File"), rec);
	const file::path fullpath(file::path(fullname.get()));
	string file(fullpath.filename().ORK_GEN_STR());
	file.resize(28, ORK(' '));
	string line(boost::log::extract<string>(BORK("Line"), rec).get());
	line.resize(4, ORK(' '));
	string function(boost::log::extract<string>(BORK("Function"), rec).get());
	function.resize(40, ORK(' '));

	//Simplified syntax is possible if attribute keywords are used.
	strm << ORK("[") << rec[severity] << ORK("]:");
	//Finally, put the record message to the stream
	strm << file << ORK("(") << line << ORK("):") << function << ORK("-- ") << rec[expr::message];
}

struct logger::impl {
public:
	typedef logger::channel_source_type channel_source_type;
	typedef logger::severity_channel_source_type severity_channel_source_type;
#if ORK_UNICODE
	typedef sinks::wtext_ostream_backend backend_type;
#else
	typedef sinks::text_ostream_backend backend_type;
#endif
	//This is not really a logging application so we do not need file features like rotation, etc.
	typedef sinks::synchronous_sink<backend_type> sink_type;
public:
	severity_channel_source_type trace;
	channel_source_type output;
	boost::shared_ptr<sink_type>p_trace_sink;
	boost::shared_ptr<sink_type>p_output_sink;
public:
	impl(const file::path&directory)
		: trace(boost::log::keywords::channel = log_channel::debug_trace)
		, output(boost::log::keywords::channel = log_channel::output_data) {
#if !ORK_STL_HAS_FILE
		/*
		Prevent crash on termination, see
		http://www.boost.org/doc/libs/1_60_0/libs/log/doc/html/log/rationale/why_crash_on_term.html
		*/
		file::path::codecvt();
#endif
		/*
		Create backends and for each attach both a console and file stream
		TODO: Some error handling for the files
		*/
		boost::shared_ptr<backend_type>trace_backend = boost::make_shared<backend_type>();
		trace_backend->add_stream(boost::shared_ptr<o_stream>(&ORK_CLOG, boost::null_deleter()));
		trace_backend->add_stream(open_log(directory / ORK("trace.log")));
		trace_backend->auto_flush(true);//Enable auto-flushing because we are using this for errors
										//Wrap it into a mutithreaded frontend
										//boost::shared_ptr<sink_type> trace_sink(new sink_type(trace_backend));
		p_trace_sink.reset(new sink_type(trace_backend));
		p_trace_sink->set_filter((
			expr::has_attr(channel) && channel == log_channel::debug_trace
#if !ORK_DEBUG && 0
			&& expr::has_attr(severity) && severity != severity_level::trace
#endif
			));
		//Add some standard formatting at the beginning
		p_trace_sink->set_formatter(&trace_formatter);

		boost::shared_ptr<backend_type>output_backend = boost::make_shared<backend_type>();
		output_backend->add_stream(boost::shared_ptr<o_stream>(&ORK_COUT, boost::null_deleter()));
		output_backend->add_stream(open_log(directory / ORK("output.log")));
		//Wrap it into a mutithreaded frontend
		//boost::shared_ptr<sink_type> output_sink(new sink_type(output_backend));
		p_output_sink.reset(new sink_type(output_backend));
		p_output_sink->set_filter((expr::has_attr(channel) && channel == log_channel::output_data));

		//Register with the core so that logging output can begin
		boost::shared_ptr<boost::log::core>core = boost::log::core::get();
		core->add_sink(p_trace_sink);
		core->add_sink(p_output_sink);
	}
	void flush_all() {
		p_trace_sink->flush();
		p_output_sink->flush();
	}
};

logger::logger(const file::path&log_directory) : p_impl(new impl(log_directory)) {}

//The logger must be terminated before main exits, so not a global!
logger::~logger() {
	/*
	Prevent crash on termination, see
	http://www.boost.org/doc/libs/1_60_0/libs/log/doc/html/log/rationale/why_crash_on_term.html
	*/
	boost::log::core::get()->remove_all_sinks();
}

logger::severity_channel_source_type& logger::log() {
	return p_impl->trace;
}

logger::channel_source_type& logger::lout() {
	return p_impl->output;
}

void logger::flush_all() {
	p_impl->flush_all();
}

logger*_g_log = nullptr;
int g_log(const string&directory) {
	static logger log(directory);
	_g_log = &log;
	return 0;
}
logger& g_log() {
	return *_g_log;
}

}//namespace ork
<commit_msg>Changed interface for open_file_log_stream<commit_after>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/

#include<fstream>
#include<iostream>
#include<mutex>

#include"ork/memory.hpp"
#include ORK_FILE_INCLUDE

#include"boost/core/null_deleter.hpp"
#include"boost/log/expressions.hpp"
#include"boost/log/sinks/sync_frontend.hpp"
#include"boost/log/sinks/text_ostream_backend.hpp"

namespace ork {

const ork::string debug_trace(ORK("debug_trace"));
const ork::string output_data(ORK("output_data"));

const ork::string&to_string(const log_channel val) {
	switch(val) {
	case log_channel::debug_trace:
		return debug_trace;
	case log_channel::output_data:
		return output_data;
	};
	ORK_UNREACHABLE
}
log_channel string2log_channel(const ork::string&str) {
	if(str == output_data) {
		return log_channel::output_data;
	}
	if(str == output_data) {
		return log_channel::output_data;
	}
	ORK_THROW(ORK("Invalid log_channel: ") << str);
}

const ork::string trace(ORK("trace"));
const ork::string debug(ORK("debug"));
const ork::string info(ORK("info"));
const ork::string warning(ORK("warning"));
const ork::string error(ORK("error"));
const ork::string fatal(ORK("fatal"));

const ork::string&to_string(const severity_level val) {
	switch(val) {
	case severity_level::trace:
		return trace;
	case severity_level::debug:
		return debug;
	case severity_level::info:
		return info;
	case severity_level::warning:
		return warning;
	case severity_level::error:
		return error;
	case severity_level::fatal:
		return fatal;
	};
	ORK_UNREACHABLE
}
severity_level string2severity_level(const ork::string&str) {
	if(str == trace) {
		return severity_level::trace;
	}
	if(str == debug) {
		return severity_level::debug;
	}
	if(str == info) {
		return severity_level::info;
	}
	if(str == warning) {
		return severity_level::warning;
	}
	if(str == error) {
		return severity_level::error;
	}
	if(str == fatal) {
		return severity_level::fatal;
	}
	ORK_THROW(ORK("Invalid severity_level: ") << str);
}

//This is little more than a synchronous wrapper for an ostream
template<class D>
class log_sink {
public:
	using stream_ptr = std::unique_ptr<o_stream, D>;
private:
	std::unique_ptr<o_stream, D>_stream;
	std::mutex _mutex;
public:
	log_sink(std::unique_ptr<o_stream, D>&&stream_) : _stream{ std::move(stream_) }, _mutex{ } {}
	ORK_MOVE_ONLY(log_sink)
public:
	void log(const string&message) {
		std::lock_guard<std::mutex>lock(_mutex);
		*_stream << message;
	}
};

std::unique_ptr<o_stream, default_deleter<o_stream>>open_file_log_stream(const file::path&file_name) {
	if(!file::ensure_directory(file_name)) {
		ORK_THROW(ORK("Could not create directory : ") << file_name.ORK_GEN_STR())
	}
	of_stream* p_stream = new of_stream();
	p_stream->open(file_name);//std::ios::app | std::ios::ate
	if(p_stream->fail()) {
		ORK_THROW(ORK("Error opening log : ") << file_name)
	}
	//p_stream->rdbuf()->pubsetbuf(0, 0);//Less performance, more likely to catch error messages
	return std::unique_ptr<o_stream, default_deleter<o_stream>>(p_stream);
}

struct log_stream::impl {
public:
	std::unique_ptr<o_stream>stream;
public:
	impl(std::unique_ptr<o_stream>&&stream_) :stream{ std::move(stream_) } {}
};

log_stream::log_stream(std::unique_ptr<o_stream>&&stream) : _pimpl{ new impl{ std::move(stream) } } {}
log_stream::~log_stream() {}

#define LOG_STREAM_OPERATOR(TYPE) \
log_stream& log_stream::operator<< (const TYPE val) {\
	*(_pimpl->stream) << val;\
	return *this;\
}
LOG_STREAM_OPERATOR(bool)
LOG_STREAM_OPERATOR(short)
LOG_STREAM_OPERATOR(unsigned short)
LOG_STREAM_OPERATOR(int)
LOG_STREAM_OPERATOR(unsigned)
LOG_STREAM_OPERATOR(long)
LOG_STREAM_OPERATOR(unsigned long)
LOG_STREAM_OPERATOR(long long)
LOG_STREAM_OPERATOR(unsigned long long)
LOG_STREAM_OPERATOR(float)
LOG_STREAM_OPERATOR(double)
LOG_STREAM_OPERATOR(long double)

#undef LOG_STREAM_OPERATOR
#define LOG_STREAM_OPERATOR(TYPE) \
log_stream& log_stream::operator<< (const TYPE val) {\
	*(_pimpl->stream) << ORK_BYTE_2_STR(val);\
	return *this;\
}

LOG_STREAM_OPERATOR(char)
LOG_STREAM_OPERATOR(char*)
LOG_STREAM_OPERATOR(bstring&)

#undef LOG_STREAM_OPERATOR
#define LOG_STREAM_OPERATOR(TYPE) \
log_stream& log_stream::operator<< (const TYPE val) {\
	*(_pimpl->stream) << ORK_WIDE_2_STR(val);\
	return *this;\
}

LOG_STREAM_OPERATOR(wchar_t)
LOG_STREAM_OPERATOR(wchar_t*)
LOG_STREAM_OPERATOR(wstring&)

log_stream& log_stream::operator<< (const void* val) {
	*(_pimpl->stream) << val;
	return *this;
}
log_stream& log_stream::operator<< (const std::streambuf* sb) {
	*(_pimpl->stream) << sb;
	return *this;
}
log_stream& log_stream::operator<< (std::ostream& (*pf)(std::ostream&)) {
	*(_pimpl->stream) << pf;
	return *this;
}
log_stream& log_stream::operator<< (std::ios& (*pf)(std::ios&)) {
	*(_pimpl->stream) << pf;
	return *this;
}
log_stream& log_stream::operator<< (std::ios_base& (*pf)(std::ios_base&)) {
	*(_pimpl->stream) << pf;
	return *this;
}

o_stream&operator<<(o_stream&strm, log_channel chan) {
	static const char_t* strings[] = {
		  ORK("Debug/Trace")
		, ORK("Output/Data")
	};

	const size_t index = static_cast<size_t>(chan);
	if(index < sizeof(strings) / sizeof(*strings)) strm << strings[index];
	else strm << index;

	return strm;
}

o_stream&operator<<(o_stream&strm, severity_level sev) {
	static const char_t* strings[] = {
		//These are fixed width, maybe this should be done in formatting instead
		  ORK("TRACE")
		, ORK("DEBUG")
		, ORK("INFO ")
		, ORK("WARN ")
		, ORK("ERROR")
		, ORK("FATAL")
	};

	const size_t index = static_cast<size_t>(sev);
	if(index < sizeof(strings) / sizeof(*strings)) strm << strings[index];
	else strm << index;

	return strm;
}

BOOST_LOG_ATTRIBUTE_KEYWORD(severity, BORK("Severity"), severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(channel, BORK("Channel"), log_channel)

namespace sources = boost::log::sources;
namespace sinks = boost::log::sinks;
namespace expr = boost::log::expressions;

#if ORK_UNICODE
typedef boost::log::wformatting_ostream formatting_ostream;
#else
typedef boost::log::formatting_ostream formatting_ostream;
#endif

void trace_formatter(const boost::log::record_view& rec, formatting_ostream& strm) {
	//Extract the Line attribute value that is added by the macro and put it into the stream
	const boost::log::value_ref<string> fullname = boost::log::extract<string>(BORK("File"), rec);
	const file::path fullpath(file::path(fullname.get()));
	string file(fullpath.filename().ORK_GEN_STR());
	file.resize(28, ORK(' '));
	string line(boost::log::extract<string>(BORK("Line"), rec).get());
	line.resize(4, ORK(' '));
	string function(boost::log::extract<string>(BORK("Function"), rec).get());
	function.resize(40, ORK(' '));

	//Simplified syntax is possible if attribute keywords are used.
	strm << ORK("[") << rec[severity] << ORK("]:");
	//Finally, put the record message to the stream
	strm << file << ORK("(") << line << ORK("):") << function << ORK("-- ") << rec[expr::message];
}

struct logger::impl {
public:
	typedef logger::channel_source_type channel_source_type;
	typedef logger::severity_channel_source_type severity_channel_source_type;
#if ORK_UNICODE
	typedef sinks::wtext_ostream_backend backend_type;
#else
	typedef sinks::text_ostream_backend backend_type;
#endif
	//This is not really a logging application so we do not need file features like rotation, etc.
	typedef sinks::synchronous_sink<backend_type> sink_type;
public:
	severity_channel_source_type trace;
	channel_source_type output;
	boost::shared_ptr<sink_type>p_trace_sink;
	boost::shared_ptr<sink_type>p_output_sink;
public:
	impl(const file::path&directory)
		: trace(boost::log::keywords::channel = log_channel::debug_trace)
		, output(boost::log::keywords::channel = log_channel::output_data) {
#if !ORK_STL_HAS_FILE
		/*
		Prevent crash on termination, see
		http://www.boost.org/doc/libs/1_60_0/libs/log/doc/html/log/rationale/why_crash_on_term.html
		*/
		file::path::codecvt();
#endif
		/*
		Create backends and for each attach both a console and file stream
		TODO: Some error handling for the files
		*/
		boost::shared_ptr<backend_type>trace_backend = boost::make_shared<backend_type>();
		trace_backend->add_stream(boost::shared_ptr<o_stream>(&ORK_CLOG, boost::null_deleter()));
		trace_backend->add_stream(open_log(directory / ORK("trace.log")));
		trace_backend->auto_flush(true);//Enable auto-flushing because we are using this for errors
										//Wrap it into a mutithreaded frontend
										//boost::shared_ptr<sink_type> trace_sink(new sink_type(trace_backend));
		p_trace_sink.reset(new sink_type(trace_backend));
		p_trace_sink->set_filter((
			expr::has_attr(channel) && channel == log_channel::debug_trace
#if !ORK_DEBUG && 0
			&& expr::has_attr(severity) && severity != severity_level::trace
#endif
			));
		//Add some standard formatting at the beginning
		p_trace_sink->set_formatter(&trace_formatter);

		boost::shared_ptr<backend_type>output_backend = boost::make_shared<backend_type>();
		output_backend->add_stream(boost::shared_ptr<o_stream>(&ORK_COUT, boost::null_deleter()));
		output_backend->add_stream(open_log(directory / ORK("output.log")));
		//Wrap it into a mutithreaded frontend
		//boost::shared_ptr<sink_type> output_sink(new sink_type(output_backend));
		p_output_sink.reset(new sink_type(output_backend));
		p_output_sink->set_filter((expr::has_attr(channel) && channel == log_channel::output_data));

		//Register with the core so that logging output can begin
		boost::shared_ptr<boost::log::core>core = boost::log::core::get();
		core->add_sink(p_trace_sink);
		core->add_sink(p_output_sink);
	}
	void flush_all() {
		p_trace_sink->flush();
		p_output_sink->flush();
	}
};

logger::logger(const file::path&log_directory) : p_impl(new impl(log_directory)) {}

//The logger must be terminated before main exits, so not a global!
logger::~logger() {
	/*
	Prevent crash on termination, see
	http://www.boost.org/doc/libs/1_60_0/libs/log/doc/html/log/rationale/why_crash_on_term.html
	*/
	boost::log::core::get()->remove_all_sinks();
}

logger::severity_channel_source_type& logger::log() {
	return p_impl->trace;
}

logger::channel_source_type& logger::lout() {
	return p_impl->output;
}

void logger::flush_all() {
	p_impl->flush_all();
}

logger*_g_log = nullptr;
int g_log(const string&directory) {
	static logger log(directory);
	_g_log = &log;
	return 0;
}
logger& g_log() {
	return *_g_log;
}

}//namespace ork
<|endoftext|>


<commit_before>// vi:cin:et:sw=4 ts=4
//
//  drafter.cc
//
//  Created by Jiri Kratochvil on 2015-02-11
//  Copyright (c) 2015 Apiary Inc. All rights reserved.
//

#include "snowcrash.h"
#include "SectionParserData.h"  // snowcrash::BlueprintParserOptions

#include "sos.h"
#include "sosJSON.h"
#include "sosYAML.h"

#include "SerializeResult.h"

#include "reporting.h"
#include "config.h"
#include "stream.h"

namespace sc = snowcrash;

/**
 *  \brief  return instance sos::Serializer based on \param `format`
 *
 *  \param format - output format for serialization
 */
sos::Serialize* CreateSerializer(const drafter::SerializeFormat& format)
{
    if (format == drafter::JSONFormat) {
        return new sos::SerializeJSON;
    }

    return new sos::SerializeYAML;
}

/**
 * \brief Serialize sos::Object into stream
 */
void Serialization(std::ostream *stream,
                   const sos::Object& object,
                   sos::Serialize* serializer)
{
    serializer->process(object, *stream);
    *stream << "\n";
    *stream << std::flush;
}

int main(int argc, const char *argv[])
{
    Config config;
    ParseCommadLineOptions(argc, argv, config);

    sc::BlueprintParserOptions options = 0;  // Or snowcrash::RequireBlueprintNameOption

    if (config.sourceMap) {
        options |= snowcrash::ExportSourcemapOption;
    }

    std::stringstream inputStream;
    std::auto_ptr<std::istream> in(CreateStreamFromName<std::istream>(config.input));
    inputStream << in->rdbuf();

    sc::ParseResult<sc::Blueprint> blueprint;
    sc::parse(inputStream.str(), options, blueprint);

    sos::Serialize* serializer = CreateSerializer(config.format);
    std::ostream *out = CreateStreamFromName<std::ostream>(config.output);

    try {
        sos::Object resultObject = drafter::WrapResult(blueprint, drafter::WrapperOptions(config.astType, config.sourceMap));

        if (!config.validate) { // If not validate, we serialize
            Serialization(out, resultObject, serializer);
        }
    }
    catch (snowcrash::Error& e) {
        blueprint.report.error = e;
    }
    catch (std::exception& e) {
        blueprint.report.error.message = e.what();
        blueprint.report.error.code = snowcrash::ApplicationError;
    }

    delete out;
    delete serializer;

    PrintReport(blueprint.report, inputStream.str(), config.lineNumbers);

    return blueprint.report.error.code;
}
<commit_msg>sc return sourcemap always<commit_after>// vi:cin:et:sw=4 ts=4
//
//  drafter.cc
//
//  Created by Jiri Kratochvil on 2015-02-11
//  Copyright (c) 2015 Apiary Inc. All rights reserved.
//

#include "snowcrash.h"
#include "SectionParserData.h"  // snowcrash::BlueprintParserOptions

#include "sos.h"
#include "sosJSON.h"
#include "sosYAML.h"

#include "SerializeResult.h"

#include "reporting.h"
#include "config.h"
#include "stream.h"

namespace sc = snowcrash;

/**
 *  \brief  return instance sos::Serializer based on \param `format`
 *
 *  \param format - output format for serialization
 */
sos::Serialize* CreateSerializer(const drafter::SerializeFormat& format)
{
    if (format == drafter::JSONFormat) {
        return new sos::SerializeJSON;
    }

    return new sos::SerializeYAML;
}

/**
 * \brief Serialize sos::Object into stream
 */
void Serialization(std::ostream *stream,
                   const sos::Object& object,
                   sos::Serialize* serializer)
{
    serializer->process(object, *stream);
    *stream << "\n";
    *stream << std::flush;
}

int main(int argc, const char *argv[])
{
    Config config;
    ParseCommadLineOptions(argc, argv, config);

    std::stringstream inputStream;
    std::auto_ptr<std::istream> in(CreateStreamFromName<std::istream>(config.input));
    inputStream << in->rdbuf();

    sc::ParseResult<sc::Blueprint> blueprint;
    sc::parse(inputStream.str(), snowcrash::ExportSourcemapOption, blueprint);

    sos::Serialize* serializer = CreateSerializer(config.format);
    std::ostream *out = CreateStreamFromName<std::ostream>(config.output);

    try {
        sos::Object resultObject = drafter::WrapResult(blueprint, drafter::WrapperOptions(config.astType, config.sourceMap));

        if (!config.validate) { // If not validate, we serialize
            Serialization(out, resultObject, serializer);
        }
    }
    catch (snowcrash::Error& e) {
        blueprint.report.error = e;
    }
    catch (std::exception& e) {
        blueprint.report.error.message = e.what();
        blueprint.report.error.code = snowcrash::ApplicationError;
    }

    delete out;
    delete serializer;

    PrintReport(blueprint.report, inputStream.str(), config.lineNumbers);

    return blueprint.report.error.code;
}
<|endoftext|>


<commit_before>//============================================================================
// Name        : Actuator.cpp
// Author      : Lunatic
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>

#include "alarm.h"
#include "engine.h"

#define NAME        "SonarXS"
#define VERSION     NAME "1.0"
#define COPYRIGHT	VERSION "  Copyright (C) 1990-2014  Lunatic Zheng, ZH"

static const char *progname = NAME;

static void help() {
	fprintf(stderr, "usage: %s [options] [filenames]\n"
			"  -name           read file named name(omit this argument)\n"
			"  -d <level>      set the logging level\n"
			"  -v              show version information\n"
			"  --version       show version information\n"
			"  -h              help information\n"
			"  --help          help information\n", progname);
}

static void usage(const char* message) {
	if (*message == '-')
		fprintf(stderr, "%s: unrecognized option %s\n", progname, message);
	else
		fprintf(stderr, "%s: %s\n", progname, message);
	help();
	exit(EXIT_FAILURE);
}
//not found return -1
static int str2level(const std::string& lv) {
	int level = -1;
	if (lv == "DEBUG")
		level = Script::Log::DEBUG;
	else if (lv == "INFO")
		level = Script::Log::INFO;
	else if (lv == "WARN")
		level = Script::Log::WARN;
	else if (lv == "ERROR")
		level = Script::Log::ERROR;
	return level;

}

static int doargs(int argc, char* argv[]) {
#define IS(s) (strcmp(argv[i],s)==0)

	int i, name = 0, version = 0, helpp = 0, log = 0;

	if (argv[0] != NULL && *argv[0] != 0)
		progname = argv[0];

	for (i = 1; i < argc; i++) {
		if (*argv[i] != '-')
			break;
		else if (IS("-name")) {
			if (i + 1 < argc) {
				name = ++i;
			} else
				usage("Illegal args!");
		} else if (IS("-d")) {
			if (i + 1 < argc) {
				log = str2level(argv[i + 1]);
				if (log == -1)
					usage(argv[i + 1]);
				i++;
			} else
				usage("Illegal args!");

		} else if (IS("-h") || IS("--help"))
			helpp++;
		else if (IS("-v") || IS("--version"))
			++version;
		else
			/* unknown option */
			usage(argv[i]);
	}
	if (version) {
		printf("%s\n", COPYRIGHT);
		if (version == argc - 1)
			exit(EXIT_SUCCESS);
	}
	if (helpp) {
		help();
		if (helpp == argc - 1)
			exit(EXIT_SUCCESS);
	}
	if (log) {
		Script::Log::level = (Script::Log::Level) log;
	}
#undef IS
	return name == 0 ? i : name;
}

static std::string& get_code(const std::string& file, std::string& code) {
	std::ifstream is(file.c_str());
	if (!is) {
		fprintf(stderr, "%s: not found this file '%s'.\n", progname, file.c_str());
		exit(EXIT_FAILURE);
	}
	std::string s;
	while (std::getline(is, s)) {
		code = code.append(s) + '\n'; //注意： 各平台的换行符不能统一 在读取的时候统一用'\n'替换
	}
	return code;
}

int main(int argc, char **argv) {
	Script::Log::level = Script::Log::DEBUG;

	int i = doargs(argc, argv);
	argc -= i;
	argv += i;
	if (argc <= 0)
		usage("no input files given");

	Script::Log::debug("Start:");

	std::string text;
	Script::Log::debug("读入文件：%s ", *argv);
	get_code(*argv, text);

	Script::Env env; //执行环境
	env.load(text);

	Script::Engine engine; //执行器
	try {
		engine.launch(env); //执行
	} catch (const char *s) {
		std::cout << s << std::endl;
	}

	Script::Log::debug("End!");

	return 0;
}

<commit_msg>link style<commit_after>//============================================================================
// Name        : Actuator.cpp
// Author      : Lunatic
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>

#include "alarm.h"
#include "engine.h"

#define NAME        "SonarXS"
#define VERSION     NAME "1.0"
#define COPYRIGHT	VERSION "  Copyright (C) 1990-2014  Lunatic Zheng, ZH"

static const char *progname = NAME;

static void help() {
	fprintf(stderr, "usage: %s [options] [filenames]\n"
			"  -name           read file named name(omit this argument)\n"
			"  -d <level>      set the logging level\n"
			"  -v              show version information\n"
			"  --version       show version information\n"
			"  -h              help information\n"
			"  --help          help information\n", progname);
}

static void usage(const char* message) {
	if (*message == '-')
		fprintf(stderr, "%s: unrecognized option %s\n", progname, message);
	else
		fprintf(stderr, "%s: %s\n", progname, message);
	help();
	exit(EXIT_FAILURE);
}
//not found return -1
static int str2level(const std::string& lv) {
	int level = -1;
	if (lv == "DEBUG")
		level = Script::Log::DEBUG;
	else if (lv == "INFO")
		level = Script::Log::INFO;
	else if (lv == "WARN")
		level = Script::Log::WARN;
	else if (lv == "ERROR")
		level = Script::Log::ERROR;
	return level;

}

static int doargs(int argc, char* argv[]) {
#define IS(s) (strcmp(argv[i],s)==0)

	int i, name = 0, version = 0, helpp = 0, log = 0;

	if (argv[0] != NULL && *argv[0] != 0)
		progname = argv[0];

	for (i = 1; i < argc; i++) {
		if (*argv[i] != '-')
			break;
		else if (IS("-name")) {
			if (i + 1 < argc) {
				name = ++i;
			} else
				usage("Illegal args!");
		} else if (IS("-d")) {
			if (i + 1 < argc) {
				log = str2level(argv[i + 1]);
				if (log == -1)
					usage(argv[i + 1]);
				i++;
			} else
				usage("Illegal args!");

		} else if (IS("-h") || IS("--help"))
			helpp++;
		else if (IS("-v") || IS("--version"))
			++version;
		else
			/* unknown option */
			usage(argv[i]);
	}
	if (version) {
		printf("%s\n", COPYRIGHT);
		if (version == argc - 1)
			exit(EXIT_SUCCESS);
	}
	if (helpp) {
		help();
		if (helpp == argc - 1)
			exit(EXIT_SUCCESS);
	}
	if (log) {
		Script::Log::level = (Script::Log::Level) log;
	}
#undef IS
	return name == 0 ? i : name;
}

static std::string& get_code(const std::string& file, std::string& code) {
	std::ifstream is(file.c_str());
	if (!is) {
		fprintf(stderr, "%s: not found this file '%s'.\n", progname, file.c_str());
		exit(EXIT_FAILURE);
	}
	std::string s;
	while (std::getline(is, s)) {
		code.append(s) += '\n';//注意： 各平台的换行符不能统一 在读取的时候统一用'\n'替换
	}
	return code;
}

int main(int argc, char **argv) {
	Script::Log::level = Script::Log::DEBUG;

	int i = doargs(argc, argv);
	argc -= i;
	argv += i;
	if (argc <= 0)
		usage("no input files given");

	Script::Log::debug("Start:");

	std::string text;
	Script::Log::debug("读入文件：%s ", *argv);
	get_code(*argv, text);

	Script::Env env; //执行环境
	env.load(text);

	Script::Engine engine; //执行器
	try {
		engine.launch(env); //执行
	} catch (const char *s) {
		std::cout << s << std::endl;
	}

	Script::Log::debug("End!");

	return 0;
}

<|endoftext|>


<commit_before>#include "../ui.h"
#include "ui-node.h"
#include "nbind/api.h"

class UiForm : public UiControl {
  public:
	UiForm();
	DEFINE_CONTROL_METHODS()
	void append(const char *label, UiControl *c, bool stretchy);
	void deleteAt(int index);
	bool getPadded();
	void setPadded(bool padded);
};

UiForm::UiForm() : UiControl((uiControl *)uiNewForm()) {}

void UiForm::append(const char *label, UiControl *c, bool stretchy) {
	uiFormAppend((uiForm *)getHandle(), label, c->getHandle(), stretchy);
}

void UiForm::deleteAt(int index) {
	uiFormDelete((uiForm *)getHandle(), index);
}

bool UiForm::getPadded() {
	return uiFormPadded((uiForm *)getHandle());
}

void UiForm::setPadded(bool padded) {
	uiFormSetPadded((uiForm *)getHandle(), padded);
}

INHERITS_CONTROL_METHODS(UiForm)

NBIND_CLASS(UiForm) {
	construct<>();
	method(append);
	method(deleteAt);
	method(getPadded);
	method(setPadded);
	getset(getPadded, setPadded);
	DECLARE_CHILD_CONTROL_METHODS()
}
<commit_msg>std::string --> UiForm<commit_after>#include <string>
#include "../ui.h"
#include "ui-node.h"
#include "nbind/api.h"

class UiForm : public UiControl {
  public:
	UiForm();
	DEFINE_CONTROL_METHODS()
	void append(std::string label, UiControl *c, bool stretchy);
	void deleteAt(int index);
	bool getPadded();
	void setPadded(bool padded);
};

UiForm::UiForm() : UiControl(uiControl(uiNewForm())) {}

void UiForm::append(std::string label, UiControl *c, bool stretchy) {
	uiFormAppend(uiForm(getHandle()), label.c_str(), c->getHandle(), stretchy);
}

void UiForm::deleteAt(int index) {
	uiFormDelete(uiForm(getHandle()), index);
}

bool UiForm::getPadded() {
	return uiFormPadded(uiForm(getHandle()));
}

void UiForm::setPadded(bool padded) {
	uiFormSetPadded(uiForm(getHandle()), padded);
}

INHERITS_CONTROL_METHODS(UiForm)

NBIND_CLASS(UiForm) {
	construct<>();
	method(append);
	method(deleteAt);
	method(getPadded);
	method(setPadded);
	getset(getPadded, setPadded);
	DECLARE_CHILD_CONTROL_METHODS()
}
<|endoftext|>


<commit_before>// main.cc for Fluxbox Window manager
// Copyright (c) 2001 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
//               and 2003-2005 Simon Bowden (rathnor at users.sourceforge.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include "fluxbox.hh"
#include "version.h"
#include "defaults.hh"

#include "FbTk/Theme.hh"
#include "FbTk/I18n.hh"
#include "FbTk/StringUtil.hh"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H

//use GNU extensions
#ifndef	 _GNU_SOURCE
#define	 _GNU_SOURCE
#endif // _GNU_SOURCE

#ifdef HAVE_CSTDLIB
  #include <cstdlib>
#else
  #include <stdlib.h>
#endif

#ifdef HAVE_CSTRING
  #include <cstring>
#else
  #include <string.h>
#endif

#include <iostream>
#include <fstream>
#include <stdexcept>
#include <typeinfo>

using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::ostream;
using std::ofstream;
using std::streambuf;
using std::auto_ptr;
using std::out_of_range;
using std::runtime_error;
using std::bad_cast;
using std::bad_alloc;
using std::exception;

static void showInfo(ostream &ostr) {
    _FB_USES_NLS;
    ostr<<_FB_CONSOLETEXT(Common, FluxboxVersion, "Fluxbox version", "Fluxbox version heading")<<": "<<__fluxbox_version<<endl;

    if (strlen(svnversion()) > 0)
        ostr << _FB_CONSOLETEXT(Common, SvnRevision, "GIT Revision", "Revision number in GIT repositary") << ": " << svnversion() << endl;
#if defined(__DATE__) && defined(__TIME__)
    ostr<<_FB_CONSOLETEXT(Common, Compiled, "Compiled", "Time fluxbox was compiled")<<": "<<__DATE__<<" "<<__TIME__<<endl;
#endif
#ifdef __fluxbox_compiler
    ostr<<_FB_CONSOLETEXT(Common, Compiler, "Compiler", "Compiler used to build fluxbox")<<": "<<__fluxbox_compiler<<endl;
#endif // __fluxbox_compiler
#ifdef __fluxbox_compiler_version
    ostr<<_FB_CONSOLETEXT(Common, CompilerVersion, "Compiler version", "Compiler version used to build fluxbox")<<": "<<__fluxbox_compiler_version<<endl;
#endif // __fluxbox_compiler_version

    ostr<<endl<<_FB_CONSOLETEXT(Common, Defaults, "Defaults", "Default values compiled in")<<":"<<endl;

    ostr<<_FB_CONSOLETEXT(Common, DefaultMenuFile, "    menu", "default menu file (right aligned - make sure same width as other default values)")<<": "<<DEFAULTMENU<<endl;
    ostr<<_FB_CONSOLETEXT(Common, DefaultStyle, "   style", "default style (right aligned - make sure same width as other default values)")<<": "<<DEFAULTSTYLE<<endl;

    ostr<<_FB_CONSOLETEXT(Common, DefaultKeyFile, "    keys", "default key file (right aligned - make sure same width as other default values)")<<": "<<DEFAULTKEYSFILE<<endl;
    ostr<<_FB_CONSOLETEXT(Common, DefaultInitFile, "    init", "default init file (right aligned - make sure same width as other default values)")<<": "<<DEFAULT_INITFILE<<endl;

#ifdef NLS
    ostr<<_FB_CONSOLETEXT(Common, DefaultLocalePath, "    nls", "location for localization files (right aligned - make sure same width as other default values)")<<": "<<LOCALEPATH<<endl;
#endif

    const char NOT[] = "-";
    ostr<<endl<<
        _FB_CONSOLETEXT(Common, CompiledOptions, "Compiled options", "Options used when compiled")
        <<" ("<<NOT<<" => "<<
        _FB_CONSOLETEXT(Common, Disabled, "disabled", "option is turned off")<<"): "<<endl<<

/**** NOTE: This list is in alphabetical order! ****/

#ifndef DEBUG
        NOT<<
#endif // DEBUG
        "DEBUG"<<endl<<

#ifndef USE_NEWWMSPEC
        NOT<<
#endif // USE_NEWWMSPEC
        "EWMH"<<endl<<

#ifndef USE_GNOME
        NOT<<
#endif // USE_GNOME
        "GNOME"<<endl<<

#ifndef HAVE_IMLIB2
        NOT<<
#endif // HAVE_IMLIB2
        "IMLIB2"<<endl<<

#ifndef NLS
        NOT<<
#endif // NLS
        "NLS"<<endl<<

#ifndef REMEMBER
        NOT<<
#endif // REMEMBER
        "REMEMBER"<<endl<<

#ifndef HAVE_XRENDER
        NOT<<
#endif // HAVE_XRENDER
        "RENDER"<<endl<<

#ifndef SHAPE
        NOT<<
#endif // SHAPE
        "SHAPE"<<endl<<

#ifndef SLIT
        NOT<<
#endif // SLIT
        "SLIT"<<endl<<

#ifndef USE_TOOLBAR
        NOT<<
#endif // USE_TOOLBAR
        "TOOLBAR"<<endl<<

#ifndef USE_XFT
        NOT<<
#endif // USE_XFT
        "XFT"<<endl<<

#ifndef XINERAMA
        NOT<<
#endif // XINERAMA
        "XINERAMA"<<endl<<

#ifndef USE_XMB
        NOT<<
#endif // USE_XMB
        "XMB"<<endl<<

#ifndef HAVE_XPM
        NOT<<
#endif // HAVE_XPM
        "XPM"<<endl<<

        endl;
}

int main(int argc, char **argv) {

    string session_display("");
    string rc_file;
    string log_filename;

    FbTk::NLSInit("fluxbox.cat");
    _FB_USES_NLS;

    int i;
    for (i = 1; i < argc; ++i) {
        string arg(argv[i]);
        if (arg == "-rc") {
            // look for alternative rc file to use

            if ((++i) >= argc) {
                cerr<<_FB_CONSOLETEXT(main, RCRequiresArg,
                              "error: '-rc' requires an argument", "the -rc option requires a file argument")<<endl;
                exit(EXIT_FAILURE);
            }

            rc_file = argv[i];
        } else if (arg == "-display") {
            // check for -display option... to run on a display other than the one
            // set by the environment variable DISPLAY

            if ((++i) >= argc) {
                cerr<<_FB_CONSOLETEXT(main, DISPLAYRequiresArg,
                              "error: '-display' requires an argument",
                              "")<<endl;
                exit(EXIT_FAILURE);
            }

            session_display = argv[i];
            string display_env = "DISPLAY=" + session_display;
            if (putenv(const_cast<char *>(display_env.c_str()))) {
                cerr<<_FB_CONSOLETEXT(main, WarnDisplayEnv,
                                "warning: couldn't set environment variable 'DISPLAY'",
                              "")<<endl;
                perror("putenv()");
            }
        } else if (arg == "-version" || arg == "-v") {
            // print current version string
            cout << "Fluxbox " << __fluxbox_version << " : (c) 2001-2007 Fluxbox Team " << endl << endl;
            exit(EXIT_SUCCESS);
        } else if (arg == "-log") {
            if (++i >= argc) {
                cerr<<_FB_CONSOLETEXT(main, LOGRequiresArg, "error: '-log' needs an argument", "")<<endl;
                exit(EXIT_FAILURE);
            }
            log_filename = argv[i];
        } else if (arg == "-help" || arg == "-h") {
            // print program usage and command line options
            printf(_FB_CONSOLETEXT(main, Usage,
                           "Fluxbox %s : (c) %s Henrik Kinnunen\n"
                           "Website: http://www.fluxbox.org/\n\n"
                           "-display <string>\t\tuse display connection.\n"
                           "-screen <all|int,int,int>\trun on specified screens only.\n"
                           "-rc <string>\t\t\tuse alternate resource file.\n"
                           "-version\t\t\tdisplay version and exit.\n"
                           "-info\t\t\t\tdisplay some useful information.\n"
                           "-log <filename>\t\t\tlog output to file.\n"
                           "-help\t\t\t\tdisplay this help text and exit.\n\n",

                           "Main usage string. Please lay it out nicely. There is one %s that is given the version").c_str(),
                   __fluxbox_version, "2001-2007");
            exit(EXIT_SUCCESS);
        } else if (arg == "-info" || arg == "-i") {
            showInfo(cout);
            exit(EXIT_SUCCESS);
        } else if (arg == "-verbose") {
            FbTk::ThemeManager::instance().setVerbose(true);
        }
    }

#ifdef __EMX__
    _chdir2(getenv("X11ROOT"));
#endif // __EMX__
    auto_ptr<Fluxbox> fluxbox;
    int exitcode=EXIT_FAILURE;

    streambuf *outbuf = 0;
    streambuf *errbuf = 0;

    ofstream log_file(log_filename.c_str());

    // setup log file
    if (log_file) {
        cerr<<_FB_CONSOLETEXT(main, LoggingTo, "Logging to", "Logging to a file")<<": "<<log_filename<<endl;
        log_file<<"------------------------------------------"<<endl;
        log_file<<_FB_CONSOLETEXT(main, LogFile, "Log File", "")<<": "<<log_filename<<endl;
        showInfo(log_file);
        log_file<<"------------------------------------------"<<endl;
        // setup log to use cout and cerr stream
        outbuf = cout.rdbuf(log_file.rdbuf());
        errbuf = cerr.rdbuf(log_file.rdbuf());
    }

    try {

        fluxbox.reset(new Fluxbox(argc, argv, session_display.c_str(), rc_file.c_str()));
        fluxbox->eventLoop();

        exitcode = EXIT_SUCCESS;

    } catch (out_of_range &oor) {
        cerr<<"Fluxbox: "<<_FB_CONSOLETEXT(main, ErrorOutOfRange, "Out of range", "Error message")<<": "<<oor.what()<<endl;
    } catch (runtime_error &re) {
        cerr<<"Fluxbox: "<<_FB_CONSOLETEXT(main, ErrorRuntime, "Runtime error", "Error message")<<": "<<re.what()<<endl;
    } catch (bad_cast &bc) {
        cerr<<"Fluxbox: "<<_FB_CONSOLETEXT(main, ErrorBadCast, "Bad cast", "Error message")<<": "<<bc.what()<<endl;
    } catch (bad_alloc &ba) {
        cerr<<"Fluxbox: "<<_FB_CONSOLETEXT(main, ErrorBadAlloc, "Bad Alloc", "Error message")<<": "<<ba.what()<<endl;
    } catch (exception &e) {
        cerr<<"Fluxbox: "<<_FB_CONSOLETEXT(main, ErrorStandardException, "Standard Exception", "Error message")<<": "<<e.what()<<endl;
    } catch (string error_str) {
        cerr<<_FB_CONSOLETEXT(Common, Error, "Error", "Error message header")<<": "<<error_str<<endl;
    } catch (...) {
        cerr<<"Fluxbox: "<<_FB_CONSOLETEXT(main, ErrorUnknown, "Unknown error", "Error message")<<"."<<endl;
        abort();
    }

    bool restarting = false;
    string restart_argument;

    if (fluxbox.get()) {
        restarting = fluxbox->isRestarting();
        restart_argument = fluxbox->getRestartArgument();
    }

    // destroy fluxbox
    fluxbox.reset(0);

    // restore cout and cin streams
    if (outbuf != 0)
        cout.rdbuf(outbuf);
    if (errbuf != 0)
        cerr.rdbuf(errbuf);

    FbTk::FbStringUtil::shutdown();

    if (restarting) {
        if (!restart_argument.empty()) {
            const char *shell = getenv("SHELL");
            if (!shell)
                shell = "/bin/sh";

            const char *arg = restart_argument.c_str();
            if (arg) {
                execlp(shell, shell, "-c", arg, (const char *) NULL);
                perror(arg);
            }
        }

        // fall back in case the above execlp doesn't work
        execvp(argv[0], argv);
        perror(argv[0]);

        const char *basename = FbTk::StringUtil::basename(argv[0]).c_str();
        execvp(basename, argv);
        perror(basename);
    }

    return exitcode;
}

<commit_msg>std::string.c_str() is never NULL<commit_after>// main.cc for Fluxbox Window manager
// Copyright (c) 2001 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
//               and 2003-2005 Simon Bowden (rathnor at users.sourceforge.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include "fluxbox.hh"
#include "version.h"
#include "defaults.hh"

#include "FbTk/Theme.hh"
#include "FbTk/I18n.hh"
#include "FbTk/StringUtil.hh"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H

//use GNU extensions
#ifndef	 _GNU_SOURCE
#define	 _GNU_SOURCE
#endif // _GNU_SOURCE

#ifdef HAVE_CSTDLIB
  #include <cstdlib>
#else
  #include <stdlib.h>
#endif

#ifdef HAVE_CSTRING
  #include <cstring>
#else
  #include <string.h>
#endif

#include <iostream>
#include <fstream>
#include <stdexcept>
#include <typeinfo>

using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::ostream;
using std::ofstream;
using std::streambuf;
using std::auto_ptr;
using std::out_of_range;
using std::runtime_error;
using std::bad_cast;
using std::bad_alloc;
using std::exception;

static void showInfo(ostream &ostr) {
    _FB_USES_NLS;
    ostr<<_FB_CONSOLETEXT(Common, FluxboxVersion, "Fluxbox version", "Fluxbox version heading")<<": "<<__fluxbox_version<<endl;

    if (strlen(svnversion()) > 0)
        ostr << _FB_CONSOLETEXT(Common, SvnRevision, "GIT Revision", "Revision number in GIT repositary") << ": " << svnversion() << endl;
#if defined(__DATE__) && defined(__TIME__)
    ostr<<_FB_CONSOLETEXT(Common, Compiled, "Compiled", "Time fluxbox was compiled")<<": "<<__DATE__<<" "<<__TIME__<<endl;
#endif
#ifdef __fluxbox_compiler
    ostr<<_FB_CONSOLETEXT(Common, Compiler, "Compiler", "Compiler used to build fluxbox")<<": "<<__fluxbox_compiler<<endl;
#endif // __fluxbox_compiler
#ifdef __fluxbox_compiler_version
    ostr<<_FB_CONSOLETEXT(Common, CompilerVersion, "Compiler version", "Compiler version used to build fluxbox")<<": "<<__fluxbox_compiler_version<<endl;
#endif // __fluxbox_compiler_version

    ostr<<endl<<_FB_CONSOLETEXT(Common, Defaults, "Defaults", "Default values compiled in")<<":"<<endl;

    ostr<<_FB_CONSOLETEXT(Common, DefaultMenuFile, "    menu", "default menu file (right aligned - make sure same width as other default values)")<<": "<<DEFAULTMENU<<endl;
    ostr<<_FB_CONSOLETEXT(Common, DefaultStyle, "   style", "default style (right aligned - make sure same width as other default values)")<<": "<<DEFAULTSTYLE<<endl;

    ostr<<_FB_CONSOLETEXT(Common, DefaultKeyFile, "    keys", "default key file (right aligned - make sure same width as other default values)")<<": "<<DEFAULTKEYSFILE<<endl;
    ostr<<_FB_CONSOLETEXT(Common, DefaultInitFile, "    init", "default init file (right aligned - make sure same width as other default values)")<<": "<<DEFAULT_INITFILE<<endl;

#ifdef NLS
    ostr<<_FB_CONSOLETEXT(Common, DefaultLocalePath, "    nls", "location for localization files (right aligned - make sure same width as other default values)")<<": "<<LOCALEPATH<<endl;
#endif

    const char NOT[] = "-";
    ostr<<endl<<
        _FB_CONSOLETEXT(Common, CompiledOptions, "Compiled options", "Options used when compiled")
        <<" ("<<NOT<<" => "<<
        _FB_CONSOLETEXT(Common, Disabled, "disabled", "option is turned off")<<"): "<<endl<<

/**** NOTE: This list is in alphabetical order! ****/

#ifndef DEBUG
        NOT<<
#endif // DEBUG
        "DEBUG"<<endl<<

#ifndef USE_NEWWMSPEC
        NOT<<
#endif // USE_NEWWMSPEC
        "EWMH"<<endl<<

#ifndef USE_GNOME
        NOT<<
#endif // USE_GNOME
        "GNOME"<<endl<<

#ifndef HAVE_IMLIB2
        NOT<<
#endif // HAVE_IMLIB2
        "IMLIB2"<<endl<<

#ifndef NLS
        NOT<<
#endif // NLS
        "NLS"<<endl<<

#ifndef REMEMBER
        NOT<<
#endif // REMEMBER
        "REMEMBER"<<endl<<

#ifndef HAVE_XRENDER
        NOT<<
#endif // HAVE_XRENDER
        "RENDER"<<endl<<

#ifndef SHAPE
        NOT<<
#endif // SHAPE
        "SHAPE"<<endl<<

#ifndef SLIT
        NOT<<
#endif // SLIT
        "SLIT"<<endl<<

#ifndef USE_TOOLBAR
        NOT<<
#endif // USE_TOOLBAR
        "TOOLBAR"<<endl<<

#ifndef USE_XFT
        NOT<<
#endif // USE_XFT
        "XFT"<<endl<<

#ifndef XINERAMA
        NOT<<
#endif // XINERAMA
        "XINERAMA"<<endl<<

#ifndef USE_XMB
        NOT<<
#endif // USE_XMB
        "XMB"<<endl<<

#ifndef HAVE_XPM
        NOT<<
#endif // HAVE_XPM
        "XPM"<<endl<<

        endl;
}

int main(int argc, char **argv) {

    string session_display("");
    string rc_file;
    string log_filename;

    FbTk::NLSInit("fluxbox.cat");
    _FB_USES_NLS;

    int i;
    for (i = 1; i < argc; ++i) {
        string arg(argv[i]);
        if (arg == "-rc") {
            // look for alternative rc file to use

            if ((++i) >= argc) {
                cerr<<_FB_CONSOLETEXT(main, RCRequiresArg,
                              "error: '-rc' requires an argument", "the -rc option requires a file argument")<<endl;
                exit(EXIT_FAILURE);
            }

            rc_file = argv[i];
        } else if (arg == "-display") {
            // check for -display option... to run on a display other than the one
            // set by the environment variable DISPLAY

            if ((++i) >= argc) {
                cerr<<_FB_CONSOLETEXT(main, DISPLAYRequiresArg,
                              "error: '-display' requires an argument",
                              "")<<endl;
                exit(EXIT_FAILURE);
            }

            session_display = argv[i];
            string display_env = "DISPLAY=" + session_display;
            if (putenv(const_cast<char *>(display_env.c_str()))) {
                cerr<<_FB_CONSOLETEXT(main, WarnDisplayEnv,
                                "warning: couldn't set environment variable 'DISPLAY'",
                              "")<<endl;
                perror("putenv()");
            }
        } else if (arg == "-version" || arg == "-v") {
            // print current version string
            cout << "Fluxbox " << __fluxbox_version << " : (c) 2001-2007 Fluxbox Team " << endl << endl;
            exit(EXIT_SUCCESS);
        } else if (arg == "-log") {
            if (++i >= argc) {
                cerr<<_FB_CONSOLETEXT(main, LOGRequiresArg, "error: '-log' needs an argument", "")<<endl;
                exit(EXIT_FAILURE);
            }
            log_filename = argv[i];
        } else if (arg == "-help" || arg == "-h") {
            // print program usage and command line options
            printf(_FB_CONSOLETEXT(main, Usage,
                           "Fluxbox %s : (c) %s Henrik Kinnunen\n"
                           "Website: http://www.fluxbox.org/\n\n"
                           "-display <string>\t\tuse display connection.\n"
                           "-screen <all|int,int,int>\trun on specified screens only.\n"
                           "-rc <string>\t\t\tuse alternate resource file.\n"
                           "-version\t\t\tdisplay version and exit.\n"
                           "-info\t\t\t\tdisplay some useful information.\n"
                           "-log <filename>\t\t\tlog output to file.\n"
                           "-help\t\t\t\tdisplay this help text and exit.\n\n",

                           "Main usage string. Please lay it out nicely. There is one %s that is given the version").c_str(),
                   __fluxbox_version, "2001-2007");
            exit(EXIT_SUCCESS);
        } else if (arg == "-info" || arg == "-i") {
            showInfo(cout);
            exit(EXIT_SUCCESS);
        } else if (arg == "-verbose") {
            FbTk::ThemeManager::instance().setVerbose(true);
        }
    }

#ifdef __EMX__
    _chdir2(getenv("X11ROOT"));
#endif // __EMX__
    auto_ptr<Fluxbox> fluxbox;
    int exitcode=EXIT_FAILURE;

    streambuf *outbuf = 0;
    streambuf *errbuf = 0;

    ofstream log_file(log_filename.c_str());

    // setup log file
    if (log_file) {
        cerr<<_FB_CONSOLETEXT(main, LoggingTo, "Logging to", "Logging to a file")<<": "<<log_filename<<endl;
        log_file<<"------------------------------------------"<<endl;
        log_file<<_FB_CONSOLETEXT(main, LogFile, "Log File", "")<<": "<<log_filename<<endl;
        showInfo(log_file);
        log_file<<"------------------------------------------"<<endl;
        // setup log to use cout and cerr stream
        outbuf = cout.rdbuf(log_file.rdbuf());
        errbuf = cerr.rdbuf(log_file.rdbuf());
    }

    try {

        fluxbox.reset(new Fluxbox(argc, argv, session_display.c_str(), rc_file.c_str()));
        fluxbox->eventLoop();

        exitcode = EXIT_SUCCESS;

    } catch (out_of_range &oor) {
        cerr<<"Fluxbox: "<<_FB_CONSOLETEXT(main, ErrorOutOfRange, "Out of range", "Error message")<<": "<<oor.what()<<endl;
    } catch (runtime_error &re) {
        cerr<<"Fluxbox: "<<_FB_CONSOLETEXT(main, ErrorRuntime, "Runtime error", "Error message")<<": "<<re.what()<<endl;
    } catch (bad_cast &bc) {
        cerr<<"Fluxbox: "<<_FB_CONSOLETEXT(main, ErrorBadCast, "Bad cast", "Error message")<<": "<<bc.what()<<endl;
    } catch (bad_alloc &ba) {
        cerr<<"Fluxbox: "<<_FB_CONSOLETEXT(main, ErrorBadAlloc, "Bad Alloc", "Error message")<<": "<<ba.what()<<endl;
    } catch (exception &e) {
        cerr<<"Fluxbox: "<<_FB_CONSOLETEXT(main, ErrorStandardException, "Standard Exception", "Error message")<<": "<<e.what()<<endl;
    } catch (string error_str) {
        cerr<<_FB_CONSOLETEXT(Common, Error, "Error", "Error message header")<<": "<<error_str<<endl;
    } catch (...) {
        cerr<<"Fluxbox: "<<_FB_CONSOLETEXT(main, ErrorUnknown, "Unknown error", "Error message")<<"."<<endl;
        abort();
    }

    bool restarting = false;
    string restart_argument;

    if (fluxbox.get()) {
        restarting = fluxbox->isRestarting();
        restart_argument = fluxbox->getRestartArgument();
    }

    // destroy fluxbox
    fluxbox.reset(0);

    // restore cout and cin streams
    if (outbuf != 0)
        cout.rdbuf(outbuf);
    if (errbuf != 0)
        cerr.rdbuf(errbuf);

    FbTk::FbStringUtil::shutdown();

    if (restarting) {
        if (!restart_argument.empty()) {
            const char *shell = getenv("SHELL");
            if (!shell)
                shell = "/bin/sh";

            execlp(shell, shell, "-c", restart_argument.c_str(), (const char *) NULL);
            perror(restart_argument.c_str());
        }

        // fall back in case the above execlp doesn't work
        execvp(argv[0], argv);
        perror(argv[0]);

        const char *basename = FbTk::StringUtil::basename(argv[0]).c_str();
        execvp(basename, argv);
        perror(basename);
    }

    return exitcode;
}

<|endoftext|>


<commit_before>#include <iostream>

#include <clang/Tooling/Tooling.h>
#include <clang/Tooling/CommonOptionsParser.h>
#include <llvm/Support/CommandLine.h>

#include "AnnotateSkeletonsAction.hh"
#include "DetectSkeletonsAction.hh"
#include "DetectDynamicAction.hh"
#include "Flags.hh"
#include "Log.hh"
#include "LoopReorderer.hh"

using namespace llvm;
using namespace clang;
using namespace clang::tooling;
using std::string;

enum ProgramMode {
  Static,
  FindReorderable
};

static cl::OptionCategory OptionsCategory("skel options");
static cl::opt<bool> Overwrite("overwrite", cl::desc("Overwrite source files"),
                               cl::cat(OptionsCategory));
static cl::alias OverwriteA("w", cl::desc("Alias for -overwrite"), cl::aliasopt(Overwrite));

static cl::opt<ProgramMode> Mode(cl::desc("Application mode"),
    cl::values(
      clEnumValN(Static, "static", "Statically analyse the program"),
      clEnumValN(FindReorderable, "reorder", "Dynamically find reorderable loops"),
      nullptr
    ), cl::cat(OptionsCategory), cl::Required);

Strategy::Type StrategyFlag;
static cl::opt<Strategy::Type, true> StrategyType(cl::desc("Reordering strategy"),
    cl::values(
      clEnumValN(Strategy::Reverse, "reverse", "Reverse the order of loop iteration"),
      nullptr
    ),
    cl::location(StrategyFlag), cl::init(Strategy::Identity), cl::cat(OptionsCategory));

int main(int argc, const char **argv) {
  CommonOptionsParser op(argc, argv, OptionsCategory);
  ClangTool Tool(op.getCompilations(), op.getSourcePathList());

  if(Mode == Static) {
    if(Overwrite) {
      return Tool.run(
          newFrontendActionFactory<AnnotateSkeletonsAction>().get());
    } else {
      return Tool.run(
          newFrontendActionFactory<DetectSkeletonsAction>().get());
    }
  }

  return Tool.run(newFrontendActionFactory<DetectDynamicAction>().get());
}
<commit_msg>Add identity flag<commit_after>#include <iostream>

#include <clang/Tooling/Tooling.h>
#include <clang/Tooling/CommonOptionsParser.h>
#include <llvm/Support/CommandLine.h>

#include "AnnotateSkeletonsAction.hh"
#include "DetectSkeletonsAction.hh"
#include "DetectDynamicAction.hh"
#include "Flags.hh"
#include "Log.hh"
#include "LoopReorderer.hh"

using namespace llvm;
using namespace clang;
using namespace clang::tooling;
using std::string;

enum ProgramMode {
  Static,
  FindReorderable
};

static cl::OptionCategory OptionsCategory("skel options");
static cl::opt<bool> Overwrite("overwrite", cl::desc("Overwrite source files"),
                               cl::cat(OptionsCategory));
static cl::alias OverwriteA("w", cl::desc("Alias for -overwrite"), cl::aliasopt(Overwrite));

static cl::opt<ProgramMode> Mode(cl::desc("Application mode"),
    cl::values(
      clEnumValN(Static, "static", "Statically analyse the program"),
      clEnumValN(FindReorderable, "reorder", "Dynamically find reorderable loops"),
      nullptr
    ), cl::cat(OptionsCategory), cl::Required);

Strategy::Type StrategyFlag;
static cl::opt<Strategy::Type, true> StrategyType(cl::desc("Reordering strategy"),
    cl::values(
      clEnumValN(Strategy::Reverse, "reverse", "Reverse the order of loop iteration"),
      clEnumValN(Strategy::Identity, "identity", "Leave loops unchanged"),
      nullptr
    ),
    cl::location(StrategyFlag), cl::init(Strategy::Identity), cl::cat(OptionsCategory));

int main(int argc, const char **argv) {
  CommonOptionsParser op(argc, argv, OptionsCategory);
  ClangTool Tool(op.getCompilations(), op.getSourcePathList());

  if(Mode == Static) {
    if(Overwrite) {
      return Tool.run(
          newFrontendActionFactory<AnnotateSkeletonsAction>().get());
    } else {
      return Tool.run(
          newFrontendActionFactory<DetectSkeletonsAction>().get());
    }
  }

  return Tool.run(newFrontendActionFactory<DetectDynamicAction>().get());
}
<|endoftext|>


<commit_before>#include <iostream>
#include <boost/program_options.hpp>

#include "args.h"

/**
 * Show help document.
 *
 * @param args The argument manager
 */
void ShowHelp(const Args &args) {
    std::cout << "BTCAddrGen version 0.1" << std::endl;
    std::cout << "Usage:" << std::endl;
    std::cout << "  ./btcaddrgen" << std::endl;
    std::cout << args.GetArgsHelpString() << std::endl;
}

/// Main program.
int main(int argc, const char *argv[]) {
    Args args(argc, argv);
    if (args.is_help()) {
        ShowHelp(args);
        return 0;
    }
    return 0;
}
<commit_msg>Improve arguments display.<commit_after>#include <iostream>
#include <boost/program_options.hpp>

#include "args.h"

/**
 * Show help document.
 *
 * @param args The argument manager
 */
void ShowHelp(const Args &args) {
    std::cout << "BTCAddrGen version 0.1" << std::endl;
    std::cout << "Usage:" << std::endl;
    std::cout << "  ./btcaddrgen" << std::endl << std::endl;
    std::cout << "Arguments:" << std::endl;
    std::cout << args.GetArgsHelpString() << std::endl;
}

/// Main program.
int main(int argc, const char *argv[]) {
    Args args(argc, argv);
    if (args.is_help()) {
        ShowHelp(args);
        return 0;
    }
    return 0;
}
<|endoftext|>