<commit_before>/*=====================================================================

QGroundControl Open Source Ground Control Station

(c) 2009 - 2011 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

This file is part of the QGROUNDCONTROL project

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

    QGROUNDCONTROL is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

======================================================================*/

/**
 * @file
 *   @brief Main executable
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *
 */

#include <QtGlobal>
#include <QApplication>
#include <QSslSocket>
#include <QProcessEnvironment>

#include "QGCApplication.h"

#define  SINGLE_INSTANCE_PORT   14499

#ifndef __mobile__
    #include "QGCSerialPortInfo.h"
#endif

#ifdef QT_DEBUG
    #ifndef __mobile__
        #include "UnitTest.h"
    #endif
    #include "CmdLineOptParser.h"
    #ifdef Q_OS_WIN
        #include <crtdbg.h>
    #endif
#endif

#ifdef QGC_ENABLE_BLUETOOTH
#include <QtBluetooth/QBluetoothSocket>
#endif

#include <iostream>

/* SDL does ugly things to main() */
#ifdef main
#undef main
#endif

#ifndef __mobile__
    Q_DECLARE_METATYPE(QGCSerialPortInfo)
#endif

#ifdef Q_OS_WIN

/// @brief Message handler which is installed using qInstallMsgHandler so you do not need
/// the MSFT debug tools installed to see qDebug(), qWarning(), qCritical and qAbort
void msgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    const char symbols[] = { 'I', 'E', '!', 'X' };
    QString output = QString("[%1] at %2:%3 - \"%4\"").arg(symbols[type]).arg(context.file).arg(context.line).arg(msg);
    std::cerr << output.toStdString() << std::endl;
    if( type == QtFatalMsg ) abort();
}

/// @brief CRT Report Hook installed using _CrtSetReportHook. We install this hook when
/// we don't want asserts to pop a dialog on windows.
int WindowsCrtReportHook(int reportType, char* message, int* returnValue)
{
    Q_UNUSED(reportType);

    std::cerr << message << std::endl;  // Output message to stderr
    *returnValue = 0;                   // Don't break into debugger
    return true;                        // We handled this fully ourselves
}

#endif

#ifdef __android__
#include <jni.h>
#include "qserialport.h"

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    Q_UNUSED(reserved);

    JNIEnv* env;
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }

    QSerialPort::setNativeMethods();

    return JNI_VERSION_1_6;
}
#endif

/**
 * @brief Starts the application
 *
 * @param argc Number of commandline arguments
 * @param argv Commandline arguments
 * @return exit code, 0 for normal exit and !=0 for error cases
 */

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

#ifndef __mobile__
    //-- Test for another instance already running. If that's the case, we simply exit.
    QHostAddress host("127.0.0.1");
    QUdpSocket socket;
    if(!socket.bind(host, SINGLE_INSTANCE_PORT, QAbstractSocket::DontShareAddress)) {
        qWarning() << "Another instance already running. Exiting.";
        exit(-1);
    }
#endif

#ifdef Q_OS_MAC
#ifndef __ios__
    // Prevent Apple's app nap from screwing us over
    // tip: the domain can be cross-checked on the command line with <defaults domains>
    QProcess::execute("defaults write org.qgroundcontrol.qgroundcontrol NSAppSleepDisabled -bool YES");
#endif
#endif

#ifdef Q_OS_WIN
    // install the message handler
    qInstallMessageHandler(msgHandler);

    // Set our own OpenGL buglist
    qputenv("QT_OPENGL_BUGLIST", ":/opengl/resources/opengl/buglist.json");
    if (QCoreApplication::arguments().contains(QStringLiteral("-angle"))) {
        QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
    } else if (QCoreApplication::arguments().contains(QStringLiteral("-swrast"))) {
        QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
    }
#endif

    // The following calls to qRegisterMetaType are done to silence debug output which warns
    // that we use these types in signals, and without calling qRegisterMetaType we can't queue
    // these signals. In general we don't queue these signals, but we do what the warning says
    // anyway to silence the debug output.
#ifndef __ios__
    qRegisterMetaType<QSerialPort::SerialPortError>();
#endif
#ifdef QGC_ENABLE_BLUETOOTH
    qRegisterMetaType<QBluetoothSocket::SocketError>();
    qRegisterMetaType<QBluetoothServiceInfo>();
#endif
    qRegisterMetaType<QAbstractSocket::SocketError>();
#ifndef __mobile__
    qRegisterMetaType<QGCSerialPortInfo>();
#endif

    // We statically link our own QtLocation plugin

#ifdef Q_OS_WIN
    // In Windows, the compiler doesn't see the use of the class created by Q_IMPORT_PLUGIN
#pragma warning( disable : 4930 4101 )
#endif

    Q_IMPORT_PLUGIN(QGeoServiceProviderFactoryQGC)

    bool runUnitTests = false;          // Run unit tests

#ifdef QT_DEBUG
    // We parse a small set of command line options here prior to QGCApplication in order to handle the ones
    // which need to be handled before a QApplication object is started.

    bool stressUnitTests = false;       // Stress test unit tests
    bool quietWindowsAsserts = false;   // Don't let asserts pop dialog boxes

    QString unitTestOptions;
    CmdLineOpt_t rgCmdLineOptions[] = {
        { "--unittest",             &runUnitTests,          &unitTestOptions },
        { "--unittest-stress",      &stressUnitTests,       &unitTestOptions },
        { "--no-windows-assert-ui", &quietWindowsAsserts,   NULL },
        // Add additional command line option flags here
    };

    ParseCmdLineOptions(argc, argv, rgCmdLineOptions, sizeof(rgCmdLineOptions)/sizeof(rgCmdLineOptions[0]), false);
    if (stressUnitTests) {
        runUnitTests = true;
    }

    if (quietWindowsAsserts) {
#ifdef Q_OS_WIN
        _CrtSetReportHook(WindowsCrtReportHook);
#endif
    }

#ifdef Q_OS_WIN
    if (runUnitTests) {
        // Don't pop up Windows Error Reporting dialog when app crashes. This prevents TeamCity from
        // hanging.
        DWORD dwMode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
        SetErrorMode(dwMode | SEM_NOGPFAULTERRORBOX);
    }
#endif
#endif // QT_DEBUG

    QGCApplication* app = new QGCApplication(argc, argv, runUnitTests);
    Q_CHECK_PTR(app);

    // There appears to be a threading issue in qRegisterMetaType which can cause it to throw a qWarning
    // about duplicate type converters. This is caused by a race condition in the Qt code. Still working
    // with them on tracking down the bug. For now we register the type which is giving us problems here
    // while we only have the main thread. That should prevent it from hitting the race condition later
    // on in the code.
    qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >();

    app->_initCommon();

    int exitCode = 0;

#ifndef __mobile__
#ifdef QT_DEBUG
    if (runUnitTests) {
        for (int i=0; i < (stressUnitTests ? 20 : 1); i++) {
            if (!app->_initForUnitTests()) {
                return -1;
            }

            // Run the test
            int failures = UnitTest::run(unitTestOptions);
            if (failures == 0) {
                qDebug() << "ALL TESTS PASSED";
                exitCode = 0;
            } else {
                qDebug() << failures << " TESTS FAILED!";
                exitCode = -failures;
                break;
            }
        }
    } else
#endif
#endif
    {
        if (!app->_initForNormalAppBoot()) {
            return -1;
        }
        exitCode = app->exec();
    }

    delete app;

    qDebug() << "After app delete";

    return exitCode;
}
<commit_msg>Don't try to use QCoreApplication::arguments before an app is created<commit_after>/*=====================================================================

QGroundControl Open Source Ground Control Station

(c) 2009 - 2011 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

This file is part of the QGROUNDCONTROL project

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

    QGROUNDCONTROL is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

======================================================================*/

/**
 * @file
 *   @brief Main executable
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *
 */

#include <QtGlobal>
#include <QApplication>
#include <QSslSocket>
#include <QProcessEnvironment>

#include "QGCApplication.h"

#define  SINGLE_INSTANCE_PORT   14499

#ifndef __mobile__
    #include "QGCSerialPortInfo.h"
#endif

#ifdef QT_DEBUG
    #ifndef __mobile__
        #include "UnitTest.h"
    #endif
    #include "CmdLineOptParser.h"
    #ifdef Q_OS_WIN
        #include <crtdbg.h>
    #endif
#endif

#ifdef QGC_ENABLE_BLUETOOTH
#include <QtBluetooth/QBluetoothSocket>
#endif

#include <iostream>

/* SDL does ugly things to main() */
#ifdef main
#undef main
#endif

#ifndef __mobile__
    Q_DECLARE_METATYPE(QGCSerialPortInfo)
#endif

#ifdef Q_OS_WIN

/// @brief Message handler which is installed using qInstallMsgHandler so you do not need
/// the MSFT debug tools installed to see qDebug(), qWarning(), qCritical and qAbort
void msgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    const char symbols[] = { 'I', 'E', '!', 'X' };
    QString output = QString("[%1] at %2:%3 - \"%4\"").arg(symbols[type]).arg(context.file).arg(context.line).arg(msg);
    std::cerr << output.toStdString() << std::endl;
    if( type == QtFatalMsg ) abort();
}

/// @brief CRT Report Hook installed using _CrtSetReportHook. We install this hook when
/// we don't want asserts to pop a dialog on windows.
int WindowsCrtReportHook(int reportType, char* message, int* returnValue)
{
    Q_UNUSED(reportType);

    std::cerr << message << std::endl;  // Output message to stderr
    *returnValue = 0;                   // Don't break into debugger
    return true;                        // We handled this fully ourselves
}

#endif

#ifdef __android__
#include <jni.h>
#include "qserialport.h"

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    Q_UNUSED(reserved);

    JNIEnv* env;
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }

    QSerialPort::setNativeMethods();

    return JNI_VERSION_1_6;
}
#endif

/**
 * @brief Starts the application
 *
 * @param argc Number of commandline arguments
 * @param argv Commandline arguments
 * @return exit code, 0 for normal exit and !=0 for error cases
 */

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

#ifndef __mobile__
    //-- Test for another instance already running. If that's the case, we simply exit.
    QHostAddress host("127.0.0.1");
    QUdpSocket socket;
    if(!socket.bind(host, SINGLE_INSTANCE_PORT, QAbstractSocket::DontShareAddress)) {
        qWarning() << "Another instance already running. Exiting.";
        exit(-1);
    }
#endif

#ifdef Q_OS_MAC
#ifndef __ios__
    // Prevent Apple's app nap from screwing us over
    // tip: the domain can be cross-checked on the command line with <defaults domains>
    QProcess::execute("defaults write org.qgroundcontrol.qgroundcontrol NSAppSleepDisabled -bool YES");
#endif
#endif

#ifdef Q_OS_WIN
    // install the message handler
    qInstallMessageHandler(msgHandler);

    // Set our own OpenGL buglist
    qputenv("QT_OPENGL_BUGLIST", ":/opengl/resources/opengl/buglist.json");

    // Allow for command line override of renderer
    for (int i = 0; i < argc; i++) {
        const QString arg(argv[i]);
        if (arg == QStringLiteral("-angle")) {
            QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
            break;
        } else if (arg == QStringLiteral("-swrast")) {
            QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
            break;
        }
    }

#endif

    // The following calls to qRegisterMetaType are done to silence debug output which warns
    // that we use these types in signals, and without calling qRegisterMetaType we can't queue
    // these signals. In general we don't queue these signals, but we do what the warning says
    // anyway to silence the debug output.
#ifndef __ios__
    qRegisterMetaType<QSerialPort::SerialPortError>();
#endif
#ifdef QGC_ENABLE_BLUETOOTH
    qRegisterMetaType<QBluetoothSocket::SocketError>();
    qRegisterMetaType<QBluetoothServiceInfo>();
#endif
    qRegisterMetaType<QAbstractSocket::SocketError>();
#ifndef __mobile__
    qRegisterMetaType<QGCSerialPortInfo>();
#endif

    // We statically link our own QtLocation plugin

#ifdef Q_OS_WIN
    // In Windows, the compiler doesn't see the use of the class created by Q_IMPORT_PLUGIN
#pragma warning( disable : 4930 4101 )
#endif

    Q_IMPORT_PLUGIN(QGeoServiceProviderFactoryQGC)

    bool runUnitTests = false;          // Run unit tests

#ifdef QT_DEBUG
    // We parse a small set of command line options here prior to QGCApplication in order to handle the ones
    // which need to be handled before a QApplication object is started.

    bool stressUnitTests = false;       // Stress test unit tests
    bool quietWindowsAsserts = false;   // Don't let asserts pop dialog boxes

    QString unitTestOptions;
    CmdLineOpt_t rgCmdLineOptions[] = {
        { "--unittest",             &runUnitTests,          &unitTestOptions },
        { "--unittest-stress",      &stressUnitTests,       &unitTestOptions },
        { "--no-windows-assert-ui", &quietWindowsAsserts,   NULL },
        // Add additional command line option flags here
    };

    ParseCmdLineOptions(argc, argv, rgCmdLineOptions, sizeof(rgCmdLineOptions)/sizeof(rgCmdLineOptions[0]), false);
    if (stressUnitTests) {
        runUnitTests = true;
    }

    if (quietWindowsAsserts) {
#ifdef Q_OS_WIN
        _CrtSetReportHook(WindowsCrtReportHook);
#endif
    }

#ifdef Q_OS_WIN
    if (runUnitTests) {
        // Don't pop up Windows Error Reporting dialog when app crashes. This prevents TeamCity from
        // hanging.
        DWORD dwMode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
        SetErrorMode(dwMode | SEM_NOGPFAULTERRORBOX);
    }
#endif
#endif // QT_DEBUG

    QGCApplication* app = new QGCApplication(argc, argv, runUnitTests);
    Q_CHECK_PTR(app);

    // There appears to be a threading issue in qRegisterMetaType which can cause it to throw a qWarning
    // about duplicate type converters. This is caused by a race condition in the Qt code. Still working
    // with them on tracking down the bug. For now we register the type which is giving us problems here
    // while we only have the main thread. That should prevent it from hitting the race condition later
    // on in the code.
    qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >();

    app->_initCommon();

    int exitCode = 0;

#ifndef __mobile__
#ifdef QT_DEBUG
    if (runUnitTests) {
        for (int i=0; i < (stressUnitTests ? 20 : 1); i++) {
            if (!app->_initForUnitTests()) {
                return -1;
            }

            // Run the test
            int failures = UnitTest::run(unitTestOptions);
            if (failures == 0) {
                qDebug() << "ALL TESTS PASSED";
                exitCode = 0;
            } else {
                qDebug() << failures << " TESTS FAILED!";
                exitCode = -failures;
                break;
            }
        }
    } else
#endif
#endif
    {
        if (!app->_initForNormalAppBoot()) {
            return -1;
        }
        exitCode = app->exec();
    }

    delete app;

    qDebug() << "After app delete";

    return exitCode;
}
<|endoftext|>


<commit_before>#include <libnova/libnova.h>
#include <deque>
#include <fstream>
#include <iostream>
#include <sstream>

#include "config.hh"
#include "drawer.hh"
#include "exceptions.hh"
#include "projection.hh"
#include "scene_storage.hh"
#include "stars.hh"
#include "svg_painter.hh"
#include "types.hh"

/*
struct ScenePrinter
    : boost::static_visitor<>
{
    void operator()(const scene::Object & o)
    {
//        std::cout << '{' << o.pos.x << ',' << o.pos.y << '}';
    }

    void operator()(const scene::Group & g)
    {
        std::cout << "g(" << g.id << "){";
        for_each(g.elements.begin(), g.elements.end(),
                 boost::apply_visitor(*this));
        std::cout << "}";
    }

    void operator()(const scene::Rectangle &)
    {
    }
    void operator()(const scene::Line &)
    {}
    void operator()(const scene::Path & p)
    {
        std::cout << p.path.size() << ',';
    }
    void operator()(const scene::Text &)
    {}
};
*/

int main(int arc, char * arv[])
{
    try
    {
        std::cout << "Processing configs... " << std::flush;
        Config config(arc, arv);
        std::cout << "done." << std::endl;

        //        return 0;

        ln_lnlat_posn observer(config.location());
        const double t(config.t());

        CanvasPoint canvas(config.canvas_dimensions());
        ln_equ_posn apparent_canvas(config.projection_dimensions()),
            center(config.projection_centre());

        std::shared_ptr<Projection> projection(ProjectionFactory::create(config.projection_type(),
                                                                         canvas, apparent_canvas, center));

        if (config.projection_level() == "horizon")
        {
            ln_hrz_posn hor;
            ln_get_hrz_from_equ(&center, &observer, t, &hor);
            ln_hrz_posn hor2(hor);
            hor2.az += 1.0;
            ln_equ_posn equ;
            ln_get_equ_from_hrz(&hor2, &observer, t, &equ);
            CanvasPoint cp(equ.ra - center.ra, equ.dec - center.dec);
            if (cp.x > 180.)
                cp.x -= 360.;

            std::cout << cp.x << ", " << cp.y << std::endl;
            projection->rotate_to_level(cp);
        }

        std::string style;
        if (! config.stylesheet().empty())
        {
            std::ifstream f(config.stylesheet());
            if (! f)
                throw ConfigError("Stylesheet '" + config.stylesheet() + "' couldn't be opened.");

            std::stringstream buf;
            buf << f.rdbuf();
            style = buf.str();
        }

        Drawer drawer(canvas, config.canvas_margin(), style);
        drawer.set_projection(projection);

        scene::Storage scn(projection);

        {
            scene::Group gr{"rectangle", "background", {}};
            gr.elements.push_back(scene::Rectangle{CanvasPoint(-canvas.x / 2., -canvas.y / 2.),
                        CanvasPoint(canvas.x, canvas.y)});
            scn.add_group(std::move(gr));
        }

        std::cout << "Loading catalogues... " << std::flush;
        for (auto c(config.begin_catalogues()), c_end(config.end_catalogues());
             c != c_end; ++c)
        {
            std::cout << c->path() << ", " << std::flush;
            c->load();

            std::deque<Star> stars;
            std::copy(c->begin_stars(), c->end_stars(), std::back_inserter(stars));
            drawer.draw(stars, c->path());

            {
                std::deque<scene::Element> objs;
                for (auto const & star : stars)
                {
                    objs.push_back(scene::Object{projection->project(star.pos_), star.vmag_});
                }
                scn.add_group(scene::Group{"catalog", c->path(), std::move(objs)});
            }
        }
        std::cout << "done." << std::endl;

        std::cout << "Loading solar objects..." << std::flush;
        SolarObjectManager solar_manager;

        {
            std::deque<std::shared_ptr<const SolarObject>> planets;
            auto planet_names(config.planets());
            for (auto const & p : planet_names)
            {
                planets.push_back(solar_manager.get(p));
            }

            drawer.draw(planets, config.t(), "planets", Drawer::magnitudo, config.planets_labels());

            {
                std::deque<scene::Element> objs;
                for (auto const & planet : planets)
                {
                    objs.push_back(scene::Object{projection->project(planet->get_equ_coords(t)), planet->get_magnitude(t)});
                }
                scn.add_group(scene::Group{"solar_system", "planets", std::move(objs)});
            }
        }

        if (config.moon())
        {
            auto const & moon{*solar_manager.get("moon")};
            drawer.draw(moon, config.t(), Drawer::sdiam, true);

            std::deque<scene::Element> obj;
            obj.push_back(scene::Object{projection->project(moon.get_equ_coords(t)), moon.get_magnitude(t)});
            scn.add_group(scene::Group{"solar_system", "moon",
                        std::move(obj)
                });
        }

        if (config.sun())
        {
            auto const & sun{*solar_manager.get("sun")};
            drawer.draw(sun, config.t(), Drawer::sdiam, true);

            std::deque<scene::Element> obj;
            obj.push_back(scene::Object{projection->project(sun.get_equ_coords(t)), sun.get_magnitude(t)});
            scn.add_group(scene::Group{"solar_system", "sun",
                        std::move(obj)
                });
        }
        std::cout << "done." << std::endl;

        {
            std::cout << "Drawing tracks... " << std::flush;
            scene::Group tracks{"tracks", "track_container", {}};
            for (auto track(config.begin_tracks()), track_end(config.end_tracks());
                 track != track_end; ++track)
            {
                std::cout << track->name << " " << std::flush;
                drawer.draw(*track, solar_manager.get(track->name));
                auto beziers(create_bezier_from_track(projection, *track, solar_manager.get(track->name)));
                for (auto const & b : beziers)
                {
                    tracks.elements.push_back(scene::Path{b});
                }
            }
            scn.add_group(std::move(tracks));
            std::cout << "done." << std::endl;
        }

        {
            scene::Group meridians{"meridians", "meridians_container", {}};
            for (double x(0); x < 360.1; x += 15.)
            {
                std::vector<ln_equ_posn> path;
                for (double y(-88.); y < 88.1; y += 2.)
                {
                    path.push_back({x, y});
                }
                drawer.draw(path);
                drawer.draw(stringify(angle{x}, as_hour), {x, 0.});

                auto bezier{create_bezier_from_path(projection, path)};
                for (auto const b : bezier)
                {
                    meridians.elements.push_back(scene::Path{b});
                }
                meridians.elements.push_back(scene::Text{stringify(angle{x}, as_hour), projection->project({x, 0})});
            }
            scn.add_group(std::move(meridians));
        }

        {
            scene::Group parallels{"parallels", "parallels_container", {}};
            for (double y(-60); y < 60.1; y += 10.)
            {
                std::vector<ln_equ_posn> path;
                for (double x(0.); x < 360.1; x += 2.)
                {
                    path.push_back({x, y});
                }
                drawer.draw(path);
                drawer.draw(stringify(angle{y}, as_degree), {0., y});

                auto bezier{create_bezier_from_path(projection, path)};
                for (auto const b : bezier)
                {
                    parallels.elements.push_back(scene::Path{b});
                }
                parallels.elements.push_back(scene::Text{stringify(angle{y}, as_degree), projection->project({0., y})});
            }
            scn.add_group(std::move(parallels));
        }

        // ecliptic
        {
            std::vector<ln_equ_posn> path;
            double t(config.t());
            for (double x(0); x < 360.1; x += 2.)
            {
                ln_lnlat_posn in{x, 0.};
                ln_equ_posn out;
                ln_get_equ_from_ecl(&in, t, &out);
                path.push_back(out);
            }
            drawer.draw(path, 0.2);

            scene::Group ecliptic{"ecliptic", "ecliptic_container", {}};
            auto bezier{create_bezier_from_path(projection, path)};
            for (auto const b : bezier)
            {
                ecliptic.elements.push_back(scene::Path{b});
            }
            scn.add_group(std::move(ecliptic));
        }

        // horizon
        {
            std::vector<ln_equ_posn> path;
            for (double x(0); x < 360.1; x += 2.)
            {
                ln_hrz_posn in{x, 0.};
                ln_equ_posn out;
                ln_get_equ_from_hrz(&in, &observer, t, &out);
                path.push_back(out);
            }
            drawer.draw(path, 0.3);

            scene::Group horizon{"horizon", "horizon_container", {}};
            auto bezier{create_bezier_from_path(projection, path)};
            for (auto const b : bezier)
            {
                horizon.elements.push_back(scene::Path{b});
            }
            scn.add_group(std::move(horizon));
        }

        drawer.store(config.output().c_str());

        std::ofstream of("test-2.svg");
        if (! of)
            throw std::runtime_error("Can't open file '" + std::string("test-2.svg") + "' for writing " + std::strerror(errno));

        SvgPainter painter(of, canvas, config.canvas_margin(), style);
        boost::apply_visitor(painter, scn);
    }
    catch (const ConfigError & e)
    {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }
    catch (const std::exception & e)
    {
        std::cerr << "Uncaught std::exception:\n\t" << e.what() << std::endl;
        return EXIT_FAILURE;
    }
}
<commit_msg>update classes and ids<commit_after>#include <libnova/libnova.h>
#include <deque>
#include <fstream>
#include <iostream>
#include <sstream>

#include "config.hh"
#include "drawer.hh"
#include "exceptions.hh"
#include "projection.hh"
#include "scene_storage.hh"
#include "stars.hh"
#include "svg_painter.hh"
#include "types.hh"

/*
struct ScenePrinter
    : boost::static_visitor<>
{
    void operator()(const scene::Object & o)
    {
//        std::cout << '{' << o.pos.x << ',' << o.pos.y << '}';
    }

    void operator()(const scene::Group & g)
    {
        std::cout << "g(" << g.id << "){";
        for_each(g.elements.begin(), g.elements.end(),
                 boost::apply_visitor(*this));
        std::cout << "}";
    }

    void operator()(const scene::Rectangle &)
    {
    }
    void operator()(const scene::Line &)
    {}
    void operator()(const scene::Path & p)
    {
        std::cout << p.path.size() << ',';
    }
    void operator()(const scene::Text &)
    {}
};
*/

int main(int arc, char * arv[])
{
    try
    {
        std::cout << "Processing configs... " << std::flush;
        Config config(arc, arv);
        std::cout << "done." << std::endl;

        //        return 0;

        ln_lnlat_posn observer(config.location());
        const double t(config.t());

        CanvasPoint canvas(config.canvas_dimensions());
        ln_equ_posn apparent_canvas(config.projection_dimensions()),
            center(config.projection_centre());

        std::shared_ptr<Projection> projection(ProjectionFactory::create(config.projection_type(),
                                                                         canvas, apparent_canvas, center));

        if (config.projection_level() == "horizon")
        {
            ln_hrz_posn hor;
            ln_get_hrz_from_equ(&center, &observer, t, &hor);
            ln_hrz_posn hor2(hor);
            hor2.az += 1.0;
            ln_equ_posn equ;
            ln_get_equ_from_hrz(&hor2, &observer, t, &equ);
            CanvasPoint cp(equ.ra - center.ra, equ.dec - center.dec);
            if (cp.x > 180.)
                cp.x -= 360.;

            std::cout << cp.x << ", " << cp.y << std::endl;
            projection->rotate_to_level(cp);
        }

        std::string style;
        if (! config.stylesheet().empty())
        {
            std::ifstream f(config.stylesheet());
            if (! f)
                throw ConfigError("Stylesheet '" + config.stylesheet() + "' couldn't be opened.");

            std::stringstream buf;
            buf << f.rdbuf();
            style = buf.str();
        }

        Drawer drawer(canvas, config.canvas_margin(), style);
        drawer.set_projection(projection);

        scene::Storage scn(projection);

        {
            scene::Group gr{"rectangle", "background", {}};
            gr.elements.push_back(scene::Rectangle{CanvasPoint(-canvas.x / 2., -canvas.y / 2.),
                        CanvasPoint(canvas.x, canvas.y)});
            scn.add_group(std::move(gr));
        }

        std::cout << "Loading catalogues... " << std::flush;
        for (auto c(config.begin_catalogues()), c_end(config.end_catalogues());
             c != c_end; ++c)
        {
            std::cout << c->path() << ", " << std::flush;
            c->load();

            std::deque<Star> stars;
            std::copy(c->begin_stars(), c->end_stars(), std::back_inserter(stars));
            drawer.draw(stars, c->path());

            {
                std::deque<scene::Element> objs;
                for (auto const & star : stars)
                {
                    objs.push_back(scene::Object{projection->project(star.pos_), star.vmag_});
                }
                scn.add_group(scene::Group{"catalog", c->path(), std::move(objs)});
            }
        }
        std::cout << "done." << std::endl;

        std::cout << "Loading solar objects..." << std::flush;
        SolarObjectManager solar_manager;

        {
            std::deque<std::shared_ptr<const SolarObject>> planets;
            auto planet_names(config.planets());
            for (auto const & p : planet_names)
            {
                planets.push_back(solar_manager.get(p));
            }

            drawer.draw(planets, config.t(), "planets", Drawer::magnitudo, config.planets_labels());

            {
                std::deque<scene::Element> objs;
                for (auto const & planet : planets)
                {
                    objs.push_back(scene::Object{projection->project(planet->get_equ_coords(t)), planet->get_magnitude(t)});
                }
                scn.add_group(scene::Group{"solar_system", "planets", std::move(objs)});
            }
        }

        if (config.moon())
        {
            auto const & moon{*solar_manager.get("moon")};
            drawer.draw(moon, config.t(), Drawer::sdiam, true);

            std::deque<scene::Element> obj;
            obj.push_back(scene::Object{projection->project(moon.get_equ_coords(t)), moon.get_magnitude(t)});
            scn.add_group(scene::Group{"solar_system", "moon",
                        std::move(obj)
                });
        }

        if (config.sun())
        {
            auto const & sun{*solar_manager.get("sun")};
            drawer.draw(sun, config.t(), Drawer::sdiam, true);

            std::deque<scene::Element> obj;
            obj.push_back(scene::Object{projection->project(sun.get_equ_coords(t)), sun.get_magnitude(t)});
            scn.add_group(scene::Group{"solar_system", "sun",
                        std::move(obj)
                });
        }
        std::cout << "done." << std::endl;

        {
            std::cout << "Drawing tracks... " << std::flush;
            scene::Group tracks{"tracks", "track_container", {}};
            for (auto track(config.begin_tracks()), track_end(config.end_tracks());
                 track != track_end; ++track)
            {
                std::cout << track->name << " " << std::flush;
                drawer.draw(*track, solar_manager.get(track->name));
                auto beziers(create_bezier_from_track(projection, *track, solar_manager.get(track->name)));
                for (auto const & b : beziers)
                {
                    tracks.elements.push_back(scene::Path{b});
                }
            }
            scn.add_group(std::move(tracks));
            std::cout << "done." << std::endl;
        }

        {
            scene::Group meridians{"grid", "meridians", {}};
            for (double x(0); x < 360.1; x += 15.)
            {
                std::vector<ln_equ_posn> path;
                for (double y(-88.); y < 88.1; y += 2.)
                {
                    path.push_back({x, y});
                }
                drawer.draw(path);
                drawer.draw(stringify(angle{x}, as_hour), {x, 0.});

                auto bezier{create_bezier_from_path(projection, path)};
                for (auto const b : bezier)
                {
                    meridians.elements.push_back(scene::Path{b});
                }
                meridians.elements.push_back(scene::Text{stringify(angle{x}, as_hour), projection->project({x, 0})});
            }
            scn.add_group(std::move(meridians));
        }

        {
            scene::Group parallels{"grid", "parallels", {}};
            for (double y(-60); y < 60.1; y += 10.)
            {
                std::vector<ln_equ_posn> path;
                for (double x(0.); x < 360.1; x += 2.)
                {
                    path.push_back({x, y});
                }
                drawer.draw(path);
                drawer.draw(stringify(angle{y}, as_degree), {0., y});

                auto bezier{create_bezier_from_path(projection, path)};
                for (auto const b : bezier)
                {
                    parallels.elements.push_back(scene::Path{b});
                }
                parallels.elements.push_back(scene::Text{stringify(angle{y}, as_degree), projection->project({0., y})});
            }
            scn.add_group(std::move(parallels));
        }

        // ecliptic
        {
            std::vector<ln_equ_posn> path;
            double t(config.t());
            for (double x(0); x < 360.1; x += 2.)
            {
                ln_lnlat_posn in{x, 0.};
                ln_equ_posn out;
                ln_get_equ_from_ecl(&in, t, &out);
                path.push_back(out);
            }
            drawer.draw(path, 0.2);

            scene::Group ecliptic{"grid", "ecliptic", {}};
            auto bezier{create_bezier_from_path(projection, path)};
            for (auto const b : bezier)
            {
                ecliptic.elements.push_back(scene::Path{b});
            }
            scn.add_group(std::move(ecliptic));
        }

        // horizon
        {
            std::vector<ln_equ_posn> path;
            for (double x(0); x < 360.1; x += 2.)
            {
                ln_hrz_posn in{x, 0.};
                ln_equ_posn out;
                ln_get_equ_from_hrz(&in, &observer, t, &out);
                path.push_back(out);
            }
            drawer.draw(path, 0.3);

            scene::Group horizon{"grid", "horizon", {}};
            auto bezier{create_bezier_from_path(projection, path)};
            for (auto const b : bezier)
            {
                horizon.elements.push_back(scene::Path{b});
            }
            scn.add_group(std::move(horizon));
        }

        drawer.store(config.output().c_str());

        std::ofstream of("test-2.svg");
        if (! of)
            throw std::runtime_error("Can't open file '" + std::string("test-2.svg") + "' for writing " + std::strerror(errno));

        SvgPainter painter(of, canvas, config.canvas_margin(), style);
        boost::apply_visitor(painter, scn);
    }
    catch (const ConfigError & e)
    {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }
    catch (const std::exception & e)
    {
        std::cerr << "Uncaught std::exception:\n\t" << e.what() << std::endl;
        return EXIT_FAILURE;
    }
}
<|endoftext|>


<commit_before>#include <iostream>
using namespace std;

extern "C" {
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <curl/curl.h>
#include <errno.h>
#include <sqlite3.h>
#include <getopt.h>
#include <libxml/xmlmemory.h>
#include "help.h"
#include "logger.h"
}

#include "localFileList.h"
#include "fileListStorage.h"
#include "amazonCredentials.h"
#include "remoteListOfFiles.h"
#include "upload.h"
#include "filePattern.h"

static char *accessKeyId=NULL, *secretAccessKey=NULL, *bucket=NULL, *endPoint = (char *) "s3.amazonaws.com",
	*source=NULL, *databasePath=NULL, *databaseFilename= (char *)".files.sqlite3";
static int performRebuild=0, performUpload=0, makeAllPublic=0, useRrs=0, showProgress=0, skipSsl=0, dryRun=0,
	connectTimeout = 0, networkTimeout = 0, uploadThreads = 0;

FilePattern *excludeFilePattern;

FILE *logStream;
int logLevel = LOG_ERR;

int rebuildDatabase(RemoteListOfFiles *remoteListOfFiles, AmazonCredentials *amazonCredentials, FileListStorage *fileListStorage) {
	int res = remoteListOfFiles->downloadList();
	if (res==LIST_FAILED) {
		return LIST_FAILED;
	}

	LOG(LOG_INFO, "[MetaUpdate] Got %d files, updating meta information", remoteListOfFiles->count);

	res = remoteListOfFiles->resolveMtimes();
	if (res==LIST_FAILED) {
		return LIST_FAILED;
	}

	if (dryRun) {
		LOG(LOG_INFO, "[MetaUpdate] [dry] Skipped storing list of files");
		return LIST_SUCCESS;
	}

	if (fileListStorage->storeRemoteListOfFiles(remoteListOfFiles) == STORAGE_FAILED) {
		LOG(LOG_FATAL, "[MetaUpdate] Failed to store list of files");
		return LIST_FAILED;
	} else {
		return LIST_SUCCESS;
	}
}

static char *endPoints[] = {
	(char *) "s3.amazonaws.com",
	(char *) "s3-us-west-2.amazonaws.com",
	(char *) "s3-us-west-1.amazonaws.com",
	(char *) "s3-eu-west-1.amazonaws.com",
	(char *) "s3-ap-southeast-1.amazonaws.com",
	(char *) "s3-ap-northeast-1.amazonaws.com",
	(char *) "s3-sa-east-1.amazonaws.com",
	NULL
};

int validateEndpoint(char *endPoint) {
	int i=0;
	while (char *e=endPoints[i++]) {
		if (e && strcmp(e, endPoint)==0) {
			return 1;
		}
	}

#ifdef TEST
	if (strcmp(endPoint, "local")==0) {
		printf("EndPoint for testing purposes engaged.\n");
		return 1;
	}
#endif

 	printf("--endPoint %s not valid, use one of:\n", endPoint);

 	i=0;
	while (char *e=endPoints[i++]) {
		printf("\t%s\n", e);
	}

	return 0;
}

char *buildDatabaseFilePath(char *databaseFilename, char *databasePath) {
	uint64_t len = strlen(databasePath)+strlen(databaseFilename)+2;
	char *databaseFilePath = (char *) malloc(len);
	databaseFilePath[0]=0;
	strcat(databaseFilePath, databasePath);
	strcat(databaseFilePath, "/");
	strcat(databaseFilePath, databaseFilename);
	return databaseFilePath;
}

void showVersion() {
	printf("clarc version " VERSION " (c) 2012 Egor Egorov <me@egorfine.com>\nMIT License  |  http://egorfine.com/clarc/\n");
}

int parseCommandline(int argc, char *argv[]) {
	if (argc==1) {
		showVersion();
		printf("Perhaps, ask --help?\n");
		exit(0);
	}

	static struct option longOpts[] = {
		{ "accessKeyId",       required_argument,  NULL,  0 },
		{ "secretAccessKey",   required_argument,  NULL,  0 },
		{ "bucket",            required_argument,  NULL,  0 },
		{ "endPoint",          required_argument,  NULL,  0 },
		{ "public",            no_argument,        NULL,  0 },
		{ "rrs",               no_argument,        NULL,  0 },
		{ "rss",               no_argument,        NULL,  0 }, // common typo
		{ "skipSsl",           no_argument,        NULL,  0 },

		{ "connectTimeout",    required_argument,  NULL,  0 },
		{ "networkTimeout",    required_argument,  NULL,  0 },
		{ "uploadThreads",     required_argument,  NULL,  0 },

		{ "source",            required_argument,  NULL,  0 },
		{ "ddbPath",           required_argument,  NULL,  0 },
		{ "dbFilename",        required_argument,  NULL,  0 },

		{ "exclude",           required_argument,  NULL,  0 },
		{ "excludeFromFile",   required_argument,  NULL,  0 },

		{ "progress",          no_argument,        NULL,  0 },
		{ "logLevel",          required_argument,  NULL,  0 },

		{ "dryRun",            no_argument,        NULL,  0 },

		{ "rebuild",           no_argument,        NULL,  0 },
		{ "upload",            no_argument,        NULL,  0 },

		{ "version",           no_argument,        NULL,  'V' },
		{ "help",              no_argument,        NULL,  'h' },

		{ NULL,                0,                  NULL,  0 }
	};

	int ch, longIndex;
	while ((ch = getopt_long(argc, argv, "Vh", longOpts, &longIndex)) != -1) {
		if (ch=='V') {
			showVersion();
			exit(0);
		} else if (ch=='h') {
			showHelp();
			exit(0);
		}

		if (ch!=0) {
			continue;
		}

		const char *longName = longOpts[longIndex].name;

		if (strcmp(longName, "accessKeyId")==0) {
			accessKeyId = strdup(optarg);

		} else if (strcmp(longName, "secretAccessKey")==0) {
			secretAccessKey = strdup(optarg);

		} else if (strcmp(longName, "bucket")==0) {
			bucket = strdup(optarg);

		} else if (strcmp(longName, "endPoint")==0) {
			endPoint = strdup(optarg);

		} else if (strcmp(longName, "networkTimeout")==0) {
			networkTimeout = atoi(optarg);
			if (networkTimeout<=0 || networkTimeout>=600) {
				printf("Network timeout invalid (must be 1..600 seconds)\n");
				exit(1);
			}

		} else if (strcmp(longName, "uploadThreads")==0) {
			uploadThreads = atoi(optarg);
			if (uploadThreads<=0 || uploadThreads>=100) {
				printf("Upload threads count invalid (must be 1..100)\n");
				exit(1);
			}

		} else if (strcmp(longName, "connectTimeout")==0) {
			connectTimeout = atoi(optarg);
			if (connectTimeout<=0 || connectTimeout>=600) {
				printf("Connect timeout invalid (must be 1..600 seconds)\n");
				exit(1);
			}

		} else if (strcmp(longName, "public")==0) {
			makeAllPublic = 1;

		} else if (strcmp(longName, "skipSsl")==0) {
			skipSsl = 1;

		} else if (strcmp(longName, "rrs")==0) {
			useRrs = 1;

		} else if (strcmp(longName, "rss")==0) {
			printf("Warning: you spelled --rss; you meant -rrs which stands for Reduced Redundancy Storage.\n");
			useRrs = 1;

		} else if (strcmp(longName, "dryRun")==0) {
			dryRun = 1;

		} else if (strcmp(longName, "progress")==0) {
			showProgress = 1;

		} else if (strcmp(longName, "logLevel")==0) {
			logLevel = atoi(optarg);
			if (logLevel <= 0 || logLevel > 5) {
				printf("--logLevel must be 1..5\n");
				exit(1);
			}

		} else if (strcmp(longName, "source")==0) {
			source = strdup(optarg);

		} else if (strcmp(longName, "dbPath")==0) {
			databasePath = strdup(optarg);

		} else if (strcmp(longName, "dbFilename")==0) {
			databaseFilename = strdup(optarg);

		} else if (strcmp(longName, "rebuild")==0) {
			performRebuild=1;

		} else if (strcmp(longName, "upload")==0) {
			performUpload=1;

		} else if (strcmp(longName, "exclude")==0) {
			if (!excludeFilePattern->add(optarg)) {
				printf("Pattern `%s' is not valid.\n", optarg);
				exit(1);
			}
		} else if (strcmp(longName, "excludeFromFile")==0) {
			if (!excludeFilePattern->readFile(optarg)) {
				printf("Cannot read or parse patterns in %s\n", optarg);
				exit(1);
			}
		}
	}

	int failed = 0;

	if (!source) {
		printf("Specify --source.\n");
		failed = 1;
	}

	if (source && source[0]!='/') {
		printf("--source must be absolute path.\n");
		failed=1;
	}

	if (!accessKeyId) {
		printf("Specify --accessKeyId.\n");
		failed = 1;
	}

	if (!secretAccessKey) {
		printf("Specify --secretAccessKey.\n");
		failed = 1;
	}

	if (!bucket) {
		printf("Specify --bucket.\n");
		failed = 1;
	}

	if (!validateEndpoint(endPoint)) {
	failed = 1;
	}

	if (!performRebuild && !performUpload) {
		printf("What shall I do? Say --rebuild and/or --upload!\n");
		failed = 1;
	}

	if (failed) {
		return 0;
	}

	while (source[strlen(source)-1]=='/') {
		source[strlen(source)-1]=0;
	}

	if (!databasePath) {
		databasePath = source;
	} else {
		while (databasePath[strlen(databasePath)-1]=='/') {
			databasePath[strlen(databasePath)-1]=0;
		}
	}

	return 1;
}

int verifySource(char *source) {
	struct stat fileInfo;
	if (lstat(source, &fileInfo)<0) {
		printf("%s doesn't exists.\n", source);
		return 0;
	}

	if (!(fileInfo.st_mode & S_IFDIR)) {
		printf("%s isn't a directory.\n", source);
		return 0;
	}

	return 1;
}

int main(int argc, char *argv[]) {
	int res;
	curl_global_init(CURL_GLOBAL_ALL);
	xmlInitParser();

	logStream = stdout;
	logLevel = LOG_DBG;

	excludeFilePattern = new FilePattern();

	if (!parseCommandline(argc, argv)) {
		exit(1);
	}

	if (!verifySource(source)) {
		exit(1);
	}

	AmazonCredentials *amazonCredentials = new AmazonCredentials(
		accessKeyId,
		secretAccessKey,
		bucket, endPoint
	);

	RemoteListOfFiles *remoteListOfFiles = new RemoteListOfFiles(amazonCredentials);
	remoteListOfFiles->showProgress = showProgress;
	if (skipSsl) {
		remoteListOfFiles->useSsl=0;
	}
	if (networkTimeout) {
		remoteListOfFiles->networkTimeout = networkTimeout;
	}
	if (connectTimeout) {
		remoteListOfFiles->connectTimeout = connectTimeout;
	}

	res = remoteListOfFiles->checkAuth();
	if (res == AUTH_FAILED_BUCKET_DOESNT_EXISTS) {
		LOG(LOG_FATAL, "[Auth] Failed: bucket doesn't exists, exit");
		exit(1);
	} else if (res == AUTH_FAILED) {
		LOG(LOG_FATAL, "[Auth] FAIL, exit");
		exit(1);
	}
	LOG(LOG_INFO, "[Auth] Success");

	char *databaseFilePath = buildDatabaseFilePath(databaseFilename, databasePath);
	LOG(LOG_DBG, "[Storage] Database path = %s", databaseFilePath);

	char errorResult[1024*100];
	FileListStorage *fileListStorage = new FileListStorage(databaseFilePath, errorResult);
	if (strlen(errorResult)>0) {
		LOG(LOG_FATAL, "[Storage] FAIL: %s, exit", errorResult);
		exit(1);
	}

	if (performRebuild) {
		if (rebuildDatabase(remoteListOfFiles, amazonCredentials, fileListStorage)==LIST_FAILED) {
			exit(1);
		}
	}

	if (performUpload) {
		if (excludeFilePattern->count==0) {
			delete excludeFilePattern;
			excludeFilePattern=NULL;
		}

		Uploader *uploader = new Uploader(amazonCredentials, excludeFilePattern);
		uploader->useRrs = useRrs;
		uploader->makeAllPublic = makeAllPublic;
		uploader->showProgress = showProgress;
		if (skipSsl) {
			uploader->useSsl=0;
		}
		if (networkTimeout) {
			uploader->networkTimeout = networkTimeout;
		}
		if (connectTimeout) {
			uploader->connectTimeout = connectTimeout;
		}
		if (uploadThreads) {
			uploader->uploadThreads = uploadThreads;
		}
		uploader->dryRun = dryRun;

#ifdef TEST
		do {
#endif
		res = uploader->uploadFiles(fileListStorage, source);
		if (res==UPLOAD_FAILED) {
			exit(1);
		}
#ifdef TEST
		fileListStorage->truncate();
		} while (true);
#endif

		res = uploader->uploadDatabase(databaseFilePath, databaseFilename);
		if (res==UPLOAD_FAILED) {
			exit(1);
		}

		delete uploader;
	}

	free(databaseFilePath);
	delete fileListStorage;
	delete amazonCredentials;

	exit(0);
}
<commit_msg>correct -v<commit_after>#include <iostream>
using namespace std;

extern "C" {
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <curl/curl.h>
#include <errno.h>
#include <sqlite3.h>
#include <getopt.h>
#include <libxml/xmlmemory.h>
#include "help.h"
#include "logger.h"
}

#include "localFileList.h"
#include "fileListStorage.h"
#include "amazonCredentials.h"
#include "remoteListOfFiles.h"
#include "upload.h"
#include "filePattern.h"

static char *accessKeyId=NULL, *secretAccessKey=NULL, *bucket=NULL, *endPoint = (char *) "s3.amazonaws.com",
	*source=NULL, *databasePath=NULL, *databaseFilename= (char *)".files.sqlite3";
static int performRebuild=0, performUpload=0, makeAllPublic=0, useRrs=0, showProgress=0, skipSsl=0, dryRun=0,
	connectTimeout = 0, networkTimeout = 0, uploadThreads = 0;

FilePattern *excludeFilePattern;

FILE *logStream;
int logLevel = LOG_ERR;

int rebuildDatabase(RemoteListOfFiles *remoteListOfFiles, AmazonCredentials *amazonCredentials, FileListStorage *fileListStorage) {
	int res = remoteListOfFiles->downloadList();
	if (res==LIST_FAILED) {
		return LIST_FAILED;
	}

	LOG(LOG_INFO, "[MetaUpdate] Got %d files, updating meta information", remoteListOfFiles->count);

	res = remoteListOfFiles->resolveMtimes();
	if (res==LIST_FAILED) {
		return LIST_FAILED;
	}

	if (dryRun) {
		LOG(LOG_INFO, "[MetaUpdate] [dry] Skipped storing list of files");
		return LIST_SUCCESS;
	}

	if (fileListStorage->storeRemoteListOfFiles(remoteListOfFiles) == STORAGE_FAILED) {
		LOG(LOG_FATAL, "[MetaUpdate] Failed to store list of files");
		return LIST_FAILED;
	} else {
		return LIST_SUCCESS;
	}
}

static char *endPoints[] = {
	(char *) "s3.amazonaws.com",
	(char *) "s3-us-west-2.amazonaws.com",
	(char *) "s3-us-west-1.amazonaws.com",
	(char *) "s3-eu-west-1.amazonaws.com",
	(char *) "s3-ap-southeast-1.amazonaws.com",
	(char *) "s3-ap-northeast-1.amazonaws.com",
	(char *) "s3-sa-east-1.amazonaws.com",
	NULL
};

int validateEndpoint(char *endPoint) {
	int i=0;
	while (char *e=endPoints[i++]) {
		if (e && strcmp(e, endPoint)==0) {
			return 1;
		}
	}

#ifdef TEST
	if (strcmp(endPoint, "local")==0) {
		printf("EndPoint for testing purposes engaged.\n");
		return 1;
	}
#endif

 	printf("--endPoint %s not valid, use one of:\n", endPoint);

 	i=0;
	while (char *e=endPoints[i++]) {
		printf("\t%s\n", e);
	}

	return 0;
}

char *buildDatabaseFilePath(char *databaseFilename, char *databasePath) {
	uint64_t len = strlen(databasePath)+strlen(databaseFilename)+2;
	char *databaseFilePath = (char *) malloc(len);
	databaseFilePath[0]=0;
	strcat(databaseFilePath, databasePath);
	strcat(databaseFilePath, "/");
	strcat(databaseFilePath, databaseFilename);
	return databaseFilePath;
}

void showVersion() {
	printf("clarc version " VERSION " (c) 2012 Egor Egorov <me@egorfine.com>\nMIT License  |  http://egorfine.com/clarc/\n");
}

int parseCommandline(int argc, char *argv[]) {
	if (argc==1) {
		showVersion();
		printf("Perhaps, ask --help?\n");
		exit(0);
	}

	static struct option longOpts[] = {
		{ "accessKeyId",       required_argument,  NULL,  0 },
		{ "secretAccessKey",   required_argument,  NULL,  0 },
		{ "bucket",            required_argument,  NULL,  0 },
		{ "endPoint",          required_argument,  NULL,  0 },
		{ "public",            no_argument,        NULL,  0 },
		{ "rrs",               no_argument,        NULL,  0 },
		{ "rss",               no_argument,        NULL,  0 }, // common typo
		{ "skipSsl",           no_argument,        NULL,  0 },

		{ "connectTimeout",    required_argument,  NULL,  0 },
		{ "networkTimeout",    required_argument,  NULL,  0 },
		{ "uploadThreads",     required_argument,  NULL,  0 },

		{ "source",            required_argument,  NULL,  0 },
		{ "ddbPath",           required_argument,  NULL,  0 },
		{ "dbFilename",        required_argument,  NULL,  0 },

		{ "exclude",           required_argument,  NULL,  0 },
		{ "excludeFromFile",   required_argument,  NULL,  0 },

		{ "progress",          no_argument,        NULL,  0 },
		{ "logLevel",          required_argument,  NULL,  0 },

		{ "dryRun",            no_argument,        NULL,  0 },

		{ "rebuild",           no_argument,        NULL,  0 },
		{ "upload",            no_argument,        NULL,  0 },

		{ "version",           no_argument,        NULL,  'V' },
		{ "help",              no_argument,        NULL,  'h' },

		{ NULL,                0,                  NULL,  0 }
	};

	int ch, longIndex;
	while ((ch = getopt_long(argc, argv, "vh", longOpts, &longIndex)) != -1) {
		if (ch=='v') {
			showVersion();
			exit(0);
		} else if (ch=='h') {
			showHelp();
			exit(0);
		}

		if (ch!=0) {
			continue;
		}

		const char *longName = longOpts[longIndex].name;

		if (strcmp(longName, "accessKeyId")==0) {
			accessKeyId = strdup(optarg);

		} else if (strcmp(longName, "secretAccessKey")==0) {
			secretAccessKey = strdup(optarg);

		} else if (strcmp(longName, "bucket")==0) {
			bucket = strdup(optarg);

		} else if (strcmp(longName, "endPoint")==0) {
			endPoint = strdup(optarg);

		} else if (strcmp(longName, "networkTimeout")==0) {
			networkTimeout = atoi(optarg);
			if (networkTimeout<=0 || networkTimeout>=600) {
				printf("Network timeout invalid (must be 1..600 seconds)\n");
				exit(1);
			}

		} else if (strcmp(longName, "uploadThreads")==0) {
			uploadThreads = atoi(optarg);
			if (uploadThreads<=0 || uploadThreads>=100) {
				printf("Upload threads count invalid (must be 1..100)\n");
				exit(1);
			}

		} else if (strcmp(longName, "connectTimeout")==0) {
			connectTimeout = atoi(optarg);
			if (connectTimeout<=0 || connectTimeout>=600) {
				printf("Connect timeout invalid (must be 1..600 seconds)\n");
				exit(1);
			}

		} else if (strcmp(longName, "public")==0) {
			makeAllPublic = 1;

		} else if (strcmp(longName, "skipSsl")==0) {
			skipSsl = 1;

		} else if (strcmp(longName, "rrs")==0) {
			useRrs = 1;

		} else if (strcmp(longName, "rss")==0) {
			printf("Warning: you spelled --rss; you meant -rrs which stands for Reduced Redundancy Storage.\n");
			useRrs = 1;

		} else if (strcmp(longName, "dryRun")==0) {
			dryRun = 1;

		} else if (strcmp(longName, "progress")==0) {
			showProgress = 1;

		} else if (strcmp(longName, "logLevel")==0) {
			logLevel = atoi(optarg);
			if (logLevel <= 0 || logLevel > 5) {
				printf("--logLevel must be 1..5\n");
				exit(1);
			}

		} else if (strcmp(longName, "source")==0) {
			source = strdup(optarg);

		} else if (strcmp(longName, "dbPath")==0) {
			databasePath = strdup(optarg);

		} else if (strcmp(longName, "dbFilename")==0) {
			databaseFilename = strdup(optarg);

		} else if (strcmp(longName, "rebuild")==0) {
			performRebuild=1;

		} else if (strcmp(longName, "upload")==0) {
			performUpload=1;

		} else if (strcmp(longName, "exclude")==0) {
			if (!excludeFilePattern->add(optarg)) {
				printf("Pattern `%s' is not valid.\n", optarg);
				exit(1);
			}
		} else if (strcmp(longName, "excludeFromFile")==0) {
			if (!excludeFilePattern->readFile(optarg)) {
				printf("Cannot read or parse patterns in %s\n", optarg);
				exit(1);
			}
		}
	}

	int failed = 0;

	if (!source) {
		printf("Specify --source.\n");
		failed = 1;
	}

	if (source && source[0]!='/') {
		printf("--source must be absolute path.\n");
		failed=1;
	}

	if (!accessKeyId) {
		printf("Specify --accessKeyId.\n");
		failed = 1;
	}

	if (!secretAccessKey) {
		printf("Specify --secretAccessKey.\n");
		failed = 1;
	}

	if (!bucket) {
		printf("Specify --bucket.\n");
		failed = 1;
	}

	if (!validateEndpoint(endPoint)) {
	failed = 1;
	}

	if (!performRebuild && !performUpload) {
		printf("What shall I do? Say --rebuild and/or --upload!\n");
		failed = 1;
	}

	if (failed) {
		return 0;
	}

	while (source[strlen(source)-1]=='/') {
		source[strlen(source)-1]=0;
	}

	if (!databasePath) {
		databasePath = source;
	} else {
		while (databasePath[strlen(databasePath)-1]=='/') {
			databasePath[strlen(databasePath)-1]=0;
		}
	}

	return 1;
}

int verifySource(char *source) {
	struct stat fileInfo;
	if (lstat(source, &fileInfo)<0) {
		printf("%s doesn't exists.\n", source);
		return 0;
	}

	if (!(fileInfo.st_mode & S_IFDIR)) {
		printf("%s isn't a directory.\n", source);
		return 0;
	}

	return 1;
}

int main(int argc, char *argv[]) {
	int res;
	curl_global_init(CURL_GLOBAL_ALL);
	xmlInitParser();

	logStream = stdout;
	logLevel = LOG_DBG;

	excludeFilePattern = new FilePattern();

	if (!parseCommandline(argc, argv)) {
		exit(1);
	}

	if (!verifySource(source)) {
		exit(1);
	}

	AmazonCredentials *amazonCredentials = new AmazonCredentials(
		accessKeyId,
		secretAccessKey,
		bucket, endPoint
	);

	RemoteListOfFiles *remoteListOfFiles = new RemoteListOfFiles(amazonCredentials);
	remoteListOfFiles->showProgress = showProgress;
	if (skipSsl) {
		remoteListOfFiles->useSsl=0;
	}
	if (networkTimeout) {
		remoteListOfFiles->networkTimeout = networkTimeout;
	}
	if (connectTimeout) {
		remoteListOfFiles->connectTimeout = connectTimeout;
	}

	res = remoteListOfFiles->checkAuth();
	if (res == AUTH_FAILED_BUCKET_DOESNT_EXISTS) {
		LOG(LOG_FATAL, "[Auth] Failed: bucket doesn't exists, exit");
		exit(1);
	} else if (res == AUTH_FAILED) {
		LOG(LOG_FATAL, "[Auth] FAIL, exit");
		exit(1);
	}
	LOG(LOG_INFO, "[Auth] Success");

	char *databaseFilePath = buildDatabaseFilePath(databaseFilename, databasePath);
	LOG(LOG_DBG, "[Storage] Database path = %s", databaseFilePath);

	char errorResult[1024*100];
	FileListStorage *fileListStorage = new FileListStorage(databaseFilePath, errorResult);
	if (strlen(errorResult)>0) {
		LOG(LOG_FATAL, "[Storage] FAIL: %s, exit", errorResult);
		exit(1);
	}

	if (performRebuild) {
		if (rebuildDatabase(remoteListOfFiles, amazonCredentials, fileListStorage)==LIST_FAILED) {
			exit(1);
		}
	}

	if (performUpload) {
		if (excludeFilePattern->count==0) {
			delete excludeFilePattern;
			excludeFilePattern=NULL;
		}

		Uploader *uploader = new Uploader(amazonCredentials, excludeFilePattern);
		uploader->useRrs = useRrs;
		uploader->makeAllPublic = makeAllPublic;
		uploader->showProgress = showProgress;
		if (skipSsl) {
			uploader->useSsl=0;
		}
		if (networkTimeout) {
			uploader->networkTimeout = networkTimeout;
		}
		if (connectTimeout) {
			uploader->connectTimeout = connectTimeout;
		}
		if (uploadThreads) {
			uploader->uploadThreads = uploadThreads;
		}
		uploader->dryRun = dryRun;

#ifdef TEST
		do {
#endif
		res = uploader->uploadFiles(fileListStorage, source);
		if (res==UPLOAD_FAILED) {
			exit(1);
		}
#ifdef TEST
		fileListStorage->truncate();
		} while (true);
#endif

		res = uploader->uploadDatabase(databaseFilePath, databaseFilename);
		if (res==UPLOAD_FAILED) {
			exit(1);
		}

		delete uploader;
	}

	free(databaseFilePath);
	delete fileListStorage;
	delete amazonCredentials;

	exit(0);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011 Google Inc. 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 Google Inc. 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 "config.h"
#include "bindings/v8/PageScriptDebugServer.h"

#include "V8Window.h"
#include "bindings/v8/ScriptController.h"
#include "bindings/v8/ScriptSourceCode.h"
#include "bindings/v8/V8Binding.h"
#include "bindings/v8/V8ScriptRunner.h"
#include "bindings/v8/V8WindowShell.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/ScriptDebugListener.h"
#include "core/frame/Frame.h"
#include "core/frame/FrameHost.h"
#include "core/page/Page.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/StdLibExtras.h"
#include "wtf/TemporaryChange.h"
#include "wtf/text/StringBuilder.h"

namespace WebCore {

static Frame* retrieveFrameWithGlobalObjectCheck(v8::Handle<v8::Context> context)
{
    if (context.IsEmpty())
        return 0;

    // Test that context has associated global dom window object.
    v8::Handle<v8::Object> global = context->Global();
    if (global.IsEmpty())
        return 0;

    global = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), worldTypeInMainThread(context->GetIsolate())));
    if (global.IsEmpty())
        return 0;

    return toFrameIfNotDetached(context);
}

void PageScriptDebugServer::setPreprocessorSource(const String& preprocessorSource)
{
    if (preprocessorSource.isEmpty())
        m_preprocessorSourceCode.clear();
    else
        m_preprocessorSourceCode = adoptPtr(new ScriptSourceCode(preprocessorSource));
    m_scriptPreprocessor.clear();
}

PageScriptDebugServer& PageScriptDebugServer::shared()
{
    DEFINE_STATIC_LOCAL(PageScriptDebugServer, server, ());
    return server;
}

PageScriptDebugServer::PageScriptDebugServer()
    : ScriptDebugServer(v8::Isolate::GetCurrent())
    , m_pausedPage(0)
{
}

void PageScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page)
{
    ScriptController& scriptController = page->mainFrame()->script();
    if (!scriptController.canExecuteScripts(NotAboutToExecuteScript))
        return;

    v8::HandleScope scope(m_isolate);
    v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext();
    v8::Context::Scope contextScope(debuggerContext);

    v8::Local<v8::Object> debuggerScript = m_debuggerScript.newLocal(m_isolate);
    if (!m_listenersMap.size()) {
        ensureDebuggerScriptCompiled();
        ASSERT(!debuggerScript->IsUndefined());
        v8::Debug::SetDebugEventListener2(&PageScriptDebugServer::v8DebugEventCallback, v8::External::New(m_isolate, this));
    }
    m_listenersMap.set(page, listener);

    V8WindowShell* shell = scriptController.existingWindowShell(DOMWrapperWorld::mainWorld());
    if (!shell || !shell->isContextInitialized())
        return;
    v8::Local<v8::Context> context = shell->context();
    v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(debuggerScript->Get(v8AtomicString(m_isolate, "getScripts")));
    v8::Handle<v8::Value> argv[] = { context->GetEmbedderData(0) };
    v8::Handle<v8::Value> value = V8ScriptRunner::callInternalFunction(getScriptsFunction, debuggerScript, WTF_ARRAY_LENGTH(argv), argv, m_isolate);
    if (value.IsEmpty())
        return;
    ASSERT(!value->IsUndefined() && value->IsArray());
    v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value);
    for (unsigned i = 0; i < scriptsArray->Length(); ++i)
        dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(m_isolate, i))));
}

void PageScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page)
{
    if (!m_listenersMap.contains(page))
        return;

    if (m_pausedPage == page)
        continueProgram();

    m_listenersMap.remove(page);

    if (m_listenersMap.isEmpty())
        v8::Debug::SetDebugEventListener2(0);
    // FIXME: Remove all breakpoints set by the agent.
}

void PageScriptDebugServer::setClientMessageLoop(PassOwnPtr<ClientMessageLoop> clientMessageLoop)
{
    m_clientMessageLoop = clientMessageLoop;
}

void PageScriptDebugServer::compileScript(ScriptState* state, const String& expression, const String& sourceURL, String* scriptId, String* exceptionMessage)
{
    ExecutionContext* executionContext = state->executionContext();
    RefPtr<Frame> protect = toDocument(executionContext)->frame();
    ScriptDebugServer::compileScript(state, expression, sourceURL, scriptId, exceptionMessage);
    if (!scriptId->isNull())
        m_compiledScriptURLs.set(*scriptId, sourceURL);
}

void PageScriptDebugServer::clearCompiledScripts()
{
    ScriptDebugServer::clearCompiledScripts();
    m_compiledScriptURLs.clear();
}

void PageScriptDebugServer::runScript(ScriptState* state, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage)
{
    String sourceURL = m_compiledScriptURLs.take(scriptId);

    ExecutionContext* executionContext = state->executionContext();
    Frame* frame = toDocument(executionContext)->frame();
    InspectorInstrumentationCookie cookie;
    if (frame)
        cookie = InspectorInstrumentation::willEvaluateScript(frame, sourceURL, TextPosition::minimumPosition().m_line.oneBasedInt());

    RefPtr<Frame> protect = frame;
    ScriptDebugServer::runScript(state, scriptId, result, wasThrown, exceptionMessage);

    if (frame)
        InspectorInstrumentation::didEvaluateScript(cookie);
}

ScriptDebugListener* PageScriptDebugServer::getDebugListenerForContext(v8::Handle<v8::Context> context)
{
    v8::HandleScope scope(m_isolate);
    Frame* frame = retrieveFrameWithGlobalObjectCheck(context);
    if (!frame)
        return 0;
    return m_listenersMap.get(frame->page());
}

void PageScriptDebugServer::runMessageLoopOnPause(v8::Handle<v8::Context> context)
{
    v8::HandleScope scope(m_isolate);
    Frame* frame = retrieveFrameWithGlobalObjectCheck(context);
    m_pausedPage = frame->page();

    // Wait for continue or step command.
    m_clientMessageLoop->run(m_pausedPage);

    // The listener may have been removed in the nested loop.
    if (ScriptDebugListener* listener = m_listenersMap.get(m_pausedPage))
        listener->didContinue();

    m_pausedPage = 0;
}

void PageScriptDebugServer::quitMessageLoopOnPause()
{
    m_clientMessageLoop->quitNow();
}

void PageScriptDebugServer::preprocessBeforeCompile(const v8::Debug::EventDetails& eventDetails)
{
    v8::Handle<v8::Context> eventContext = eventDetails.GetEventContext();
    Frame* frame = retrieveFrameWithGlobalObjectCheck(eventContext);
    if (!frame)
        return;

    if (!canPreprocess(frame))
        return;

    v8::Handle<v8::Object> eventData = eventDetails.GetEventData();
    v8::Local<v8::Context> debugContext = v8::Debug::GetDebugContext();
    v8::Context::Scope contextScope(debugContext);
    v8::TryCatch tryCatch;
    // <script> tag source and attribute value source are preprocessed before we enter V8.
    // Avoid preprocessing any internal scripts by processing only eval source in this V8 event handler.
    v8::Handle<v8::Value> argvEventData[] = { eventData };
    v8::Handle<v8::Value> v8Value = callDebuggerMethod("isEvalCompilation", WTF_ARRAY_LENGTH(argvEventData), argvEventData);
    if (v8Value.IsEmpty() || !v8Value->ToBoolean()->Value())
        return;

    // The name and source are in the JS event data.
    String scriptName = toCoreStringWithUndefinedOrNullCheck(callDebuggerMethod("getScriptName", WTF_ARRAY_LENGTH(argvEventData), argvEventData));
    String script = toCoreStringWithUndefinedOrNullCheck(callDebuggerMethod("getScriptSource", WTF_ARRAY_LENGTH(argvEventData), argvEventData));

    String preprocessedSource  = m_scriptPreprocessor->preprocessSourceCode(script, scriptName);

    v8::Handle<v8::Value> argvPreprocessedScript[] = { eventData, v8String(debugContext->GetIsolate(), preprocessedSource) };
    callDebuggerMethod("setScriptSource", WTF_ARRAY_LENGTH(argvPreprocessedScript), argvPreprocessedScript);
}

static bool isCreatingPreprocessor = false;

bool PageScriptDebugServer::canPreprocess(Frame* frame)
{
    ASSERT(frame);

    if (!m_preprocessorSourceCode || !frame->page() || isCreatingPreprocessor)
        return false;

    // We delay the creation of the preprocessor until just before the first JS from the
    // Web page to ensure that the debugger's console initialization code has completed.
    if (!m_scriptPreprocessor) {
        TemporaryChange<bool> isPreprocessing(isCreatingPreprocessor, true);
        m_scriptPreprocessor = adoptPtr(new ScriptPreprocessor(*m_preprocessorSourceCode.get(), frame));
    }

    if (m_scriptPreprocessor->isValid())
        return true;

    m_scriptPreprocessor.clear();
    // Don't retry the compile if we fail one time.
    m_preprocessorSourceCode.clear();
    return false;
}

// Source to Source processing iff debugger enabled and it has loaded a preprocessor.
PassOwnPtr<ScriptSourceCode> PageScriptDebugServer::preprocess(Frame* frame, const ScriptSourceCode& sourceCode)
{
    if (!canPreprocess(frame))
        return PassOwnPtr<ScriptSourceCode>();

    String preprocessedSource = m_scriptPreprocessor->preprocessSourceCode(sourceCode.source(), sourceCode.url());
    return adoptPtr(new ScriptSourceCode(preprocessedSource, sourceCode.url()));
}

String PageScriptDebugServer::preprocessEventListener(Frame* frame, const String& source, const String& url, const String& functionName)
{
    if (!canPreprocess(frame))
        return source;

    return m_scriptPreprocessor->preprocessSourceCode(source, url, functionName);
}

} // namespace WebCore
<commit_msg>retrieveFrameWithGlobalObjectCheck should check contextHasCorrectPrototype()<commit_after>/*
 * Copyright (c) 2011 Google Inc. 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 Google Inc. 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 "config.h"
#include "bindings/v8/PageScriptDebugServer.h"

#include "V8Window.h"
#include "bindings/v8/ScriptController.h"
#include "bindings/v8/ScriptSourceCode.h"
#include "bindings/v8/V8Binding.h"
#include "bindings/v8/V8ScriptRunner.h"
#include "bindings/v8/V8WindowShell.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/ScriptDebugListener.h"
#include "core/frame/Frame.h"
#include "core/frame/FrameHost.h"
#include "core/page/Page.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/StdLibExtras.h"
#include "wtf/TemporaryChange.h"
#include "wtf/text/StringBuilder.h"

namespace WebCore {

static Frame* retrieveFrameWithGlobalObjectCheck(v8::Handle<v8::Context> context)
{
    if (context.IsEmpty())
        return 0;

    // Test that context has associated global dom window object.
    if (!V8WindowShell::contextHasCorrectPrototype(context))
        return 0;

    v8::Handle<v8::Value> global = context->Global()->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), worldTypeInMainThread(context->GetIsolate())));
    if (global.IsEmpty())
        return 0;

    return toFrameIfNotDetached(context);
}

void PageScriptDebugServer::setPreprocessorSource(const String& preprocessorSource)
{
    if (preprocessorSource.isEmpty())
        m_preprocessorSourceCode.clear();
    else
        m_preprocessorSourceCode = adoptPtr(new ScriptSourceCode(preprocessorSource));
    m_scriptPreprocessor.clear();
}

PageScriptDebugServer& PageScriptDebugServer::shared()
{
    DEFINE_STATIC_LOCAL(PageScriptDebugServer, server, ());
    return server;
}

PageScriptDebugServer::PageScriptDebugServer()
    : ScriptDebugServer(v8::Isolate::GetCurrent())
    , m_pausedPage(0)
{
}

void PageScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page)
{
    ScriptController& scriptController = page->mainFrame()->script();
    if (!scriptController.canExecuteScripts(NotAboutToExecuteScript))
        return;

    v8::HandleScope scope(m_isolate);
    v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext();
    v8::Context::Scope contextScope(debuggerContext);

    v8::Local<v8::Object> debuggerScript = m_debuggerScript.newLocal(m_isolate);
    if (!m_listenersMap.size()) {
        ensureDebuggerScriptCompiled();
        ASSERT(!debuggerScript->IsUndefined());
        v8::Debug::SetDebugEventListener2(&PageScriptDebugServer::v8DebugEventCallback, v8::External::New(m_isolate, this));
    }
    m_listenersMap.set(page, listener);

    V8WindowShell* shell = scriptController.existingWindowShell(DOMWrapperWorld::mainWorld());
    if (!shell || !shell->isContextInitialized())
        return;
    v8::Local<v8::Context> context = shell->context();
    v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(debuggerScript->Get(v8AtomicString(m_isolate, "getScripts")));
    v8::Handle<v8::Value> argv[] = { context->GetEmbedderData(0) };
    v8::Handle<v8::Value> value = V8ScriptRunner::callInternalFunction(getScriptsFunction, debuggerScript, WTF_ARRAY_LENGTH(argv), argv, m_isolate);
    if (value.IsEmpty())
        return;
    ASSERT(!value->IsUndefined() && value->IsArray());
    v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value);
    for (unsigned i = 0; i < scriptsArray->Length(); ++i)
        dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(m_isolate, i))));
}

void PageScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page)
{
    if (!m_listenersMap.contains(page))
        return;

    if (m_pausedPage == page)
        continueProgram();

    m_listenersMap.remove(page);

    if (m_listenersMap.isEmpty())
        v8::Debug::SetDebugEventListener2(0);
    // FIXME: Remove all breakpoints set by the agent.
}

void PageScriptDebugServer::setClientMessageLoop(PassOwnPtr<ClientMessageLoop> clientMessageLoop)
{
    m_clientMessageLoop = clientMessageLoop;
}

void PageScriptDebugServer::compileScript(ScriptState* state, const String& expression, const String& sourceURL, String* scriptId, String* exceptionMessage)
{
    ExecutionContext* executionContext = state->executionContext();
    RefPtr<Frame> protect = toDocument(executionContext)->frame();
    ScriptDebugServer::compileScript(state, expression, sourceURL, scriptId, exceptionMessage);
    if (!scriptId->isNull())
        m_compiledScriptURLs.set(*scriptId, sourceURL);
}

void PageScriptDebugServer::clearCompiledScripts()
{
    ScriptDebugServer::clearCompiledScripts();
    m_compiledScriptURLs.clear();
}

void PageScriptDebugServer::runScript(ScriptState* state, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage)
{
    String sourceURL = m_compiledScriptURLs.take(scriptId);

    ExecutionContext* executionContext = state->executionContext();
    Frame* frame = toDocument(executionContext)->frame();
    InspectorInstrumentationCookie cookie;
    if (frame)
        cookie = InspectorInstrumentation::willEvaluateScript(frame, sourceURL, TextPosition::minimumPosition().m_line.oneBasedInt());

    RefPtr<Frame> protect = frame;
    ScriptDebugServer::runScript(state, scriptId, result, wasThrown, exceptionMessage);

    if (frame)
        InspectorInstrumentation::didEvaluateScript(cookie);
}

ScriptDebugListener* PageScriptDebugServer::getDebugListenerForContext(v8::Handle<v8::Context> context)
{
    v8::HandleScope scope(m_isolate);
    Frame* frame = retrieveFrameWithGlobalObjectCheck(context);
    if (!frame)
        return 0;
    return m_listenersMap.get(frame->page());
}

void PageScriptDebugServer::runMessageLoopOnPause(v8::Handle<v8::Context> context)
{
    v8::HandleScope scope(m_isolate);
    Frame* frame = retrieveFrameWithGlobalObjectCheck(context);
    m_pausedPage = frame->page();

    // Wait for continue or step command.
    m_clientMessageLoop->run(m_pausedPage);

    // The listener may have been removed in the nested loop.
    if (ScriptDebugListener* listener = m_listenersMap.get(m_pausedPage))
        listener->didContinue();

    m_pausedPage = 0;
}

void PageScriptDebugServer::quitMessageLoopOnPause()
{
    m_clientMessageLoop->quitNow();
}

void PageScriptDebugServer::preprocessBeforeCompile(const v8::Debug::EventDetails& eventDetails)
{
    v8::Handle<v8::Context> eventContext = eventDetails.GetEventContext();
    Frame* frame = retrieveFrameWithGlobalObjectCheck(eventContext);
    if (!frame)
        return;

    if (!canPreprocess(frame))
        return;

    v8::Handle<v8::Object> eventData = eventDetails.GetEventData();
    v8::Local<v8::Context> debugContext = v8::Debug::GetDebugContext();
    v8::Context::Scope contextScope(debugContext);
    v8::TryCatch tryCatch;
    // <script> tag source and attribute value source are preprocessed before we enter V8.
    // Avoid preprocessing any internal scripts by processing only eval source in this V8 event handler.
    v8::Handle<v8::Value> argvEventData[] = { eventData };
    v8::Handle<v8::Value> v8Value = callDebuggerMethod("isEvalCompilation", WTF_ARRAY_LENGTH(argvEventData), argvEventData);
    if (v8Value.IsEmpty() || !v8Value->ToBoolean()->Value())
        return;

    // The name and source are in the JS event data.
    String scriptName = toCoreStringWithUndefinedOrNullCheck(callDebuggerMethod("getScriptName", WTF_ARRAY_LENGTH(argvEventData), argvEventData));
    String script = toCoreStringWithUndefinedOrNullCheck(callDebuggerMethod("getScriptSource", WTF_ARRAY_LENGTH(argvEventData), argvEventData));

    String preprocessedSource  = m_scriptPreprocessor->preprocessSourceCode(script, scriptName);

    v8::Handle<v8::Value> argvPreprocessedScript[] = { eventData, v8String(debugContext->GetIsolate(), preprocessedSource) };
    callDebuggerMethod("setScriptSource", WTF_ARRAY_LENGTH(argvPreprocessedScript), argvPreprocessedScript);
}

static bool isCreatingPreprocessor = false;

bool PageScriptDebugServer::canPreprocess(Frame* frame)
{
    ASSERT(frame);

    if (!m_preprocessorSourceCode || !frame->page() || isCreatingPreprocessor)
        return false;

    // We delay the creation of the preprocessor until just before the first JS from the
    // Web page to ensure that the debugger's console initialization code has completed.
    if (!m_scriptPreprocessor) {
        TemporaryChange<bool> isPreprocessing(isCreatingPreprocessor, true);
        m_scriptPreprocessor = adoptPtr(new ScriptPreprocessor(*m_preprocessorSourceCode.get(), frame));
    }

    if (m_scriptPreprocessor->isValid())
        return true;

    m_scriptPreprocessor.clear();
    // Don't retry the compile if we fail one time.
    m_preprocessorSourceCode.clear();
    return false;
}

// Source to Source processing iff debugger enabled and it has loaded a preprocessor.
PassOwnPtr<ScriptSourceCode> PageScriptDebugServer::preprocess(Frame* frame, const ScriptSourceCode& sourceCode)
{
    if (!canPreprocess(frame))
        return PassOwnPtr<ScriptSourceCode>();

    String preprocessedSource = m_scriptPreprocessor->preprocessSourceCode(sourceCode.source(), sourceCode.url());
    return adoptPtr(new ScriptSourceCode(preprocessedSource, sourceCode.url()));
}

String PageScriptDebugServer::preprocessEventListener(Frame* frame, const String& source, const String& url, const String& functionName)
{
    if (!canPreprocess(frame))
        return source;

    return m_scriptPreprocessor->preprocessSourceCode(source, url, functionName);
}

} // namespace WebCore
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	LTC2348-16 ドライバー @n
			LTC2348/16 bits A/D コンバーター @n
			Copyright 2017 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include "common/delay.hpp"
#include "common/format.hpp"

/// F_ICK は速度パラメーター計算で必要で、設定が無いとエラーにします。
#ifndef F_ICK
#  error "LTC2348_16.hpp requires F_ICK to be defined"
#endif

namespace chip {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  LTC2348-16 データ出力定義
		@param[in]	CK	SCKO 定義
		@param[in]	O0	SDO0 定義
		@param[in]	O2	SDO2 定義
		@param[in]	O4	SDO4 定義
		@param[in]	O5	SDO6 定義
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class CK, class O0, class O2, class O4, class O6>
	struct LTC2348_SDO_t {
		typedef CK	SCKO;
		typedef O0	SDO0;
		typedef O2	SDO2;
		typedef O4	SDO4;
		typedef O6	SDO6;
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  LTC2348-16 テンプレートクラス
		@param[in]	CSN		デバイス選択
		@param[in]	CNV		コンバート制御
		@param[in]	BUSY	ビジー信号
		@param[in]	PD		パワーダウン制御（1: PowerDown）
		@param[in]	SDI		制御データ
		@param[in]	SCKI	制御クロック
		@param[in]	SDO		データ出力定義
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class CSN, class CNV, class BUSY, class PD, class SDI, class SCKI, class SDO>
	class LTC2348_16 {

		uint32_t	span_;

		uint32_t	data_[8];

		uint16_t	busy_loop_;
		uint16_t	clk_loop_;
		uint16_t	cnv_loop_;

		bool		device_;

		void get_data_loop_(uint32_t ofs, uint32_t span)
		{
			SDI::P = 0;
			uint32_t mask = 0x00800000;
			uint32_t d0 = 0;
			uint32_t d1 = 0;
			uint32_t d2 = 0;
			uint32_t d3 = 0;
			volatile uint16_t ll = clk_loop_ >> 1;
			if(ll > 10) ll -= 10; else ll = 0;
			while(mask > 0) {
				d0 <<= 1;
				d0 |= SDO::SDO0::P();
				d1 <<= 1;
				d1 |= SDO::SDO2::P();
				d2 <<= 1;
				d2 |= SDO::SDO4::P();
				d3 <<= 1;
				d3 |= SDO::SDO6::P();

				volatile uint16_t l = ll;
				while(l > 0) { --l; }
				SCKI::P = 0;

				if(span & mask) {
					SDI::P = 1;
				} else {
					SDI::P = 0;
				}
				mask >>= 1;

				volatile uint16_t h = clk_loop_ >> 1;
				while(h > 0) { --h; }
				SCKI::P = 1;
			}
			data_[0 + ofs] = d0;
			data_[2 + ofs] = d1;
			data_[4 + ofs] = d2;
			data_[6 + ofs] = d3;
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		LTC2348_16() : span_(0), busy_loop_(0), clk_loop_(0), cnv_loop_(0), device_(false) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  スパンデータの取得
			@return スパンデータ
		*/
		//-----------------------------------------------------------------//
		uint32_t get_span() const { return span_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  デバイスの開始 @n
					制御線を初期化して、デバイスのゆ有無を確認
			@param[in]	speed	制御クロック速度
			@param[in]	span	変換スパン
			@return デバイスが有効なら「true」
		*/
		//-----------------------------------------------------------------//
		bool start(uint32_t speed, uint8_t span)
		{
			{
				uint32_t cnt = static_cast<uint32_t>(F_ICK) / speed;
				float a = static_cast<float>(cnt);
				a /= 10.974f;
				cnt = static_cast<uint32_t>(a);
				if(cnt > 65535) return false;
				clk_loop_ = cnt;
			}
			{  // BUSY loop 200ns (5MHz)
				uint32_t cnt = static_cast<uint32_t>(F_ICK) / 5000000;
				if(cnt > 65535) return false;
				busy_loop_ = cnt;
			}
			{  // tCONV: 500ns/ch 200ksps
				uint32_t cnt = static_cast<uint32_t>(F_ICK) / 200000;
				if(cnt > 65535) return false;
				cnv_loop_ = cnt;
			}

			uint32_t ss = 0;
			for(int i = 0; i < 8; ++i) {
				ss <<= 3;
				ss |= static_cast<uint32_t>(span & 7);
			}
			span_ = ss;

			CSN::DIR = 1;
			CSN::P = 1;
			CNV::DIR = 1;
			CNV::P = 0;
			BUSY::DIR = 0;
			PD::DIR = 1;
			PD::P = 0;
			SDI::DIR = 1;
			SDI::P = 0;
			SCKI::DIR = 1;
			SCKI::P = 0;

			SDO::SCKO::DIR = 0;

			SDO::SDO0::DIR = 0;
			SDO::SDO2::DIR = 0;
			SDO::SDO4::DIR = 0;
			SDO::SDO6::DIR = 0;

			utils::delay::milli_second(1);
			device_ = convert();

			return device_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  デバイスの応答確認
			@return デバイスが接続されている場合「true」
		*/
		//-----------------------------------------------------------------//
		bool probe() const {
			return device_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換を開始
			@return 変換正常終了なら「true」
		*/
		//-----------------------------------------------------------------//
		bool convert()
		{
			SCKI::P = 0;
			SDI::P = 0;

			if(BUSY::P() != 0) {
				return false;
			}

			// tBUSYLH: CNV=1 で BUSY が応答する最大時間 (max 30ns) @n
			// tCNVH: CNV 要求パルス (min 40ns)
			{
				CNV::P = 1;
				uint16_t n = busy_loop_;
				while(n > 0) {
					if(BUSY::P() == 1) {
						break;
					}
					--n;
				}
				if(n == 0) {
					CNV::P = 0;
					CSN::P = 1;
					return false;
				}
			}

			CSN::P = 0;

			// 変換待ち 最大 500ns
			{
				uint16_t n = cnv_loop_;
				while(n > 0) {
					if(BUSY::P() == 0) break;
					--n;
				}
/// 			utils::format("Conversion count: %d\n") % static_cast<int>(cnv_loop_ - n);
				CNV::P = 0;
				if(n == 0) {
					CSN::P = 1;
					return false;
				}
			}

			get_data_loop_(0, span_);
			get_data_loop_(1, 0x000000);

			CSN::P = 1;

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換値を取得
			@param[in]	ch	チャネル（０～７）
			@return 変換値
		*/
		//-----------------------------------------------------------------//
		uint16_t get_value(uint8_t ch) const {
			return data_[ch & 7] >> 8;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換値を取得
			@param[in]	ch	チャネル（０～７）
			@return 変換値
		*/
		//-----------------------------------------------------------------//
		uint32_t get_data(uint8_t ch) const {
			return data_[ch & 7];
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換電圧を取得
			@param[in]	ch	チャネル（０～７）
			@return 変換電圧
		*/
		//-----------------------------------------------------------------//
		float get_voltage(uint8_t ch) const {
			float gain = 5.12f;
			return static_cast<float>(data_[ch & 7]) / 65535.0f * gain;
		}
	};
}
<commit_msg>update<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	LTC2348-16 ドライバー @n
			LTC2348/16 bits A/D コンバーター @n
			Copyright 2017 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include "common/delay.hpp"
#include "common/format.hpp"

/// F_ICK は速度パラメーター計算で必要で、設定が無いとエラーにします。
#ifndef F_ICK
#  error "LTC2348_16.hpp requires F_ICK to be defined"
#endif

namespace chip {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  LTC2348-16 データ出力定義
		@param[in]	CK	SCKO 定義
		@param[in]	O0	SDO0 定義
		@param[in]	O2	SDO2 定義
		@param[in]	O4	SDO4 定義
		@param[in]	O5	SDO6 定義
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class CK, class O0, class O2, class O4, class O6>
	struct LTC2348_SDO_t {
		typedef CK	SCKO;
		typedef O0	SDO0;
		typedef O2	SDO2;
		typedef O4	SDO4;
		typedef O6	SDO6;
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  LTC2348-16 テンプレートクラス
		@param[in]	CSN		デバイス選択
		@param[in]	CNV		コンバート制御
		@param[in]	BUSY	ビジー信号
		@param[in]	PD		パワーダウン制御（1: PowerDown）
		@param[in]	SDI		制御データ
		@param[in]	SCKI	制御クロック
		@param[in]	SDO		データ出力定義
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class CSN, class CNV, class BUSY, class PD, class SDI, class SCKI, class SDO>
	class LTC2348_16 {
	public:
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  ソフト・スパン種別 @n
					Internal VREFBUF: 4.096V
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class span_type : uint8_t {
			DISABLE,  		///< 000, Chanel Disable
			P5_12,			///< 001, 1.25 * VREFBUF          (+0      to +5.12V)
			M5P5,			///< 010, 2.5  * VREFBUF / 1.024  (-5V     to +5V)
			P5_12M5_12,		///< 011, 2.5  * VREFBUF          (-5.12V  to +5.12V)
			P10,			///< 100, 2.5  * VREFBUF / 1.024  (+0      to +10V)
			P10_24,			///< 101, 2.5  * VREFBUF          (+0      to +10.24V)
			M10P10,			///< 110, 5.0  * VREFBUF / 1.024  (-10V    to +10V)
			M10_24P10_24,	///< 111, 5.0  * VREFBUF          (-10.24V to +10.24V)
		};

	private:
		uint32_t	span_;

		uint32_t	data_[8];

		uint16_t	busy_loop_;
		uint16_t	clk_loop_;
		uint16_t	cnv_loop_;

		bool		device_;

		void get_data_loop_(uint32_t ofs, uint32_t span)
		{
			SDI::P = 0;
			uint32_t mask = 0x00800000;
			uint32_t d0 = 0;
			uint32_t d1 = 0;
			uint32_t d2 = 0;
			uint32_t d3 = 0;
			volatile uint16_t ll = clk_loop_ >> 1;
			if(ll > 10) ll -= 10; else ll = 0;
			while(mask > 0) {
				d0 <<= 1;
				d0 |= SDO::SDO0::P();
				d1 <<= 1;
				d1 |= SDO::SDO2::P();
				d2 <<= 1;
				d2 |= SDO::SDO4::P();
				d3 <<= 1;
				d3 |= SDO::SDO6::P();

				volatile uint16_t l = ll;
				while(l > 0) { --l; }
				SCKI::P = 0;

				if(span & mask) {
					SDI::P = 1;
				} else {
					SDI::P = 0;
				}
				mask >>= 1;

				volatile uint16_t h = clk_loop_ >> 1;
				while(h > 0) { --h; }
				SCKI::P = 1;
			}
			data_[0 + ofs] = d0;
			data_[2 + ofs] = d1;
			data_[4 + ofs] = d2;
			data_[6 + ofs] = d3;
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		LTC2348_16() : span_(0), busy_loop_(0), clk_loop_(0), cnv_loop_(0), device_(false) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  デバイスの開始 @n
					制御線を初期化して、デバイスのゆ有無を確認
			@param[in]	speed	制御クロック速度（ソフトループなので正確ではない）
			@param[in]	span	変換スパン種別（全てのチャネルに同一のスパンが設定される）
			@return デバイスが有効なら「true」
		*/
		//-----------------------------------------------------------------//
		bool start(uint32_t speed, span_type span)
		{
			{
				uint32_t cnt = static_cast<uint32_t>(F_ICK) / speed;
				float a = static_cast<float>(cnt);
				a /= 10.974f;
				cnt = static_cast<uint32_t>(a);
				if(cnt > 65535) return false;
				clk_loop_ = cnt;
			}
			{  // BUSY loop 200ns (5MHz)
				uint32_t cnt = static_cast<uint32_t>(F_ICK) / 5000000;
				if(cnt > 65535) return false;
				busy_loop_ = cnt;
			}
			{  // tCONV: 500ns/ch 200ksps
				uint32_t cnt = static_cast<uint32_t>(F_ICK) / 200000;
				if(cnt > 65535) return false;
				cnv_loop_ = cnt;
			}

			uint32_t ss = 0;
			for(int i = 0; i < 8; ++i) {
				ss <<= 3;
				ss |= static_cast<uint32_t>(span);
			}
			span_ = ss;

			CSN::DIR  = 1;
			CSN::P    = 1;
			CNV::DIR  = 1;
			CNV::P    = 0;
			BUSY::DIR = 0;
			PD::DIR   = 1;
			PD::P     = 0;
			SDI::DIR  = 1;
			SDI::P    = 0;
			SCKI::DIR = 1;
			SCKI::P   = 0;

			SDO::SCKO::DIR = 0;

			SDO::SDO0::DIR = 0;
			SDO::SDO2::DIR = 0;
			SDO::SDO4::DIR = 0;
			SDO::SDO6::DIR = 0;

			utils::delay::milli_second(1);
			device_ = convert();

			return device_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  デバイスの応答確認
			@return デバイスが接続されている場合「true」
		*/
		//-----------------------------------------------------------------//
		bool probe() const {
			return device_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  チャネルにスパン種別を設定
			@param[in]	ch		チャネル
			@param[in]	span	スパン種別
		*/
		//-----------------------------------------------------------------//
		void set_span(uint8_t ch, span_type span)
		{
			span_ &= ~(0b111 << (ch * 3));
			span_ |= static_cast<uint32_t>(span) << (ch * 3);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  チャネルのスパン種別を取得
			@param[in]	ch		チャネル
			@return スパン種別
		*/
		//-----------------------------------------------------------------//
		span_type get_span(uint8_t ch) const
		{
			return static_cast<span_type>((span_ >> (ch * 3)) & 0b111);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換を開始
			@return 変換正常終了なら「true」
		*/
		//-----------------------------------------------------------------//
		bool convert()
		{
			SCKI::P = 0;
			SDI::P = 0;

			if(BUSY::P() != 0) {
				return false;
			}

			// tBUSYLH: CNV=1 で BUSY が応答する最大時間 (max 30ns) @n
			// tCNVH: CNV 要求パルス (min 40ns)
			{
				CNV::P = 1;
				uint16_t n = busy_loop_;
				while(n > 0) {
					if(BUSY::P() == 1) {
						break;
					}
					--n;
				}
				if(n == 0) {
					CNV::P = 0;
					CSN::P = 1;
					return false;
				}
			}

			CSN::P = 0;

			// 変換待ち 最大 500ns
			{
				uint16_t n = cnv_loop_;
				while(n > 0) {
					if(BUSY::P() == 0) break;
					--n;
				}
/// 			utils::format("Conversion count: %d\n") % static_cast<int>(cnv_loop_ - n);
				CNV::P = 0;
				if(n == 0) {
					CSN::P = 1;
					return false;
				}
			}

			get_data_loop_(0, span_);
			get_data_loop_(1, 0x000000);

			CSN::P = 1;

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  Ａ／Ｄ変換値を取得（０～６５５３５）
			@param[in]	ch	チャネル（０～７）
			@return 変換値
		*/
		//-----------------------------------------------------------------//
		uint16_t get_value(uint8_t ch) const {
			return data_[ch & 7] >> 8;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換データ（２４ビット生データ）を取得
			@param[in]	ch	チャネル（０～７）
			@return 変換値
		*/
		//-----------------------------------------------------------------//
		uint32_t get_data(uint8_t ch) const {
			return data_[ch & 7];
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換電圧に変換して取得
			@param[in]	ch	チャネル（０～７）
			@return 変換電圧
		*/
		//-----------------------------------------------------------------//
		float get_voltage(uint8_t ch) const {
			uint32_t span = (span_ >> (ch * 3)) & 7;
			float ofs = 0.0f;
			if(span == 2 || span == 3 || span == 6 || span == 7) {
				ofs = 0.5f;
			}
			static const float gain[8] = { 0.0f, 5.12f, 5.0f, 5.12f, 10.0f, 10.24f, 10.0f, 10.24f };
			return ((static_cast<float>(data_[ch & 7] >> 8) / 65535.0f) - ofs) * gain[span];
		}
	};
}
<|endoftext|>