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

//===- PrepareReductionDispatch.cpp ----------------------------*- C++//-*-===//
//
// Prepare dispatch regions that implement reductions before SPIR-V lowering.
//
//===----------------------------------------------------------------------===//
#include "iree/compiler/IR/Ops.h"
#include "iree/compiler/Utils/DispatchUtils.h"
#include "mlir/IR/Function.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Pass/Pass.h"

namespace mlir {
namespace iree_compiler {

namespace {

/// The entry function of the reduction dispatches is empty. This pattern fills
/// the body with an iree.load_input of the reduction input followed by an
/// iree.store_reduce for the later lowering passes to generate the appropriate
/// SPIR-V code.
struct AddReductionEntryFnBody : public OpRewritePattern<FuncOp> {
  using OpRewritePattern<FuncOp>::OpRewritePattern;
  PatternMatchResult matchAndRewrite(FuncOp fn,
                                     PatternRewriter &rewriter) const override;
};

/// Pass to prepare the reduction dispatch entry functions.
struct PrepareReductionDispatchPass
    : public OperationPass<PrepareReductionDispatchPass> {
  void runOnOperation() override;
};
}  // namespace

PatternMatchResult AddReductionEntryFnBody::matchAndRewrite(
    FuncOp fn, PatternRewriter &rewriter) const {
  if (!fn.getAttr("iree.executable.reduction") || !fn.empty()) {
    return matchFailure();
  }
  OpBuilder::InsertionGuard guard(rewriter);
  rewriter.setInsertionPointToStart(fn.addEntryBlock());
  if (fn.getNumArguments() != 3) {
    return matchFailure();
  }
  auto src = fn.getArgument(0);
  auto dst = fn.getArgument(2);
  fn.setArgAttr(2, "iree.executable.reduction.output",
                UnitAttr::get(fn.getContext()));
  auto applyFn =
      fn.getAttrOfType<FlatSymbolRefAttr>("iree.executable.reduction.apply");
  auto srcType = src->getType().cast<MemRefType>();
  auto loc = fn.getLoc();
  auto loadInputOp = rewriter.create<IREE::LoadInputOp>(
      loc, RankedTensorType::get(srcType.getShape(), srcType.getElementType()),
      src);
  rewriter.create<IREE::StoreReduceOp>(loc, loadInputOp.getResult(), dst,
                                       applyFn);
  rewriter.create<IREE::ReturnOp>(fn.getLoc());

  // Finally update the workload size to be determined by the size of the input.
  auto shape = src->getType().cast<ShapedType>().getShape();
  std::array<int32_t, 3> workload = {1, 1, 1};
  calculateWorkload(shape, workload);
  SmallVector<APInt, 3> workloadAPInt;
  workloadAPInt.reserve(3);
  for (auto workloadVal : workload) {
    workloadAPInt.emplace_back(32, static_cast<uint64_t>(workloadVal), true);
  }
  fn.setAttr(
      "iree.executable.workload",
      DenseElementsAttr::get(
          RankedTensorType::get(3, IntegerType::get(32, rewriter.getContext())),
          workloadAPInt)
          .cast<DenseIntElementsAttr>());

  rewriter.updatedRootInPlace(fn);
  return matchSuccess();
}

void PrepareReductionDispatchPass::runOnOperation() {
  OwningRewritePatternList patterns;
  patterns.insert<AddReductionEntryFnBody>(&getContext());
  Operation *op = getOperation();
  applyPatternsGreedily(op->getRegions(), patterns);
}

static PassRegistration<PrepareReductionDispatchPass> pass(
    "iree-spirv-prepare-reduction-dispatch",
    "Prepare the entry function for generation of reduction dispatches");

std::unique_ptr<Pass> createPrepareReductionDispatchPass() {
  return std::make_unique<PrepareReductionDispatchPass>();
}

}  // namespace iree_compiler
}  // namespace mlir
<commit_msg>Change the `notifyRootUpdated` API to be transaction based.<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//===- PrepareReductionDispatch.cpp ----------------------------*- C++//-*-===//
//
// Prepare dispatch regions that implement reductions before SPIR-V lowering.
//
//===----------------------------------------------------------------------===//
#include "iree/compiler/IR/Ops.h"
#include "iree/compiler/Utils/DispatchUtils.h"
#include "mlir/IR/Function.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Pass/Pass.h"

namespace mlir {
namespace iree_compiler {

namespace {

/// The entry function of the reduction dispatches is empty. This pattern fills
/// the body with an iree.load_input of the reduction input followed by an
/// iree.store_reduce for the later lowering passes to generate the appropriate
/// SPIR-V code.
struct AddReductionEntryFnBody : public OpRewritePattern<FuncOp> {
  using OpRewritePattern<FuncOp>::OpRewritePattern;
  PatternMatchResult matchAndRewrite(FuncOp fn,
                                     PatternRewriter &rewriter) const override;
};

/// Pass to prepare the reduction dispatch entry functions.
struct PrepareReductionDispatchPass
    : public OperationPass<PrepareReductionDispatchPass> {
  void runOnOperation() override;
};
}  // namespace

PatternMatchResult AddReductionEntryFnBody::matchAndRewrite(
    FuncOp fn, PatternRewriter &rewriter) const {
  if (!fn.getAttr("iree.executable.reduction") || !fn.empty()) {
    return matchFailure();
  }
  OpBuilder::InsertionGuard guard(rewriter);
  rewriter.setInsertionPointToStart(fn.addEntryBlock());
  if (fn.getNumArguments() != 3) {
    return matchFailure();
  }
  rewriter.startRootUpdate(fn);

  auto src = fn.getArgument(0);
  auto dst = fn.getArgument(2);
  fn.setArgAttr(2, "iree.executable.reduction.output",
                UnitAttr::get(fn.getContext()));
  auto applyFn =
      fn.getAttrOfType<FlatSymbolRefAttr>("iree.executable.reduction.apply");
  auto srcType = src->getType().cast<MemRefType>();
  auto loc = fn.getLoc();
  auto loadInputOp = rewriter.create<IREE::LoadInputOp>(
      loc, RankedTensorType::get(srcType.getShape(), srcType.getElementType()),
      src);
  rewriter.create<IREE::StoreReduceOp>(loc, loadInputOp.getResult(), dst,
                                       applyFn);
  rewriter.create<IREE::ReturnOp>(fn.getLoc());

  // Finally update the workload size to be determined by the size of the input.
  auto shape = src->getType().cast<ShapedType>().getShape();
  std::array<int32_t, 3> workload = {1, 1, 1};
  calculateWorkload(shape, workload);
  SmallVector<APInt, 3> workloadAPInt;
  workloadAPInt.reserve(3);
  for (auto workloadVal : workload) {
    workloadAPInt.emplace_back(32, static_cast<uint64_t>(workloadVal), true);
  }
  fn.setAttr(
      "iree.executable.workload",
      DenseElementsAttr::get(
          RankedTensorType::get(3, IntegerType::get(32, rewriter.getContext())),
          workloadAPInt)
          .cast<DenseIntElementsAttr>());

  rewriter.finalizeRootUpdate(fn);
  return matchSuccess();
}

void PrepareReductionDispatchPass::runOnOperation() {
  OwningRewritePatternList patterns;
  patterns.insert<AddReductionEntryFnBody>(&getContext());
  Operation *op = getOperation();
  applyPatternsGreedily(op->getRegions(), patterns);
}

static PassRegistration<PrepareReductionDispatchPass> pass(
    "iree-spirv-prepare-reduction-dispatch",
    "Prepare the entry function for generation of reduction dispatches");

std::unique_ptr<Pass> createPrepareReductionDispatchPass() {
  return std::make_unique<PrepareReductionDispatchPass>();
}

}  // namespace iree_compiler
}  // namespace mlir
<|endoftext|>


<commit_before>#include "file.h"
#include "string.h"
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <memory>
#include <stdexcept>
#include <string>

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#define PLATFORM_WINDOWS
#endif

#ifdef PLATFORM_WINDOWS
#include <direct.h>
#include <shlwapi.h>
#include <windows.h>
#else
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#endif

#ifdef PLATFORM_WINDOWS
// This is the only module that requires windows character conversion

std::string to_string(const wchar_t* str = L"")
{
    if (!str) {
        str = L"";
    }
    auto length = WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, nullptr, nullptr);
    std::unique_ptr<char[]> buffer(new char[length + 1]);
    WideCharToMultiByte(CP_UTF8, 0, str, -1, buffer.get(), length, nullptr, nullptr);

    return std::string(buffer.get());
}

// use unique_ptr to prevent memory leak with exceptions.
inline std::unique_ptr<wchar_t[]> to_wchar(const std::string str)
{
    auto length = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
    std::unique_ptr<wchar_t[]> buffer(new wchar_t[length + 1]);
    MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, buffer.get(), length);

    return std::move(buffer);
}
#endif

using namespace UnTech;

std::string File::readUtf8TextFile(const std::string& filename)
{
    std::ifstream in(filename, std::ios::in | std::ios::binary);
    if (in) {
        uint8_t bom[3];
        in.read((char*)bom, sizeof(bom));

        in.seekg(0, std::ios::end);
        size_t size = in.tellg();

        // check for BOM
        if (size > 3 && bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF) {
            in.seekg(3, std::ios::beg);
            size -= 3;
        }
        else {
            in.seekg(0, std::ios::beg);
        }

        std::string ret;
        ret.reserve(size + 1);

        ret.assign((std::istreambuf_iterator<char>(in)), (std::istreambuf_iterator<char>()));

        in.close();

        if (!String::checkUtf8WellFormed(ret)) {
            throw std::runtime_error("File is not UTF-8 Well Formed");
        }

        return (ret);
    }
    throw std::runtime_error("Cannot open file");
}

std::pair<std::string, std::string> File::splitFilename(const std::string& filename)
{
    if (filename.empty()) {
        return { std::string(), std::string() };
    }

#ifdef PLATFORM_WINDOWS
    // search both types of slash in windows.
    auto i = filename.find_last_of("\\/");
#else
    auto i = filename.find_last_of('/');
#endif

    if (i == std::string::npos) {
        return { std::string(), filename };
    }
    else {
        return { filename.substr(0, i + 1), filename.substr(i + 1) };
    }
}

std::string File::cwd()
{
#ifdef PLATFORM_WINDOWS
    wchar_t wpath[PATH_MAX] = L"";

    if (!_wgetcwd(wpath, PATH_MAX)) {
        throw std::runtime_error("Error getting working directory");
    }

    return to_string(wpath);

#else
    char* dir = get_current_dir_name();

    if (dir) {
        std::string ret(dir);
        free(dir);
        return ret;
    }
    else {
        throw std::runtime_error("Error with path");
    }
#endif
}

std::string File::cleanPath(const std::string& path)
{
    if (path.empty()) {
        return path;
    }

#ifdef PLATFORM_WINDOWS
    const char SEP = '\\';

    std::string newPath = path;
    std::replace(newPath.begin(), newPath.end(), '/', '\\');

    const char* source = newPath.c_str();

#else
    const char SEP = '/';

    const char* source = path.c_str();
#endif

    char ret[path.length() + 1];

    char* pos = ret;
    char* dirs[path.length() / 2];
    size_t nDirs = 0;

    while (*source != '\0') {
        // Start of a directory/file

        if (source[0] == '.' && source[1] == SEP) {
            // ignore all . directories
            source += 2;
        }

        else if (source[0] == '.' && source[1] == '.' && source[2] == SEP) {
            if (nDirs > 1) {
                // shift pos to previous directory

                pos = dirs[nDirs - 2];
                nDirs--;
                source += 3;
            }
            else {
                pos[0] = source[0];
                pos[1] = source[1];
                pos[2] = source[2];
                pos += 3;
                source += 3;
            }
        }

        else {
            // loop until end of directory separator

            while (*source != '\0' && *source != SEP) {
                *(pos++) = *(source++);
            }

            // include terminator ('/' or '\0').
            *(pos++) = *(source++);

            if (*(source - 1) == '\0') {
                break;
            }
            else if (*(source - 1) == SEP) {
                // remember previous dir position
                dirs[nDirs] = pos;
                nDirs++;
            }
        }

#ifndef PLATFORM_WINDOWS
        // ignore duplicate separators
        while (*source == SEP) {
            source++;
        }
#endif
    }

    return std::string(ret);
}

std::string File::joinPath(const std::string& dir, const std::string& path)
{
#ifdef PLATFORM_WINDOWS
    auto wdir = to_wchar(dir);
    auto wpath = to_wchar(path);
    wchar_t wjoined[PATH_MAX] = L"";

    PathCombineW(wjoined, wdir.get(), wpath.get());

    return to_string(wjoined);

#else
    if (path.front() == '/') {
        return path;
    }

    std::string join;
    join.reserve(dir.length() + path.length() + 1);

    if (!dir.empty() && dir.back() != '/') {
        join = dir + '/' + path;
    }
    else {
        join = dir + path;
    }

    return cleanPath(join);
#endif
}

std::string File::fullPath(const std::string& path)
{
#ifdef PLATFORM_WINDOWS
    wchar_t wfullpath[PATH_MAX] = L"";
    auto wpath = to_wchar(path);

    if (!_wfullpath(wfullpath, wpath.get(), PATH_MAX)) {
        throw std::runtime_error("Error expanding path");
    }

    return to_string(wfullpath);

#else
    if (path.front() == '/') {
        return path;
    }

    return joinPath(cwd(), path);
#endif
}

std::string File::relativePath(const std::string& sourceDir, const std::string& destPath)
{
    if (sourceDir.empty()) {
        return File::fullPath(destPath);
    }

#ifdef PLATFORM_WINDOWS
    wchar_t wrelpath[PATH_MAX] = L"";
    auto wsource = to_wchar(sourceDir);
    auto wdest = to_wchar(destPath);

    if (!PathRelativePathToW(wrelpath, wsource.get(), FILE_ATTRIBUTE_DIRECTORY, wdest.get(), FILE_ATTRIBUTE_NORMAL)) {
        return File::fullPath(destPath);
    }

    if (wrelpath[0] != L'\\') {
        return to_string(wrelpath);
    }
    else {
        return to_string(wrelpath + 1);
    }

#else

    std::string source = File::fullPath(sourceDir);
    std::string dest = File::fullPath(destPath);

    if (source.empty() || dest.empty()
        || source.front() != '/' || dest.front() != '/') {

        return dest;
    }

    std::string ret;

    // Get common root directories
    size_t lastCommonSep = 0;
    {
        size_t i = 0;
        while (i < source.size() && i < dest.size() && source[i] == dest[i]) {
            if (source[i] == '/') {
                lastCommonSep = i;
            }
            i++;
        }

        if (i == source.size() && dest.size() > source.size() && dest[i] == '/') {
            lastCommonSep = i;
        }
    }

    if (source.size() > lastCommonSep) {
        size_t p = lastCommonSep + 1;

        while ((p = source.find('/', p)) != std::string::npos) {
            ret += "../";
            p += 1;
        }
    }

    ret += dest.substr(lastCommonSep + 1);

    return ret;
#endif
}

#ifdef PLATFORM_WINDOWS
void File::atomicWrite(const std::string& filename, const void* data, size_t size)
{
    const size_t BLOCK_SIZE = 4096;

    // atomically creating a tempfile name is hard
    // just simplify it by using a ~ temp file instead.
    auto tmpFilename = to_wchar(filename + "~");

    // open file normally.
    // error out if file exists.
    HANDLE hFile = CreateFileW(tmpFilename.get(), GENERIC_WRITE, 0, nullptr,
                               CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);

    if (hFile == INVALID_HANDLE_VALUE) {
        if (GetLastError() == ERROR_FILE_EXISTS) {
            throw std::runtime_error("Temporary file already exists: " + filename + "~");
        }
        else {
            throw std::runtime_error("Cannot open temporary file " + filename + "~");
        }
    }

    const uint8_t* ptr = static_cast<const uint8_t*>(data);
    size_t todo = size;

    while (todo > 0) {
        DWORD toWrite = std::min(BLOCK_SIZE, todo);
        DWORD written = 0;

        auto ret = WriteFile(hFile, ptr, toWrite, &written, NULL);

        if (ret == FALSE || written != toWrite) {
            CloseHandle(hFile);
            throw std::runtime_error("Error writing file");
        }

        ptr += toWrite;
        todo -= toWrite;
    }

    CloseHandle(hFile);

    auto wFilename = to_wchar(filename);
    bool s = MoveFileExW(tmpFilename.get(), wFilename.get(),
                         MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
    if (!s) {
        throw std::runtime_error("MoveFileEx failed");
    }
}
#else
void File::atomicWrite(const std::string& filename, const void* data, size_t size)
{
    const size_t BLOCK_SIZE = 4096;

    int fd;
    char tmpFilename[filename.size() + 12];
    strncpy(tmpFilename, filename.c_str(), filename.size() + 1);
    strncpy(tmpFilename + filename.size(), "-tmpXXXXXX", 12);

    struct stat statbuf;
    if (stat(filename.c_str(), &statbuf) == 0) {
        if (S_ISLNK(statbuf.st_mode)) {
            throw std::runtime_error("Cannot write to a symbolic link");
        }

        // check if we can write to file
        bool canWrite = ((getuid() == statbuf.st_uid) && (statbuf.st_mode & S_IWUSR))
                        || ((getgid() == statbuf.st_gid) && (statbuf.st_mode & S_IWGRP))
                        || (statbuf.st_mode & S_IWOTH);
        if (!canWrite) {
            throw std::runtime_error("User can not write to " + filename);
        }

        fd = mkostemp(tmpFilename, O_WRONLY);
        if (fd < 0) {
            throw std::system_error(errno, std::system_category());
        }

        // mkostemp sets file permission to 0600
        // Set the permissions to match filename
        chmod(tmpFilename, statbuf.st_mode);
        chown(tmpFilename, statbuf.st_uid, statbuf.st_gid);
    }
    else {
        fd = mkostemp(tmpFilename, O_WRONLY);
        if (fd < 0) {
            throw std::system_error(errno, std::system_category());
        }

        // mkostemp sets file permission to 0600
        // Set the permissions what user would expect
        mode_t mask = umask(0);
        umask(mask);
        chmod(tmpFilename, 0666 & ~mask);
    }

    const uint8_t* ptr = static_cast<const uint8_t*>(data);
    size_t todo = size;
    ssize_t done;

    while (todo > 0) {
        done = ::write(fd, ptr, std::min(BLOCK_SIZE, todo));
        if (done < 0) {
            auto err = errno;
            close(fd);
            throw std::system_error(err, std::system_category());
        }

        ptr += done;
        todo -= done;
    }

    int r;
    r = close(fd);
    if (r != 0) {
        throw std::system_error(errno, std::system_category());
    }

    r = rename(tmpFilename, filename.c_str());
    if (r != 0) {
        throw std::system_error(errno, std::system_category());
    }
}
#endif
<commit_msg>ui: include filename in File::readUtf8TextFile exceptions<commit_after>#include "file.h"
#include "string.h"
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <memory>
#include <stdexcept>
#include <string>

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#define PLATFORM_WINDOWS
#endif

#ifdef PLATFORM_WINDOWS
#include <direct.h>
#include <shlwapi.h>
#include <windows.h>
#else
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#endif

#ifdef PLATFORM_WINDOWS
// This is the only module that requires windows character conversion

std::string to_string(const wchar_t* str = L"")
{
    if (!str) {
        str = L"";
    }
    auto length = WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, nullptr, nullptr);
    std::unique_ptr<char[]> buffer(new char[length + 1]);
    WideCharToMultiByte(CP_UTF8, 0, str, -1, buffer.get(), length, nullptr, nullptr);

    return std::string(buffer.get());
}

// use unique_ptr to prevent memory leak with exceptions.
inline std::unique_ptr<wchar_t[]> to_wchar(const std::string str)
{
    auto length = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
    std::unique_ptr<wchar_t[]> buffer(new wchar_t[length + 1]);
    MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, buffer.get(), length);

    return std::move(buffer);
}
#endif

using namespace UnTech;

std::string File::readUtf8TextFile(const std::string& filename)
{
    std::ifstream in(filename, std::ios::in | std::ios::binary);
    if (in) {
        uint8_t bom[3];
        in.read((char*)bom, sizeof(bom));

        in.seekg(0, std::ios::end);
        size_t size = in.tellg();

        // check for BOM
        if (size > 3 && bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF) {
            in.seekg(3, std::ios::beg);
            size -= 3;
        }
        else {
            in.seekg(0, std::ios::beg);
        }

        std::string ret;
        ret.reserve(size + 1);

        ret.assign((std::istreambuf_iterator<char>(in)), (std::istreambuf_iterator<char>()));

        in.close();

        if (!String::checkUtf8WellFormed(ret)) {
            throw std::runtime_error("Cannot open file: " + filename + " : Not UTF-8 Well Formed");
        }

        return (ret);
    }
    throw std::runtime_error("Cannot open file: " + filename);
}

std::pair<std::string, std::string> File::splitFilename(const std::string& filename)
{
    if (filename.empty()) {
        return { std::string(), std::string() };
    }

#ifdef PLATFORM_WINDOWS
    // search both types of slash in windows.
    auto i = filename.find_last_of("\\/");
#else
    auto i = filename.find_last_of('/');
#endif

    if (i == std::string::npos) {
        return { std::string(), filename };
    }
    else {
        return { filename.substr(0, i + 1), filename.substr(i + 1) };
    }
}

std::string File::cwd()
{
#ifdef PLATFORM_WINDOWS
    wchar_t wpath[PATH_MAX] = L"";

    if (!_wgetcwd(wpath, PATH_MAX)) {
        throw std::runtime_error("Error getting working directory");
    }

    return to_string(wpath);

#else
    char* dir = get_current_dir_name();

    if (dir) {
        std::string ret(dir);
        free(dir);
        return ret;
    }
    else {
        throw std::runtime_error("Error with path");
    }
#endif
}

std::string File::cleanPath(const std::string& path)
{
    if (path.empty()) {
        return path;
    }

#ifdef PLATFORM_WINDOWS
    const char SEP = '\\';

    std::string newPath = path;
    std::replace(newPath.begin(), newPath.end(), '/', '\\');

    const char* source = newPath.c_str();

#else
    const char SEP = '/';

    const char* source = path.c_str();
#endif

    char ret[path.length() + 1];

    char* pos = ret;
    char* dirs[path.length() / 2];
    size_t nDirs = 0;

    while (*source != '\0') {
        // Start of a directory/file

        if (source[0] == '.' && source[1] == SEP) {
            // ignore all . directories
            source += 2;
        }

        else if (source[0] == '.' && source[1] == '.' && source[2] == SEP) {
            if (nDirs > 1) {
                // shift pos to previous directory

                pos = dirs[nDirs - 2];
                nDirs--;
                source += 3;
            }
            else {
                pos[0] = source[0];
                pos[1] = source[1];
                pos[2] = source[2];
                pos += 3;
                source += 3;
            }
        }

        else {
            // loop until end of directory separator

            while (*source != '\0' && *source != SEP) {
                *(pos++) = *(source++);
            }

            // include terminator ('/' or '\0').
            *(pos++) = *(source++);

            if (*(source - 1) == '\0') {
                break;
            }
            else if (*(source - 1) == SEP) {
                // remember previous dir position
                dirs[nDirs] = pos;
                nDirs++;
            }
        }

#ifndef PLATFORM_WINDOWS
        // ignore duplicate separators
        while (*source == SEP) {
            source++;
        }
#endif
    }

    return std::string(ret);
}

std::string File::joinPath(const std::string& dir, const std::string& path)
{
#ifdef PLATFORM_WINDOWS
    auto wdir = to_wchar(dir);
    auto wpath = to_wchar(path);
    wchar_t wjoined[PATH_MAX] = L"";

    PathCombineW(wjoined, wdir.get(), wpath.get());

    return to_string(wjoined);

#else
    if (path.front() == '/') {
        return path;
    }

    std::string join;
    join.reserve(dir.length() + path.length() + 1);

    if (!dir.empty() && dir.back() != '/') {
        join = dir + '/' + path;
    }
    else {
        join = dir + path;
    }

    return cleanPath(join);
#endif
}

std::string File::fullPath(const std::string& path)
{
#ifdef PLATFORM_WINDOWS
    wchar_t wfullpath[PATH_MAX] = L"";
    auto wpath = to_wchar(path);

    if (!_wfullpath(wfullpath, wpath.get(), PATH_MAX)) {
        throw std::runtime_error("Error expanding path");
    }

    return to_string(wfullpath);

#else
    if (path.front() == '/') {
        return path;
    }

    return joinPath(cwd(), path);
#endif
}

std::string File::relativePath(const std::string& sourceDir, const std::string& destPath)
{
    if (sourceDir.empty()) {
        return File::fullPath(destPath);
    }

#ifdef PLATFORM_WINDOWS
    wchar_t wrelpath[PATH_MAX] = L"";
    auto wsource = to_wchar(sourceDir);
    auto wdest = to_wchar(destPath);

    if (!PathRelativePathToW(wrelpath, wsource.get(), FILE_ATTRIBUTE_DIRECTORY, wdest.get(), FILE_ATTRIBUTE_NORMAL)) {
        return File::fullPath(destPath);
    }

    if (wrelpath[0] != L'\\') {
        return to_string(wrelpath);
    }
    else {
        return to_string(wrelpath + 1);
    }

#else

    std::string source = File::fullPath(sourceDir);
    std::string dest = File::fullPath(destPath);

    if (source.empty() || dest.empty()
        || source.front() != '/' || dest.front() != '/') {

        return dest;
    }

    std::string ret;

    // Get common root directories
    size_t lastCommonSep = 0;
    {
        size_t i = 0;
        while (i < source.size() && i < dest.size() && source[i] == dest[i]) {
            if (source[i] == '/') {
                lastCommonSep = i;
            }
            i++;
        }

        if (i == source.size() && dest.size() > source.size() && dest[i] == '/') {
            lastCommonSep = i;
        }
    }

    if (source.size() > lastCommonSep) {
        size_t p = lastCommonSep + 1;

        while ((p = source.find('/', p)) != std::string::npos) {
            ret += "../";
            p += 1;
        }
    }

    ret += dest.substr(lastCommonSep + 1);

    return ret;
#endif
}

#ifdef PLATFORM_WINDOWS
void File::atomicWrite(const std::string& filename, const void* data, size_t size)
{
    const size_t BLOCK_SIZE = 4096;

    // atomically creating a tempfile name is hard
    // just simplify it by using a ~ temp file instead.
    auto tmpFilename = to_wchar(filename + "~");

    // open file normally.
    // error out if file exists.
    HANDLE hFile = CreateFileW(tmpFilename.get(), GENERIC_WRITE, 0, nullptr,
                               CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);

    if (hFile == INVALID_HANDLE_VALUE) {
        if (GetLastError() == ERROR_FILE_EXISTS) {
            throw std::runtime_error("Temporary file already exists: " + filename + "~");
        }
        else {
            throw std::runtime_error("Cannot open temporary file " + filename + "~");
        }
    }

    const uint8_t* ptr = static_cast<const uint8_t*>(data);
    size_t todo = size;

    while (todo > 0) {
        DWORD toWrite = std::min(BLOCK_SIZE, todo);
        DWORD written = 0;

        auto ret = WriteFile(hFile, ptr, toWrite, &written, NULL);

        if (ret == FALSE || written != toWrite) {
            CloseHandle(hFile);
            throw std::runtime_error("Error writing file");
        }

        ptr += toWrite;
        todo -= toWrite;
    }

    CloseHandle(hFile);

    auto wFilename = to_wchar(filename);
    bool s = MoveFileExW(tmpFilename.get(), wFilename.get(),
                         MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
    if (!s) {
        throw std::runtime_error("MoveFileEx failed");
    }
}
#else
void File::atomicWrite(const std::string& filename, const void* data, size_t size)
{
    const size_t BLOCK_SIZE = 4096;

    int fd;
    char tmpFilename[filename.size() + 12];
    strncpy(tmpFilename, filename.c_str(), filename.size() + 1);
    strncpy(tmpFilename + filename.size(), "-tmpXXXXXX", 12);

    struct stat statbuf;
    if (stat(filename.c_str(), &statbuf) == 0) {
        if (S_ISLNK(statbuf.st_mode)) {
            throw std::runtime_error("Cannot write to a symbolic link");
        }

        // check if we can write to file
        bool canWrite = ((getuid() == statbuf.st_uid) && (statbuf.st_mode & S_IWUSR))
                        || ((getgid() == statbuf.st_gid) && (statbuf.st_mode & S_IWGRP))
                        || (statbuf.st_mode & S_IWOTH);
        if (!canWrite) {
            throw std::runtime_error("User can not write to " + filename);
        }

        fd = mkostemp(tmpFilename, O_WRONLY);
        if (fd < 0) {
            throw std::system_error(errno, std::system_category());
        }

        // mkostemp sets file permission to 0600
        // Set the permissions to match filename
        chmod(tmpFilename, statbuf.st_mode);
        chown(tmpFilename, statbuf.st_uid, statbuf.st_gid);
    }
    else {
        fd = mkostemp(tmpFilename, O_WRONLY);
        if (fd < 0) {
            throw std::system_error(errno, std::system_category());
        }

        // mkostemp sets file permission to 0600
        // Set the permissions what user would expect
        mode_t mask = umask(0);
        umask(mask);
        chmod(tmpFilename, 0666 & ~mask);
    }

    const uint8_t* ptr = static_cast<const uint8_t*>(data);
    size_t todo = size;
    ssize_t done;

    while (todo > 0) {
        done = ::write(fd, ptr, std::min(BLOCK_SIZE, todo));
        if (done < 0) {
            auto err = errno;
            close(fd);
            throw std::system_error(err, std::system_category());
        }

        ptr += done;
        todo -= done;
    }

    int r;
    r = close(fd);
    if (r != 0) {
        throw std::system_error(errno, std::system_category());
    }

    r = rename(tmpFilename, filename.c_str());
    if (r != 0) {
        throw std::system_error(errno, std::system_category());
    }
}
#endif
<|endoftext|>


<commit_before>//===-- LLVMTargetMachine.cpp - Implement the LLVMTargetMachine class -----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the LLVMTargetMachine class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;

// Enable or disable FastISel. Both options are needed, because
// FastISel is enabled by default with -fast, and we wish to be
// able to enable or disable fast-isel independently from -O0.
static cl::opt<cl::boolOrDefault>
EnableFastISelOption("fast-isel", cl::Hidden,
  cl::desc("Enable the \"fast\" instruction selector"));

static cl::opt<bool> ShowMCEncoding("show-mc-encoding", cl::Hidden,
    cl::desc("Show encoding in .s output"));
static cl::opt<bool> ShowMCInst("show-mc-inst", cl::Hidden,
    cl::desc("Show instruction structure in .s output"));

static cl::opt<cl::boolOrDefault>
AsmVerbose("asm-verbose", cl::desc("Add comments to directives."),
           cl::init(cl::BOU_UNSET));

static bool getVerboseAsm() {
  switch (AsmVerbose) {
  case cl::BOU_UNSET: return TargetMachine::getAsmVerbosityDefault();
  case cl::BOU_TRUE:  return true;
  case cl::BOU_FALSE: return false;
  }
  llvm_unreachable("Invalid verbose asm state");
}

LLVMTargetMachine::LLVMTargetMachine(const Target &T, StringRef Triple,
                                     StringRef CPU, StringRef FS,
                                     TargetOptions Options,
                                     Reloc::Model RM, CodeModel::Model CM,
                                     CodeGenOpt::Level OL)
  : TargetMachine(T, Triple, CPU, FS, Options) {
  CodeGenInfo = T.createMCCodeGenInfo(Triple, RM, CM, OL);
  AsmInfo = T.createMCAsmInfo(Triple);
  // TargetSelect.h moved to a different directory between LLVM 2.9 and 3.0,
  // and if the old one gets included then MCAsmInfo will be NULL and
  // we'll crash later.
  // Provide the user with a useful error message about what's wrong.
  assert(AsmInfo && "MCAsmInfo not initialized."
         "Make sure you include the correct TargetSelect.h"
         "and that InitializeAllTargetMCs() is being invoked!");
}

/// addPassesToX helper drives creation and initialization of TargetPassConfig.
static MCContext *addPassesToGenerateCode(LLVMTargetMachine *TM,
                                          PassManagerBase &PM,
                                          bool DisableVerify,
                                          AnalysisID StartAfter,
                                          AnalysisID StopAfter) {
  // Targets may override createPassConfig to provide a target-specific sublass.
  TargetPassConfig *PassConfig = TM->createPassConfig(PM);
  PassConfig->setStartStopPasses(StartAfter, StopAfter);

  // Set PassConfig options provided by TargetMachine.
  PassConfig->setDisableVerify(DisableVerify);

  PM.add(PassConfig);

  PassConfig->addIRPasses();

  PassConfig->addPassesToHandleExceptions();

  PassConfig->addISelPrepare();

  // Install a MachineModuleInfo class, which is an immutable pass that holds
  // all the per-module stuff we're generating, including MCContext.
  MachineModuleInfo *MMI =
    new MachineModuleInfo(*TM->getMCAsmInfo(), *TM->getRegisterInfo(),
                          &TM->getTargetLowering()->getObjFileLowering());
  PM.add(MMI);
  MCContext *Context = &MMI->getContext(); // Return the MCContext by-ref.

  // Set up a MachineFunction for the rest of CodeGen to work on.
  PM.add(new MachineFunctionAnalysis(*TM));

  // Enable FastISel with -fast, but allow that to be overridden.
  if (EnableFastISelOption == cl::BOU_TRUE ||
      (TM->getOptLevel() == CodeGenOpt::None &&
       EnableFastISelOption != cl::BOU_FALSE))
    TM->setFastISel(true);

  // Ask the target for an isel.
  if (PassConfig->addInstSelector())
    return NULL;

  PassConfig->addMachinePasses();

  PassConfig->setInitialized();

  return Context;
}

bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
                                            formatted_raw_ostream &Out,
                                            CodeGenFileType FileType,
                                            bool DisableVerify,
                                            AnalysisID StartAfter,
                                            AnalysisID StopAfter) {
  // Add common CodeGen passes.
  MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify,
                                               StartAfter, StopAfter);
  if (!Context)
    return true;

  if (StopAfter) {
    // FIXME: The intent is that this should eventually write out a YAML file,
    // containing the LLVM IR, the machine-level IR (when stopping after a
    // machine-level pass), and whatever other information is needed to
    // deserialize the code and resume compilation.  For now, just write the
    // LLVM IR.
    PM.add(createPrintModulePass(&Out));
    return false;
  }

  if (hasMCSaveTempLabels())
    Context->setAllowTemporaryLabels(false);

  const MCAsmInfo &MAI = *getMCAsmInfo();
  const MCRegisterInfo &MRI = *getRegisterInfo();
  const MCSubtargetInfo &STI = getSubtarget<MCSubtargetInfo>();
  OwningPtr<MCStreamer> AsmStreamer;

  switch (FileType) {
  case CGFT_AssemblyFile: {
    MCInstPrinter *InstPrinter =
      getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI,
                                      *getInstrInfo(),
                                      Context->getRegisterInfo(), STI);

    // Create a code emitter if asked to show the encoding.
    MCCodeEmitter *MCE = 0;
    MCAsmBackend *MAB = 0;
    if (ShowMCEncoding) {
      const MCSubtargetInfo &STI = getSubtarget<MCSubtargetInfo>();
      MCE = getTarget().createMCCodeEmitter(*getInstrInfo(), MRI, STI,
                                            *Context);
      MAB = getTarget().createMCAsmBackend(getTargetTriple(), TargetCPU);
    }

    MCStreamer *S = getTarget().createAsmStreamer(*Context, Out,
                                                  getVerboseAsm(),
                                                  hasMCUseLoc(),
                                                  hasMCUseCFI(),
                                                  hasMCUseDwarfDirectory(),
                                                  InstPrinter,
                                                  MCE, MAB,
                                                  ShowMCInst);
    AsmStreamer.reset(S);
    break;
  }
  case CGFT_ObjectFile: {
    // Create the code emitter for the target if it exists.  If not, .o file
    // emission fails.
    MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(*getInstrInfo(), MRI,
                                                         STI, *Context);
    MCAsmBackend *MAB = getTarget().createMCAsmBackend(getTargetTriple(), TargetCPU);
    if (MCE == 0 || MAB == 0)
      return true;

    AsmStreamer.reset(getTarget().createMCObjectStreamer(getTargetTriple(),
                                                         *Context, *MAB, Out,
                                                         MCE, hasMCRelaxAll(),
                                                         hasMCNoExecStack()));
    AsmStreamer.get()->InitSections();
    break;
  }
  case CGFT_Null:
    // The Null output is intended for use for performance analysis and testing,
    // not real users.
    AsmStreamer.reset(createNullStreamer(*Context));
    break;
  }

  // Create the AsmPrinter, which takes ownership of AsmStreamer if successful.
  FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer);
  if (Printer == 0)
    return true;

  // If successful, createAsmPrinter took ownership of AsmStreamer.
  AsmStreamer.take();

  PM.add(Printer);

  PM.add(createGCInfoDeleter());
  return false;
}

/// addPassesToEmitMachineCode - Add passes to the specified pass manager to
/// get machine code emitted.  This uses a JITCodeEmitter object to handle
/// actually outputting the machine code and resolving things like the address
/// of functions.  This method should returns true if machine code emission is
/// not supported.
///
bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM,
                                                   JITCodeEmitter &JCE,
                                                   bool DisableVerify) {
  // Add common CodeGen passes.
  MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify, 0, 0);
  if (!Context)
    return true;

  addCodeEmitter(PM, JCE);
  PM.add(createGCInfoDeleter());

  return false; // success!
}

/// addPassesToEmitMC - Add passes to the specified pass manager to get
/// machine code emitted with the MCJIT. This method returns true if machine
/// code is not supported. It fills the MCContext Ctx pointer which can be
/// used to build custom MCStreamer.
///
bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM,
                                          MCContext *&Ctx,
                                          raw_ostream &Out,
                                          bool DisableVerify) {
  // Add common CodeGen passes.
  Ctx = addPassesToGenerateCode(this, PM, DisableVerify, 0, 0);
  if (!Ctx)
    return true;

  if (hasMCSaveTempLabels())
    Ctx->setAllowTemporaryLabels(false);

  // Create the code emitter for the target if it exists.  If not, .o file
  // emission fails.
  const MCRegisterInfo &MRI = *getRegisterInfo();
  const MCSubtargetInfo &STI = getSubtarget<MCSubtargetInfo>();
  MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(*getInstrInfo(), MRI,
                                                       STI, *Ctx);
  MCAsmBackend *MAB = getTarget().createMCAsmBackend(getTargetTriple(), TargetCPU);
  if (MCE == 0 || MAB == 0)
    return true;

  OwningPtr<MCStreamer> AsmStreamer;
  AsmStreamer.reset(getTarget().createMCObjectStreamer(getTargetTriple(), *Ctx,
                                                       *MAB, Out, MCE,
                                                       hasMCRelaxAll(),
                                                       hasMCNoExecStack()));
  AsmStreamer.get()->InitSections();

  // Create the AsmPrinter, which takes ownership of AsmStreamer if successful.
  FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer);
  if (Printer == 0)
    return true;

  // If successful, createAsmPrinter took ownership of AsmStreamer.
  AsmStreamer.take();

  PM.add(Printer);

  return false; // success!
}
<commit_msg>Fix 80-col violation<commit_after>//===-- LLVMTargetMachine.cpp - Implement the LLVMTargetMachine class -----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the LLVMTargetMachine class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;

// Enable or disable FastISel. Both options are needed, because
// FastISel is enabled by default with -fast, and we wish to be
// able to enable or disable fast-isel independently from -O0.
static cl::opt<cl::boolOrDefault>
EnableFastISelOption("fast-isel", cl::Hidden,
  cl::desc("Enable the \"fast\" instruction selector"));

static cl::opt<bool> ShowMCEncoding("show-mc-encoding", cl::Hidden,
    cl::desc("Show encoding in .s output"));
static cl::opt<bool> ShowMCInst("show-mc-inst", cl::Hidden,
    cl::desc("Show instruction structure in .s output"));

static cl::opt<cl::boolOrDefault>
AsmVerbose("asm-verbose", cl::desc("Add comments to directives."),
           cl::init(cl::BOU_UNSET));

static bool getVerboseAsm() {
  switch (AsmVerbose) {
  case cl::BOU_UNSET: return TargetMachine::getAsmVerbosityDefault();
  case cl::BOU_TRUE:  return true;
  case cl::BOU_FALSE: return false;
  }
  llvm_unreachable("Invalid verbose asm state");
}

LLVMTargetMachine::LLVMTargetMachine(const Target &T, StringRef Triple,
                                     StringRef CPU, StringRef FS,
                                     TargetOptions Options,
                                     Reloc::Model RM, CodeModel::Model CM,
                                     CodeGenOpt::Level OL)
  : TargetMachine(T, Triple, CPU, FS, Options) {
  CodeGenInfo = T.createMCCodeGenInfo(Triple, RM, CM, OL);
  AsmInfo = T.createMCAsmInfo(Triple);
  // TargetSelect.h moved to a different directory between LLVM 2.9 and 3.0,
  // and if the old one gets included then MCAsmInfo will be NULL and
  // we'll crash later.
  // Provide the user with a useful error message about what's wrong.
  assert(AsmInfo && "MCAsmInfo not initialized."
         "Make sure you include the correct TargetSelect.h"
         "and that InitializeAllTargetMCs() is being invoked!");
}

/// addPassesToX helper drives creation and initialization of TargetPassConfig.
static MCContext *addPassesToGenerateCode(LLVMTargetMachine *TM,
                                          PassManagerBase &PM,
                                          bool DisableVerify,
                                          AnalysisID StartAfter,
                                          AnalysisID StopAfter) {
  // Targets may override createPassConfig to provide a target-specific sublass.
  TargetPassConfig *PassConfig = TM->createPassConfig(PM);
  PassConfig->setStartStopPasses(StartAfter, StopAfter);

  // Set PassConfig options provided by TargetMachine.
  PassConfig->setDisableVerify(DisableVerify);

  PM.add(PassConfig);

  PassConfig->addIRPasses();

  PassConfig->addPassesToHandleExceptions();

  PassConfig->addISelPrepare();

  // Install a MachineModuleInfo class, which is an immutable pass that holds
  // all the per-module stuff we're generating, including MCContext.
  MachineModuleInfo *MMI =
    new MachineModuleInfo(*TM->getMCAsmInfo(), *TM->getRegisterInfo(),
                          &TM->getTargetLowering()->getObjFileLowering());
  PM.add(MMI);
  MCContext *Context = &MMI->getContext(); // Return the MCContext by-ref.

  // Set up a MachineFunction for the rest of CodeGen to work on.
  PM.add(new MachineFunctionAnalysis(*TM));

  // Enable FastISel with -fast, but allow that to be overridden.
  if (EnableFastISelOption == cl::BOU_TRUE ||
      (TM->getOptLevel() == CodeGenOpt::None &&
       EnableFastISelOption != cl::BOU_FALSE))
    TM->setFastISel(true);

  // Ask the target for an isel.
  if (PassConfig->addInstSelector())
    return NULL;

  PassConfig->addMachinePasses();

  PassConfig->setInitialized();

  return Context;
}

bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
                                            formatted_raw_ostream &Out,
                                            CodeGenFileType FileType,
                                            bool DisableVerify,
                                            AnalysisID StartAfter,
                                            AnalysisID StopAfter) {
  // Add common CodeGen passes.
  MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify,
                                               StartAfter, StopAfter);
  if (!Context)
    return true;

  if (StopAfter) {
    // FIXME: The intent is that this should eventually write out a YAML file,
    // containing the LLVM IR, the machine-level IR (when stopping after a
    // machine-level pass), and whatever other information is needed to
    // deserialize the code and resume compilation.  For now, just write the
    // LLVM IR.
    PM.add(createPrintModulePass(&Out));
    return false;
  }

  if (hasMCSaveTempLabels())
    Context->setAllowTemporaryLabels(false);

  const MCAsmInfo &MAI = *getMCAsmInfo();
  const MCRegisterInfo &MRI = *getRegisterInfo();
  const MCSubtargetInfo &STI = getSubtarget<MCSubtargetInfo>();
  OwningPtr<MCStreamer> AsmStreamer;

  switch (FileType) {
  case CGFT_AssemblyFile: {
    MCInstPrinter *InstPrinter =
      getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI,
                                      *getInstrInfo(),
                                      Context->getRegisterInfo(), STI);

    // Create a code emitter if asked to show the encoding.
    MCCodeEmitter *MCE = 0;
    MCAsmBackend *MAB = 0;
    if (ShowMCEncoding) {
      const MCSubtargetInfo &STI = getSubtarget<MCSubtargetInfo>();
      MCE = getTarget().createMCCodeEmitter(*getInstrInfo(), MRI, STI,
                                            *Context);
      MAB = getTarget().createMCAsmBackend(getTargetTriple(), TargetCPU);
    }

    MCStreamer *S = getTarget().createAsmStreamer(*Context, Out,
                                                  getVerboseAsm(),
                                                  hasMCUseLoc(),
                                                  hasMCUseCFI(),
                                                  hasMCUseDwarfDirectory(),
                                                  InstPrinter,
                                                  MCE, MAB,
                                                  ShowMCInst);
    AsmStreamer.reset(S);
    break;
  }
  case CGFT_ObjectFile: {
    // Create the code emitter for the target if it exists.  If not, .o file
    // emission fails.
    MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(*getInstrInfo(), MRI,
                                                         STI, *Context);
    MCAsmBackend *MAB = getTarget().createMCAsmBackend(getTargetTriple(),
                                                       TargetCPU);
    if (MCE == 0 || MAB == 0)
      return true;

    AsmStreamer.reset(getTarget().createMCObjectStreamer(getTargetTriple(),
                                                         *Context, *MAB, Out,
                                                         MCE, hasMCRelaxAll(),
                                                         hasMCNoExecStack()));
    AsmStreamer.get()->InitSections();
    break;
  }
  case CGFT_Null:
    // The Null output is intended for use for performance analysis and testing,
    // not real users.
    AsmStreamer.reset(createNullStreamer(*Context));
    break;
  }

  // Create the AsmPrinter, which takes ownership of AsmStreamer if successful.
  FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer);
  if (Printer == 0)
    return true;

  // If successful, createAsmPrinter took ownership of AsmStreamer.
  AsmStreamer.take();

  PM.add(Printer);

  PM.add(createGCInfoDeleter());
  return false;
}

/// addPassesToEmitMachineCode - Add passes to the specified pass manager to
/// get machine code emitted.  This uses a JITCodeEmitter object to handle
/// actually outputting the machine code and resolving things like the address
/// of functions.  This method should returns true if machine code emission is
/// not supported.
///
bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM,
                                                   JITCodeEmitter &JCE,
                                                   bool DisableVerify) {
  // Add common CodeGen passes.
  MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify, 0, 0);
  if (!Context)
    return true;

  addCodeEmitter(PM, JCE);
  PM.add(createGCInfoDeleter());

  return false; // success!
}

/// addPassesToEmitMC - Add passes to the specified pass manager to get
/// machine code emitted with the MCJIT. This method returns true if machine
/// code is not supported. It fills the MCContext Ctx pointer which can be
/// used to build custom MCStreamer.
///
bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM,
                                          MCContext *&Ctx,
                                          raw_ostream &Out,
                                          bool DisableVerify) {
  // Add common CodeGen passes.
  Ctx = addPassesToGenerateCode(this, PM, DisableVerify, 0, 0);
  if (!Ctx)
    return true;

  if (hasMCSaveTempLabels())
    Ctx->setAllowTemporaryLabels(false);

  // Create the code emitter for the target if it exists.  If not, .o file
  // emission fails.
  const MCRegisterInfo &MRI = *getRegisterInfo();
  const MCSubtargetInfo &STI = getSubtarget<MCSubtargetInfo>();
  MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(*getInstrInfo(), MRI,
                                                       STI, *Ctx);
  MCAsmBackend *MAB = getTarget().createMCAsmBackend(getTargetTriple(), TargetCPU);
  if (MCE == 0 || MAB == 0)
    return true;

  OwningPtr<MCStreamer> AsmStreamer;
  AsmStreamer.reset(getTarget().createMCObjectStreamer(getTargetTriple(), *Ctx,
                                                       *MAB, Out, MCE,
                                                       hasMCRelaxAll(),
                                                       hasMCNoExecStack()));
  AsmStreamer.get()->InitSections();

  // Create the AsmPrinter, which takes ownership of AsmStreamer if successful.
  FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer);
  if (Printer == 0)
    return true;

  // If successful, createAsmPrinter took ownership of AsmStreamer.
  AsmStreamer.take();

  PM.add(Printer);

  return false; // success!
}
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of mcompositor.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QPropertyAnimation>
#include <QParallelAnimationGroup>
#include <QPointF>
#include <QtDebug>
#include <mcompositewindow.h>
#include <mcompositewindowshadereffect.h>
#include <mstatusbartexture.h>

#include "mpositionanimation.h"

static QRectF screen;

MPositionAnimation::MPositionAnimation(QObject* parent)
    :MCompositeWindowAnimation(parent)
{
    setReplaceable(false);
    // only use the position animation
    animationGroup()->removeAnimation(scaleAnimation());
    animationGroup()->removeAnimation(opacityAnimation());
    position = positionAnimation();

    if (screen.isEmpty())
        screen = QApplication::desktop()->availableGeometry();
}

MPositionAnimation::~MPositionAnimation()
{
    // don't delete externally referenced animation objects
    for (int i = 0; i < animationGroup()->animationCount(); ++i)
        if (animationGroup()->animationAt(i) != position)
            animationGroup()->takeAnimation(i);
}

void MPositionAnimation::setEnabled(bool enabled)
{
    if (enabled && (animationGroup()->indexOfAnimation(position) == -1))
        animationGroup()->addAnimation(position);
    else if (!enabled) {
        animationGroup()->stop();
        animationGroup()->removeAnimation(position);
    }
}

MSheetAnimation::MSheetAnimation(QObject* parent)
    :MPositionAnimation(parent)
{
    // From the UX specs
    positionAnimation()->setDuration(350);
}

void MSheetAnimation::windowShown()
{
    setEnabled(true);
    targetWindow()->setOpacity(1.0);

    bool portrait = targetWindow()->propertyCache()->orientationAngle() % 180;
    positionAnimation()->setEasingCurve(QEasingCurve::OutExpo);

    if (portrait) {
        positionAnimation()->setStartValue(screen.topRight());
        positionAnimation()->setEndValue(QPointF(0,0));
    } else {
        positionAnimation()->setStartValue(screen.bottomLeft());
        positionAnimation()->setEndValue(QPointF(0,0));
    }

    animationGroup()->setDirection(QAbstractAnimation::Forward);
    start();
}

void MSheetAnimation::windowClosed()
{
    setEnabled(true);
    positionAnimation()->setEasingCurve(QEasingCurve::InOutExpo);
    animationGroup()->setDirection(QAbstractAnimation::Backward);
    animationGroup()->start();
}

class MStatusBarCrop: public MCompositeWindowShaderEffect
{
    Q_OBJECT
 public:
    MStatusBarCrop(QObject* parent)
        :MCompositeWindowShaderEffect(parent),
         appwindow(0),
         portrait(false)
    {
         p_transform.rotate(90);
         p_transform.translate(0, -screen.height());
         p_transform = p_transform.inverted();
    }

    virtual void drawTexture(const QTransform &transform,
                     const QRectF &drawRect, qreal opacity)
    {
        const MStatusBarTexture *sbtex = MStatusBarTexture::instance();
        QRectF draw_rect(drawRect);
        if (appwindow && appwindow->propertyCache()
            && !appwindow->propertyCache()->statusbarGeometry().isEmpty()) {
            // subtract statusbar
            if (portrait)
                draw_rect.setLeft(sbtex->portraitRect().height());
            else
                draw_rect.setTop(sbtex->landscapeRect().height());
        }

        // original texture with cropped statusbar
        glBindTexture(GL_TEXTURE_2D, texture());
        drawSource(transform, draw_rect, opacity, true);

        // draw status bar texture
        if (!portrait) {
            glBindTexture(GL_TEXTURE_2D, sbtex->landscapeTexture());
            drawSource(QTransform(),
                       sbtex->landscapeRect(), 1.0);
        } else {
            glBindTexture(GL_TEXTURE_2D, sbtex->portraitTexture());
            drawSource(p_transform,
                       sbtex->portraitRect(), 1.0);
        }
    }

    void setAppWindow(MCompositeWindow* a)
    {
        appwindow = a;
    }

    void setPortrait(bool p)
    {
        portrait = p;
    }

private:
    MCompositeWindow* appwindow;
    QTransform p_transform;
    bool portrait;
};

MChainedAnimation::MChainedAnimation(QObject* parent)
    :MPositionAnimation(parent)
{
    // UX subview specs
    positionAnimation()->setDuration(500);
    positionAnimation()->setEasingCurve(QEasingCurve::InOutExpo);

    invoker_pos = new QPropertyAnimation(this);
    invoker_pos->setPropertyName("pos");
    invoker_pos->setEasingCurve(QEasingCurve::InOutExpo);
    invoker_pos->setDuration(500);
    animationGroup()->addAnimation(invoker_pos);

    connect(animationGroup(), SIGNAL(finished()), SLOT(endAnimation()));
    cropper = new MStatusBarCrop(this);
}

void MChainedAnimation::windowShown()
{
    qDebug() << __func__;
    setEnabled(true);

    MStatusBarTexture::instance()->updatePixmap();
    // sb geometry is shared by targetwindow and invokerwindow
    cropper->setAppWindow(targetWindow());
    cropper->installEffect(targetWindow());
    cropper->installEffect(invokerWindow());
    targetWindow()->setOpacity(1.0);
    invokerWindow()->setVisible(true);
    invoker_pos->setTargetObject(invokerWindow());

    bool portrait = targetWindow()->propertyCache()->orientationAngle() % 180;
    cropper->setPortrait(portrait);
    if (portrait) {
        positionAnimation()->setStartValue(screen.translated(0,-screen.height())
                                           .topLeft());
        positionAnimation()->setEndValue(QPointF(0,0));
        invoker_pos->setStartValue(QPointF(0,0));
        invoker_pos->setEndValue(screen.bottomLeft());
    } else {
        positionAnimation()->setStartValue(screen.topRight());
        positionAnimation()->setEndValue(QPointF(0,0));
        invoker_pos->setStartValue(QPointF(0,0));
        invoker_pos->setEndValue(screen.translated(0,-screen.width())
                                 .topLeft());
    }

    animationGroup()->setDirection(QAbstractAnimation::Forward);
    start();
}

void MChainedAnimation::windowClosed()
{
    qDebug() << __func__;
    setEnabled(true);

    MStatusBarTexture::instance()->updatePixmap();
    cropper->setAppWindow(targetWindow());
    cropper->installEffect(targetWindow());
    cropper->installEffect(invokerWindow());
    invokerWindow()->setVisible(true);
    invoker_pos->setTargetObject(invokerWindow());

    animationGroup()->setDirection(QAbstractAnimation::Backward);
    animationGroup()->start();
}

MCompositeWindow* MChainedAnimation::invokerWindow()
{
    if (targetWindow()->propertyCache()->invokedBy() != None)
        return MCompositeWindow::compositeWindow(targetWindow()->propertyCache()->invokedBy());
    return 0;
}

void MChainedAnimation::endAnimation()
{
    cropper->removeEffect(targetWindow());
    cropper->removeEffect(invokerWindow());
    MStatusBarTexture::instance()->untrackDamages();
}

#include "mpositionanimation.moc"
<commit_msg>remove qDebugs introduced by ad01c67c3b6e3<commit_after>/***************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of mcompositor.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QPropertyAnimation>
#include <QParallelAnimationGroup>
#include <QPointF>
#include <QtDebug>
#include <mcompositewindow.h>
#include <mcompositewindowshadereffect.h>
#include <mstatusbartexture.h>

#include "mpositionanimation.h"

static QRectF screen;

MPositionAnimation::MPositionAnimation(QObject* parent)
    :MCompositeWindowAnimation(parent)
{
    setReplaceable(false);
    // only use the position animation
    animationGroup()->removeAnimation(scaleAnimation());
    animationGroup()->removeAnimation(opacityAnimation());
    position = positionAnimation();

    if (screen.isEmpty())
        screen = QApplication::desktop()->availableGeometry();
}

MPositionAnimation::~MPositionAnimation()
{
    // don't delete externally referenced animation objects
    for (int i = 0; i < animationGroup()->animationCount(); ++i)
        if (animationGroup()->animationAt(i) != position)
            animationGroup()->takeAnimation(i);
}

void MPositionAnimation::setEnabled(bool enabled)
{
    if (enabled && (animationGroup()->indexOfAnimation(position) == -1))
        animationGroup()->addAnimation(position);
    else if (!enabled) {
        animationGroup()->stop();
        animationGroup()->removeAnimation(position);
    }
}

MSheetAnimation::MSheetAnimation(QObject* parent)
    :MPositionAnimation(parent)
{
    // From the UX specs
    positionAnimation()->setDuration(350);
}

void MSheetAnimation::windowShown()
{
    setEnabled(true);
    targetWindow()->setOpacity(1.0);

    bool portrait = targetWindow()->propertyCache()->orientationAngle() % 180;
    positionAnimation()->setEasingCurve(QEasingCurve::OutExpo);

    if (portrait) {
        positionAnimation()->setStartValue(screen.topRight());
        positionAnimation()->setEndValue(QPointF(0,0));
    } else {
        positionAnimation()->setStartValue(screen.bottomLeft());
        positionAnimation()->setEndValue(QPointF(0,0));
    }

    animationGroup()->setDirection(QAbstractAnimation::Forward);
    start();
}

void MSheetAnimation::windowClosed()
{
    setEnabled(true);
    positionAnimation()->setEasingCurve(QEasingCurve::InOutExpo);
    animationGroup()->setDirection(QAbstractAnimation::Backward);
    animationGroup()->start();
}

class MStatusBarCrop: public MCompositeWindowShaderEffect
{
    Q_OBJECT
 public:
    MStatusBarCrop(QObject* parent)
        :MCompositeWindowShaderEffect(parent),
         appwindow(0),
         portrait(false)
    {
         p_transform.rotate(90);
         p_transform.translate(0, -screen.height());
         p_transform = p_transform.inverted();
    }

    virtual void drawTexture(const QTransform &transform,
                     const QRectF &drawRect, qreal opacity)
    {
        const MStatusBarTexture *sbtex = MStatusBarTexture::instance();
        QRectF draw_rect(drawRect);
        if (appwindow && appwindow->propertyCache()
            && !appwindow->propertyCache()->statusbarGeometry().isEmpty()) {
            // subtract statusbar
            if (portrait)
                draw_rect.setLeft(sbtex->portraitRect().height());
            else
                draw_rect.setTop(sbtex->landscapeRect().height());
        }

        // original texture with cropped statusbar
        glBindTexture(GL_TEXTURE_2D, texture());
        drawSource(transform, draw_rect, opacity, true);

        // draw status bar texture
        if (!portrait) {
            glBindTexture(GL_TEXTURE_2D, sbtex->landscapeTexture());
            drawSource(QTransform(),
                       sbtex->landscapeRect(), 1.0);
        } else {
            glBindTexture(GL_TEXTURE_2D, sbtex->portraitTexture());
            drawSource(p_transform,
                       sbtex->portraitRect(), 1.0);
        }
    }

    void setAppWindow(MCompositeWindow* a)
    {
        appwindow = a;
    }

    void setPortrait(bool p)
    {
        portrait = p;
    }

private:
    MCompositeWindow* appwindow;
    QTransform p_transform;
    bool portrait;
};

MChainedAnimation::MChainedAnimation(QObject* parent)
    :MPositionAnimation(parent)
{
    // UX subview specs
    positionAnimation()->setDuration(500);
    positionAnimation()->setEasingCurve(QEasingCurve::InOutExpo);

    invoker_pos = new QPropertyAnimation(this);
    invoker_pos->setPropertyName("pos");
    invoker_pos->setEasingCurve(QEasingCurve::InOutExpo);
    invoker_pos->setDuration(500);
    animationGroup()->addAnimation(invoker_pos);

    connect(animationGroup(), SIGNAL(finished()), SLOT(endAnimation()));
    cropper = new MStatusBarCrop(this);
}

void MChainedAnimation::windowShown()
{
    setEnabled(true);

    MStatusBarTexture::instance()->updatePixmap();
    // sb geometry is shared by targetwindow and invokerwindow
    cropper->setAppWindow(targetWindow());
    cropper->installEffect(targetWindow());
    cropper->installEffect(invokerWindow());
    targetWindow()->setOpacity(1.0);
    invokerWindow()->setVisible(true);
    invoker_pos->setTargetObject(invokerWindow());

    bool portrait = targetWindow()->propertyCache()->orientationAngle() % 180;
    cropper->setPortrait(portrait);
    if (portrait) {
        positionAnimation()->setStartValue(screen.translated(0,-screen.height())
                                           .topLeft());
        positionAnimation()->setEndValue(QPointF(0,0));
        invoker_pos->setStartValue(QPointF(0,0));
        invoker_pos->setEndValue(screen.bottomLeft());
    } else {
        positionAnimation()->setStartValue(screen.topRight());
        positionAnimation()->setEndValue(QPointF(0,0));
        invoker_pos->setStartValue(QPointF(0,0));
        invoker_pos->setEndValue(screen.translated(0,-screen.width())
                                 .topLeft());
    }

    animationGroup()->setDirection(QAbstractAnimation::Forward);
    start();
}

void MChainedAnimation::windowClosed()
{
    setEnabled(true);

    MStatusBarTexture::instance()->updatePixmap();
    cropper->setAppWindow(targetWindow());
    cropper->installEffect(targetWindow());
    cropper->installEffect(invokerWindow());
    invokerWindow()->setVisible(true);
    invoker_pos->setTargetObject(invokerWindow());

    animationGroup()->setDirection(QAbstractAnimation::Backward);
    animationGroup()->start();
}

MCompositeWindow* MChainedAnimation::invokerWindow()
{
    if (targetWindow()->propertyCache()->invokedBy() != None)
        return MCompositeWindow::compositeWindow(targetWindow()->propertyCache()->invokedBy());
    return 0;
}

void MChainedAnimation::endAnimation()
{
    cropper->removeEffect(targetWindow());
    cropper->removeEffect(invokerWindow());
    MStatusBarTexture::instance()->untrackDamages();
}

#include "mpositionanimation.moc"
<|endoftext|>


<commit_before>#include "GramsDisplay.h"

GramsDisplay::GramsDisplay(uint8_t pin_clk, uint8_t pin_dio)
    : SevenSegmentTM1637(pin_clk, pin_dio)
{
    init();
    setBacklight(100);
}

void GramsDisplay::display(float grams)
{
    if (tooLargeToDisplay(grams))
        print("----");
    else
        printGrams(grams);
}

bool GramsDisplay::tooLargeToDisplay(float grams)
{
    return (grams >= 10000 || grams <= -1000);
}

void GramsDisplay::printGrams(float grams)
{
    static char string_buffer[NUM_DIGITS + 1];
    static uint8_t display_buffer[NUM_DIGITS];

    const auto show_decigrams = shouldShowDecigrams(grams);
    createDisplayString(string_buffer, show_decigrams, grams);
    addLeadingZeroIfNeeded(string_buffer, show_decigrams, grams);
    addMinusSignIfNeeded(string_buffer, grams);
    encode(display_buffer, string_buffer, NUM_DIGITS);
    addDecimalPointIfNeeded(display_buffer, show_decigrams);
    printRaw(display_buffer);
}

bool GramsDisplay::shouldShowDecigrams(float grams)
{
    return (grams > -100 && grams < 1000);
}

void GramsDisplay::createDisplayString(char* buffer, bool show_decigrams,
                                       float grams)
{
    const long display_value =
        lroundf(abs(show_decigrams ? grams * 10 : grams));
    sprintf(buffer, "%4li", display_value);
}

void GramsDisplay::addLeadingZeroIfNeeded(char* buffer, bool show_decigrams,
                                          float grams)
{
    const auto need_leading_zero = show_decigrams && abs(grams) < 1.0;
    if (need_leading_zero)
        buffer[2] = '0';
}

void GramsDisplay::addMinusSignIfNeeded(char* buffer, float grams)
{
    const auto is_negative = grams < 0;
    if (is_negative)
        buffer[0] = '-';
}

void GramsDisplay::addDecimalPointIfNeeded(uint8_t* buffer, bool show_decigrams)
{
    if (show_decigrams)
        buffer[2] += DECIMAL_POINT;
}
<commit_msg>Remove unnecessary parens<commit_after>#include "GramsDisplay.h"

GramsDisplay::GramsDisplay(uint8_t pin_clk, uint8_t pin_dio)
    : SevenSegmentTM1637(pin_clk, pin_dio)
{
    init();
    setBacklight(100);
}

void GramsDisplay::display(float grams)
{
    if (tooLargeToDisplay(grams))
        print("----");
    else
        printGrams(grams);
}

bool GramsDisplay::tooLargeToDisplay(float grams)
{
    return (grams >= 10000 || grams <= -1000);
}

void GramsDisplay::printGrams(float grams)
{
    static char string_buffer[NUM_DIGITS + 1];
    static uint8_t display_buffer[NUM_DIGITS];

    const auto show_decigrams = shouldShowDecigrams(grams);
    createDisplayString(string_buffer, show_decigrams, grams);
    addLeadingZeroIfNeeded(string_buffer, show_decigrams, grams);
    addMinusSignIfNeeded(string_buffer, grams);
    encode(display_buffer, string_buffer, NUM_DIGITS);
    addDecimalPointIfNeeded(display_buffer, show_decigrams);
    printRaw(display_buffer);
}

bool GramsDisplay::shouldShowDecigrams(float grams)
{
    return grams > -100 && grams < 1000;
}

void GramsDisplay::createDisplayString(char* buffer, bool show_decigrams,
                                       float grams)
{
    const long display_value =
        lroundf(abs(show_decigrams ? grams * 10 : grams));
    sprintf(buffer, "%4li", display_value);
}

void GramsDisplay::addLeadingZeroIfNeeded(char* buffer, bool show_decigrams,
                                          float grams)
{
    const auto need_leading_zero = show_decigrams && abs(grams) < 1.0;
    if (need_leading_zero)
        buffer[2] = '0';
}

void GramsDisplay::addMinusSignIfNeeded(char* buffer, float grams)
{
    const auto is_negative = grams < 0;
    if (is_negative)
        buffer[0] = '-';
}

void GramsDisplay::addDecimalPointIfNeeded(uint8_t* buffer, bool show_decigrams)
{
    if (show_decigrams)
        buffer[2] += DECIMAL_POINT;
}
<|endoftext|>


<commit_before>#include "download.h"

Download *Download::self = 0;

Download *Download::instance() {
    if(!self)
        self = new Download();
    return self;
}

QString Download::getError() {
    return error;
}

void Download::onTimer() {
    if (isReady) {
        if (!queue -> isEmpty()) {
            isReady = false;

            ModelItem * item = queue -> takeFirst();
            item -> setDownloadProgress(0);
            QNetworkReply * m_http = manager() -> get(QNetworkRequest(item -> toUrl()));
            DownloadPosition * pos = downloads -> take(item);
            downloads -> insert(m_http, pos);
            QObject::connect(m_http, SIGNAL(finished()), this, SLOT(downloadConnectionResponsed()));
            emit slotChanged("( Last " + QString::number(queue -> count()) + ") " + item -> data(TITLEID).toString());
        } else {
            emit slotChanged("(O_o)");
        }
    }
}

void Download::finishDownload() {
//    QFutureWatcher<QNetworkReply *> * curr = (QFutureWatcher<QNetworkReply *>)sender();
    delete downloader -> result();
    isReady = true;
    delete downloader;
    downloader = 0;
}

void Download::start(Model * model, ModelItem * item, QUrl savePath) {
    queue -> append(item);
    downloads -> insert(item, new DownloadPosition(model, item, savePath));
}

void Download::downloadConnectionResponsed() {
    QNetworkReply * reply = (QNetworkReply*)QObject::sender();

    downloader = new QFutureWatcher<QNetworkReply *>();
    connect(downloader, SIGNAL(finished()), this, SLOT(finishDownload()));
    downloader -> setFuture(QtConcurrent::run(this, &Download::downloading, reply));
}

QNetworkReply * Download::downloading(QNetworkReply * reply) {
    DownloadPosition * position = downloads -> value(reply);
    QObject::connect(this, SIGNAL(downloadFinished(ModelItem *, bool)), position -> model, SLOT(itemDownloadFinished(ModelItem *, bool)));
    QObject::connect(this, SIGNAL(downloadProgress(ModelItem *, int)), position -> model, SLOT(itemDownloadProgress(ModelItem *, int)));

    QFile file(position -> savePath.toLocalFile());

//    QIODevice::Append | QIODevice::Unbuffered

    if (!file.open(QIODevice::WriteOnly)) {
        emit downloadError(position -> item, file.errorString());
        emit downloadFinished(position -> item, false);
    } else {
        if (!file.resize(reply -> bytesAvailable())) {
            emit downloadError(position -> item, file.errorString());
            emit downloadFinished(position -> item, false);
        } else {
            QByteArray buffer;
            qint64 pos = 0;
            double limit = reply -> bytesAvailable();
            int bufferLength = 1024 * 1024 * 1; //1 mb

            while(!reply -> atEnd()) {
                try {
                    buffer = reply -> read(bufferLength);
                    pos += buffer.length();
                    file.write(buffer);

                    progress = (pos/limit) * 100;
                    emit downloadProgress(position -> item, progress);
                }

                catch(...) {
                    emit downloadError(position -> item, "Some error occured while download...");
                    emit downloadFinished(position -> item, false);
                }
            }

            file.close();
            reply -> close();
            emit downloadFinished(position -> item, true);
        }
    }

    QObject::disconnect(this, SIGNAL(downloadFinished(ModelItem *, bool)), position -> model, SLOT(itemDownloadFinished(ModelItem *, bool)));
    QObject::disconnect(this, SIGNAL(downloadProgress(ModelItem *, int)), position -> model, SLOT(itemDownloadProgress(ModelItem *, int)));
    return reply;
}

CustomNetworkAccessManager * Download::manager() const {
    return netManager;
}

int Download::getProgress() const {
    return progress;
}

int Download::getQueueLength() const {
    return queue -> count();
}
<commit_msg>update message<commit_after>#include "download.h"

Download *Download::self = 0;

Download *Download::instance() {
    if(!self)
        self = new Download();
    return self;
}

QString Download::getError() {
    return error;
}

void Download::onTimer() {
    if (isReady) {
        if (!queue -> isEmpty()) {
            isReady = false;

            ModelItem * item = queue -> takeFirst();
            item -> setDownloadProgress(0);
            QNetworkReply * m_http = manager() -> get(QNetworkRequest(item -> toUrl()));
            DownloadPosition * pos = downloads -> take(item);
            downloads -> insert(m_http, pos);
            QObject::connect(m_http, SIGNAL(finished()), this, SLOT(downloadConnectionResponsed()));
            emit slotChanged("(Downloads remain: " + QString::number(queue -> count()) + ") " + item -> data(TITLEID).toString());
        } else {
            emit slotChanged("(O_o)");
        }
    }
}

void Download::finishDownload() {
//    QFutureWatcher<QNetworkReply *> * curr = (QFutureWatcher<QNetworkReply *>)sender();
    delete downloader -> result();
    isReady = true;
    delete downloader;
    downloader = 0;
}

void Download::start(Model * model, ModelItem * item, QUrl savePath) {
    queue -> append(item);
    downloads -> insert(item, new DownloadPosition(model, item, savePath));
}

void Download::downloadConnectionResponsed() {
    QNetworkReply * reply = (QNetworkReply*)QObject::sender();

    downloader = new QFutureWatcher<QNetworkReply *>();
    connect(downloader, SIGNAL(finished()), this, SLOT(finishDownload()));
    downloader -> setFuture(QtConcurrent::run(this, &Download::downloading, reply));
}

QNetworkReply * Download::downloading(QNetworkReply * reply) {
    DownloadPosition * position = downloads -> value(reply);
    QObject::connect(this, SIGNAL(downloadFinished(ModelItem *, bool)), position -> model, SLOT(itemDownloadFinished(ModelItem *, bool)));
    QObject::connect(this, SIGNAL(downloadProgress(ModelItem *, int)), position -> model, SLOT(itemDownloadProgress(ModelItem *, int)));

    QFile file(position -> savePath.toLocalFile());

//    QIODevice::Append | QIODevice::Unbuffered

    if (!file.open(QIODevice::WriteOnly)) {
        emit downloadError(position -> item, file.errorString());
        emit downloadFinished(position -> item, false);
    } else {
        if (!file.resize(reply -> bytesAvailable())) {
            emit downloadError(position -> item, file.errorString());
            emit downloadFinished(position -> item, false);
        } else {
            QByteArray buffer;
            qint64 pos = 0;
            double limit = reply -> bytesAvailable();
            int bufferLength = 1024 * 1024 * 1; //1 mb

            while(!reply -> atEnd()) {
                try {
                    buffer = reply -> read(bufferLength);
                    pos += buffer.length();
                    file.write(buffer);

                    progress = (pos/limit) * 100;
                    emit downloadProgress(position -> item, progress);
                }

                catch(...) {
                    emit downloadError(position -> item, "Some error occured while download...");
                    emit downloadFinished(position -> item, false);
                }
            }

            file.close();
            reply -> close();
            emit downloadFinished(position -> item, true);
        }
    }

    QObject::disconnect(this, SIGNAL(downloadFinished(ModelItem *, bool)), position -> model, SLOT(itemDownloadFinished(ModelItem *, bool)));
    QObject::disconnect(this, SIGNAL(downloadProgress(ModelItem *, int)), position -> model, SLOT(itemDownloadProgress(ModelItem *, int)));
    return reply;
}

CustomNetworkAccessManager * Download::manager() const {
    return netManager;
}

int Download::getProgress() const {
    return progress;
}

int Download::getQueueLength() const {
    return queue -> count();
}
<|endoftext|>


<commit_before>/**
 ** \file object/system-class.cc
 ** \brief Creation of the URBI object system.
 */

//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>

#include "parser/uparser.hh"
#include "kernel/userver.hh"
#include "kernel/uconnection.hh"

#include "runner/runner.hh"

#include "object/alien.hh"
#include "object/system-class.hh"

namespace object
{
  rObject system_class;

  /*--------------------.
  | System primitives.  |
  `--------------------*/

#define SERVER_FUNCTION(Function)					\
  static rObject							\
  system_class_ ## Function (runner::Runner&, objects_type args)	\
  {									\
    CHECK_ARG_COUNT (1);						\
    ::urbiserver->Function();						\
    return void_class;							\
  }

  SERVER_FUNCTION(reboot)
  SERVER_FUNCTION(shutdown)

#undef SERVER_FUNCTION

  static rObject
  system_class_sleep (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (2);
    FETCH_ARG(1, Float);
    libport::utime_t deadline =
      ::urbiserver->getTime() +
      static_cast<libport::utime_t>(arg1->value_get() * 1000.0);
    r.yield_until (deadline);
    return void_class;
  }

  static rObject
  system_class_time (runner::Runner&, objects_type)
  {
    return Float::fresh(::urbiserver->getTime() / 1000.0);
  }

  static rObject
  execute_parsed (runner::Runner& r, parser::UParser& p, UrbiException e)
  {
    ast::Nary errs;
    p.process_errors(&errs);
    errs.accept(r);

    if (ast::Nary* ast = p.ast_get())
    {
      ast->accept(r);
      //FIXME: deleting the tree now causes segv.
      //delete p.command_tree_get();
      //p.command_tree_set (0);
      return r.current_get();
    }
    else
      throw e;
  }

  static rObject
  system_class_assert_(runner::Runner&, objects_type args)
  {
    CHECK_ARG_COUNT(3);
    FETCH_ARG(2, String);
    if (!IS_TRUE(args[1]))
      throw PrimitiveError
	("assert_",
	 "assertion `" + arg2->value_get().name_get() + "' failed");
    return void_class;
  }

  static rObject
  system_class_eval (runner::Runner& r, objects_type args)
  {
    FETCH_ARG(1, String);
    parser::UParser p;
    p.parse(arg1->value_get());
    return execute_parsed(r, p, PrimitiveError("",
	std::string("Error executing command.")));
  }

  static rObject
  system_class_searchFile (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (2);
    FETCH_ARG(1, String);

    UServer& s = r.lobby_get()->value_get().connection.server_get();
    try
    {
      return String::fresh(libport::Symbol(
			     s.find_file(arg1->value_get ().name_get ())));
    }
    catch (libport::file_library::Not_found&)
    {
      throw
	PrimitiveError("searchFile",
		       "Unable to find file: "
		       + arg1->value_get().name_get());
      // Never reached
      assertion(false);
      return 0;
    }
  }

  static rObject
  system_class_loadFile (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (2);
    FETCH_ARG(1, String);

    std::string filename = arg1->value_get().name_get();

    if (!libport::path (filename).exists ())
      throw PrimitiveError("loadFile",
			   "No such file: " + filename);

    parser::UParser p;

    p.parse_file(arg1->value_get());
    return
      execute_parsed(r, p,
		     PrimitiveError("", //same message than k1
				    "Error loading file: " + filename));
  }

  static rObject
  system_class_currentRunner (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    rObject res = object::Object::fresh();
    res->proto_add (task_class);
    res->slot_set (SYMBOL (runner), box (scheduler::rJob, r.myself_get ()));
    return res;
  }

  static rObject
  system_class_cycle (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return Float::fresh (r.scheduler_get ().cycle_get ());
  }

  static rObject
  system_class_fresh (runner::Runner&, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return String::fresh(libport::Symbol::fresh());
  }

  static rObject
  system_class_lobby (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return r.lobby_get();
  }

  static rObject
  system_class_quit (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    r.lobby_get()->value_get().connection.close();
    return void_class;
  }

#define SERVER_SET_VAR(Function, Variable, Value)			\
  static rObject							\
  system_class_ ## Function (runner::Runner&, objects_type args)	\
  {									\
    CHECK_ARG_COUNT (1);						\
    ::urbiserver->Variable = Value;					\
    return void_class;							\
  }

  SERVER_SET_VAR(debugoff, debugOutput, false)
  SERVER_SET_VAR(debugon, debugOutput, true)
  SERVER_SET_VAR(stopall, stopall, true)

#undef SERVER_SET_VAR

  void
  system_class_initialize ()
  {
    /// \a Call gives the name of the C++ function, and \a Name that in Urbi.
#define DECLARE(Name)				\
    DECLARE_PRIMITIVE(system, Name)

    DECLARE(assert_);
    DECLARE(currentRunner);
    DECLARE(cycle);
    DECLARE(debugoff);
    DECLARE(debugon);
    DECLARE(eval);
    DECLARE(fresh);
    DECLARE(loadFile);
    DECLARE(lobby);
    DECLARE(quit);
    DECLARE(reboot);
    DECLARE(searchFile);
    DECLARE(shutdown);
    DECLARE(sleep);
    DECLARE(stopall);
    DECLARE(time);
#undef DECLARE
  }

}; // namespace object
<commit_msg>Use namespace-level parsing functions.<commit_after>/**
 ** \file object/system-class.cc
 ** \brief Creation of the URBI object system.
 */

//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>

#include "parser/uparser.hh"
#include "kernel/userver.hh"
#include "kernel/uconnection.hh"

#include "runner/runner.hh"

#include "object/alien.hh"
#include "object/system-class.hh"

namespace object
{
  rObject system_class;

  /*--------------------.
  | System primitives.  |
  `--------------------*/

#define SERVER_FUNCTION(Function)					\
  static rObject							\
  system_class_ ## Function (runner::Runner&, objects_type args)	\
  {									\
    CHECK_ARG_COUNT (1);						\
    ::urbiserver->Function();						\
    return void_class;							\
  }

  SERVER_FUNCTION(reboot)
  SERVER_FUNCTION(shutdown)

#undef SERVER_FUNCTION

  static rObject
  system_class_sleep (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (2);
    FETCH_ARG(1, Float);
    libport::utime_t deadline =
      ::urbiserver->getTime() +
      static_cast<libport::utime_t>(arg1->value_get() * 1000.0);
    r.yield_until (deadline);
    return void_class;
  }

  static rObject
  system_class_time (runner::Runner&, objects_type)
  {
    return Float::fresh(::urbiserver->getTime() / 1000.0);
  }

  static rObject
  execute_parsed (runner::Runner& r, parser::UParser& p, UrbiException e)
  {
    ast::Nary errs;
    p.process_errors(&errs);
    errs.accept(r);

    if (ast::Nary* ast = p.ast_get())
    {
      ast->accept(r);
      //FIXME: deleting the tree now causes segv.
      //delete p.command_tree_get();
      //p.command_tree_set (0);
      return r.current_get();
    }
    else
      throw e;
  }

  static rObject
  system_class_assert_(runner::Runner&, objects_type args)
  {
    CHECK_ARG_COUNT(3);
    FETCH_ARG(2, String);
    if (!IS_TRUE(args[1]))
      throw PrimitiveError
	("assert_",
	 "assertion `" + arg2->value_get().name_get() + "' failed");
    return void_class;
  }

  static rObject
  system_class_eval (runner::Runner& r, objects_type args)
  {
    FETCH_ARG(1, String);
    parser::UParser p = parser::parse(arg1->value_get());
    return execute_parsed(r, p, PrimitiveError("",
	std::string("Error executing command.")));
  }

  static rObject
  system_class_searchFile (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (2);
    FETCH_ARG(1, String);

    UServer& s = r.lobby_get()->value_get().connection.server_get();
    try
    {
      return String::fresh(libport::Symbol(
			     s.find_file(arg1->value_get ().name_get ())));
    }
    catch (libport::file_library::Not_found&)
    {
      throw
	PrimitiveError("searchFile",
		       "Unable to find file: "
		       + arg1->value_get().name_get());
      // Never reached
      assertion(false);
      return 0;
    }
  }

  static rObject
  system_class_loadFile (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (2);
    FETCH_ARG(1, String);

    std::string filename = arg1->value_get().name_get();

    if (!libport::path (filename).exists ())
      throw PrimitiveError("loadFile",
			   "No such file: " + filename);

    parser::UParser p = parser::parse_file(filename);
    return
      execute_parsed(r, p,
		     PrimitiveError("", //same message than k1
				    "Error loading file: " + filename));
  }

  static rObject
  system_class_currentRunner (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    rObject res = object::Object::fresh();
    res->proto_add (task_class);
    res->slot_set (SYMBOL (runner), box (scheduler::rJob, r.myself_get ()));
    return res;
  }

  static rObject
  system_class_cycle (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return Float::fresh (r.scheduler_get ().cycle_get ());
  }

  static rObject
  system_class_fresh (runner::Runner&, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return String::fresh(libport::Symbol::fresh());
  }

  static rObject
  system_class_lobby (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    return r.lobby_get();
  }

  static rObject
  system_class_quit (runner::Runner& r, objects_type args)
  {
    CHECK_ARG_COUNT (1);
    r.lobby_get()->value_get().connection.close();
    return void_class;
  }

#define SERVER_SET_VAR(Function, Variable, Value)			\
  static rObject							\
  system_class_ ## Function (runner::Runner&, objects_type args)	\
  {									\
    CHECK_ARG_COUNT (1);						\
    ::urbiserver->Variable = Value;					\
    return void_class;							\
  }

  SERVER_SET_VAR(debugoff, debugOutput, false)
  SERVER_SET_VAR(debugon, debugOutput, true)
  SERVER_SET_VAR(stopall, stopall, true)

#undef SERVER_SET_VAR

  void
  system_class_initialize ()
  {
    /// \a Call gives the name of the C++ function, and \a Name that in Urbi.
#define DECLARE(Name)				\
    DECLARE_PRIMITIVE(system, Name)

    DECLARE(assert_);
    DECLARE(currentRunner);
    DECLARE(cycle);
    DECLARE(debugoff);
    DECLARE(debugon);
    DECLARE(eval);
    DECLARE(fresh);
    DECLARE(loadFile);
    DECLARE(lobby);
    DECLARE(quit);
    DECLARE(reboot);
    DECLARE(searchFile);
    DECLARE(shutdown);
    DECLARE(sleep);
    DECLARE(stopall);
    DECLARE(time);
#undef DECLARE
  }

}; // namespace object
<|endoftext|>