<commit_before>/*
 * Copyright (C) 2016 Florent Revest <revestflo@gmail.com>
 * All rights reserved.
 *
 * You may use this file under the terms of BSD license as follows:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the author nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "flatmeshnode.h"

#include <math.h>

#include <QScreen>
#include <QElapsedTimer>

/* Used to compute a triangle color from its distance to the center */
static inline QColor interpolateColors(const QColor& color1, const QColor& color2, qreal ratio)
{
    /* Linear scale is too harsh, this looks better. This is not supposed to be called very often */
    ratio = pow(ratio, 1.7);
    if (ratio>1) ratio=1;

    int r = color1.red()*(1-ratio) + color2.red()*ratio;
    int g = color1.green()*(1-ratio) + color2.green()*ratio;
    int b = color1.blue()*(1-ratio) + color2.blue()*ratio;

    return QColor(r, g, b);
}

FlatMeshNode::FlatMeshNode(QQuickWindow *window, QRectF boundingRect)
    : QSGSimpleRectNode(boundingRect, Qt::transparent),
      m_animationState(0), m_window(window)
{
    connect(window, SIGNAL(afterRendering()), this, SLOT(maybeAnimate()));

    connect(window, SIGNAL(widthChanged(int)), this, SLOT(generateGrid()));
    connect(window, SIGNAL(heightChanged(int)), this, SLOT(generateGrid()));

    srand(time(NULL));
    generateGrid();

    for(int y = 0; y < NUM_POINTS_Y-1; y++) {
        for(int x = 0; x < NUM_POINTS_X-1; x++) {
            for(int n = 0; n < 2; n++) {
                QSGGeometryNode *triangle = new QSGGeometryNode();

                QSGFlatColorMaterial *color = new QSGFlatColorMaterial;
                triangle->setOpaqueMaterial(color);

                QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 3);
                triangle->setGeometry(geometry);

                appendChildNode(triangle);
            }
        }
    }
}

void FlatMeshNode::updateColors()
{
    int centerX = m_unitWidth*((NUM_POINTS_X-2)/2);
    int centerY = m_unitHeight*((NUM_POINTS_Y-2)/2);
    int radius = rect().width()*0.6;

    QSGGeometryNode *triangle = static_cast<QSGGeometryNode *>(firstChild());
    for(int y = 0; y < NUM_POINTS_Y-1; y++) {
        for(int x = 0; x < NUM_POINTS_X-1; x++) {
            for(int n = 0; n < 2; n++) {
                QSGFlatColorMaterial *color = static_cast<QSGFlatColorMaterial *>(triangle->opaqueMaterial());
                color->setColor(interpolateColors(m_centerColor, m_outerColor,
                                sqrt(pow(m_points[y*NUM_POINTS_Y+x].centerX-centerX, 2) + pow(m_points[y*NUM_POINTS_Y+x].centerY-centerY, 2))/radius));
                triangle->setOpaqueMaterial(color);

                triangle->markDirty(QSGNode::DirtyMaterial);
                triangle = static_cast<QSGGeometryNode *>(triangle->nextSibling());
            }
        }
    }
}

void FlatMeshNode::setCenterColor(QColor c)
{
    if (c == m_centerColor)
        return;
    m_centerColor = c;
    updateColors();
}

void FlatMeshNode::setOuterColor(QColor c)
{
    if (c == m_outerColor)
        return;
    m_outerColor = c;
    updateColors();
}

/* When the size changes, regenerate a grid of points that serves as a base for further operations */
void FlatMeshNode::generateGrid()
{
    m_unitWidth = rect().width()/(NUM_POINTS_X-2);
    m_unitHeight = rect().height()/(NUM_POINTS_Y-2);

    for(int y = 0; y < NUM_POINTS_Y; y++) {
        for(int x = 0; x < NUM_POINTS_X; x++) {
            Point *point = &m_points[y*NUM_POINTS_Y+x];
            point->centerX = m_unitWidth*x;
            point->centerY = m_unitHeight*y;

            if(x != 0 && x != (NUM_POINTS_X-1)) {
                point->animOriginX = point->centerX + rand()%m_unitWidth - m_unitWidth/2;
                point->animEndX = point->centerX + rand()%m_unitWidth - m_unitWidth/2;
            }
            else
                point->animEndX = point->animOriginX = point->centerX;

            if(y != 0 && y != (NUM_POINTS_Y-1)) {
                point->animOriginY = point->centerY + rand()%m_unitHeight - m_unitHeight/2;
                point->animEndY = point->centerY + rand()%m_unitHeight - m_unitHeight/2;
            }
            else
                point->animEndY = point->animOriginY = point->centerY;
        }
    }
}

void FlatMeshNode::setAnimated(bool animated)
{
    m_animated = animated;
}

void FlatMeshNode::maybeAnimate()
{
    static QElapsedTimer t;
    if(!t.isValid()) t.start();
    if (m_animated && t.elapsed() >= 100) {
        t.restart();
        m_animationState += 0.03;

        /* Interpolate all points positions according to the animationState */
        for(int i = 0; i < NUM_POINTS_X*NUM_POINTS_Y; i++) {
            Point *p = &m_points[i];

            p->currentPos.x = p->animOriginX + (p->animEndX-p->animOriginX)*m_animationState;
            p->currentPos.y = p->animOriginY + (p->animEndY-p->animOriginY)*m_animationState;
        }

        /* Update all triangles' geometries according to the new points position */
        QSGGeometryNode *triangle = static_cast<QSGGeometryNode *>(firstChild());
        for(int i = 0; i < NUM_POINTS_X*NUM_POINTS_Y; i++) {
            if(m_points[i].centerX != m_unitWidth*(NUM_POINTS_X-1) && m_points[i].centerY != m_unitHeight*(NUM_POINTS_Y-1)) {
                int random = rand()%2;
                for(int n = 0; n < 2; n++) {
                    QSGGeometry::Point2D *v = triangle->geometry()->vertexDataAsPoint2D();
                    if(random==0) {
                        if(n==0) {
                            v[0] = m_points[i].currentPos;
                            v[1] = m_points[i+NUM_POINTS_X].currentPos;
                            v[2] = m_points[i+NUM_POINTS_X+1].currentPos;
                        } else if(n==1) {
                            v[0] = m_points[i].currentPos;
                            v[1] = m_points[i+1].currentPos;
                            v[2] = m_points[i+NUM_POINTS_X+1].currentPos;
                        }
                    } else {
                        if(n==0) {
                            v[0] = m_points[i].currentPos;
                            v[1] = m_points[i+NUM_POINTS_X].currentPos;
                            v[2] = m_points[i+1].currentPos;
                        } else if(n==1) {
                            v[0] = m_points[i+NUM_POINTS_X].currentPos;
                            v[1] = m_points[i+1].currentPos;
                            v[2] = m_points[i+NUM_POINTS_X+1].currentPos;
                        }
                    }
                    triangle->markDirty(QSGNode::DirtyGeometry);
                    triangle = static_cast<QSGGeometryNode *>(triangle->nextSibling());
                }
            }
        }

        /* Regenerate a set of animation end points when the animation is finished */
        if(m_animationState >= 1.0) {
            m_animationState = 0.0;

            for(int y = 0; y < NUM_POINTS_Y; y++) {
                for(int x = 0; x < NUM_POINTS_X; x++) {
                    Point *point = &m_points[y*NUM_POINTS_Y+x];

                    if(x != 0 && x != (NUM_POINTS_X-1)) {
                        point->animOriginX = point->animEndX;
                        point->animEndX = point->centerX + rand()%m_unitWidth - m_unitWidth/2;
                    }
                    if(y != 0 && y != (NUM_POINTS_Y-1)) {
                        point->animOriginY = point->animEndY;
                        point->animEndY = point->centerY + rand()%m_unitHeight - m_unitHeight/2;
                    }
                }
            }
        }
    }
}
<commit_msg>FlatMeshNode: don't skip first frame<commit_after>/*
 * Copyright (C) 2016 Florent Revest <revestflo@gmail.com>
 * All rights reserved.
 *
 * You may use this file under the terms of BSD license as follows:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the author nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "flatmeshnode.h"

#include <math.h>

#include <QScreen>
#include <QElapsedTimer>

/* Used to compute a triangle color from its distance to the center */
static inline QColor interpolateColors(const QColor& color1, const QColor& color2, qreal ratio)
{
    /* Linear scale is too harsh, this looks better. This is not supposed to be called very often */
    ratio = pow(ratio, 1.7);
    if (ratio>1) ratio=1;

    int r = color1.red()*(1-ratio) + color2.red()*ratio;
    int g = color1.green()*(1-ratio) + color2.green()*ratio;
    int b = color1.blue()*(1-ratio) + color2.blue()*ratio;

    return QColor(r, g, b);
}

FlatMeshNode::FlatMeshNode(QQuickWindow *window, QRectF boundingRect)
    : QSGSimpleRectNode(boundingRect, Qt::transparent),
      m_animationState(0), m_window(window)
{
    connect(window, SIGNAL(afterRendering()), this, SLOT(maybeAnimate()));

    connect(window, SIGNAL(widthChanged(int)), this, SLOT(generateGrid()));
    connect(window, SIGNAL(heightChanged(int)), this, SLOT(generateGrid()));

    srand(time(NULL));
    generateGrid();

    for(int y = 0; y < NUM_POINTS_Y-1; y++) {
        for(int x = 0; x < NUM_POINTS_X-1; x++) {
            for(int n = 0; n < 2; n++) {
                QSGGeometryNode *triangle = new QSGGeometryNode();

                QSGFlatColorMaterial *color = new QSGFlatColorMaterial;
                triangle->setOpaqueMaterial(color);

                QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 3);
                triangle->setGeometry(geometry);

                appendChildNode(triangle);
            }
        }
    }
}

void FlatMeshNode::updateColors()
{
    int centerX = m_unitWidth*((NUM_POINTS_X-2)/2);
    int centerY = m_unitHeight*((NUM_POINTS_Y-2)/2);
    int radius = rect().width()*0.6;

    QSGGeometryNode *triangle = static_cast<QSGGeometryNode *>(firstChild());
    for(int y = 0; y < NUM_POINTS_Y-1; y++) {
        for(int x = 0; x < NUM_POINTS_X-1; x++) {
            for(int n = 0; n < 2; n++) {
                QSGFlatColorMaterial *color = static_cast<QSGFlatColorMaterial *>(triangle->opaqueMaterial());
                color->setColor(interpolateColors(m_centerColor, m_outerColor,
                                sqrt(pow(m_points[y*NUM_POINTS_Y+x].centerX-centerX, 2) + pow(m_points[y*NUM_POINTS_Y+x].centerY-centerY, 2))/radius));
                triangle->setOpaqueMaterial(color);

                triangle->markDirty(QSGNode::DirtyMaterial);
                triangle = static_cast<QSGGeometryNode *>(triangle->nextSibling());
            }
        }
    }
}

void FlatMeshNode::setCenterColor(QColor c)
{
    if (c == m_centerColor)
        return;
    m_centerColor = c;
    updateColors();
}

void FlatMeshNode::setOuterColor(QColor c)
{
    if (c == m_outerColor)
        return;
    m_outerColor = c;
    updateColors();
}

/* When the size changes, regenerate a grid of points that serves as a base for further operations */
void FlatMeshNode::generateGrid()
{
    m_unitWidth = rect().width()/(NUM_POINTS_X-2);
    m_unitHeight = rect().height()/(NUM_POINTS_Y-2);

    for(int y = 0; y < NUM_POINTS_Y; y++) {
        for(int x = 0; x < NUM_POINTS_X; x++) {
            Point *point = &m_points[y*NUM_POINTS_Y+x];
            point->centerX = m_unitWidth*x;
            point->centerY = m_unitHeight*y;

            if(x != 0 && x != (NUM_POINTS_X-1)) {
                point->animOriginX = point->centerX + rand()%m_unitWidth - m_unitWidth/2;
                point->animEndX = point->centerX + rand()%m_unitWidth - m_unitWidth/2;
            }
            else
                point->animEndX = point->animOriginX = point->centerX;

            if(y != 0 && y != (NUM_POINTS_Y-1)) {
                point->animOriginY = point->centerY + rand()%m_unitHeight - m_unitHeight/2;
                point->animEndY = point->centerY + rand()%m_unitHeight - m_unitHeight/2;
            }
            else
                point->animEndY = point->animOriginY = point->centerY;
        }
    }
}

void FlatMeshNode::setAnimated(bool animated)
{
    m_animated = animated;
}

void FlatMeshNode::maybeAnimate()
{
    static QElapsedTimer t;
    bool firstFrame = false;
    if(!t.isValid()) {
        t.start();
        firstFrame = true;
    }
    if (firstFrame || (m_animated && t.restart() >= 100)) {
        m_animationState += 0.03;

        /* Interpolate all points positions according to the animationState */
        for(int i = 0; i < NUM_POINTS_X*NUM_POINTS_Y; i++) {
            Point *p = &m_points[i];

            p->currentPos.x = p->animOriginX + (p->animEndX-p->animOriginX)*m_animationState;
            p->currentPos.y = p->animOriginY + (p->animEndY-p->animOriginY)*m_animationState;
        }

        /* Update all triangles' geometries according to the new points position */
        qreal lastCenterX = m_unitWidth*(NUM_POINTS_X-1);
        qreal lastcenterY = m_unitHeight*(NUM_POINTS_Y-1);
        QSGGeometryNode *triangle = static_cast<QSGGeometryNode *>(firstChild());
        for(int i = 0; i < NUM_POINTS_X*NUM_POINTS_Y; i++) {
            if(m_points[i].centerX != lastCenterX && m_points[i].centerY != lastcenterY) {
                int random = rand()%2;
                for(int n = 0; n < 2; n++) {
                    QSGGeometry::Point2D *v = triangle->geometry()->vertexDataAsPoint2D();
                    if(random) {
                        if(n) {
                            v[0] = m_points[i].currentPos;
                            v[1] = m_points[i+NUM_POINTS_X].currentPos;
                            v[2] = m_points[i+NUM_POINTS_X+1].currentPos;
                        } else {
                            v[0] = m_points[i].currentPos;
                            v[1] = m_points[i+1].currentPos;
                            v[2] = m_points[i+NUM_POINTS_X+1].currentPos;
                        }
                    } else {
                        if(n) {
                            v[0] = m_points[i].currentPos;
                            v[1] = m_points[i+NUM_POINTS_X].currentPos;
                            v[2] = m_points[i+1].currentPos;
                        } else {
                            v[0] = m_points[i+NUM_POINTS_X].currentPos;
                            v[1] = m_points[i+1].currentPos;
                            v[2] = m_points[i+NUM_POINTS_X+1].currentPos;
                        }
                    }
                    triangle->markDirty(QSGNode::DirtyGeometry);
                    triangle = static_cast<QSGGeometryNode *>(triangle->nextSibling());
                }
            }
        }

        /* Regenerate a set of animation end points when the animation is finished */
        if(m_animationState >= 1.0) {
            m_animationState = 0.0;

            for(int y = 0; y < NUM_POINTS_Y; y++) {
                for(int x = 0; x < NUM_POINTS_X; x++) {
                    Point *point = &m_points[y*NUM_POINTS_Y+x];

                    if(x != 0 && x != (NUM_POINTS_X-1)) {
                        point->animOriginX = point->animEndX;
                        point->animEndX = point->centerX + rand()%m_unitWidth - m_unitWidth/2;
                    }
                    if(y != 0 && y != (NUM_POINTS_Y-1)) {
                        point->animOriginY = point->animEndY;
                        point->animEndY = point->centerY + rand()%m_unitHeight - m_unitHeight/2;
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/**
Copyright (c) 2017, Philip Deegan.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
    * Neither the name of Philip Deegan nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "maiken.hpp"

#ifdef _MKN_WITH_MKN_RAM_
#include "maiken/github.hpp"
bool maiken::Application::get_binaries() {
  size_t suxcess = 0;
  kul::Dir outD(inst ? inst.real() : buildDir());
  const auto files = kul::String::SPLIT(this->binary(), " ");
  for (const std::string &file : files) {
    std::string fn = file.substr(file.rfind("/") + 1);
    kul::https::Get(file)
        .withHeaders({{"User-Agent", "Mozilla not a virus"},
                      {"Accept", "application/octet-stream"},
                      {"Content-Disposition", "attachment; filename=" + fn}})
        .withResponse([&](const kul::http::Response &r) {
          if (r.status() == 200) {
            kul::File dl(fn);
            if (dl.is()) {
              suxcess++;
              dl.mv(outD);
            }
          }
        })
        .send();
  }
  return suxcess == files.size();
}
#endif

namespace maiken {
class ObjectMerger {
 public:
  static void into(const Application &root) {
    kul::Dir robj(root.buildDir().join("obj"));
    for (auto a : root.dependencies()) {
      kul::Dir obj(a->buildDir().join("obj"));
      if (obj)
        for (auto f : obj.files()) f.cp(robj);
    }
  }
};
}  // namespace maiken

void maiken::Application::process() KTHROW(kul::Exception) {
  const kul::hash::set::String &cmds(CommandStateMachine::INSTANCE().commands());
  const auto gEnvVars = maiken::AppVars::INSTANCE().envVars();
  for(auto const& ev : gEnvVars) KLOG(INF) << ev.first << " : " << ev.second;

  kul::os::PushDir pushd(this->project().dir());
  auto loadModules = [&](Application &app) {
#ifndef _MKN_DISABLE_MODULES_
    for (auto mod = app.modDeps.begin(); mod != app.modDeps.end(); ++mod) {
      app.mods.push_back(ModuleLoader::LOAD(**mod));
    }
    for (auto &modLoader : app.mods) modLoader->module()->init(app, app.modInit(modLoader->app()));
#endif  //_MKN_DISABLE_MODULES_
  };
  auto proc = [&](Application &app, bool work) {
    kul::env::CWD(app.project().dir());

    if (work) {
      if (!app.buildDir()) app.buildDir().mk();
      if (BuildRecorder::INSTANCE().has(app.buildDir().real())) return;
      BuildRecorder::INSTANCE().add(app.buildDir().real());
    }
    kul::Dir mkn(app.buildDir().join(".mkn"));
    std::vector<std::pair<std::string, std::string>> oldEvs;
    for (const auto &ev : app.envVars()) {
      const std::string v = kul::env::GET(ev.name());
      oldEvs.push_back(std::pair<std::string, std::string>(ev.name(), v));
      kul::env::SET(ev.name(), ev.toString().c_str());
      maiken::AppVars::INSTANCE().envVar(ev.name(), ev.toString());
    }
    if (cmds.count(STR_CLEAN) && app.buildDir().is()) {
      app.buildDir().rm();
      mkn.rm();
    }
    if (cmds.count(STR_MERGE) && app.ro) ObjectMerger::into(app);
#ifdef _MKN_WITH_MKN_RAM_
    if (work && !app.bin.empty() && app.get_binaries()) work = false;  // doesn't work yet
#endif
    app.loadTimeStamps();

    kul::hash::set::String objects;
    if (cmds.count(STR_BUILD) || cmds.count(STR_COMPILE)) {
      for (auto &modLoader : app.mods)
        modLoader->module()->compile(app, app.modCompile(modLoader->app()));
      if (work) app.compile(objects);
    }
    if (cmds.count(STR_BUILD) || cmds.count(STR_LINK)) {
      if (work)
        for (auto &modLoader : app.mods)
          modLoader->module()->link(app, app.modLink(modLoader->app()));
      if ((cmds.count(STR_MERGE) && app.ro) || !cmds.count(STR_MERGE)) {
        app.findObjects(objects);
        app.link(objects);
      }
    }
    for (const auto &oldEv : oldEvs) kul::env::SET(oldEv.first.c_str(), oldEv.second.c_str());
    for (const auto e : gEnvVars) maiken::AppVars::INSTANCE().envVar(e.first, e.second);
  };

  auto _mods = ModuleMinimiser::modules(*this);
  for (auto &mod : ModuleMinimiser::modules(*this)) {
    bool build = mod.second->is_build_required();
    bool is_build_stale = mod.second->is_build_stale();
    if (!build && (is_build_stale && !maiken::AppVars::INSTANCE().quiet())) {
      std::stringstream ss;
      ss << "The project @ " << mod.second->project().dir() << " appears to be stale" << std::endl;
      ss << "\tWould you like to build it (Y/n) - this message can be removed "
            "with -q"
         << std::endl;
      build = kul::String::BOOL(kul::cli::receive(ss.str()));
    }
    if (build) {
      CommandStateMachine::INSTANCE().main(0);
      for (auto &m : _mods) m.second->process();
      CommandStateMachine::INSTANCE().main(1);
    }
  }
  for (auto app = this->deps.rbegin(); app != this->deps.rend(); ++app) loadModules(**app);
  loadModules(*this);
  for (auto app = this->deps.rbegin(); app != this->deps.rend(); ++app) {
    if ((*app)->ig) continue;
    if ((*app)->lang.empty()) (*app)->resolveLang();
    (*app)->main.clear();
    proc(**app, !(*app)->srcs.empty());
  }
  if (!this->ig) proc(*this, (!this->srcs.empty() || !this->main.empty()));
  if (cmds.count(STR_TEST)) {
    for (auto &modLoader : mods) modLoader->module()->test(*this, this->modTest(modLoader->app()));
    test();
  }
  if (cmds.count(STR_PACK)) {
    pack();
    for (auto &modLoader : mods) modLoader->module()->pack(*this, this->modPack(modLoader->app()));
  }
  if (CommandStateMachine::INSTANCE().main() && (cmds.count(STR_RUN) || cmds.count(STR_DBG)))
    run(cmds.count(STR_DBG));
  CommandStateMachine::INSTANCE().reset();
  AppVars::INSTANCE().show(0);
}
<commit_msg>rm var print<commit_after>/**
Copyright (c) 2017, Philip Deegan.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
    * Neither the name of Philip Deegan nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "maiken.hpp"

#ifdef _MKN_WITH_MKN_RAM_
#include "maiken/github.hpp"
bool maiken::Application::get_binaries() {
  size_t suxcess = 0;
  kul::Dir outD(inst ? inst.real() : buildDir());
  const auto files = kul::String::SPLIT(this->binary(), " ");
  for (const std::string &file : files) {
    std::string fn = file.substr(file.rfind("/") + 1);
    kul::https::Get(file)
        .withHeaders({{"User-Agent", "Mozilla not a virus"},
                      {"Accept", "application/octet-stream"},
                      {"Content-Disposition", "attachment; filename=" + fn}})
        .withResponse([&](const kul::http::Response &r) {
          if (r.status() == 200) {
            kul::File dl(fn);
            if (dl.is()) {
              suxcess++;
              dl.mv(outD);
            }
          }
        })
        .send();
  }
  return suxcess == files.size();
}
#endif

namespace maiken {
class ObjectMerger {
 public:
  static void into(const Application &root) {
    kul::Dir robj(root.buildDir().join("obj"));
    for (auto a : root.dependencies()) {
      kul::Dir obj(a->buildDir().join("obj"));
      if (obj)
        for (auto f : obj.files()) f.cp(robj);
    }
  }
};
}  // namespace maiken

void maiken::Application::process() KTHROW(kul::Exception) {
  auto const& cmds = CommandStateMachine::INSTANCE().commands();
  auto const& gEnvVars = maiken::AppVars::INSTANCE().envVars();

  kul::os::PushDir pushd(this->project().dir());
  auto loadModules = [&](Application &app) {
#ifndef _MKN_DISABLE_MODULES_
    for (auto mod = app.modDeps.begin(); mod != app.modDeps.end(); ++mod) {
      app.mods.push_back(ModuleLoader::LOAD(**mod));
    }
    for (auto &modLoader : app.mods) modLoader->module()->init(app, app.modInit(modLoader->app()));
#endif  //_MKN_DISABLE_MODULES_
  };
  auto proc = [&](Application &app, bool work) {
    kul::env::CWD(app.project().dir());

    if (work) {
      if (!app.buildDir()) app.buildDir().mk();
      if (BuildRecorder::INSTANCE().has(app.buildDir().real())) return;
      BuildRecorder::INSTANCE().add(app.buildDir().real());
    }
    kul::Dir mkn(app.buildDir().join(".mkn"));
    std::vector<std::pair<std::string, std::string>> oldEvs;
    for (const auto &ev : app.envVars()) {
      const std::string v = kul::env::GET(ev.name());
      oldEvs.push_back(std::pair<std::string, std::string>(ev.name(), v));
      kul::env::SET(ev.name(), ev.toString().c_str());
      maiken::AppVars::INSTANCE().envVar(ev.name(), ev.toString());
    }
    if (cmds.count(STR_CLEAN) && app.buildDir().is()) {
      app.buildDir().rm();
      mkn.rm();
    }
    if (cmds.count(STR_MERGE) && app.ro) ObjectMerger::into(app);
#ifdef _MKN_WITH_MKN_RAM_
    if (work && !app.bin.empty() && app.get_binaries()) work = false;  // doesn't work yet
#endif
    app.loadTimeStamps();

    kul::hash::set::String objects;
    if (cmds.count(STR_BUILD) || cmds.count(STR_COMPILE)) {
      for (auto &modLoader : app.mods)
        modLoader->module()->compile(app, app.modCompile(modLoader->app()));
      if (work) app.compile(objects);
    }
    if (cmds.count(STR_BUILD) || cmds.count(STR_LINK)) {
      if (work)
        for (auto &modLoader : app.mods)
          modLoader->module()->link(app, app.modLink(modLoader->app()));
      if ((cmds.count(STR_MERGE) && app.ro) || !cmds.count(STR_MERGE)) {
        app.findObjects(objects);
        app.link(objects);
      }
    }
    for (const auto &oldEv : oldEvs) kul::env::SET(oldEv.first.c_str(), oldEv.second.c_str());
    for (const auto e : gEnvVars) maiken::AppVars::INSTANCE().envVar(e.first, e.second);
  };

  auto _mods = ModuleMinimiser::modules(*this);
  for (auto &mod : ModuleMinimiser::modules(*this)) {
    bool build = mod.second->is_build_required();
    bool is_build_stale = mod.second->is_build_stale();
    if (!build && (is_build_stale && !maiken::AppVars::INSTANCE().quiet())) {
      std::stringstream ss;
      ss << "The project @ " << mod.second->project().dir() << " appears to be stale" << std::endl;
      ss << "\tWould you like to build it (Y/n) - this message can be removed "
            "with -q"
         << std::endl;
      build = kul::String::BOOL(kul::cli::receive(ss.str()));
    }
    if (build) {
      CommandStateMachine::INSTANCE().main(0);
      for (auto &m : _mods) m.second->process();
      CommandStateMachine::INSTANCE().main(1);
    }
  }
  for (auto app = this->deps.rbegin(); app != this->deps.rend(); ++app) loadModules(**app);
  loadModules(*this);
  for (auto app = this->deps.rbegin(); app != this->deps.rend(); ++app) {
    if ((*app)->ig) continue;
    if ((*app)->lang.empty()) (*app)->resolveLang();
    (*app)->main.clear();
    proc(**app, !(*app)->srcs.empty());
  }
  if (!this->ig) proc(*this, (!this->srcs.empty() || !this->main.empty()));
  if (cmds.count(STR_TEST)) {
    for (auto &modLoader : mods) modLoader->module()->test(*this, this->modTest(modLoader->app()));
    test();
  }
  if (cmds.count(STR_PACK)) {
    pack();
    for (auto &modLoader : mods) modLoader->module()->pack(*this, this->modPack(modLoader->app()));
  }
  if (CommandStateMachine::INSTANCE().main() && (cmds.count(STR_RUN) || cmds.count(STR_DBG)))
    run(cmds.count(STR_DBG));
  CommandStateMachine::INSTANCE().reset();
  AppVars::INSTANCE().show(0);
}
<|endoftext|>


<commit_before>#include <cerrno>
#include <cstring>
#include <ctime>
#include <iostream>

#include <pqxx/connection>
#include <pqxx/transaction>
#include <pqxx/transactor>
#include <pqxx/trigger>
#include <pqxx/result>

using namespace PGSTD;
using namespace pqxx;

// Example program for libpqxx.  Send notification to self.
//
// Usage: test004 [connect-string]
//
// Where connect-string is a set of connection options in Postgresql's
// PQconnectdb() format, eg. "dbname=template1" to select from a database
// called template1, or "host=foo.bar.net user=smith" to connect to a
// backend running on host foo.bar.net, logging in as user smith.

namespace
{

int Backend_PID = 0;

// Sample implementation of trigger handler
class TestTrig : public trigger
{
  bool m_Done;

public:
  explicit TestTrig(connection_base &C) : trigger(C, "trig"), m_Done(false) {}

  virtual void operator()(int be_pid)
  {
    m_Done = true;
    if (be_pid != Backend_PID)
      throw logic_error("Expected notification from backend process " +
		        to_string(Backend_PID) +
			", but got one from " +
			to_string(be_pid));

    cout << "Received notification: " << name() << " pid=" << be_pid << endl;
  }

  bool Done() const { return m_Done; }
};

// A transactor to trigger our trigger handler
class Notify : public transactor<>
{
  string m_Trigger;

public:
  explicit Notify(string TrigName) :
    transactor<>("Notifier"), m_Trigger(TrigName) { }

  void operator()(argument_type &T)
  {
    T.exec("NOTIFY \"" + m_Trigger + "\"");
    Backend_PID = T.conn().backendpid();
  }

  void OnAbort(const char Reason[]) throw ()
  {
    try
    {
      cerr << "Notify failed!" << endl;
      if (Reason) cerr << "Reason: " << Reason << endl;
    }
    catch (const exception &)
    {
    }
  }
};

} // namespace

int main(int, char *argv[])
{
  try
  {
    connection C(argv[1]);
    cout << "Adding trigger..." << endl;
    TestTrig Trig(C);

    cout << "Sending notification..." << endl;
    C.perform(Notify(Trig.name()));

    int notifs = 0;
    for (int i=0; (i < 20) && !Trig.Done(); ++i)
    {
      if (notifs)
	throw logic_error("Got " + to_string(notifs) +
	    " unexpected notification(s)!");
      pqxx::internal::sleep_seconds(1);
      notifs = C.get_notifs();
      cout << ".";
    }
    cout << endl;

    if (!Trig.Done())
    {
      cout << "No notification received!" << endl;
      return 1;
    }
    if (notifs != 1)
      throw logic_error("Expected 1 notification, got " + to_string(notifs));
  }
  catch (const sql_error &e)
  {
    // If we're interested in the text of a failed query, we can write separate
    // exception handling code for this type of exception
    cerr << "SQL error: " << e.what() << endl
         << "Query was: '" << e.query() << "'" << endl;
    return 1;
  }
  catch (const exception &e)
  {
    // All exceptions thrown by libpqxx are derived from std::exception
    cerr << "Exception: " << e.what() << endl;
    return 2;
  }
  catch (...)
  {
    // This is really unexpected (see above)
    cerr << "Unhandled exception" << endl;
    return 100;
  }

  return 0;
}

<commit_msg>Added comment<commit_after>#include <cerrno>
#include <cstring>
#include <ctime>
#include <iostream>

#include <pqxx/connection>
#include <pqxx/transaction>
#include <pqxx/transactor>
#include <pqxx/trigger>
#include <pqxx/result>

using namespace PGSTD;
using namespace pqxx;

// Example program for libpqxx.  Send notification to self.
//
// Usage: test004 [connect-string]
//
// Where connect-string is a set of connection options in Postgresql's
// PQconnectdb() format, eg. "dbname=template1" to select from a database
// called template1, or "host=foo.bar.net user=smith" to connect to a
// backend running on host foo.bar.net, logging in as user smith.

namespace
{

int Backend_PID = 0;

// Sample implementation of trigger handler
class TestTrig : public trigger
{
  bool m_Done;

public:
  explicit TestTrig(connection_base &C) : trigger(C, "trig"), m_Done(false) {}

  virtual void operator()(int be_pid)
  {
    m_Done = true;
    if (be_pid != Backend_PID)
      throw logic_error("Expected notification from backend process " +
		        to_string(Backend_PID) +
			", but got one from " +
			to_string(be_pid));

    cout << "Received notification: " << name() << " pid=" << be_pid << endl;
  }

  bool Done() const { return m_Done; }
};

// A transactor to trigger our trigger handler
class Notify : public transactor<>
{
  string m_Trigger;

public:
  explicit Notify(string TrigName) :
    transactor<>("Notifier"), m_Trigger(TrigName) { }

  void operator()(argument_type &T)
  {
    T.exec("NOTIFY \"" + m_Trigger + "\"");
    Backend_PID = T.conn().backendpid();
  }

  void OnAbort(const char Reason[]) throw ()
  {
    try
    {
      cerr << "Notify failed!" << endl;
      if (Reason) cerr << "Reason: " << Reason << endl;
    }
    catch (const exception &)
    {
    }
  }
};

} // namespace

int main(int, char *argv[])
{
  try
  {
    connection C(argv[1]);
    cout << "Adding trigger..." << endl;
    TestTrig Trig(C);

    cout << "Sending notification..." << endl;
    C.perform(Notify(Trig.name()));

    int notifs = 0;
    for (int i=0; (i < 20) && !Trig.Done(); ++i)
    {
      if (notifs)
	throw logic_error("Got " + to_string(notifs) +
	    " unexpected notification(s)!");
      // Sleep one second using a libpqxx-internal function.  Kids, don't try
      // this at home!  The pqxx::internal namespace is not for third-party use
      // and may change radically at any time.
      pqxx::internal::sleep_seconds(1);
      notifs = C.get_notifs();
      cout << ".";
    }
    cout << endl;

    if (!Trig.Done())
    {
      cout << "No notification received!" << endl;
      return 1;
    }
    if (notifs != 1)
      throw logic_error("Expected 1 notification, got " + to_string(notifs));
  }
  catch (const sql_error &e)
  {
    // If we're interested in the text of a failed query, we can write separate
    // exception handling code for this type of exception
    cerr << "SQL error: " << e.what() << endl
         << "Query was: '" << e.query() << "'" << endl;
    return 1;
  }
  catch (const exception &e)
  {
    // All exceptions thrown by libpqxx are derived from std::exception
    cerr << "Exception: " << e.what() << endl;
    return 2;
  }
  catch (...)
  {
    // This is really unexpected (see above)
    cerr << "Unhandled exception" << endl;
    return 100;
  }

  return 0;
}

<|endoftext|>


<commit_before><commit_msg>Always check return of stat #6345<commit_after><|endoftext|>


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

/*
 * POSIX platform functions.
 */
#ifndef _WIN32

#include "native.h"
#include "generic.h"
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemInfo(JNIEnv *env, jclass target, jobject info, jobject result) {
    jclass infoClass = env->GetObjectClass(info);

    struct utsname machine_info;
    if (uname(&machine_info) != 0) {
        mark_failed_with_errno(env, "could not query machine details", result);
        return;
    }

    jfieldID osNameField = env->GetFieldID(infoClass, "osName", "Ljava/lang/String;");
    env->SetObjectField(info, osNameField, char_to_java(env, machine_info.sysname, result));
    jfieldID osVersionField = env->GetFieldID(infoClass, "osVersion", "Ljava/lang/String;");
    env->SetObjectField(info, osVersionField, char_to_java(env, machine_info.release, result));
    jfieldID machineArchitectureField = env->GetFieldID(infoClass, "machineArchitecture", "Ljava/lang/String;");
    env->SetObjectField(info, machineArchitectureField, char_to_java(env, machine_info.machine, result));
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixTypeFunctions_getNativeTypeInfo(JNIEnv *env, jclass target, jobject info) {
    jclass infoClass = env->GetObjectClass(info);
    env->SetIntField(info, env->GetFieldID(infoClass, "int_bytes", "I"), sizeof(int));
    env->SetIntField(info, env->GetFieldID(infoClass, "u_long_bytes", "I"), sizeof(u_long));
    env->SetIntField(info, env->GetFieldID(infoClass, "size_t_bytes", "I"), sizeof(size_t));
    env->SetIntField(info, env->GetFieldID(infoClass, "uid_t_bytes", "I"), sizeof(uid_t));
    env->SetIntField(info, env->GetFieldID(infoClass, "gid_t_bytes", "I"), sizeof(gid_t));
    env->SetIntField(info, env->GetFieldID(infoClass, "off_t_bytes", "I"), sizeof(off_t));
}

/*
 * File functions
 */

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_chmod(JNIEnv *env, jclass target, jstring path, jint mode, jobject result) {
    char* pathStr = java_to_char(env, path, result);
    if (pathStr == NULL) {
        return;
    }
    int retval = chmod(pathStr, mode);
    free(pathStr);
    if (retval != 0) {
        mark_failed_with_errno(env, "could not chmod file", result);
    }
}

jlong timestamp(struct timespec t) {
    return t.tv_sec * 1000 + t.tv_nsec / 1000;
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_stat(JNIEnv *env, jclass target, jstring path, jobject dest, jobject result) {
    struct stat fileInfo;
    char* pathStr = java_to_char(env, path, result);
    if (pathStr == NULL) {
        return;
    }
    int retval = lstat(pathStr, &fileInfo);
    free(pathStr);
    if (retval != 0 && errno != ENOENT) {
        mark_failed_with_errno(env, "could not stat file", result);
        return;
    }

    jclass destClass = env->GetObjectClass(dest);
    jfieldID modeField = env->GetFieldID(destClass, "mode", "I");
    jfieldID typeField = env->GetFieldID(destClass, "type", "I");
    jfieldID sizeField = env->GetFieldID(destClass, "size", "J");
    jfieldID uidField = env->GetFieldID(destClass, "uid", "I");
    jfieldID gidField = env->GetFieldID(destClass, "gid", "I");
    jfieldID blockSizeField = env->GetFieldID(destClass, "blockSize", "J");
    jfieldID accessTimeField = env->GetFieldID(destClass, "accessTime", "J");
    jfieldID modificationTimeField = env->GetFieldID(destClass, "modificationTime", "J");
    jfieldID statusChangeTime = env->GetFieldID(destClass, "statusChangeTime", "J");

    if (retval != 0) {
        env->SetIntField(dest, typeField, FILE_TYPE_MISSING);
    } else {
        env->SetIntField(dest, modeField, 0777 & fileInfo.st_mode);
        int type;
        switch (fileInfo.st_mode & S_IFMT) {
            case S_IFREG:
                type = FILE_TYPE_FILE;
                break;
            case S_IFDIR:
                type = FILE_TYPE_DIRECTORY;
                break;
            case S_IFLNK:
                type = FILE_TYPE_SYMLINK;
                break;
            default:
                type= FILE_TYPE_OTHER;
        }
        env->SetIntField(dest, typeField, type);
        env->SetIntField(dest, uidField, fileInfo.st_uid);
        env->SetIntField(dest, gidField, fileInfo.st_gid);
        if (type == FILE_TYPE_FILE) {
            env->SetLongField(dest, sizeField, fileInfo.st_size);
        }
        env->SetLongField(dest, blockSizeField, fileInfo.st_blksize);
#ifdef __linux__
        env->SetLongField(dest, accessTimeField, fileInfo.st_atime * 1000);
        env->SetLongField(dest, modificationTimeField, fileInfo.st_mtime * 1000);
        env->SetLongField(dest, statusChangeTime, fileInfo.st_ctime * 1000);
#else
        env->SetLongField(dest, accessTimeField, timestamp(fileInfo.st_atimespec));
        env->SetLongField(dest, modificationTimeField, timestamp(fileInfo.st_mtimespec));
        env->SetLongField(dest, statusChangeTime, timestamp(fileInfo.st_ctimespec));
#endif
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_symlink(JNIEnv *env, jclass target, jstring path, jstring contents, jobject result) {
    char* pathStr = java_to_char(env, path, result);
    if (pathStr == NULL) {
        return;
    }
    char* contentStr = java_to_char(env, contents, result);
    if (contentStr == NULL) {
        free(pathStr);
        return;
    }
    int retval = symlink(contentStr, pathStr);
    free(contentStr);
    free(pathStr);
    if (retval != 0) {
        mark_failed_with_errno(env, "could not symlink", result);
    }
}

JNIEXPORT jstring JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_readlink(JNIEnv *env, jclass target, jstring path, jobject result) {
    struct stat link_info;
    char* pathStr = java_to_char(env, path, result);
    if (pathStr == NULL) {
        return NULL;
    }
    int retval = lstat(pathStr, &link_info);
    if (retval != 0) {
        free(pathStr);
        mark_failed_with_errno(env, "could not lstat file", result);
        return NULL;
    }

    char* contents = (char*)malloc(link_info.st_size + 1);
    if (contents == NULL) {
        free(pathStr);
        mark_failed_with_message(env, "could not create array", result);
        return NULL;
    }

    retval = readlink(pathStr, contents, link_info.st_size);
    free(pathStr);
    if (retval < 0) {
        free(contents);
        mark_failed_with_errno(env, "could not readlink", result);
        return NULL;
    }
    contents[link_info.st_size] = 0;
    jstring contents_str = char_to_java(env, contents, result);
    free(contents);
    return contents_str;
}

/*
 * Process functions
 */

JNIEXPORT jint JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getPid(JNIEnv *env, jclass target) {
    return getpid();
}

JNIEXPORT jstring JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getWorkingDirectory(JNIEnv *env, jclass target, jobject result) {
    char* path = getcwd(NULL, 0);
    if (path == NULL) {
        mark_failed_with_errno(env, "could not getcwd()", result);
        return NULL;
    }
    jstring dir = char_to_java(env, path, result);
    free(path);
    return dir;
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_setWorkingDirectory(JNIEnv *env, jclass target, jstring dir, jobject result) {
    char* path = java_to_char(env, dir, result);
    if (path == NULL) {
        return;
    }
    if (chdir(path) != 0) {
        mark_failed_with_errno(env, "could not setcwd()", result);
    }
    free(path);
}

JNIEXPORT jstring JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getEnvironmentVariable(JNIEnv *env, jclass target, jstring var, jobject result) {
    char* varStr = java_to_char(env, var, result);
    char* valueStr = getenv(varStr);
    free(varStr);
    if (valueStr == NULL) {
        return NULL;
    }
    return char_to_java(env, valueStr, result);
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_setEnvironmentVariable(JNIEnv *env, jclass target, jstring var, jstring value, jobject result) {
    char* varStr = java_to_char(env, var, result);
    if (value == NULL) {
        if (setenv(varStr, "", 1) != 0) {
            mark_failed_with_errno(env, "could not putenv()", result);
        }
    } else {
        char* valueStr = java_to_char(env, value, result);
        if (setenv(varStr, valueStr, 1) != 0) {
            mark_failed_with_errno(env, "could not putenv()", result);
        }
        free(valueStr);
    }
    free(varStr);
}

/*
 * Terminal functions
 */

JNIEXPORT jboolean JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixTerminalFunctions_isatty(JNIEnv *env, jclass target, jint output) {
    struct stat fileInfo;
    int result;
    switch (output) {
    case 0:
    case 1:
        return isatty(output+1) ? JNI_TRUE : JNI_FALSE;
    default:
        return JNI_FALSE;
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixTerminalFunctions_getTerminalSize(JNIEnv *env, jclass target, jint output, jobject dimension, jobject result) {
    struct winsize screen_size;
    int retval = ioctl(output+1, TIOCGWINSZ, &screen_size);
    if (retval != 0) {
        mark_failed_with_errno(env, "could not fetch terminal size", result);
        return;
    }
    jclass dimensionClass = env->GetObjectClass(dimension);
    jfieldID widthField = env->GetFieldID(dimensionClass, "cols", "I");
    env->SetIntField(dimension, widthField, screen_size.ws_col);
    jfieldID heightField = env->GetFieldID(dimensionClass, "rows", "I");
    env->SetIntField(dimension, heightField, screen_size.ws_row);
}

#endif
<commit_msg>Fixed times reported for `FileInfo` on 32bit linux.<commit_after>/*
 * Copyright 2012 Adam Murdoch
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/*
 * POSIX platform functions.
 */
#ifndef _WIN32

#include "native.h"
#include "generic.h"
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemInfo(JNIEnv *env, jclass target, jobject info, jobject result) {
    jclass infoClass = env->GetObjectClass(info);

    struct utsname machine_info;
    if (uname(&machine_info) != 0) {
        mark_failed_with_errno(env, "could not query machine details", result);
        return;
    }

    jfieldID osNameField = env->GetFieldID(infoClass, "osName", "Ljava/lang/String;");
    env->SetObjectField(info, osNameField, char_to_java(env, machine_info.sysname, result));
    jfieldID osVersionField = env->GetFieldID(infoClass, "osVersion", "Ljava/lang/String;");
    env->SetObjectField(info, osVersionField, char_to_java(env, machine_info.release, result));
    jfieldID machineArchitectureField = env->GetFieldID(infoClass, "machineArchitecture", "Ljava/lang/String;");
    env->SetObjectField(info, machineArchitectureField, char_to_java(env, machine_info.machine, result));
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixTypeFunctions_getNativeTypeInfo(JNIEnv *env, jclass target, jobject info) {
    jclass infoClass = env->GetObjectClass(info);
    env->SetIntField(info, env->GetFieldID(infoClass, "int_bytes", "I"), sizeof(int));
    env->SetIntField(info, env->GetFieldID(infoClass, "u_long_bytes", "I"), sizeof(u_long));
    env->SetIntField(info, env->GetFieldID(infoClass, "size_t_bytes", "I"), sizeof(size_t));
    env->SetIntField(info, env->GetFieldID(infoClass, "uid_t_bytes", "I"), sizeof(uid_t));
    env->SetIntField(info, env->GetFieldID(infoClass, "gid_t_bytes", "I"), sizeof(gid_t));
    env->SetIntField(info, env->GetFieldID(infoClass, "off_t_bytes", "I"), sizeof(off_t));
}

/*
 * File functions
 */

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_chmod(JNIEnv *env, jclass target, jstring path, jint mode, jobject result) {
    char* pathStr = java_to_char(env, path, result);
    if (pathStr == NULL) {
        return;
    }
    int retval = chmod(pathStr, mode);
    free(pathStr);
    if (retval != 0) {
        mark_failed_with_errno(env, "could not chmod file", result);
    }
}

jlong timestamp(struct timespec t) {
    return (jlong)(t.tv_sec) * 1000 + (jlong)(t.tv_nsec) / 1000;
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_stat(JNIEnv *env, jclass target, jstring path, jobject dest, jobject result) {
    struct stat fileInfo;
    char* pathStr = java_to_char(env, path, result);
    if (pathStr == NULL) {
        return;
    }
    int retval = lstat(pathStr, &fileInfo);
    free(pathStr);
    if (retval != 0 && errno != ENOENT) {
        mark_failed_with_errno(env, "could not stat file", result);
        return;
    }

    jclass destClass = env->GetObjectClass(dest);
    jfieldID modeField = env->GetFieldID(destClass, "mode", "I");
    jfieldID typeField = env->GetFieldID(destClass, "type", "I");
    jfieldID sizeField = env->GetFieldID(destClass, "size", "J");
    jfieldID uidField = env->GetFieldID(destClass, "uid", "I");
    jfieldID gidField = env->GetFieldID(destClass, "gid", "I");
    jfieldID blockSizeField = env->GetFieldID(destClass, "blockSize", "J");
    jfieldID accessTimeField = env->GetFieldID(destClass, "accessTime", "J");
    jfieldID modificationTimeField = env->GetFieldID(destClass, "modificationTime", "J");
    jfieldID statusChangeTime = env->GetFieldID(destClass, "statusChangeTime", "J");

    if (retval != 0) {
        env->SetIntField(dest, typeField, FILE_TYPE_MISSING);
    } else {
        env->SetIntField(dest, modeField, 0777 & fileInfo.st_mode);
        int type;
        switch (fileInfo.st_mode & S_IFMT) {
            case S_IFREG:
                type = FILE_TYPE_FILE;
                break;
            case S_IFDIR:
                type = FILE_TYPE_DIRECTORY;
                break;
            case S_IFLNK:
                type = FILE_TYPE_SYMLINK;
                break;
            default:
                type= FILE_TYPE_OTHER;
        }
        env->SetIntField(dest, typeField, type);
        env->SetIntField(dest, uidField, fileInfo.st_uid);
        env->SetIntField(dest, gidField, fileInfo.st_gid);
        if (type == FILE_TYPE_FILE) {
            env->SetLongField(dest, sizeField, fileInfo.st_size);
        }
        env->SetLongField(dest, blockSizeField, fileInfo.st_blksize);
#ifdef __linux__
        env->SetLongField(dest, accessTimeField, timestamp(fileInfo.st_atim));
        env->SetLongField(dest, modificationTimeField, timestamp(fileInfo.st_mtim));
        env->SetLongField(dest, statusChangeTime, timestamp(fileInfo.st_ctim));
#else
        env->SetLongField(dest, accessTimeField, timestamp(fileInfo.st_atimespec));
        env->SetLongField(dest, modificationTimeField, timestamp(fileInfo.st_mtimespec));
        env->SetLongField(dest, statusChangeTime, timestamp(fileInfo.st_ctimespec));
#endif
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_symlink(JNIEnv *env, jclass target, jstring path, jstring contents, jobject result) {
    char* pathStr = java_to_char(env, path, result);
    if (pathStr == NULL) {
        return;
    }
    char* contentStr = java_to_char(env, contents, result);
    if (contentStr == NULL) {
        free(pathStr);
        return;
    }
    int retval = symlink(contentStr, pathStr);
    free(contentStr);
    free(pathStr);
    if (retval != 0) {
        mark_failed_with_errno(env, "could not symlink", result);
    }
}

JNIEXPORT jstring JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_readlink(JNIEnv *env, jclass target, jstring path, jobject result) {
    struct stat link_info;
    char* pathStr = java_to_char(env, path, result);
    if (pathStr == NULL) {
        return NULL;
    }
    int retval = lstat(pathStr, &link_info);
    if (retval != 0) {
        free(pathStr);
        mark_failed_with_errno(env, "could not lstat file", result);
        return NULL;
    }

    char* contents = (char*)malloc(link_info.st_size + 1);
    if (contents == NULL) {
        free(pathStr);
        mark_failed_with_message(env, "could not create array", result);
        return NULL;
    }

    retval = readlink(pathStr, contents, link_info.st_size);
    free(pathStr);
    if (retval < 0) {
        free(contents);
        mark_failed_with_errno(env, "could not readlink", result);
        return NULL;
    }
    contents[link_info.st_size] = 0;
    jstring contents_str = char_to_java(env, contents, result);
    free(contents);
    return contents_str;
}

/*
 * Process functions
 */

JNIEXPORT jint JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getPid(JNIEnv *env, jclass target) {
    return getpid();
}

JNIEXPORT jstring JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getWorkingDirectory(JNIEnv *env, jclass target, jobject result) {
    char* path = getcwd(NULL, 0);
    if (path == NULL) {
        mark_failed_with_errno(env, "could not getcwd()", result);
        return NULL;
    }
    jstring dir = char_to_java(env, path, result);
    free(path);
    return dir;
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_setWorkingDirectory(JNIEnv *env, jclass target, jstring dir, jobject result) {
    char* path = java_to_char(env, dir, result);
    if (path == NULL) {
        return;
    }
    if (chdir(path) != 0) {
        mark_failed_with_errno(env, "could not setcwd()", result);
    }
    free(path);
}

JNIEXPORT jstring JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getEnvironmentVariable(JNIEnv *env, jclass target, jstring var, jobject result) {
    char* varStr = java_to_char(env, var, result);
    char* valueStr = getenv(varStr);
    free(varStr);
    if (valueStr == NULL) {
        return NULL;
    }
    return char_to_java(env, valueStr, result);
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_setEnvironmentVariable(JNIEnv *env, jclass target, jstring var, jstring value, jobject result) {
    char* varStr = java_to_char(env, var, result);
    if (value == NULL) {
        if (setenv(varStr, "", 1) != 0) {
            mark_failed_with_errno(env, "could not putenv()", result);
        }
    } else {
        char* valueStr = java_to_char(env, value, result);
        if (setenv(varStr, valueStr, 1) != 0) {
            mark_failed_with_errno(env, "could not putenv()", result);
        }
        free(valueStr);
    }
    free(varStr);
}

/*
 * Terminal functions
 */

JNIEXPORT jboolean JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixTerminalFunctions_isatty(JNIEnv *env, jclass target, jint output) {
    struct stat fileInfo;
    int result;
    switch (output) {
    case 0:
    case 1:
        return isatty(output+1) ? JNI_TRUE : JNI_FALSE;
    default:
        return JNI_FALSE;
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixTerminalFunctions_getTerminalSize(JNIEnv *env, jclass target, jint output, jobject dimension, jobject result) {
    struct winsize screen_size;
    int retval = ioctl(output+1, TIOCGWINSZ, &screen_size);
    if (retval != 0) {
        mark_failed_with_errno(env, "could not fetch terminal size", result);
        return;
    }
    jclass dimensionClass = env->GetObjectClass(dimension);
    jfieldID widthField = env->GetFieldID(dimensionClass, "cols", "I");
    env->SetIntField(dimension, widthField, screen_size.ws_col);
    jfieldID heightField = env->GetFieldID(dimensionClass, "rows", "I");
    env->SetIntField(dimension, heightField, screen_size.ws_row);
}

#endif
<|endoftext|>


<commit_before>//! @file getcpinfo.cpp
//! @author Aaron Ktaz <v-aakatz@microsoft.com>
//! @brief Implements GetCpInfoW Win32 API

#include <errno.h>
#include <string>
#include <langinfo.h>
#include "getcpinfo.h"

//! @brief GetCPInfoW retrieves the name of the code page associated with
//! the current thread.
//!
//! GetCpInfoW the Unicode variation. See [MSDN documentation].
//!
//! @param[in] codepage
//! @parblock
//! An UINT Identifier for the code page for which to retrieve information.
//! See Code Page Identifiers for details
//! 65001 in the number for UTF8.  It is the only valid inpur parameter
//!because Linux and Unix only use UTF8 for codepage
//!
//! @endparblock
//!
//! @param[out] cpinfo
//! @parblock
//! Pointer to a CPINFO structure that receives information about the code page
//!
//! LPCPINFO is a pointer to the structure _cpinfo used to contain the information
//! about a code page
//!
//! _cpinfo is a struct that comprises
//!
//! UINT MaxCharSize;
//! Maximum length, in bytes, of a character in the code page.
//! The length can be 1 for a single-byte character set (SBCS),
//! 2 for a double-byte character set (DBCS), or a value larger
//! than 2 for other character set types. The function cannot
//! use the size to distinguish an SBCS or a DBCS from other
//! character sets because of other factors, for example,
//! the use of ISCII or ISO-2022-xx code pages.
//!
//! BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR];
//! Default character used when translating character
//! strings to the specific code page. This character is used by
//! the WideCharToMultiByte function if an explicit default
//! character is not specified. The default is usually the "?"
//! character for the code page
//!
//! BYTE LeadByte[const_cpinfo::MAX_LEADBYTES];
//! A fixed-length array of lead byte ranges, for which the number
//! of lead byte ranges is variable. If the code page has no lead
//! bytes, every element of the array is set to NULL. If the code
//! page has lead bytes, the array specifies a starting value and
//! an ending value for each range. Ranges are inclusive, and the
//! maximum number of ranges for any code page is five. The array
//! uses two bytes to describe each range, with two null bytes as
//! a terminator after the last range.
//!
//! MAX_DEFAULTCHAR is an int of size 2
//! MAX_LEADBYTES is an int of size 12
//!
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_INVALID_PARAMETER: parameter is not valid
//!
//! @retval TRUE If the function succeeds, the return value is a nonzero
//! value, and cpinfo is population with information about the code page
//!
//! @retval FALSE If the function fails, the return value is zero. To get
//! extended error information, call GetLastError.
//!
//! [MSDN documentation]:https://msdn.microsoft.com/en-us/library/windows/desktop/dd318078%28v=vs.85%29.aspx
//! [_cpinfo]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317780%28v=vs.85%29.aspx
//! [CodePageIdentifiers] https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx

BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo)
{
    errno = FALSE;

    // Select locale from environment
    setlocale(LC_ALL, "");

    // Check that locale is UTF-8
    if (nl_langinfo(CODESET) != std::string("UTF-8"))
    {
        errno = ERROR_BAD_ENVIRONMENT;
        return FALSE;
    }

    // 65001 is the code page for UTF8, Linux and Unix default it UTF8
    if (codepage != const_cpinfo::UTF8)
    {
        //If other value is used return error because Linux and Unix only used UTF-8 for codepage
        errno = ERROR_INVALID_PARAMETER;
        return FALSE;
    }

    // UTF-8 uses the default char for DefaultChar[0] which is '?'
    cpinfo->DefaultChar[0] = '?';
    cpinfo->DefaultChar[1] = '0';
    cpinfo->MaxCharSize = 4;
    for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ )
    {
        // UTF-8 uses the default has no LeadByte as result LeadByte is '0'
        cpinfo->LeadByte[i] = '0';

    }
    return TRUE;

}

<commit_msg>Changes to documentation<commit_after>//! @file getcpinfo.cpp
//! @author Aaron Ktaz <v-aakatz@microsoft.com>
//! @brief Implements GetCpInfoW Win32 API

#include <errno.h>
#include <string>
#include <langinfo.h>
#include "getcpinfo.h"

//! @brief GetCPInfoW retrieves the name of the code page associated with
//! the current thread.
//!
//! GetCpInfoW the Unicode variation. See [MSDN documentation].
//!
//! @param[in] codepage
//! @parblock
//! An UINT Identifier for the code page for which to retrieve information.
//! See Code Page Identifiers for details
//! 65001 in the number for UTF8.  It is the only valid input parameter
//!because Linux and Unix only use UTF8 for codepage
//!
//! @endparblock
//!
//! @param[out] cpinfo
//! @parblock
//! Pointer to a CPINFO structure that receives information about the code page
//!
//! LPCPINFO is a pointer to the structure _cpinfo used to contain the information
//! about a code page
//!
//!
//! typedef struct _cpinfo {
//!    UINT MaxCharSize;
//!    BYTE DefaultChar[MAX_DEFAULTCHAR];
//!    BYTE LeadByte[MAX_LEADBYTES];
//! } CPINFO, *LPCPINFO;
//!
//! _cpinfo is a struct that comprises
//!
//! UINT MaxCharSize;
//! Maximum length, in bytes, of a character in the code page.
//! The length can be 1 for a single-byte character set (SBCS),
//! 2 for a double-byte character set (DBCS), or a value larger
//! than 2 for other character set types. The function cannot
//! use the size to distinguish an SBCS or a DBCS from other
//! character sets because of other factors, for example,
//! the use of ISCII or ISO-2022-xx code pages.
//!
//! BYTE DefaultChar[const_cpinfo::MAX_DEFAULTCHAR];
//! Default character used when translating character
//! strings to the specific code page. This character is used by
//! the WideCharToMultiByte function if an explicit default
//! character is not specified. The default is usually the "?"
//! character for the code page
//!
//! BYTE LeadByte[const_cpinfo::MAX_LEADBYTES];
//! A fixed-length array of lead byte ranges, for which the number
//! of lead byte ranges is variable. If the code page has no lead
//! bytes, every element of the array is set to NULL. If the code
//! page has lead bytes, the array specifies a starting value and
//! an ending value for each range. Ranges are inclusive, and the
//! maximum number of ranges for any code page is five. The array
//! uses two bytes to describe each range, with two null bytes as
//! a terminator after the last range.
//!
//! MAX_DEFAULTCHAR is an int of size 2
//! MAX_LEADBYTES is an int of size 12
//!
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_INVALID_PARAMETER: parameter is not valid
//!
//! @retval TRUE If the function succeeds, the return value is a nonzero
//! value, and cpinfo is population with information about the code page
//!
//! @retval FALSE If the function fails, the return value is zero. To get
//! extended error information, call GetLastError.
//!
//! [MSDN documentation]:https://msdn.microsoft.com/en-us/library/windows/desktop/dd318078%28v=vs.85%29.aspx
//! [_cpinfo]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317780(v=vs.85).aspx
//! [CodePageIdentifiers] https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx

BOOL GetCPInfoW(UINT codepage, CPINFO* cpinfo)
{
    errno = FALSE;

    // Select locale from environment
    setlocale(LC_ALL, "");

    // Check that locale is UTF-8
    if (nl_langinfo(CODESET) != std::string("UTF-8"))
    {
        errno = ERROR_BAD_ENVIRONMENT;
        return FALSE;
    }

    if (codepage != const_cpinfo::UTF8)
    {
        //If other value is used return error because Linux and Unix only used UTF-8 for codepage
        errno = ERROR_INVALID_PARAMETER;
        return FALSE;
    }

    // UTF-8 uses the default char for DefaultChar[0] which is '?'
    cpinfo->DefaultChar[0] = '?';
    cpinfo->DefaultChar[1] = '0';
    cpinfo->MaxCharSize = 4;

    for (int i = 0; i < const_cpinfo::MAX_LEADBYTES; i++ )
    {
        // UTF-8 uses the default has no LeadByte as result LeadByte is '0'
        cpinfo->LeadByte[i] = '0';
    }

    return TRUE;

}

<|endoftext|>


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

#include "manifest_parser.h"

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

#include "graph.h"
#include "state.h"
#include "util.h"
#include "version.h"

ManifestParser::ManifestParser(State* state, FileReader* file_reader,
                               ManifestParserOptions options)
    : Parser(state, file_reader),
      options_(options), quiet_(false) {
  env_ = &state->bindings_;
}

bool ManifestParser::Parse(const string& filename, const string& input,
                           string* err) {
  lexer_.Start(filename, input);

  for (;;) {
    Lexer::Token token = lexer_.ReadToken();
    switch (token) {
    case Lexer::POOL:
      if (!ParsePool(err))
        return false;
      break;
    case Lexer::BUILD:
      if (!ParseEdge(err))
        return false;
      break;
    case Lexer::RULE:
      if (!ParseRule(err))
        return false;
      break;
    case Lexer::DEFAULT:
      if (!ParseDefault(err))
        return false;
      break;
    case Lexer::IDENT: {
      lexer_.UnreadToken();
      string name;
      EvalString let_value;
      if (!ParseLet(&name, &let_value, err))
        return false;
      string value = let_value.Evaluate(env_);
      // Check ninja_required_version immediately so we can exit
      // before encountering any syntactic surprises.
      if (name == "ninja_required_version")
        CheckNinjaVersion(value);
      env_->AddBinding(name, value);
      break;
    }
    case Lexer::INCLUDE:
      if (!ParseFileInclude(false, err))
        return false;
      break;
    case Lexer::SUBNINJA:
      if (!ParseFileInclude(true, err))
        return false;
      break;
    case Lexer::ERROR: {
      return lexer_.Error(lexer_.DescribeLastError(), err);
    }
    case Lexer::TEOF:
      return true;
    case Lexer::NEWLINE:
      break;
    default:
      return lexer_.Error(string("unexpected ") + Lexer::TokenName(token),
                          err);
    }
  }
  return false;  // not reached
}

bool ManifestParser::ParsePool(string* err) {
  string name;
  if (!lexer_.ReadIdent(&name))
    return lexer_.Error("expected pool name", err);

  if (!ExpectToken(Lexer::NEWLINE, err))
    return false;

  if (state_->LookupPool(name) != NULL)
    return lexer_.Error("duplicate pool '" + name + "'", err);

  int depth = -1;

  while (lexer_.PeekToken(Lexer::INDENT)) {
    string key;
    EvalString value;
    if (!ParseLet(&key, &value, err))
      return false;

    if (key == "depth") {
      string depth_string = value.Evaluate(env_);
      depth = atol(depth_string.c_str());
      if (depth < 0)
        return lexer_.Error("invalid pool depth", err);
    } else {
      return lexer_.Error("unexpected variable '" + key + "'", err);
    }
  }

  if (depth < 0)
    return lexer_.Error("expected 'depth =' line", err);

  state_->AddPool(new Pool(name, depth));
  return true;
}

bool ManifestParser::ParseRule(string* err) {
  string name;
  if (!lexer_.ReadIdent(&name))
    return lexer_.Error("expected rule name", err);

  if (!ExpectToken(Lexer::NEWLINE, err))
    return false;

  if (env_->LookupRuleCurrentScope(name) != NULL)
    return lexer_.Error("duplicate rule '" + name + "'", err);

  Rule* rule = new Rule(name);  // XXX scoped_ptr

  while (lexer_.PeekToken(Lexer::INDENT)) {
    string key;
    EvalString value;
    if (!ParseLet(&key, &value, err))
      return false;

    if (Rule::IsReservedBinding(key)) {
      rule->AddBinding(key, value);
    } else {
      // Die on other keyvals for now; revisit if we want to add a
      // scope here.
      return lexer_.Error("unexpected variable '" + key + "'", err);
    }
  }

  if (rule->bindings_["rspfile"].empty() !=
      rule->bindings_["rspfile_content"].empty()) {
    return lexer_.Error("rspfile and rspfile_content need to be "
                        "both specified", err);
  }

  if (rule->bindings_["command"].empty())
    return lexer_.Error("expected 'command =' line", err);

  env_->AddRule(rule);
  return true;
}

bool ManifestParser::ParseLet(string* key, EvalString* value, string* err) {
  if (!lexer_.ReadIdent(key))
    return lexer_.Error("expected variable name", err);
  if (!ExpectToken(Lexer::EQUALS, err))
    return false;
  if (!lexer_.ReadVarValue(value, err))
    return false;
  return true;
}

bool ManifestParser::ParseDefault(string* err) {
  EvalString eval;
  if (!lexer_.ReadPath(&eval, err))
    return false;
  if (eval.empty())
    return lexer_.Error("expected target name", err);

  do {
    string path = eval.Evaluate(env_);
    string path_err;
    uint64_t slash_bits;  // Unused because this only does lookup.
    if (!CanonicalizePath(&path, &slash_bits, &path_err))
      return lexer_.Error(path_err, err);
    if (!state_->AddDefault(path, &path_err))
      return lexer_.Error(path_err, err);

    eval.Clear();
    if (!lexer_.ReadPath(&eval, err))
      return false;
  } while (!eval.empty());

  if (!ExpectToken(Lexer::NEWLINE, err))
    return false;

  return true;
}

bool ManifestParser::ParseEdge(string* err) {
  vector<EvalString> ins, outs;

  {
    EvalString out;
    if (!lexer_.ReadPath(&out, err))
      return false;
    while (!out.empty()) {
      outs.push_back(out);

      out.Clear();
      if (!lexer_.ReadPath(&out, err))
        return false;
    }
  }

  // Add all implicit outs, counting how many as we go.
  int implicit_outs = 0;
  if (lexer_.PeekToken(Lexer::PIPE)) {
    for (;;) {
      EvalString out;
      if (!lexer_.ReadPath(&out, err))
        return err;
      if (out.empty())
        break;
      outs.push_back(out);
      ++implicit_outs;
    }
  }

  if (outs.empty())
    return lexer_.Error("expected path", err);

  if (!ExpectToken(Lexer::COLON, err))
    return false;

  string rule_name;
  if (!lexer_.ReadIdent(&rule_name))
    return lexer_.Error("expected build command name", err);

  const Rule* rule = env_->LookupRule(rule_name);
  if (!rule)
    return lexer_.Error("unknown build rule '" + rule_name + "'", err);

  for (;;) {
    // XXX should we require one path here?
    EvalString in;
    if (!lexer_.ReadPath(&in, err))
      return false;
    if (in.empty())
      break;
    ins.push_back(in);
  }

  // Add all implicit deps, counting how many as we go.
  int implicit = 0;
  if (lexer_.PeekToken(Lexer::PIPE)) {
    for (;;) {
      EvalString in;
      if (!lexer_.ReadPath(&in, err))
        return err;
      if (in.empty())
        break;
      ins.push_back(in);
      ++implicit;
    }
  }

  // Add all order-only deps, counting how many as we go.
  int order_only = 0;
  if (lexer_.PeekToken(Lexer::PIPE2)) {
    for (;;) {
      EvalString in;
      if (!lexer_.ReadPath(&in, err))
        return false;
      if (in.empty())
        break;
      ins.push_back(in);
      ++order_only;
    }
  }

  if (!ExpectToken(Lexer::NEWLINE, err))
    return false;

  // Bindings on edges are rare, so allocate per-edge envs only when needed.
  bool has_indent_token = lexer_.PeekToken(Lexer::INDENT);
  BindingEnv* env = has_indent_token ? new BindingEnv(env_) : env_;
  while (has_indent_token) {
    string key;
    EvalString val;
    if (!ParseLet(&key, &val, err))
      return false;

    env->AddBinding(key, val.Evaluate(env_));
    has_indent_token = lexer_.PeekToken(Lexer::INDENT);
  }

  Edge* edge = state_->AddEdge(rule);
  edge->env_ = env;

  string pool_name = edge->GetBinding("pool");
  if (!pool_name.empty()) {
    Pool* pool = state_->LookupPool(pool_name);
    if (pool == NULL)
      return lexer_.Error("unknown pool name '" + pool_name + "'", err);
    edge->pool_ = pool;
  }

  edge->outputs_.reserve(outs.size());
  for (size_t i = 0, e = outs.size(); i != e; ++i) {
    string path = outs[i].Evaluate(env);
    string path_err;
    uint64_t slash_bits;
    if (!CanonicalizePath(&path, &slash_bits, &path_err))
      return lexer_.Error(path_err, err);
    if (!state_->AddOut(edge, path, slash_bits)) {
      if (options_.dupe_edge_action_ == kDupeEdgeActionError) {
        lexer_.Error("multiple rules generate " + path + " [-w dupbuild=err]",
                     err);
        return false;
      } else {
        if (!quiet_) {
          Warning("multiple rules generate %s. "
                  "builds involving this target will not be correct; "
                  "continuing anyway [-w dupbuild=warn]",
                  path.c_str());
        }
        if (e - i <= static_cast<size_t>(implicit_outs))
          --implicit_outs;
      }
    }
  }
  if (edge->outputs_.empty()) {
    // All outputs of the edge are already created by other edges. Don't add
    // this edge.  Do this check before input nodes are connected to the edge.
    state_->edges_.pop_back();
    delete edge;
    return true;
  }
  edge->implicit_outs_ = implicit_outs;

  edge->inputs_.reserve(ins.size());
  for (vector<EvalString>::iterator i = ins.begin(); i != ins.end(); ++i) {
    string path = i->Evaluate(env);
    string path_err;
    uint64_t slash_bits;
    if (!CanonicalizePath(&path, &slash_bits, &path_err))
      return lexer_.Error(path_err, err);
    state_->AddIn(edge, path, slash_bits);
  }
  edge->implicit_deps_ = implicit;
  edge->order_only_deps_ = order_only;

  if (options_.phony_cycle_action_ == kPhonyCycleActionWarn &&
      edge->maybe_phonycycle_diagnostic()) {
    // CMake 2.8.12.x and 3.0.x incorrectly write phony build statements
    // that reference themselves.  Ninja used to tolerate these in the
    // build graph but that has since been fixed.  Filter them out to
    // support users of those old CMake versions.
    Node* out = edge->outputs_[0];
    vector<Node*>::iterator new_end =
        remove(edge->inputs_.begin(), edge->inputs_.end(), out);
    if (new_end != edge->inputs_.end()) {
      edge->inputs_.erase(new_end, edge->inputs_.end());
      if (!quiet_) {
        Warning("phony target '%s' names itself as an input; "
                "ignoring [-w phonycycle=warn]",
                out->path().c_str());
      }
    }
  }

  // Multiple outputs aren't (yet?) supported with depslog.
  string deps_type = edge->GetBinding("deps");
  if (!deps_type.empty() && edge->outputs_.size() > 1) {
    return lexer_.Error("multiple outputs aren't (yet?) supported by depslog; "
                        "bring this up on the mailing list if it affects you",
                        err);
  }

  // Lookup, validate, and save any dyndep binding.  It will be used later
  // to load generated dependency information dynamically, but it must
  // be one of our manifest-specified inputs.
  string dyndep = edge->GetUnescapedDyndep();
  if (!dyndep.empty()) {
    uint64_t slash_bits;
    if (!CanonicalizePath(&dyndep, &slash_bits, err))
      return false;
    edge->dyndep_ = state_->GetNode(dyndep, slash_bits);
    edge->dyndep_->set_dyndep_pending(true);
    vector<Node*>::iterator dgi =
      std::find(edge->inputs_.begin(), edge->inputs_.end(), edge->dyndep_);
    if (dgi == edge->inputs_.end()) {
      return lexer_.Error("dyndep '" + dyndep + "' is not an input", err);
    }
  }

  return true;
}

bool ManifestParser::ParseFileInclude(bool new_scope, string* err) {
  EvalString eval;
  if (!lexer_.ReadPath(&eval, err))
    return false;
  string path = eval.Evaluate(env_);

  ManifestParser subparser(state_, file_reader_, options_);
  if (new_scope) {
    subparser.env_ = new BindingEnv(env_);
  } else {
    subparser.env_ = env_;
  }

  if (!subparser.Load(path, err, &lexer_))
    return false;

  if (!ExpectToken(Lexer::NEWLINE, err))
    return false;

  return true;
}
<commit_msg>Fix minor typo of return value<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "manifest_parser.h"

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

#include "graph.h"
#include "state.h"
#include "util.h"
#include "version.h"

ManifestParser::ManifestParser(State* state, FileReader* file_reader,
                               ManifestParserOptions options)
    : Parser(state, file_reader),
      options_(options), quiet_(false) {
  env_ = &state->bindings_;
}

bool ManifestParser::Parse(const string& filename, const string& input,
                           string* err) {
  lexer_.Start(filename, input);

  for (;;) {
    Lexer::Token token = lexer_.ReadToken();
    switch (token) {
    case Lexer::POOL:
      if (!ParsePool(err))
        return false;
      break;
    case Lexer::BUILD:
      if (!ParseEdge(err))
        return false;
      break;
    case Lexer::RULE:
      if (!ParseRule(err))
        return false;
      break;
    case Lexer::DEFAULT:
      if (!ParseDefault(err))
        return false;
      break;
    case Lexer::IDENT: {
      lexer_.UnreadToken();
      string name;
      EvalString let_value;
      if (!ParseLet(&name, &let_value, err))
        return false;
      string value = let_value.Evaluate(env_);
      // Check ninja_required_version immediately so we can exit
      // before encountering any syntactic surprises.
      if (name == "ninja_required_version")
        CheckNinjaVersion(value);
      env_->AddBinding(name, value);
      break;
    }
    case Lexer::INCLUDE:
      if (!ParseFileInclude(false, err))
        return false;
      break;
    case Lexer::SUBNINJA:
      if (!ParseFileInclude(true, err))
        return false;
      break;
    case Lexer::ERROR: {
      return lexer_.Error(lexer_.DescribeLastError(), err);
    }
    case Lexer::TEOF:
      return true;
    case Lexer::NEWLINE:
      break;
    default:
      return lexer_.Error(string("unexpected ") + Lexer::TokenName(token),
                          err);
    }
  }
  return false;  // not reached
}

bool ManifestParser::ParsePool(string* err) {
  string name;
  if (!lexer_.ReadIdent(&name))
    return lexer_.Error("expected pool name", err);

  if (!ExpectToken(Lexer::NEWLINE, err))
    return false;

  if (state_->LookupPool(name) != NULL)
    return lexer_.Error("duplicate pool '" + name + "'", err);

  int depth = -1;

  while (lexer_.PeekToken(Lexer::INDENT)) {
    string key;
    EvalString value;
    if (!ParseLet(&key, &value, err))
      return false;

    if (key == "depth") {
      string depth_string = value.Evaluate(env_);
      depth = atol(depth_string.c_str());
      if (depth < 0)
        return lexer_.Error("invalid pool depth", err);
    } else {
      return lexer_.Error("unexpected variable '" + key + "'", err);
    }
  }

  if (depth < 0)
    return lexer_.Error("expected 'depth =' line", err);

  state_->AddPool(new Pool(name, depth));
  return true;
}

bool ManifestParser::ParseRule(string* err) {
  string name;
  if (!lexer_.ReadIdent(&name))
    return lexer_.Error("expected rule name", err);

  if (!ExpectToken(Lexer::NEWLINE, err))
    return false;

  if (env_->LookupRuleCurrentScope(name) != NULL)
    return lexer_.Error("duplicate rule '" + name + "'", err);

  Rule* rule = new Rule(name);  // XXX scoped_ptr

  while (lexer_.PeekToken(Lexer::INDENT)) {
    string key;
    EvalString value;
    if (!ParseLet(&key, &value, err))
      return false;

    if (Rule::IsReservedBinding(key)) {
      rule->AddBinding(key, value);
    } else {
      // Die on other keyvals for now; revisit if we want to add a
      // scope here.
      return lexer_.Error("unexpected variable '" + key + "'", err);
    }
  }

  if (rule->bindings_["rspfile"].empty() !=
      rule->bindings_["rspfile_content"].empty()) {
    return lexer_.Error("rspfile and rspfile_content need to be "
                        "both specified", err);
  }

  if (rule->bindings_["command"].empty())
    return lexer_.Error("expected 'command =' line", err);

  env_->AddRule(rule);
  return true;
}

bool ManifestParser::ParseLet(string* key, EvalString* value, string* err) {
  if (!lexer_.ReadIdent(key))
    return lexer_.Error("expected variable name", err);
  if (!ExpectToken(Lexer::EQUALS, err))
    return false;
  if (!lexer_.ReadVarValue(value, err))
    return false;
  return true;
}

bool ManifestParser::ParseDefault(string* err) {
  EvalString eval;
  if (!lexer_.ReadPath(&eval, err))
    return false;
  if (eval.empty())
    return lexer_.Error("expected target name", err);

  do {
    string path = eval.Evaluate(env_);
    string path_err;
    uint64_t slash_bits;  // Unused because this only does lookup.
    if (!CanonicalizePath(&path, &slash_bits, &path_err))
      return lexer_.Error(path_err, err);
    if (!state_->AddDefault(path, &path_err))
      return lexer_.Error(path_err, err);

    eval.Clear();
    if (!lexer_.ReadPath(&eval, err))
      return false;
  } while (!eval.empty());

  if (!ExpectToken(Lexer::NEWLINE, err))
    return false;

  return true;
}

bool ManifestParser::ParseEdge(string* err) {
  vector<EvalString> ins, outs;

  {
    EvalString out;
    if (!lexer_.ReadPath(&out, err))
      return false;
    while (!out.empty()) {
      outs.push_back(out);

      out.Clear();
      if (!lexer_.ReadPath(&out, err))
        return false;
    }
  }

  // Add all implicit outs, counting how many as we go.
  int implicit_outs = 0;
  if (lexer_.PeekToken(Lexer::PIPE)) {
    for (;;) {
      EvalString out;
      if (!lexer_.ReadPath(&out, err))
        return false;
      if (out.empty())
        break;
      outs.push_back(out);
      ++implicit_outs;
    }
  }

  if (outs.empty())
    return lexer_.Error("expected path", err);

  if (!ExpectToken(Lexer::COLON, err))
    return false;

  string rule_name;
  if (!lexer_.ReadIdent(&rule_name))
    return lexer_.Error("expected build command name", err);

  const Rule* rule = env_->LookupRule(rule_name);
  if (!rule)
    return lexer_.Error("unknown build rule '" + rule_name + "'", err);

  for (;;) {
    // XXX should we require one path here?
    EvalString in;
    if (!lexer_.ReadPath(&in, err))
      return false;
    if (in.empty())
      break;
    ins.push_back(in);
  }

  // Add all implicit deps, counting how many as we go.
  int implicit = 0;
  if (lexer_.PeekToken(Lexer::PIPE)) {
    for (;;) {
      EvalString in;
      if (!lexer_.ReadPath(&in, err))
        return false;
      if (in.empty())
        break;
      ins.push_back(in);
      ++implicit;
    }
  }

  // Add all order-only deps, counting how many as we go.
  int order_only = 0;
  if (lexer_.PeekToken(Lexer::PIPE2)) {
    for (;;) {
      EvalString in;
      if (!lexer_.ReadPath(&in, err))
        return false;
      if (in.empty())
        break;
      ins.push_back(in);
      ++order_only;
    }
  }

  if (!ExpectToken(Lexer::NEWLINE, err))
    return false;

  // Bindings on edges are rare, so allocate per-edge envs only when needed.
  bool has_indent_token = lexer_.PeekToken(Lexer::INDENT);
  BindingEnv* env = has_indent_token ? new BindingEnv(env_) : env_;
  while (has_indent_token) {
    string key;
    EvalString val;
    if (!ParseLet(&key, &val, err))
      return false;

    env->AddBinding(key, val.Evaluate(env_));
    has_indent_token = lexer_.PeekToken(Lexer::INDENT);
  }

  Edge* edge = state_->AddEdge(rule);
  edge->env_ = env;

  string pool_name = edge->GetBinding("pool");
  if (!pool_name.empty()) {
    Pool* pool = state_->LookupPool(pool_name);
    if (pool == NULL)
      return lexer_.Error("unknown pool name '" + pool_name + "'", err);
    edge->pool_ = pool;
  }

  edge->outputs_.reserve(outs.size());
  for (size_t i = 0, e = outs.size(); i != e; ++i) {
    string path = outs[i].Evaluate(env);
    string path_err;
    uint64_t slash_bits;
    if (!CanonicalizePath(&path, &slash_bits, &path_err))
      return lexer_.Error(path_err, err);
    if (!state_->AddOut(edge, path, slash_bits)) {
      if (options_.dupe_edge_action_ == kDupeEdgeActionError) {
        lexer_.Error("multiple rules generate " + path + " [-w dupbuild=err]",
                     err);
        return false;
      } else {
        if (!quiet_) {
          Warning("multiple rules generate %s. "
                  "builds involving this target will not be correct; "
                  "continuing anyway [-w dupbuild=warn]",
                  path.c_str());
        }
        if (e - i <= static_cast<size_t>(implicit_outs))
          --implicit_outs;
      }
    }
  }
  if (edge->outputs_.empty()) {
    // All outputs of the edge are already created by other edges. Don't add
    // this edge.  Do this check before input nodes are connected to the edge.
    state_->edges_.pop_back();
    delete edge;
    return true;
  }
  edge->implicit_outs_ = implicit_outs;

  edge->inputs_.reserve(ins.size());
  for (vector<EvalString>::iterator i = ins.begin(); i != ins.end(); ++i) {
    string path = i->Evaluate(env);
    string path_err;
    uint64_t slash_bits;
    if (!CanonicalizePath(&path, &slash_bits, &path_err))
      return lexer_.Error(path_err, err);
    state_->AddIn(edge, path, slash_bits);
  }
  edge->implicit_deps_ = implicit;
  edge->order_only_deps_ = order_only;

  if (options_.phony_cycle_action_ == kPhonyCycleActionWarn &&
      edge->maybe_phonycycle_diagnostic()) {
    // CMake 2.8.12.x and 3.0.x incorrectly write phony build statements
    // that reference themselves.  Ninja used to tolerate these in the
    // build graph but that has since been fixed.  Filter them out to
    // support users of those old CMake versions.
    Node* out = edge->outputs_[0];
    vector<Node*>::iterator new_end =
        remove(edge->inputs_.begin(), edge->inputs_.end(), out);
    if (new_end != edge->inputs_.end()) {
      edge->inputs_.erase(new_end, edge->inputs_.end());
      if (!quiet_) {
        Warning("phony target '%s' names itself as an input; "
                "ignoring [-w phonycycle=warn]",
                out->path().c_str());
      }
    }
  }

  // Multiple outputs aren't (yet?) supported with depslog.
  string deps_type = edge->GetBinding("deps");
  if (!deps_type.empty() && edge->outputs_.size() > 1) {
    return lexer_.Error("multiple outputs aren't (yet?) supported by depslog; "
                        "bring this up on the mailing list if it affects you",
                        err);
  }

  // Lookup, validate, and save any dyndep binding.  It will be used later
  // to load generated dependency information dynamically, but it must
  // be one of our manifest-specified inputs.
  string dyndep = edge->GetUnescapedDyndep();
  if (!dyndep.empty()) {
    uint64_t slash_bits;
    if (!CanonicalizePath(&dyndep, &slash_bits, err))
      return false;
    edge->dyndep_ = state_->GetNode(dyndep, slash_bits);
    edge->dyndep_->set_dyndep_pending(true);
    vector<Node*>::iterator dgi =
      std::find(edge->inputs_.begin(), edge->inputs_.end(), edge->dyndep_);
    if (dgi == edge->inputs_.end()) {
      return lexer_.Error("dyndep '" + dyndep + "' is not an input", err);
    }
  }

  return true;
}

bool ManifestParser::ParseFileInclude(bool new_scope, string* err) {
  EvalString eval;
  if (!lexer_.ReadPath(&eval, err))
    return false;
  string path = eval.Evaluate(env_);

  ManifestParser subparser(state_, file_reader_, options_);
  if (new_scope) {
    subparser.env_ = new BindingEnv(env_);
  } else {
    subparser.env_ = env_;
  }

  if (!subparser.Load(path, err, &lexer_))
    return false;

  if (!ExpectToken(Lexer::NEWLINE, err))
    return false;

  return true;
}
<|endoftext|>


<commit_before>#include "math_container.h"

using std::complex;

/******************************************************/
/*solve the equation cosh(x)=exp(y), input y, return x*/
/******************************************************/
complex<double> coshx_eq_expy(double y)
{
    complex<double> ey={exp(y),0};
    complex<double> gamma=log(ey-sqrt(ey*ey-1.0));

    //Since gamma is pure real or pure imaginary, set it:
    if( abs( gamma.real() ) < abs( gamma.imag() ) )  gamma=complex<double>( 0, gamma.imag() );
    else                                             gamma=complex<double>( gamma.real(), 0 );

    return gamma;
}
<commit_msg>Use namespace std, if we do not set this there is a bug?.<commit_after>#include "math_container.h"

using namespace std;

/******************************************************/
/*solve the equation cosh(x)=exp(y), input y, return x*/
/******************************************************/
complex<double> coshx_eq_expy(double y)
{
    complex<double> ey={exp(y),0};
    complex<double> gamma=log(ey-sqrt(ey*ey-1.0));

    //Since gamma is pure real or pure imaginary, set it:
    if( abs( gamma.real() ) < abs( gamma.imag() ) )  gamma=complex<double>( 0, gamma.imag() );
    else                                             gamma=complex<double>( gamma.real(), 0 );

    return gamma;
}
<|endoftext|>