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

#include "MBRBlockDevice.h"
#include <algorithm>

// On disk structures, all entries are little endian
MBED_PACKED(struct) mbr_entry {
    uint8_t status;
    uint8_t chs_start[3];
    uint8_t type;
    uint8_t chs_stop[3];
    uint32_t lba_offset;
    uint32_t lba_size;
};

MBED_PACKED(struct) mbr_table {
    struct mbr_entry entries[4];
    uint8_t signature[2];
};

// Little-endian conversion, should compile to noop
// if system is little-endian
static inline uint32_t tole32(uint32_t a)
{
    union {
        uint32_t u32;
        uint8_t u8[4];
    } w;

    w.u8[0] = a >>  0;
    w.u8[1] = a >>  8;
    w.u8[2] = a >> 16;
    w.u8[3] = a >> 24;

    return w.u32;
}

static inline uint32_t fromle32(uint32_t a)
{
    return tole32(a);
}

static void tochs(uint32_t lba, uint8_t chs[3])
{
    uint32_t sector = std::min<uint32_t>(lba, 0xfffffd)+1;
    chs[0] = (sector >> 6) & 0xff;
    chs[1] = ((sector >> 0) & 0x3f) | ((sector >> 16) & 0xc0);
    chs[2] = (sector >> 14) & 0xff;
}

// Partition after address are turned into absolute
// addresses, assumes bd is initialized
static int partition_absolute(
        BlockDevice *bd, int part, uint8_t type,
        bd_size_t offset, bd_size_t size)
{
    // Allocate smallest buffer necessary to write MBR
    uint32_t buffer_size = std::max<uint32_t>(bd->get_program_size(), sizeof(struct mbr_table));
    uint8_t *buffer = new uint8_t[buffer_size];

    // Check for existing MBR
    int err = bd->read(buffer, 512-buffer_size, buffer_size);
    if (err) {
        delete[] buffer;
        return err;
    }

    struct mbr_table *table = reinterpret_cast<struct mbr_table*>(
            &buffer[buffer_size - sizeof(struct mbr_table)]);
    if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) {
        // Setup default values for MBR
        table->signature[0] = 0x55;
        table->signature[1] = 0xaa;
        memset(table->entries, 0, sizeof(table->entries));
    }

    // Setup new partition
    MBED_ASSERT(part >= 1 && part <= 4);
    table->entries[part-1].status = 0x00; // inactive (not bootable)
    table->entries[part-1].type = type;

    // lba dimensions
    uint32_t sector = std::max<uint32_t>(bd->get_erase_size(), 512);
    uint32_t lba_offset = offset / sector;
    uint32_t lba_size = size / sector;
    table->entries[part-1].lba_offset = tole32(lba_offset);
    table->entries[part-1].lba_size = tole32(lba_size);

    // chs dimensions
    tochs(lba_offset,            table->entries[part-1].chs_start);
    tochs(lba_offset+lba_size-1, table->entries[part-1].chs_stop);

    // Write out MBR
    err = bd->erase(0, bd->get_erase_size());
    if (err) {
        delete[] buffer;
        return err;
    }

    err = bd->program(buffer, 512-buffer_size, buffer_size);
    delete[] buffer;
    return err;
}

int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type, bd_addr_t start)
{
    int err = bd->init();
    if (err) {
        return err;
    }

    // Calculate dimensions
    bd_size_t offset = ((int64_t)start < 0) ? -start : start;
    bd_size_t size = bd->size();

    if (offset < 512) {
        offset += std::max<uint32_t>(bd->get_erase_size(), 512);
    }

    size -= offset;

    err = partition_absolute(bd, part, type, offset, size);
    if (err) {
        return err;
    }

    err = bd->deinit();
    if (err) {
        return err;
    }

    return 0;
}

int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type,
        bd_addr_t start, bd_addr_t stop)
{
    int err = bd->init();
    if (err) {
        return err;
    }

    // Calculate dimensions
    bd_size_t offset = ((int64_t)start < 0) ? -start : start;
    bd_size_t size = ((int64_t)stop < 0) ? -stop : stop;

    if (offset < 512) {
        offset += std::max<uint32_t>(bd->get_erase_size(), 512);
    }

    size -= offset;

    err = partition_absolute(bd, part, type, offset, size);
    if (err) {
        return err;
    }

    err = bd->deinit();
    if (err) {
        return err;
    }

    return 0;
}

MBRBlockDevice::MBRBlockDevice(BlockDevice *bd, int part)
    : _bd(bd), _part(part)
{
    MBED_ASSERT(_part >= 1 && _part <= 4);
}

int MBRBlockDevice::init()
{
    // Allocate smallest buffer necessary to write MBR
    uint32_t buffer_size = std::max<uint32_t>(_bd->get_read_size(), sizeof(struct mbr_table));
    uint8_t *buffer = new uint8_t[buffer_size];

    int err = _bd->read(buffer, 512-buffer_size, buffer_size);
    if (err) {
        delete[] buffer;
        return err;
    }

    // Check for valid table
    struct mbr_table *table = reinterpret_cast<struct mbr_table*>(
            &buffer[buffer_size - sizeof(struct mbr_table)]);
    if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) {
        delete[] buffer;
        return BD_ERROR_INVALID_MBR;
    }

    // Check for valid entry
    if (table->entries[_part-1].type == 0x00) {
        delete[] buffer;
        return BD_ERROR_INVALID_PARTITION;
    }

    // Get partition attributes
    bd_size_t sector = std::max<uint32_t>(_bd->get_erase_size(), 512);
    _type = table->entries[_part-1].type;
    _offset = fromle32(table->entries[_part-1].lba_offset) * sector;
    _size   = fromle32(table->entries[_part-1].lba_size)   * sector;

    // Check that block addresses are valid
    MBED_ASSERT(_bd->is_valid_erase(_offset, _size));

    delete[] buffer;
    return 0;
}

int MBRBlockDevice::deinit()
{
    return _bd->deinit();
}

int MBRBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{
    MBED_ASSERT(is_valid_read(addr, size));
    return _bd->read(b, addr + _offset, size);
}

int MBRBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{
    MBED_ASSERT(is_valid_program(addr, size));
    return _bd->program(b, addr + _offset, size);
}

int MBRBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
    MBED_ASSERT(is_valid_erase(addr, size));
    return _bd->erase(addr + _offset, size);
}

bd_size_t MBRBlockDevice::get_read_size() const
{
    return _bd->get_read_size();
}

bd_size_t MBRBlockDevice::get_program_size() const
{
    return _bd->get_program_size();
}

bd_size_t MBRBlockDevice::get_erase_size() const
{
    return _bd->get_erase_size();
}

bd_size_t MBRBlockDevice::size() const
{
    return _size;
}

bd_size_t MBRBlockDevice::get_partition_start() const
{
    return _offset;
}

bd_size_t MBRBlockDevice::get_partition_stop() const
{
    return _offset+_size;
}

uint8_t MBRBlockDevice::get_partition_type() const
{
    return _type;
}

int MBRBlockDevice::get_partition_number() const
{
    return _part;
}
<commit_msg>bd: Fix missing init in MBRBlockDevice<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2017 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "MBRBlockDevice.h"
#include <algorithm>

// On disk structures, all entries are little endian
MBED_PACKED(struct) mbr_entry {
    uint8_t status;
    uint8_t chs_start[3];
    uint8_t type;
    uint8_t chs_stop[3];
    uint32_t lba_offset;
    uint32_t lba_size;
};

MBED_PACKED(struct) mbr_table {
    struct mbr_entry entries[4];
    uint8_t signature[2];
};

// Little-endian conversion, should compile to noop
// if system is little-endian
static inline uint32_t tole32(uint32_t a)
{
    union {
        uint32_t u32;
        uint8_t u8[4];
    } w;

    w.u8[0] = a >>  0;
    w.u8[1] = a >>  8;
    w.u8[2] = a >> 16;
    w.u8[3] = a >> 24;

    return w.u32;
}

static inline uint32_t fromle32(uint32_t a)
{
    return tole32(a);
}

static void tochs(uint32_t lba, uint8_t chs[3])
{
    uint32_t sector = std::min<uint32_t>(lba, 0xfffffd)+1;
    chs[0] = (sector >> 6) & 0xff;
    chs[1] = ((sector >> 0) & 0x3f) | ((sector >> 16) & 0xc0);
    chs[2] = (sector >> 14) & 0xff;
}

// Partition after address are turned into absolute
// addresses, assumes bd is initialized
static int partition_absolute(
        BlockDevice *bd, int part, uint8_t type,
        bd_size_t offset, bd_size_t size)
{
    // Allocate smallest buffer necessary to write MBR
    uint32_t buffer_size = std::max<uint32_t>(bd->get_program_size(), sizeof(struct mbr_table));
    uint8_t *buffer = new uint8_t[buffer_size];

    // Check for existing MBR
    int err = bd->read(buffer, 512-buffer_size, buffer_size);
    if (err) {
        delete[] buffer;
        return err;
    }

    struct mbr_table *table = reinterpret_cast<struct mbr_table*>(
            &buffer[buffer_size - sizeof(struct mbr_table)]);
    if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) {
        // Setup default values for MBR
        table->signature[0] = 0x55;
        table->signature[1] = 0xaa;
        memset(table->entries, 0, sizeof(table->entries));
    }

    // Setup new partition
    MBED_ASSERT(part >= 1 && part <= 4);
    table->entries[part-1].status = 0x00; // inactive (not bootable)
    table->entries[part-1].type = type;

    // lba dimensions
    uint32_t sector = std::max<uint32_t>(bd->get_erase_size(), 512);
    uint32_t lba_offset = offset / sector;
    uint32_t lba_size = size / sector;
    table->entries[part-1].lba_offset = tole32(lba_offset);
    table->entries[part-1].lba_size = tole32(lba_size);

    // chs dimensions
    tochs(lba_offset,            table->entries[part-1].chs_start);
    tochs(lba_offset+lba_size-1, table->entries[part-1].chs_stop);

    // Write out MBR
    err = bd->erase(0, bd->get_erase_size());
    if (err) {
        delete[] buffer;
        return err;
    }

    err = bd->program(buffer, 512-buffer_size, buffer_size);
    delete[] buffer;
    return err;
}

int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type, bd_addr_t start)
{
    int err = bd->init();
    if (err) {
        return err;
    }

    // Calculate dimensions
    bd_size_t offset = ((int64_t)start < 0) ? -start : start;
    bd_size_t size = bd->size();

    if (offset < 512) {
        offset += std::max<uint32_t>(bd->get_erase_size(), 512);
    }

    size -= offset;

    err = partition_absolute(bd, part, type, offset, size);
    if (err) {
        return err;
    }

    err = bd->deinit();
    if (err) {
        return err;
    }

    return 0;
}

int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type,
        bd_addr_t start, bd_addr_t stop)
{
    int err = bd->init();
    if (err) {
        return err;
    }

    // Calculate dimensions
    bd_size_t offset = ((int64_t)start < 0) ? -start : start;
    bd_size_t size = ((int64_t)stop < 0) ? -stop : stop;

    if (offset < 512) {
        offset += std::max<uint32_t>(bd->get_erase_size(), 512);
    }

    size -= offset;

    err = partition_absolute(bd, part, type, offset, size);
    if (err) {
        return err;
    }

    err = bd->deinit();
    if (err) {
        return err;
    }

    return 0;
}

MBRBlockDevice::MBRBlockDevice(BlockDevice *bd, int part)
    : _bd(bd), _part(part)
{
    MBED_ASSERT(_part >= 1 && _part <= 4);
}

int MBRBlockDevice::init()
{
    int err = _bd->init();
    if (err) {
        return err;
    }

    // Allocate smallest buffer necessary to write MBR
    uint32_t buffer_size = std::max<uint32_t>(_bd->get_read_size(), sizeof(struct mbr_table));
    uint8_t *buffer = new uint8_t[buffer_size];

    err = _bd->read(buffer, 512-buffer_size, buffer_size);
    if (err) {
        delete[] buffer;
        return err;
    }

    // Check for valid table
    struct mbr_table *table = reinterpret_cast<struct mbr_table*>(
            &buffer[buffer_size - sizeof(struct mbr_table)]);
    if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) {
        delete[] buffer;
        return BD_ERROR_INVALID_MBR;
    }

    // Check for valid entry
    if (table->entries[_part-1].type == 0x00) {
        delete[] buffer;
        return BD_ERROR_INVALID_PARTITION;
    }

    // Get partition attributes
    bd_size_t sector = std::max<uint32_t>(_bd->get_erase_size(), 512);
    _type = table->entries[_part-1].type;
    _offset = fromle32(table->entries[_part-1].lba_offset) * sector;
    _size   = fromle32(table->entries[_part-1].lba_size)   * sector;

    // Check that block addresses are valid
    MBED_ASSERT(_bd->is_valid_erase(_offset, _size));

    delete[] buffer;
    return 0;
}

int MBRBlockDevice::deinit()
{
    return _bd->deinit();
}

int MBRBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{
    MBED_ASSERT(is_valid_read(addr, size));
    return _bd->read(b, addr + _offset, size);
}

int MBRBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{
    MBED_ASSERT(is_valid_program(addr, size));
    return _bd->program(b, addr + _offset, size);
}

int MBRBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
    MBED_ASSERT(is_valid_erase(addr, size));
    return _bd->erase(addr + _offset, size);
}

bd_size_t MBRBlockDevice::get_read_size() const
{
    return _bd->get_read_size();
}

bd_size_t MBRBlockDevice::get_program_size() const
{
    return _bd->get_program_size();
}

bd_size_t MBRBlockDevice::get_erase_size() const
{
    return _bd->get_erase_size();
}

bd_size_t MBRBlockDevice::size() const
{
    return _size;
}

bd_size_t MBRBlockDevice::get_partition_start() const
{
    return _offset;
}

bd_size_t MBRBlockDevice::get_partition_stop() const
{
    return _offset+_size;
}

uint8_t MBRBlockDevice::get_partition_type() const
{
    return _type;
}

int MBRBlockDevice::get_partition_number() const
{
    return _part;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iomanip>
#include <istream>
#include <sstream>
#include <iostream>
#include <string>

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <boost/spirit/include/classic_position_iterator.hpp>

#include "parser/SpiritParser.hpp"
#include "lexer/SpiritLexer.hpp"

#include "ast/Program.hpp"

namespace qi = boost::spirit::qi;

using namespace eddic;

template <typename Iterator, typename AttributeT>
struct Rule {
    typedef typename boost::spirit::qi::rule<Iterator, AttributeT> type;
};

template <typename Iterator, typename Lexer>
struct EddiGrammar : qi::grammar<Iterator, ast::Program()> {
    EddiGrammar(const Lexer& lexer) : EddiGrammar::base_type(program, "EDDI Grammar") {
        value = additiveValue.alias();

        additiveValue %=
                multiplicativeValue
            >>  *(
                    (lexer.addition > multiplicativeValue)
                |   (lexer.subtraction > multiplicativeValue)
                );

        multiplicativeValue %=
                unaryValue
            >>  *(
                    (lexer.multiplication > unaryValue)
                |   (lexer.division > unaryValue)
                |   (lexer.modulo > unaryValue)
                );

        //TODO Support + - primaryValue
        unaryValue = primaryValue.alias();

        primaryValue =
                constant
            |   variable
            |   (lexer.left_parenth >> value > lexer.right_parenth);

        integer %=
                qi::eps
            >>  lexer.integer;

        variable %=
                qi::eps
            >>  lexer.word;

        litteral %=
                qi::eps
            >> lexer.litteral;

        constant %=
                integer
            |   litteral;

        true_ %=
                qi::eps
            >>  lexer.true_;

        false_ %=
                qi::eps
            >>  lexer.false_;

        binary_condition %=
                value
            >>  (
                    lexer.greater_equals
                |   lexer.greater
                |   lexer.less_equals
                |   lexer.less
                |   lexer.not_equals
                |   lexer.equals
                )
            >>   value;

        condition %=
                true_
            |   false_
            |   binary_condition;

        else_if_ %=
                lexer.else_
            >>  lexer.if_
            >>  lexer.left_parenth
            >>  condition
            >>  lexer.right_parenth
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace;

        else_ %=
                lexer.else_
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace;

        if_ %=
                lexer.if_
            >>  lexer.left_parenth
            >>  condition
            >>  lexer.right_parenth
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace
            >>  *(else_if_)
            >>  -(else_);

        for_ %=
                lexer.for_
            >   lexer.left_parenth
            >   -declaration
            >   lexer.stop
            >   -condition
            >   lexer.stop
            >   -repeatable_instruction
            >   lexer.right_parenth
            >   lexer.left_brace
            >   (*instruction)
            >   lexer.right_brace;

        foreach_ =
                lexer.foreach_
            >   lexer.left_parenth
            >   lexer.word
            >   lexer.word
            >   lexer.from_
            >   lexer.integer
            >   lexer.to_
            >   lexer.integer
            >   lexer.right_parenth
            >   lexer.left_brace
            >   *(instruction)
            >   lexer.right_brace;

        while_ %=
                lexer.while_
            >   lexer.left_parenth
            >   condition
            >   lexer.right_parenth
            >   lexer.left_brace
            >   *(instruction)
            >   lexer.right_brace;

        declaration %=
                lexer.word
            >>  lexer.word
            >>  lexer.assign
            >>  value;

        assignment %=
                lexer.word
            >>  lexer.assign
            >>  value;

        globalDeclaration %=
                lexer.word
            >>  lexer.word
            >>  lexer.assign
            >>  constant
            >>  lexer.stop;

        functionCall %=
                lexer.word
            >>  lexer.left_parenth
            >>  -( value >> *( lexer.comma > value))
            >>  lexer.right_parenth;

        swap %=
                lexer.word
            >>  lexer.swap
            >>  lexer.word;

        instruction %=
                (functionCall > lexer.stop)
            |   (assignment > lexer.stop)
            |   (declaration > lexer.stop)
            |   if_
            |   for_
            |   while_
            |   foreach_
            |   (swap > lexer.stop);

        repeatable_instruction = assignment | declaration | swap;

        arg %=
                lexer.word
            >>  lexer.word;

        function %=
                lexer.word
            >>  lexer.word
            >>  lexer.left_parenth
            >>  -( arg >> *( lexer.comma > arg))
            >>  lexer.right_parenth
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace;

        program %=
                qi::eps
            >>  *(function | globalDeclaration);

        //Name the rules
        globalDeclaration.name("EDDI global variable");
        function.name("EDDI function declaration");
        program.name("EDDI program");
   }

   qi::rule<Iterator, ast::Program()> program;
   qi::rule<Iterator, ast::GlobalVariableDeclaration()> globalDeclaration;
   qi::rule<Iterator, ast::FunctionDeclaration()> function;
   qi::rule<Iterator, ast::FunctionParameter()> arg;

   qi::rule<Iterator, ast::Instruction()> instruction;
   qi::rule<Iterator, ast::Instruction()> repeatable_instruction;
   qi::rule<Iterator, ast::Swap()> swap;
   qi::rule<Iterator, ast::FunctionCall()> functionCall;
   qi::rule<Iterator, ast::Declaration()> declaration;
   qi::rule<Iterator, ast::Assignment()> assignment;
   qi::rule<Iterator, ast::While()> while_;
   qi::rule<Iterator, ast::For()> for_;
   qi::rule<Iterator, ast::Foreach()> foreach_;
   qi::rule<Iterator, ast::If()> if_;

   qi::rule<Iterator, ast::Else()> else_;
   qi::rule<Iterator, ast::ElseIf()> else_if_;

   qi::rule<Iterator, ast::Value()> value;
   qi::rule<Iterator, ast::Value()> primaryValue;
   qi::rule<Iterator, ast::Value()> unaryValue;
   qi::rule<Iterator, ast::ComposedValue()> additiveValue;
   qi::rule<Iterator, ast::ComposedValue()> multiplicativeValue;
   qi::rule<Iterator, ast::Value()> constant;
   qi::rule<Iterator, ast::Integer()> integer;
   qi::rule<Iterator, ast::Litteral()> litteral;
   qi::rule<Iterator, ast::VariableValue()> variable;

   qi::rule<Iterator, ast::Condition()> condition;
   qi::rule<Iterator, ast::True()> true_;
   qi::rule<Iterator, ast::False()> false_;
   qi::rule<Iterator, ast::BinaryCondition()> binary_condition;
};

bool SpiritParser::parse(const std::string& file, ast::Program& program){
    std::ifstream in(file.c_str());
    in.unsetf(std::ios::skipws);

    in.seekg(0, std::istream::end);
    std::size_t size(static_cast<size_t>(in.tellg()));

    in.seekg(0, std::istream::beg);

    std::string contents(size, 0);
    in.read(&contents[0], size);

    pos_iterator_type position_begin(contents.begin(), contents.end(), file);
    pos_iterator_type position_end;

    SimpleLexer<lexer_type> lexer;
    EddiGrammar<lexer_type::iterator_type, SimpleLexer<lexer_type>> grammar(lexer);

    try {
        bool r = lex::tokenize_and_parse(position_begin, position_end, lexer, grammar, program);

        if(r && position_begin == position_end) {
            return true;
        } else {
            std::cout << "Parsing failed" << std::endl;
            const spirit::classic::file_position_base<std::string>& pos = position_begin.get_position();
            std::cout <<
                "Error at file " << pos.file << " line " << pos.line << " column " << pos.column << std::endl <<
                "'" << position_begin.get_currentline() << "'" << std::endl <<
                std::setw(pos.column) << " " << "^- here";

            return false;
        }
    } catch (const qi::expectation_failure<lexer_type::iterator_type>& exception) {
        std::cout << "Parsing failed" << std::endl;

        //TODO Improve to get information from exception
        const spirit::classic::file_position_base<std::string>& pos = position_begin.get_position();

        std::cout <<
            "Error at file " << pos.file << " line " << pos.line << " column " << pos.column << " Expecting " << exception.what_ << std::endl <<
            "'" << position_begin.get_currentline() << "'" << std::endl <<
            std::setw(pos.column) << " " << "^- here" << std::endl;

        return false;
    }
}
<commit_msg>Enable global variables to have a default value<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iomanip>
#include <istream>
#include <sstream>
#include <iostream>
#include <string>

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <boost/spirit/include/classic_position_iterator.hpp>

#include "parser/SpiritParser.hpp"
#include "lexer/SpiritLexer.hpp"

#include "ast/Program.hpp"

namespace qi = boost::spirit::qi;

using namespace eddic;

template <typename Iterator, typename AttributeT>
struct Rule {
    typedef typename boost::spirit::qi::rule<Iterator, AttributeT> type;
};

template <typename Iterator, typename Lexer>
struct EddiGrammar : qi::grammar<Iterator, ast::Program()> {
    EddiGrammar(const Lexer& lexer) : EddiGrammar::base_type(program, "EDDI Grammar") {
        value = additiveValue.alias();

        additiveValue %=
                multiplicativeValue
            >>  *(
                    (lexer.addition > multiplicativeValue)
                |   (lexer.subtraction > multiplicativeValue)
                );

        multiplicativeValue %=
                unaryValue
            >>  *(
                    (lexer.multiplication > unaryValue)
                |   (lexer.division > unaryValue)
                |   (lexer.modulo > unaryValue)
                );

        //TODO Support + - primaryValue
        unaryValue = primaryValue.alias();

        primaryValue =
                constant
            |   variable
            |   (lexer.left_parenth >> value > lexer.right_parenth);

        integer %=
                qi::eps
            >>  lexer.integer;

        variable %=
                qi::eps
            >>  lexer.word;

        litteral %=
                qi::eps
            >> lexer.litteral;

        constant %=
                integer
            |   litteral;

        true_ %=
                qi::eps
            >>  lexer.true_;

        false_ %=
                qi::eps
            >>  lexer.false_;

        binary_condition %=
                value
            >>  (
                    lexer.greater_equals
                |   lexer.greater
                |   lexer.less_equals
                |   lexer.less
                |   lexer.not_equals
                |   lexer.equals
                )
            >>   value;

        condition %=
                true_
            |   false_
            |   binary_condition;

        else_if_ %=
                lexer.else_
            >>  lexer.if_
            >>  lexer.left_parenth
            >>  condition
            >>  lexer.right_parenth
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace;

        else_ %=
                lexer.else_
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace;

        if_ %=
                lexer.if_
            >>  lexer.left_parenth
            >>  condition
            >>  lexer.right_parenth
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace
            >>  *(else_if_)
            >>  -(else_);

        for_ %=
                lexer.for_
            >   lexer.left_parenth
            >   -declaration
            >   lexer.stop
            >   -condition
            >   lexer.stop
            >   -repeatable_instruction
            >   lexer.right_parenth
            >   lexer.left_brace
            >   (*instruction)
            >   lexer.right_brace;

        foreach_ =
                lexer.foreach_
            >   lexer.left_parenth
            >   lexer.word
            >   lexer.word
            >   lexer.from_
            >   lexer.integer
            >   lexer.to_
            >   lexer.integer
            >   lexer.right_parenth
            >   lexer.left_brace
            >   *(instruction)
            >   lexer.right_brace;

        while_ %=
                lexer.while_
            >   lexer.left_parenth
            >   condition
            >   lexer.right_parenth
            >   lexer.left_brace
            >   *(instruction)
            >   lexer.right_brace;

        declaration %=
                lexer.word
            >>  lexer.word
            >>  lexer.assign
            >>  value;

        assignment %=
                lexer.word
            >>  lexer.assign
            >>  value;

        globalDeclaration %=
                lexer.word
            >>  lexer.word
            >>  -(lexer.assign >> constant)
            >>  lexer.stop;

        functionCall %=
                lexer.word
            >>  lexer.left_parenth
            >>  -( value >> *( lexer.comma > value))
            >>  lexer.right_parenth;

        swap %=
                lexer.word
            >>  lexer.swap
            >>  lexer.word;

        instruction %=
                (functionCall > lexer.stop)
            |   (assignment > lexer.stop)
            |   (declaration > lexer.stop)
            |   if_
            |   for_
            |   while_
            |   foreach_
            |   (swap > lexer.stop);

        repeatable_instruction = assignment | declaration | swap;

        arg %=
                lexer.word
            >>  lexer.word;

        function %=
                lexer.word
            >>  lexer.word
            >>  lexer.left_parenth
            >>  -( arg >> *( lexer.comma > arg))
            >>  lexer.right_parenth
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace;

        program %=
                qi::eps
            >>  *(function | globalDeclaration);

        //Name the rules
        globalDeclaration.name("EDDI global variable");
        function.name("EDDI function declaration");
        program.name("EDDI program");
   }

   qi::rule<Iterator, ast::Program()> program;
   qi::rule<Iterator, ast::GlobalVariableDeclaration()> globalDeclaration;
   qi::rule<Iterator, ast::FunctionDeclaration()> function;
   qi::rule<Iterator, ast::FunctionParameter()> arg;

   qi::rule<Iterator, ast::Instruction()> instruction;
   qi::rule<Iterator, ast::Instruction()> repeatable_instruction;
   qi::rule<Iterator, ast::Swap()> swap;
   qi::rule<Iterator, ast::FunctionCall()> functionCall;
   qi::rule<Iterator, ast::Declaration()> declaration;
   qi::rule<Iterator, ast::Assignment()> assignment;
   qi::rule<Iterator, ast::While()> while_;
   qi::rule<Iterator, ast::For()> for_;
   qi::rule<Iterator, ast::Foreach()> foreach_;
   qi::rule<Iterator, ast::If()> if_;

   qi::rule<Iterator, ast::Else()> else_;
   qi::rule<Iterator, ast::ElseIf()> else_if_;

   qi::rule<Iterator, ast::Value()> value;
   qi::rule<Iterator, ast::Value()> primaryValue;
   qi::rule<Iterator, ast::Value()> unaryValue;
   qi::rule<Iterator, ast::ComposedValue()> additiveValue;
   qi::rule<Iterator, ast::ComposedValue()> multiplicativeValue;
   qi::rule<Iterator, ast::Value()> constant;
   qi::rule<Iterator, ast::Integer()> integer;
   qi::rule<Iterator, ast::Litteral()> litteral;
   qi::rule<Iterator, ast::VariableValue()> variable;

   qi::rule<Iterator, ast::Condition()> condition;
   qi::rule<Iterator, ast::True()> true_;
   qi::rule<Iterator, ast::False()> false_;
   qi::rule<Iterator, ast::BinaryCondition()> binary_condition;
};

bool SpiritParser::parse(const std::string& file, ast::Program& program){
    std::ifstream in(file.c_str());
    in.unsetf(std::ios::skipws);

    in.seekg(0, std::istream::end);
    std::size_t size(static_cast<size_t>(in.tellg()));

    in.seekg(0, std::istream::beg);

    std::string contents(size, 0);
    in.read(&contents[0], size);

    pos_iterator_type position_begin(contents.begin(), contents.end(), file);
    pos_iterator_type position_end;

    SimpleLexer<lexer_type> lexer;
    EddiGrammar<lexer_type::iterator_type, SimpleLexer<lexer_type>> grammar(lexer);

    try {
        bool r = lex::tokenize_and_parse(position_begin, position_end, lexer, grammar, program);

        if(r && position_begin == position_end) {
            return true;
        } else {
            std::cout << "Parsing failed" << std::endl;
            const spirit::classic::file_position_base<std::string>& pos = position_begin.get_position();
            std::cout <<
                "Error at file " << pos.file << " line " << pos.line << " column " << pos.column << std::endl <<
                "'" << position_begin.get_currentline() << "'" << std::endl <<
                std::setw(pos.column) << " " << "^- here";

            return false;
        }
    } catch (const qi::expectation_failure<lexer_type::iterator_type>& exception) {
        std::cout << "Parsing failed" << std::endl;

        //TODO Improve to get information from exception
        const spirit::classic::file_position_base<std::string>& pos = position_begin.get_position();

        std::cout <<
            "Error at file " << pos.file << " line " << pos.line << " column " << pos.column << " Expecting " << exception.what_ << std::endl <<
            "'" << position_begin.get_currentline() << "'" << std::endl <<
            std::setw(pos.column) << " " << "^- here" << std::endl;

        return false;
    }
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * Copyright (C) 2012
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#define __STDC_CONSTANT_MACROS 1

#include <vlc_common.h>
#include <vlc_network.h>

#include <ctime>

#include "helper.h"
#include "htsmessage.h"

sys_common_t::~sys_common_t()
{
	if(netfd >= 0)
		net_Close(netfd);
}

uint32_t HTSPNextSeqNum(sys_common_t *sys)
{
	uint32_t res = sys->nextSeqNum++;
	if(sys->nextSeqNum > 2147483647)
		sys->nextSeqNum = 1;
	return res;
}

bool TransmitMessageEx(vlc_object_t *obj, sys_common_t *sys, HtsMessage m)
{
	if(sys->netfd < 0)
	{
		msg_Dbg(obj, "Invalid netfd in TransmitMessage");
		return false;
	}

	void *buf;
	uint32_t len;

	if(!m.Serialize(&len, &buf))
	{
		msg_Dbg(obj, "Serialising message failed");
		return false;
	}

	if(net_Write(obj, sys->netfd, NULL, buf, len) != (ssize_t)len)
	{
		msg_Dbg(obj, "net_Write failed");
		return false;
	}

	free(buf);

	return true;
}

HtsMessage ReadMessageEx(vlc_object_t *obj, sys_common_t *sys)
{
	char *buf;
	uint32_t len;
	ssize_t readSize;

	if(sys->queue.size())
	{
		HtsMessage res = sys->queue.front();
		sys->queue.pop_front();
		return res;
	}

	time_t start = time(0);
	while((readSize = net_Read(obj, sys->netfd, NULL, &len, sizeof(len), false)) != sizeof(len))
	{
		if(readSize == 0)
		{
			msg_Err(obj, "Size Read EOF!");
			return HtsMessage();
		}

		if(readSize > 0)
		{
			msg_Err(obj, "Error reading from socket");
			return HtsMessage();
		}

		if(difftime(time(0), start) > READ_TIMEOUT)
		{
			msg_Err(obj, "Read timed out!");
			return HtsMessage();
		}
	}

	len = ntohl(len);
	if(len == 0)
		return HtsMessage();

	buf = (char*)malloc(len);

	char *wbuf = buf;
	uint32_t tlen = len;
	start = time(0);
	while((readSize = net_Read(obj, sys->netfd, NULL, wbuf, tlen, false)) < tlen)
	{
		wbuf += readSize;
		tlen -= readSize;

		if(difftime(time(0), start) > READ_TIMEOUT || readSize == 0)
		{
			if(readSize == 0)
				msg_Err(obj, "Read EOF!");
			else
				msg_Err(obj, "Read timed out!");
			free(buf);
			return HtsMessage();
		}

	}
	if(readSize > tlen)
	{
		msg_Dbg(obj, "WTF");
		free(buf);
		return HtsMessage();
	}

	HtsMessage result = HtsMessage::Deserialize(len, buf);
	free(buf);
	return result;
}

HtsMessage ReadResultEx(vlc_object_t *obj, sys_common_t *sys, HtsMessage m, bool sequence)
{
	uint32_t iSequence = 0;
	if(sequence)
	{
		iSequence = HTSPNextSeqNum(sys);
		m.getRoot()->setData("seq", iSequence);
	}

	if(!TransmitMessageEx(obj, sys, m))
	{
		msg_Err(obj, "TransmitMessage failed!");
		return HtsMessage();
	}

	std::deque<HtsMessage> queue;
	sys->queue.swap(queue);

	while((m = ReadMessageEx(obj, sys)).isValid())
	{
		if(!sequence)
			break;
		if(m.getRoot()->contains("seq") && m.getRoot()->getU32("seq") == iSequence)
			break;

		queue.push_back(m);
		if(queue.size() >= MAX_QUEUE_SIZE)
		{
			msg_Err(obj, "Max queue size reached!");
			sys->queue.swap(queue);
			return HtsMessage();
		}
	}

	sys->queue.swap(queue);

	if(!m.isValid())
	{
		msg_Err(obj, "ReadMessage failed!");
		return HtsMessage();
	}

	if(m.getRoot()->contains("error"))
	{
		msg_Err(obj, "HTSP Error: %s", m.getRoot()->getStr("error").c_str());
		return HtsMessage();
	}
	if(m.getRoot()->getU32("noaccess") != 0)
	{
		msg_Err(obj, "Access Denied");
		return HtsMessage();
	}

	return m;
}

bool ReadSuccessEx(vlc_object_t *obj, sys_common_t *sys, HtsMessage m, const std::string &action, bool sequence)
{
	if(!ReadResultEx(obj, sys, m, sequence).isValid())
	{
		msg_Err(obj, "ReadSuccess - failed to %s", action.c_str());
		return false;
	}
	return true;
}
<commit_msg>Let vlc handle all timing related stuff<commit_after>/*****************************************************************************
 * Copyright (C) 2012
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#define __STDC_CONSTANT_MACROS 1

#include <vlc_common.h>
#include <vlc_network.h>

#include <ctime>

#include "helper.h"
#include "htsmessage.h"

sys_common_t::~sys_common_t()
{
	if(netfd >= 0)
		net_Close(netfd);
}

uint32_t HTSPNextSeqNum(sys_common_t *sys)
{
	uint32_t res = sys->nextSeqNum++;
	if(sys->nextSeqNum > 2147483647)
		sys->nextSeqNum = 1;
	return res;
}

bool TransmitMessageEx(vlc_object_t *obj, sys_common_t *sys, HtsMessage m)
{
	if(sys->netfd < 0)
	{
		msg_Dbg(obj, "Invalid netfd in TransmitMessage");
		return false;
	}

	void *buf;
	uint32_t len;

	if(!m.Serialize(&len, &buf))
	{
		msg_Dbg(obj, "Serialising message failed");
		return false;
	}

	if(net_Write(obj, sys->netfd, NULL, buf, len) != (ssize_t)len)
	{
		msg_Dbg(obj, "net_Write failed");
		return false;
	}

	free(buf);

	return true;
}

HtsMessage ReadMessageEx(vlc_object_t *obj, sys_common_t *sys)
{
	char *buf;
	uint32_t len;
	ssize_t readSize;

	if(sys->queue.size())
	{
		HtsMessage res = sys->queue.front();
		sys->queue.pop_front();
		return res;
	}

	if((readSize = net_Read(obj, sys->netfd, NULL, &len, sizeof(len), true)) != sizeof(len))
	{
		if(readSize == 0)
		{
			msg_Err(obj, "Size Read EOF!");
			return HtsMessage();
		}

		msg_Err(obj, "Error reading size: %m");
		return HtsMessage();
	}

	len = ntohl(len);
	if(len == 0)
		return HtsMessage();

	buf = (char*)malloc(len);

	if((readSize = net_Read(obj, sys->netfd, NULL, buf, len, true)) != len)
	{
		if(readSize == 0)
		{
			msg_Err(obj, "Data Read EOF!");
			return HtsMessage();
		}

		msg_Err(obj, "Error reading data: %m");
		return HtsMessage();
	}

	HtsMessage result = HtsMessage::Deserialize(len, buf);
	free(buf);
	return result;
}

HtsMessage ReadResultEx(vlc_object_t *obj, sys_common_t *sys, HtsMessage m, bool sequence)
{
	uint32_t iSequence = 0;
	if(sequence)
	{
		iSequence = HTSPNextSeqNum(sys);
		m.getRoot()->setData("seq", iSequence);
	}

	if(!TransmitMessageEx(obj, sys, m))
	{
		msg_Err(obj, "TransmitMessage failed!");
		return HtsMessage();
	}

	std::deque<HtsMessage> queue;
	sys->queue.swap(queue);

	while((m = ReadMessageEx(obj, sys)).isValid())
	{
		if(!sequence)
			break;
		if(m.getRoot()->contains("seq") && m.getRoot()->getU32("seq") == iSequence)
			break;

		queue.push_back(m);
		if(queue.size() >= MAX_QUEUE_SIZE)
		{
			msg_Err(obj, "Max queue size reached!");
			sys->queue.swap(queue);
			return HtsMessage();
		}
	}

	sys->queue.swap(queue);

	if(!m.isValid())
	{
		msg_Err(obj, "ReadMessage failed!");
		return HtsMessage();
	}

	if(m.getRoot()->contains("error"))
	{
		msg_Err(obj, "HTSP Error: %s", m.getRoot()->getStr("error").c_str());
		return HtsMessage();
	}
	if(m.getRoot()->getU32("noaccess") != 0)
	{
		msg_Err(obj, "Access Denied");
		return HtsMessage();
	}

	return m;
}

bool ReadSuccessEx(vlc_object_t *obj, sys_common_t *sys, HtsMessage m, const std::string &action, bool sequence)
{
	if(!ReadResultEx(obj, sys, m, sequence).isValid())
	{
		msg_Err(obj, "ReadSuccess - failed to %s", action.c_str());
		return false;
	}
	return true;
}
<|endoftext|>


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

#include "QUECTEL_EC2X.h"

#include "PinNames.h"
#include "AT_CellularNetwork.h"
#include "rtos/ThisThread.h"

using namespace mbed;
using namespace rtos;
using namespace events;

static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = {
    AT_CellularNetwork::RegistrationModeLAC,    // C_EREG
    AT_CellularNetwork::RegistrationModeLAC,    // C_GREG
    AT_CellularNetwork::RegistrationModeLAC,    // C_REG
    1,  // AT_CGSN_WITH_TYPE
    1,  // AT_CGDATA
    0,  // AT_CGAUTH
    1,  // AT_CNMI
    1,  // AT_CSMP
    1,  // AT_CMGF
    1,  // AT_CSDH
    1,  // PROPERTY_IPV4_STACK
    1,  // PROPERTY_IPV6_STACK
    1,  // PROPERTY_IPV4V6_STACK
    0,  // PROPERTY_NON_IP_PDP_TYPE
    1,  // PROPERTY_AT_CGEREP
};

QUECTEL_EC2X::QUECTEL_EC2X(FileHandle *fh, PinName pwr, PinName rst)
    : AT_CellularDevice(fh),
      _pwr_key(pwr, 0),
      _rst(rst, 0)

{
    AT_CellularBase::set_cellular_properties(cellular_properties);
}

#if MBED_CONF_QUECTEL_EC2X_PROVIDE_DEFAULT
#include "UARTSerial.h"
CellularDevice *CellularDevice::get_default_instance()
{
    static UARTSerial serial(MBED_CONF_QUECTEL_EC2X_TX,
                             MBED_CONF_QUECTEL_EC2X_RX,
                             MBED_CONF_QUECTEL_EC2X_BAUDRATE);
#if defined(MBED_CONF_QUECTEL_EC2X_RTS) && defined(MBED_CONF_QUECTEL_EC2X_CTS)
    serial.set_flow_control(SerialBase::RTSCTS, MBED_CONF_QUECTEL_EC2X_RTS, MBED_CONF_QUECTEL_EC2X_CTS);
#endif
    static QUECTEL_EC2X device(&serial, MBED_CONF_QUECTEL_EC2X_PWR, MBED_CONF_QUECTEL_EC2X_RST);
    return &device;
}

nsapi_error_t QUECTEL_EC2X::hard_power_on()
{
    if (_pwr_key.is_connected()) {
        _pwr_key = 1;
        ThisThread::sleep_for(600);
        _pwr_key = 0;
        ThisThread::sleep_for(100);
    }

    return NSAPI_ERROR_OK;
}

nsapi_error_t QUECTEL_EC2X::hard_power_off()

{
    if (_pwr_key.is_connected()) {
        _pwr_key = 1;
        ThisThread::sleep_for(750);
        _pwr_key = 0;
        ThisThread::sleep_for(100);
    }

    return NSAPI_ERROR_OK;
}

nsapi_error_t QUECTEL_EC2X::soft_power_on()
{
    if (_rst.is_connected()) {
        _rst = 1;
        ThisThread::sleep_for(460);
        _rst = 0;
        ThisThread::sleep_for(100);
    }

    _at->lock();

    _at->set_at_timeout(5000);
    _at->resp_start();
    _at->set_stop_tag("RDY");
    bool rdy = _at->consume_to_stop_tag();
    _at->set_stop_tag(OK);

    _at->unlock();

    if (!rdy) {
        return NSAPI_ERROR_DEVICE_ERROR;
    }

    return NSAPI_ERROR_OK;
}

nsapi_error_t QUECTEL_EC2X::soft_power_off()
{
    if (_pwr_key.is_connected()) {
        _pwr_key = 1;
        ThisThread::sleep_for(750);
        _pwr_key = 0;
        ThisThread::sleep_for(100);
    }

    return NSAPI_ERROR_OK;
}

#endif
<commit_msg>AT+CGSN with EC2X does not take parameter<commit_after>/*
 * Copyright (c) 2019, Arm Limited and affiliates.
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "QUECTEL_EC2X.h"

#include "PinNames.h"
#include "AT_CellularNetwork.h"
#include "rtos/ThisThread.h"

using namespace mbed;
using namespace rtos;
using namespace events;

static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = {
    AT_CellularNetwork::RegistrationModeLAC,    // C_EREG
    AT_CellularNetwork::RegistrationModeLAC,    // C_GREG
    AT_CellularNetwork::RegistrationModeLAC,    // C_REG
    0,  // AT_CGSN_WITH_TYPE
    1,  // AT_CGDATA
    0,  // AT_CGAUTH
    1,  // AT_CNMI
    1,  // AT_CSMP
    1,  // AT_CMGF
    1,  // AT_CSDH
    1,  // PROPERTY_IPV4_STACK
    1,  // PROPERTY_IPV6_STACK
    1,  // PROPERTY_IPV4V6_STACK
    0,  // PROPERTY_NON_IP_PDP_TYPE
    1,  // PROPERTY_AT_CGEREP
};

QUECTEL_EC2X::QUECTEL_EC2X(FileHandle *fh, PinName pwr, PinName rst)
    : AT_CellularDevice(fh),
      _pwr_key(pwr, 0),
      _rst(rst, 0)

{
    AT_CellularBase::set_cellular_properties(cellular_properties);
}

#if MBED_CONF_QUECTEL_EC2X_PROVIDE_DEFAULT
#include "UARTSerial.h"
CellularDevice *CellularDevice::get_default_instance()
{
    static UARTSerial serial(MBED_CONF_QUECTEL_EC2X_TX,
                             MBED_CONF_QUECTEL_EC2X_RX,
                             MBED_CONF_QUECTEL_EC2X_BAUDRATE);
#if defined(MBED_CONF_QUECTEL_EC2X_RTS) && defined(MBED_CONF_QUECTEL_EC2X_CTS)
    serial.set_flow_control(SerialBase::RTSCTS, MBED_CONF_QUECTEL_EC2X_RTS, MBED_CONF_QUECTEL_EC2X_CTS);
#endif
    static QUECTEL_EC2X device(&serial, MBED_CONF_QUECTEL_EC2X_PWR, MBED_CONF_QUECTEL_EC2X_RST);
    return &device;
}

nsapi_error_t QUECTEL_EC2X::hard_power_on()
{
    if (_pwr_key.is_connected()) {
        _pwr_key = 1;
        ThisThread::sleep_for(600);
        _pwr_key = 0;
        ThisThread::sleep_for(100);
    }

    return NSAPI_ERROR_OK;
}

nsapi_error_t QUECTEL_EC2X::hard_power_off()

{
    if (_pwr_key.is_connected()) {
        _pwr_key = 1;
        ThisThread::sleep_for(750);
        _pwr_key = 0;
        ThisThread::sleep_for(100);
    }

    return NSAPI_ERROR_OK;
}

nsapi_error_t QUECTEL_EC2X::soft_power_on()
{
    if (_rst.is_connected()) {
        _rst = 1;
        ThisThread::sleep_for(460);
        _rst = 0;
        ThisThread::sleep_for(100);
    }

    _at->lock();

    _at->set_at_timeout(5000);
    _at->resp_start();
    _at->set_stop_tag("RDY");
    bool rdy = _at->consume_to_stop_tag();
    _at->set_stop_tag(OK);

    _at->unlock();

    if (!rdy) {
        return NSAPI_ERROR_DEVICE_ERROR;
    }

    return NSAPI_ERROR_OK;
}

nsapi_error_t QUECTEL_EC2X::soft_power_off()
{
    if (_pwr_key.is_connected()) {
        _pwr_key = 1;
        ThisThread::sleep_for(750);
        _pwr_key = 0;
        ThisThread::sleep_for(100);
    }

    return NSAPI_ERROR_OK;
}

#endif
<|endoftext|>


<commit_before>#include "server.hh"
#include "serializable.hh"
#include "networkEvents.hh"
#include "../logger.hh"

#include <atomic>
#include <memory>
#include <sstream>

using namespace std;

static atomic<unsigned int> clientIdCounter( 0 ); // Should be good enough.

Client::Client( tcp::socket socket ) : m_socket( move( socket ) )
{
	m_clientId = ++clientIdCounter;
	memset( m_data, 0, maxLength );
}

void Client::SetRead()
{
	auto self( shared_from_this() );
	m_socket.async_read_some(
		asio::buffer( m_data, maxLength ),
		[this, self]( boost::system::error_code ec, size_t length )
		{
			char buffer[USHRT_MAX];

			// Check for errors
			if( ec.value() )
			{
				LOG_ERROR( "Client::Read() got error " << ec.value() << ": '" << ec.message() << "'" );

				auto partEvent      = new PartEvent();
				partEvent->type     = NETWORK_EVENT;
				partEvent->subType  = NETWORK_PART;
				partEvent->clientId = 0;
				eventQueue->AddEvent( partEvent );

				m_socket.close();
				return;
			}

			// Apped the received data to the readStream
			readStream.write( m_data, length );

			// Read more if we don't have enough data even
			// for the header alone
			size_t streamLength = readStream.str().length();
			if( streamLength < sizeof( unsigned short ) )
			{
				SetRead();
				return;
			}

			// Read the package byte count
			size_t packetLength = UnserializeUint16( readStream );

			// Reverse the reading point back and
			// wait for more data if we don't have enough
			if( streamLength < packetLength )
			{
				long pos = static_cast<long>( readStream.tellg() );
				readStream.seekg( pos - sizeof( unsigned short ) );
				SetRead();
				return;
			}

			// We got all the data for the package!
			readStream.read( buffer, packetLength-2 );
			stringstream packetStream(
				stringstream::in |
				stringstream::out |
				stringstream::binary
			);
			packetStream.write( buffer, packetLength-2 );

			// Create the event
			auto dataInEvent      = new DataInEvent();
			dataInEvent->type     = NETWORK_EVENT;
			dataInEvent->subType  = NETWORK_DATA_IN;
			dataInEvent->clientId = m_clientId;
			dataInEvent->data     = packetStream.str();
			eventQueue->AddEvent( dataInEvent );

			// Set this as a callback again
			SetRead();
		});
}

void Client::Write( string msg )
{
	lock_guard<mutex> writeLock( writeMutex );

	boost::asio::streambuf request;
	ostream requestStream( &request );

	unsigned short msgLength = msg.length() + 2;
	requestStream.write( reinterpret_cast<char*>( &msgLength ), 2 );

    requestStream << msg;

	boost::asio::write( m_socket, request );
}

Server::Server()
{
	m_port     = 22001;
	m_socket   = nullptr;
	m_acceptor = nullptr;
}

Server::Server( asio::io_service& ioService, short port )
{
	Init( ioService, port );
}

Server::~Server()
{
}

void Server::Init( asio::io_service& ioService, short port )
{
	m_port     = port;
	m_socket   = new asio::ip::tcp::socket( ioService );
	m_acceptor = new asio::ip::tcp::acceptor(
		ioService,
		tcp::endpoint( tcp::v4(), port )
	);
}

void Server::Accept()
{
	if( !m_acceptor || !m_socket )
	{
		LOG_ERROR( "Server::Accept() Error: Server is uninitialized!" );
	}

	m_acceptor->async_accept(
		*m_socket,
		[this]( boost::system::error_code ec )
		{
			if( !ec )
			{
				auto client = make_shared<Client>( move( *m_socket ) );
				client->SetEventQueue( eventQueue );
				client->SetRead();
				clientListMutex.lock();
				clientList[client->m_clientId] = client;
				clientListMutex.unlock();

				auto joinEvent      = new JoinEvent();
				joinEvent->type     = NETWORK_EVENT;
				joinEvent->subType  = NETWORK_JOIN;
				joinEvent->clientId = client->m_clientId;
				eventQueue->AddEvent( joinEvent );
			}

			Accept();
		});
}

std::shared_ptr<Client> Server::GetClient( unsigned int id )
{
	lock_guard<mutex> clientListLock( clientListMutex );
	return clientList[id];
}

<commit_msg>Oops, surely we want to know who disconnected.<commit_after>#include "server.hh"
#include "serializable.hh"
#include "networkEvents.hh"
#include "../logger.hh"

#include <atomic>
#include <memory>
#include <sstream>

using namespace std;

static atomic<unsigned int> clientIdCounter( 0 ); // Should be good enough.

Client::Client( tcp::socket socket ) : m_socket( move( socket ) )
{
	m_clientId = ++clientIdCounter;
	memset( m_data, 0, maxLength );
}

void Client::SetRead()
{
	auto self( shared_from_this() );
	m_socket.async_read_some(
		asio::buffer( m_data, maxLength ),
		[this, self]( boost::system::error_code ec, size_t length )
		{
			char buffer[USHRT_MAX];

			// Check for errors
			if( ec.value() )
			{
				LOG_ERROR( "Client::Read() got error " << ec.value() << ": '" << ec.message() << "'" );

				auto partEvent      = new PartEvent();
				partEvent->type     = NETWORK_EVENT;
				partEvent->subType  = NETWORK_PART;
				partEvent->clientId = m_clientId;
				eventQueue->AddEvent( partEvent );

				m_socket.close();
				return;
			}

			// Apped the received data to the readStream
			readStream.write( m_data, length );

			// Read more if we don't have enough data even
			// for the header alone
			size_t streamLength = readStream.str().length();
			if( streamLength < sizeof( unsigned short ) )
			{
				SetRead();
				return;
			}

			// Read the package byte count
			size_t packetLength = UnserializeUint16( readStream );

			// Reverse the reading point back and
			// wait for more data if we don't have enough
			if( streamLength < packetLength )
			{
				long pos = static_cast<long>( readStream.tellg() );
				readStream.seekg( pos - sizeof( unsigned short ) );
				SetRead();
				return;
			}

			// We got all the data for the package!
			readStream.read( buffer, packetLength-2 );
			stringstream packetStream(
				stringstream::in |
				stringstream::out |
				stringstream::binary
			);
			packetStream.write( buffer, packetLength-2 );

			// Create the event
			auto dataInEvent      = new DataInEvent();
			dataInEvent->type     = NETWORK_EVENT;
			dataInEvent->subType  = NETWORK_DATA_IN;
			dataInEvent->clientId = m_clientId;
			dataInEvent->data     = packetStream.str();
			eventQueue->AddEvent( dataInEvent );

			// Set this as a callback again
			SetRead();
		});
}

void Client::Write( string msg )
{
	lock_guard<mutex> writeLock( writeMutex );

	boost::asio::streambuf request;
	ostream requestStream( &request );

	unsigned short msgLength = msg.length() + 2;
	requestStream.write( reinterpret_cast<char*>( &msgLength ), 2 );

    requestStream << msg;

	boost::asio::write( m_socket, request );
}

Server::Server()
{
	m_port     = 22001;
	m_socket   = nullptr;
	m_acceptor = nullptr;
}

Server::Server( asio::io_service& ioService, short port )
{
	Init( ioService, port );
}

Server::~Server()
{
}

void Server::Init( asio::io_service& ioService, short port )
{
	m_port     = port;
	m_socket   = new asio::ip::tcp::socket( ioService );
	m_acceptor = new asio::ip::tcp::acceptor(
		ioService,
		tcp::endpoint( tcp::v4(), port )
	);
}

void Server::Accept()
{
	if( !m_acceptor || !m_socket )
	{
		LOG_ERROR( "Server::Accept() Error: Server is uninitialized!" );
	}

	m_acceptor->async_accept(
		*m_socket,
		[this]( boost::system::error_code ec )
		{
			if( !ec )
			{
				auto client = make_shared<Client>( move( *m_socket ) );
				client->SetEventQueue( eventQueue );
				client->SetRead();
				clientListMutex.lock();
				clientList[client->m_clientId] = client;
				clientListMutex.unlock();

				auto joinEvent      = new JoinEvent();
				joinEvent->type     = NETWORK_EVENT;
				joinEvent->subType  = NETWORK_JOIN;
				joinEvent->clientId = client->m_clientId;
				eventQueue->AddEvent( joinEvent );
			}

			Accept();
		});
}

std::shared_ptr<Client> Server::GetClient( unsigned int id )
{
	lock_guard<mutex> clientListLock( clientListMutex );
	return clientList[id];
}

<|endoftext|>


<commit_before>#include <qapplication.h>
#include <qlayout.h>
#include <qwt_plot.h>
#include <qwt_plot_marker.h>
#include <qwt_plot_curve.h>
#include <qwt_legend.h>
#include <qwt_point_data.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_panner.h>
#include <qwt_plot_magnifier.h>
#include <qwt_text.h>
#include <qwt_math.h>
#include <math.h>

//-----------------------------------------------------------------
//              simple.cpp
//
//      A simple example which shows how to use QwtPlot connected
//      to a data class without any storage, calculating each values
//      on the fly.
//-----------------------------------------------------------------

class FunctionData: public QwtSyntheticPointData
{
public:
    FunctionData( double( *y )( double ) ):
        QwtSyntheticPointData( 100 ),
        d_y( y )
    {
    }

    virtual double y( double x ) const
    {
        return d_y( x );
    }

private:
    double( *d_y )( double );
};

class Plot : public QwtPlot
{
public:
    Plot( QWidget *parent = NULL );

protected:
    virtual void resizeEvent( QResizeEvent * );

private:
    void populate();
    void updateGradient();
};

Plot::Plot( QWidget *parent ):
    QwtPlot( parent )
{
    // panning with the left mouse button
    ( void ) new QwtPlotPanner( canvas() );

    // zoom in/out with the wheel
    ( void ) new QwtPlotMagnifier( canvas() );

    setAutoFillBackground( true );
    setPalette( QPalette( QColor( 165, 193, 228 ) ) );
    updateGradient();

    setTitle( "A Simple QwtPlot Demonstration" );
    insertLegend( new QwtLegend(), QwtPlot::RightLegend );

    // axes
    setAxisTitle( xBottom, "x -->" );
    setAxisScale( xBottom, 0.0, 10.0 );

    setAxisTitle( yLeft, "y -->" );
    setAxisScale( yLeft, -1.0, 1.0 );

    // canvas
    canvas()->setLineWidth( 1 );
    canvas()->setFrameStyle( QFrame::Box | QFrame::Plain );
    canvas()->setBorderRadius( 15 );

    QPalette canvasPalette( Qt::white );
    canvasPalette.setColor( QPalette::Foreground, QColor( 133, 190, 232 ) );
    canvas()->setPalette( canvasPalette );

    populate();
}

void Plot::populate()
{
    // Insert new curves
    QwtPlotCurve *cSin = new QwtPlotCurve( "y = sin(x)" );
    cSin->setRenderHint( QwtPlotItem::RenderAntialiased );
    cSin->setLegendAttribute( QwtPlotCurve::LegendShowLine, true );
    cSin->setPen( QPen( Qt::red ) );
    cSin->attach( this );

    QwtPlotCurve *cCos = new QwtPlotCurve( "y = cos(x)" );
    cCos->setRenderHint( QwtPlotItem::RenderAntialiased );
    cCos->setLegendAttribute( QwtPlotCurve::LegendShowLine, true );
    cCos->setPen( QPen( Qt::blue ) );
    cCos->attach( this );

    // Create sin and cos data
    cSin->setData( new FunctionData( ::sin ) );
    cCos->setData( new FunctionData( ::cos ) );

    // Insert markers

    //  ...a horizontal line at y = 0...
    QwtPlotMarker *mY = new QwtPlotMarker();
    mY->setLabel( QString::fromLatin1( "y = 0" ) );
    mY->setLabelAlignment( Qt::AlignRight | Qt::AlignTop );
    mY->setLineStyle( QwtPlotMarker::HLine );
    mY->setYValue( 0.0 );
    mY->attach( this );

    //  ...a vertical line at x = 2 * pi
    QwtPlotMarker *mX = new QwtPlotMarker();
    mX->setLabel( QString::fromLatin1( "x = 2 pi" ) );
    mX->setLabelAlignment( Qt::AlignLeft | Qt::AlignBottom );
    mX->setLabelOrientation( Qt::Vertical );
    mX->setLineStyle( QwtPlotMarker::VLine );
    mX->setLinePen( QPen( Qt::black, 0, Qt::DashDotLine ) );
    mX->setXValue( 2.0 * M_PI );
    mX->attach( this );
}

void Plot::updateGradient()
{
    QPalette pal = palette();

    const QColor buttonColor = pal.color( QPalette::Button );

#ifdef Q_WS_X11
    // Qt 4.7.1: QGradient::StretchToDeviceMode is buggy on X11

    QLinearGradient gradient( rect().topLeft(), rect().bottomLeft() );
    gradient.setColorAt( 0.0, Qt::white );
    gradient.setColorAt( 0.7, buttonColor );
    gradient.setColorAt( 1.0, buttonColor );
#else
    QLinearGradient gradient( 0, 0, 0, 1 );
    gradient.setCoordinateMode( QGradient::StretchToDeviceMode );
    gradient.setColorAt( 0.0, Qt::white );
    gradient.setColorAt( 0.7, buttonColor );
    gradient.setColorAt( 1.0, buttonColor );
#endif

    pal.setBrush( QPalette::Window, gradient );
    setPalette( pal );
}

void Plot::resizeEvent( QResizeEvent *event )
{
    QwtPlot::resizeEvent( event );
#ifdef Q_WS_X11
    updateGradient();
#endif
}

int main( int argc, char **argv )
{
    QApplication a( argc, argv );

    Plot *plot = new Plot();

    // We put a dummy widget around to have
    // so that Qt paints a widget background
    // when resizing

    QWidget window;
    QHBoxLayout *layout = new QHBoxLayout( &window );
    layout->setContentsMargins( 0, 0, 0, 0 );
    layout->addWidget( plot );

    window.resize( 600, 400 );
    window.show();

    return a.exec();
}
<commit_msg>Arrow symbol added <commit_after>#include <qapplication.h>
#include <qlayout.h>
#include <qwt_plot.h>
#include <qwt_plot_marker.h>
#include <qwt_plot_curve.h>
#include <qwt_legend.h>
#include <qwt_point_data.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_panner.h>
#include <qwt_plot_magnifier.h>
#include <qwt_text.h>
#include <qwt_symbol.h>
#include <qwt_math.h>
#include <math.h>

//-----------------------------------------------------------------
//              simple.cpp
//
//      A simple example which shows how to use QwtPlot connected
//      to a data class without any storage, calculating each values
//      on the fly.
//-----------------------------------------------------------------

class FunctionData: public QwtSyntheticPointData
{
public:
    FunctionData( double( *y )( double ) ):
        QwtSyntheticPointData( 100 ),
        d_y( y )
    {
    }

    virtual double y( double x ) const
    {
        return d_y( x );
    }

private:
    double( *d_y )( double );
};

class ArrowSymbol: public QwtSymbol
{
public:
    ArrowSymbol()
    {
        QPen pen( Qt::black, 0 );
        pen.setJoinStyle( Qt::MiterJoin );

        setPen( pen );
        setBrush( Qt::red );

        QPainterPath path;
        path.moveTo( 0, 8 );
        path.lineTo( 0, 5 );
        path.lineTo( -3, 5 );
        path.lineTo( 0, 0 );
        path.lineTo( 3, 5 );
        path.lineTo( 0, 5 );

        QTransform transform;
        transform.rotate( -30.0 );
        path = transform.map( path );

        setPath( path );

        setSize( 10, 14 );
    }
};

class Plot : public QwtPlot
{
public:
    Plot( QWidget *parent = NULL );

protected:
    virtual void resizeEvent( QResizeEvent * );

private:
    void populate();
    void updateGradient();
};

Plot::Plot( QWidget *parent ):
    QwtPlot( parent )
{
    // panning with the left mouse button
    ( void ) new QwtPlotPanner( canvas() );

    // zoom in/out with the wheel
    ( void ) new QwtPlotMagnifier( canvas() );

    setAutoFillBackground( true );
    setPalette( QPalette( QColor( 165, 193, 228 ) ) );
    updateGradient();

    setTitle( "A Simple QwtPlot Demonstration" );
    insertLegend( new QwtLegend(), QwtPlot::RightLegend );

    // axes
    setAxisTitle( xBottom, "x -->" );
    setAxisScale( xBottom, 0.0, 10.0 );

    setAxisTitle( yLeft, "y -->" );
    setAxisScale( yLeft, -1.0, 1.0 );

    // canvas
    canvas()->setLineWidth( 1 );
    canvas()->setFrameStyle( QFrame::Box | QFrame::Plain );
    canvas()->setBorderRadius( 15 );

    QPalette canvasPalette( Qt::white );
    canvasPalette.setColor( QPalette::Foreground, QColor( 133, 190, 232 ) );
    canvas()->setPalette( canvasPalette );

    populate();
}

void Plot::populate()
{
    // Insert new curves
    QwtPlotCurve *cSin = new QwtPlotCurve( "y = sin(x)" );
    cSin->setRenderHint( QwtPlotItem::RenderAntialiased );
    cSin->setLegendAttribute( QwtPlotCurve::LegendShowLine, true );
    cSin->setPen( QPen( Qt::red ) );
    cSin->attach( this );

    QwtPlotCurve *cCos = new QwtPlotCurve( "y = cos(x)" );
    cCos->setRenderHint( QwtPlotItem::RenderAntialiased );
    cCos->setLegendAttribute( QwtPlotCurve::LegendShowLine, true );
    cCos->setPen( QPen( Qt::blue ) );
    cCos->attach( this );

    // Create sin and cos data
    cSin->setData( new FunctionData( ::sin ) );
    cCos->setData( new FunctionData( ::cos ) );

    // Insert markers

    //  ...a horizontal line at y = 0...
    QwtPlotMarker *mY = new QwtPlotMarker();
    mY->setLabel( QString::fromLatin1( "y = 0" ) );
    mY->setLabelAlignment( Qt::AlignRight | Qt::AlignTop );
    mY->setLineStyle( QwtPlotMarker::HLine );
    mY->setYValue( 0.0 );
    mY->attach( this );

    //  ...a vertical line at x = 2 * pi
    QwtPlotMarker *mX = new QwtPlotMarker();
    mX->setLabel( QString::fromLatin1( "x = 2 pi" ) );
    mX->setLabelAlignment( Qt::AlignLeft | Qt::AlignBottom );
    mX->setLabelOrientation( Qt::Vertical );
    mX->setLineStyle( QwtPlotMarker::VLine );
    mX->setLinePen( QPen( Qt::black, 0, Qt::DashDotLine ) );
    mX->setXValue( 2.0 * M_PI );
    mX->attach( this );

    const double x = 7.7;

    // an arrow at a specific position
    QwtPlotMarker *mPos = new QwtPlotMarker();
    mPos->setRenderHint( QwtPlotItem::RenderAntialiased, true );
    mPos->setSymbol( new ArrowSymbol() );
    mPos->setValue( QPointF( x, ::sin( x ) ) );
    mPos->setLabel(
        QString( "( %1,%2 )" ).arg( x ).arg( ::sin( x ) ) );
    mPos->setLabelAlignment( Qt::AlignRight | Qt::AlignBottom );
    mPos->attach( this );
}

void Plot::updateGradient()
{
    QPalette pal = palette();

    const QColor buttonColor = pal.color( QPalette::Button );

#ifdef Q_WS_X11
    // Qt 4.7.1: QGradient::StretchToDeviceMode is buggy on X11

    QLinearGradient gradient( rect().topLeft(), rect().bottomLeft() );
    gradient.setColorAt( 0.0, Qt::white );
    gradient.setColorAt( 0.7, buttonColor );
    gradient.setColorAt( 1.0, buttonColor );
#else
    QLinearGradient gradient( 0, 0, 0, 1 );
    gradient.setCoordinateMode( QGradient::StretchToDeviceMode );
    gradient.setColorAt( 0.0, Qt::white );
    gradient.setColorAt( 0.7, buttonColor );
    gradient.setColorAt( 1.0, buttonColor );
#endif

    pal.setBrush( QPalette::Window, gradient );
    setPalette( pal );
}

void Plot::resizeEvent( QResizeEvent *event )
{
    QwtPlot::resizeEvent( event );
#ifdef Q_WS_X11
    updateGradient();
#endif
}

int main( int argc, char **argv )
{
    QApplication a( argc, argv );

    Plot *plot = new Plot();

    // We put a dummy widget around to have
    // so that Qt paints a widget background
    // when resizing

    QWidget window;
    QHBoxLayout *layout = new QHBoxLayout( &window );
    layout->setContentsMargins( 0, 0, 0, 0 );
    layout->addWidget( plot );

    window.resize( 600, 400 );
    window.show();

    return a.exec();
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// drop_plan.cpp
//
// Identification: src/planner/drop_plan.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "planner/update_plan.h"

#include "planner/project_info.h"
#include "common/types.h"

#include "storage/data_table.h"
#include "catalog/bootstrapper.h"
#include "parser/statement_update.h"
#include "parser/table_ref.h"

namespace peloton {
namespace planner {

UpdatePlan::UpdatePlan(storage::DataTable *table,
		std::unique_ptr<const planner::ProjectInfo> project_info) :
		target_table_(table), project_info_(std::move(project_info)), updates(
				NULL), where(NULL) {
}

UpdatePlan::UpdatePlan(parser::UpdateStatement *parse_tree) {
	auto t_ref = parse_tree->table;
	table_name = std::string(t_ref->name);
	target_table_ = catalog::Bootstrapper::global_catalog->GetTableFromDatabase(
			DEFAULT_DB_NAME, table_name);

	updates = new std::vector<parser::UpdateClause*>();
	for(auto update : *parse_tree->updates) {
		updates->emplace_back(update->Copy());
	}

	TargetList tlist;
	DirectMapList dmlist;
	oid_t col_id;
	auto schema = target_table_->GetSchema();

	std::vector<oid_t> columns;
	for (auto update : *updates) {

		// get oid_t of the column and push it to the vector;
		col_id = schema->GetColumnID(std::string(update->column));

		LOG_INFO("This is the column ID -------------------------> %d" , col_id);

		columns.push_back(col_id);
		tlist.emplace_back(col_id, update->value);
	}

	for (uint i = 0; i < schema->GetColumns().size(); i++) {
		if(schema->GetColumns()[i].column_name != schema->GetColumns()[col_id].column_name)
		dmlist.emplace_back(i,
				std::pair<oid_t, oid_t>(0, i));
	}

	std::unique_ptr<const planner::ProjectInfo> project_info(
			new planner::ProjectInfo(std::move(tlist), std::move(dmlist)));
	project_info_ = std::move(project_info);

	auto expr = parse_tree->where->Copy();
	ReplaceColumnExpressions(expr);

	std::unique_ptr<planner::SeqScanPlan> seq_scan_node(
			new planner::SeqScanPlan(target_table_, expr, columns));
	AddChild(std::move(seq_scan_node));
}

void UpdatePlan::ReplaceColumnExpressions(expression::AbstractExpression* expression) {
  LOG_INFO("Expression Type --> %s", ExpressionTypeToString(expression->GetExpressionType()).c_str());
  LOG_INFO("Left Type --> %s", ExpressionTypeToString(expression->GetLeft()->GetExpressionType()).c_str());
  LOG_INFO("Right Type --> %s", ExpressionTypeToString(expression->GetRight()->GetExpressionType()).c_str());
  if(expression->GetLeft()->GetExpressionType() == EXPRESSION_TYPE_COLUMN_REF) {
    auto expr = expression->GetLeft();
    std::string col_name(expr->getName());
    LOG_INFO("Column name: %s", col_name.c_str());
    delete expr;
    expression->setLeft(ConvertToTupleValueExpression(col_name));
  }
  else if (expression->GetRight()->GetExpressionType() == EXPRESSION_TYPE_COLUMN_REF) {
    auto expr = expression->GetRight();
    std::string col_name(expr->getName());
    LOG_INFO("Column name: %s", col_name.c_str());
    delete expr;
    expression->setRight(ConvertToTupleValueExpression(col_name));
  }
  else {
	  ReplaceColumnExpressions(expression->GetModifiableLeft());
	  ReplaceColumnExpressions(expression->GetModifiableRight());

  }
}
/**
 * This function generates a TupleValue expression from the column name
 */
expression::AbstractExpression* UpdatePlan::ConvertToTupleValueExpression (std::string column_name) {
	auto schema = target_table_->GetSchema();
    auto column_id = schema->GetColumnID(column_name);
    LOG_INFO("Column id in table: %u", column_id);
    expression::TupleValueExpression *expr =
        new expression::TupleValueExpression(schema->GetType(column_id), 0, column_id);
	return expr;
}

}  // namespace planner
}  // namespace peloton
<commit_msg>update_plan<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// drop_plan.cpp
//
// Identification: src/planner/drop_plan.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "planner/update_plan.h"

#include "planner/project_info.h"
#include "common/types.h"

#include "storage/data_table.h"
#include "catalog/bootstrapper.h"
#include "parser/statement_update.h"
#include "parser/table_ref.h"

namespace peloton {
namespace planner {

UpdatePlan::UpdatePlan(storage::DataTable *table,
		std::unique_ptr<const planner::ProjectInfo> project_info) :
		target_table_(table), project_info_(std::move(project_info)), updates(
				NULL), where(NULL) {
}

UpdatePlan::UpdatePlan(parser::UpdateStatement *parse_tree) {
	auto t_ref = parse_tree->table;
	table_name = std::string(t_ref->name);
	target_table_ = catalog::Bootstrapper::global_catalog->GetTableFromDatabase(
			DEFAULT_DB_NAME, table_name);

	updates = parse_tree->updates;
	TargetList tlist;
	DirectMapList dmlist;
	oid_t col_id;
	auto schema = target_table_->GetSchema();

	std::vector<oid_t> columns;
	for (auto update : *updates) {

		// get oid_t of the column and push it to the vector;
		col_id = schema->GetColumnID(std::string(update->column));

		LOG_INFO("This is the column ID -------------------------> %d" , col_id);

		columns.push_back(col_id);
		tlist.emplace_back(col_id, update->value->Copy());
	}

	for (uint i = 0; i < schema->GetColumns().size(); i++) {
		if(schema->GetColumns()[i].column_name != schema->GetColumns()[col_id].column_name)
		dmlist.emplace_back(i,
				std::pair<oid_t, oid_t>(0, i));
	}

	std::unique_ptr<const planner::ProjectInfo> project_info(
			new planner::ProjectInfo(std::move(tlist), std::move(dmlist)));
	project_info_ = std::move(project_info);

	auto expr = parse_tree->where->Copy();
	ReplaceColumnExpressions(expr);

	std::unique_ptr<planner::SeqScanPlan> seq_scan_node(
			new planner::SeqScanPlan(target_table_, expr, columns));
	AddChild(std::move(seq_scan_node));
}

void UpdatePlan::ReplaceColumnExpressions(expression::AbstractExpression* expression) {
  LOG_INFO("Expression Type --> %s", ExpressionTypeToString(expression->GetExpressionType()).c_str());
  LOG_INFO("Left Type --> %s", ExpressionTypeToString(expression->GetLeft()->GetExpressionType()).c_str());
  LOG_INFO("Right Type --> %s", ExpressionTypeToString(expression->GetRight()->GetExpressionType()).c_str());
  if(expression->GetLeft()->GetExpressionType() == EXPRESSION_TYPE_COLUMN_REF) {
    auto expr = expression->GetLeft();
    std::string col_name(expr->getName());
    LOG_INFO("Column name: %s", col_name.c_str());
    delete expr;
    expression->setLeft(ConvertToTupleValueExpression(col_name));
  }
  else if (expression->GetRight()->GetExpressionType() == EXPRESSION_TYPE_COLUMN_REF) {
    auto expr = expression->GetRight();
    std::string col_name(expr->getName());
    LOG_INFO("Column name: %s", col_name.c_str());
    delete expr;
    expression->setRight(ConvertToTupleValueExpression(col_name));
  }
  else {
	  ReplaceColumnExpressions(expression->GetModifiableLeft());
	  ReplaceColumnExpressions(expression->GetModifiableRight());

  }
}
/**
 * This function generates a TupleValue expression from the column name
 */
expression::AbstractExpression* UpdatePlan::ConvertToTupleValueExpression (std::string column_name) {
	auto schema = target_table_->GetSchema();
    auto column_id = schema->GetColumnID(column_name);
    LOG_INFO("Column id in table: %u", column_id);
    expression::TupleValueExpression *expr =
        new expression::TupleValueExpression(schema->GetType(column_id), 0, column_id);
	return expr;
}

}  // namespace planner
}  // namespace peloton
<|endoftext|>