<commit_before>/*
 * Copyright (C) 2017-2018 Nagisa Sekiguchi
 *
 * 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 <sys/wait.h>

#include <algorithm>
#include <cerrno>

#include "vm.h"
#include "logger.h"

namespace ydsh {

Proc Proc::fork(DSState &st, pid_t pgid, bool foreground) {
    SignalGuard guard;

    pid_t pid = ::fork();
    if(pid == 0) {  // child process
        if(st.isJobControl()) {
            setpgid(0, pgid);
            if(foreground) {
                tcsetpgrp(STDIN_FILENO, getpgid(0));
            }
            setJobControlSignalSetting(st, false);
        }

        // clear queued signal
        DSState::signalQueue.clear();
        unsetFlag(DSState::eventDesc, DSState::VM_EVENT_SIGNAL | DSState::VM_EVENT_MASK);

        // clear JobTable entries
        st.jobTable.detachAll();

        // update PID, PPID
        st.setGlobal(toIndex(BuiltinVarOffset::PID), DSValue::create<Int_Object>(st.pool.getInt32Type(), getpid()));
        st.setGlobal(toIndex(BuiltinVarOffset::PPID), DSValue::create<Int_Object>(st.pool.getInt32Type(), getppid()));
    } else if(pid > 0) {
        if(st.isJobControl()) {
            setpgid(pid, pgid);
            if(foreground) {
                tcsetpgrp(STDIN_FILENO, getpgid(pid));
            }
        }
    }
    return Proc(pid);
}

void tryToForeground(const DSState &st) {
    if(st.isForeground()) {
        tcsetpgrp(STDIN_FILENO, getpgid(0));
    }
}

// ##################
// ##     Proc     ##
// ##################

int Proc::wait(bool nonblocking) {
    if(this->state() != TERMINATED) {
        int status = 0;
        int option = nonblocking ? (WUNTRACED | WNOHANG | WCONTINUED) : WUNTRACED;
        int ret = waitpid(this->pid_, &status, option);
        if(ret == -1) {
            fatal("%s\n", strerror(errno));
        }

        // dump waitpid result
        LOG_L(DUMP_WAIT, [&](std::ostream &stream) {
            stream << "opt: " << (nonblocking ? "nonblocking" : "blocking") << std::endl;
            stream << "pid: " << this->pid() << ", before state: "
                   << (this->state() == Proc::RUNNING ? "RUNNING" : "STOPPED") << std::endl;
            stream << "ret: " << ret << std::endl;
            if(ret > 0) {
                stream << "after state: ";
                if(WIFEXITED(status)) {
                    stream << "TERMINATED" << std::endl
                           << "kind: EXITED, status: " << WEXITSTATUS(status);
                } else if(WIFSIGNALED(status)) {
                    stream << "TERMINATED" << std::endl
                           << "kind: SIGNALED, status: " << WTERMSIG(status);
                } else if(WIFSTOPPED(status)) {
                    stream << "STOPPED" << std::endl
                           << "kind: STOPPED, status: " << WSTOPSIG(status);
                } else if(WIFCONTINUED(status)) {
                    stream << "RUNNING" << std::endl << "kind: CONTINUED";
                }
                stream << std::endl;
            }
        });

        if(ret > 0) {
            // update status
            if(WIFEXITED(status)) {
                this->state_ = TERMINATED;
                this->exitStatus_ = WEXITSTATUS(status);
            } else if(WIFSIGNALED(status)) {
                this->state_ = TERMINATED;
                this->exitStatus_ = WTERMSIG(status) + 128;
            } else if(WIFSTOPPED(status)) {
                this->state_ = STOPPED;
                this->exitStatus_ = WSTOPSIG(status) + 128;
            } else if(WIFCONTINUED(status)) {
                this->state_ = RUNNING;
            }

            if(this->state_ == TERMINATED) {
                this->pid_ = -1;
            }
        }
    }
    return this->exitStatus_;
}

// #####################
// ##     JobImpl     ##
// #####################

bool JobImpl::restoreStdin() {
    if(this->oldStdin > -1 && this->hasOwnership()) {
        dup2(this->oldStdin, STDIN_FILENO);
        close(this->oldStdin);
        return true;
    }
    return false;
}

void JobImpl::send(int sigNum, bool group) const {
    if(group) {
        if(this->state != Proc::TERMINATED) {
            kill(-this->getPid(0), sigNum);
        }
        return;
    }
    for(unsigned int i = 0; i < this->procSize; i++) {
        this->procs[i].send(sigNum);
    }
}

int JobImpl::wait(bool nonblocking) {
    if(!hasOwnership()) {
        return -1;
    }
    if(!this->available()) {
        return this->procs[this->procSize - 1].exitStatus();
    }

    unsigned int terminateCount = 0;
    unsigned int lastStatus = 0;
    for(unsigned int i = 0; i < this->procSize; i++) {
        auto &proc = this->procs[i];
        int s = proc.wait(nonblocking);
        if(proc.state() == Proc::TERMINATED) {
            terminateCount++;
            lastStatus = s;
        }
    }
    if(terminateCount == this->procSize) {
        this->state = Proc::TERMINATED;
    }
    return lastStatus;
}

// ######################
// ##     JobTable     ##
// ######################

void JobTable::attach(Job job, bool disowned) {
    if(job->getJobId() != 0) {
        return;
    }

    if(disowned) {
        this->entries.push_back(std::move(job));
        return;
    }

    auto pair = this->findEmptyEntry();
    this->entries.insert(this->beginJob() + pair.first, job);
    job->jobId = pair.second;
    this->latestEntry = std::move(job);
    this->jobSize++;
}

Job JobTable::detach(unsigned int jobId, bool remove) {
    auto iter = this->findEntryIter(jobId);
    if(iter == this->endJob()) {
        return nullptr;
    }
    auto job = *iter;
    this->detachByIter(iter);
    if(!remove) {
        this->entries.push_back(job);
    }
    return job;
}

JobTable::EntryIter JobTable::detachByIter(ConstEntryIter iter) {
    if(iter != this->entries.end()) {
        /**
         * convert const_iterator -> iterator
         */
        auto actual = this->entries.begin() + (iter - this->entries.cbegin());
        Job job = *actual;
        if(job->getJobId() > 0) {
            this->jobSize--;
        }
        job->jobId = 0;

        /**
         * in C++11, vector::erase accepts const_iterator.
         * but in libstdc++ 4.8, vector::erase(const_iterator) is not implemented.
         */
        auto next = this->entries.erase(actual);

        // change latest entry
        if(this->latestEntry == job) {
            this->latestEntry = nullptr;
            if(!this->entries.empty()) {
                this->latestEntry = this->entries.back();
            }
        }
        return next;
    }
    return this->entries.end();
}

void JobTable::updateStatus() {
    for(auto begin = this->entries.begin(); begin != this->entries.end();) {
        (*begin)->wait(true);
        if((*begin)->available()) {
            ++begin;
        } else {
            begin = this->detachByIter(begin);
        }
    }
}

std::pair<unsigned int, unsigned int> JobTable::findEmptyEntry() const {
    const unsigned int size = this->jobSize;
    if(size == 0) {
        return {0, 1};
    }

    if(this->entries.back()->jobId == size) {
        return {size, size + 1};
    }

    /**
     *  | 3 | 4 |
     *
     *  | 1 | 4 |
     *
     *  | 1 | 2 | 3 | 4 | 7 |
     */
    for(unsigned int i = 0; i < size; i++) {
        if(this->entries[i]->jobId != i + 1) {
            return {i, i + 1};  //FIXME: optimize lookup
        }
    }

    fatal("normally unreachable\n");
}

struct Comparator {
    bool operator()(const Job &x, unsigned int y) const {
        return x->getJobId() < y;
    }

    bool operator()(unsigned int x, const Job &y) const {
        return x < y->getJobId();
    }
};

JobTable::ConstEntryIter JobTable::findEntryIter(unsigned int jobId) const {
    if(jobId > 0) {
        auto iter = std::lower_bound(this->beginJob(), this->endJob(), jobId, Comparator());
        if(iter != this->endJob() && (*iter)->jobId == jobId) {
            return iter;
        }
    }
    return this->endJob();
}

} // namespace ydsh<commit_msg>when first proc pid of job is equivalent to pgid, send to process group<commit_after>/*
 * Copyright (C) 2017-2018 Nagisa Sekiguchi
 *
 * 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 <sys/wait.h>

#include <algorithm>
#include <cerrno>

#include "vm.h"
#include "logger.h"

namespace ydsh {

Proc Proc::fork(DSState &st, pid_t pgid, bool foreground) {
    SignalGuard guard;

    pid_t pid = ::fork();
    if(pid == 0) {  // child process
        if(st.isJobControl()) {
            setpgid(0, pgid);
            if(foreground) {
                tcsetpgrp(STDIN_FILENO, getpgid(0));
            }
            setJobControlSignalSetting(st, false);
        }

        // clear queued signal
        DSState::signalQueue.clear();
        unsetFlag(DSState::eventDesc, DSState::VM_EVENT_SIGNAL | DSState::VM_EVENT_MASK);

        // clear JobTable entries
        st.jobTable.detachAll();

        // update PID, PPID
        st.setGlobal(toIndex(BuiltinVarOffset::PID), DSValue::create<Int_Object>(st.pool.getInt32Type(), getpid()));
        st.setGlobal(toIndex(BuiltinVarOffset::PPID), DSValue::create<Int_Object>(st.pool.getInt32Type(), getppid()));
    } else if(pid > 0) {
        if(st.isJobControl()) {
            setpgid(pid, pgid);
            if(foreground) {
                tcsetpgrp(STDIN_FILENO, getpgid(pid));
            }
        }
    }
    return Proc(pid);
}

void tryToForeground(const DSState &st) {
    if(st.isForeground()) {
        tcsetpgrp(STDIN_FILENO, getpgid(0));
    }
}

// ##################
// ##     Proc     ##
// ##################

int Proc::wait(bool nonblocking) {
    if(this->state() != TERMINATED) {
        int status = 0;
        int option = nonblocking ? (WUNTRACED | WNOHANG | WCONTINUED) : WUNTRACED;
        int ret = waitpid(this->pid_, &status, option);
        if(ret == -1) {
            fatal("%s\n", strerror(errno));
        }

        // dump waitpid result
        LOG_L(DUMP_WAIT, [&](std::ostream &stream) {
            stream << "opt: " << (nonblocking ? "nonblocking" : "blocking") << std::endl;
            stream << "pid: " << this->pid() << ", before state: "
                   << (this->state() == Proc::RUNNING ? "RUNNING" : "STOPPED") << std::endl;
            stream << "ret: " << ret << std::endl;
            if(ret > 0) {
                stream << "after state: ";
                if(WIFEXITED(status)) {
                    stream << "TERMINATED" << std::endl
                           << "kind: EXITED, status: " << WEXITSTATUS(status);
                } else if(WIFSIGNALED(status)) {
                    stream << "TERMINATED" << std::endl
                           << "kind: SIGNALED, status: " << WTERMSIG(status);
                } else if(WIFSTOPPED(status)) {
                    stream << "STOPPED" << std::endl
                           << "kind: STOPPED, status: " << WSTOPSIG(status);
                } else if(WIFCONTINUED(status)) {
                    stream << "RUNNING" << std::endl << "kind: CONTINUED";
                }
                stream << std::endl;
            }
        });

        if(ret > 0) {
            // update status
            if(WIFEXITED(status)) {
                this->state_ = TERMINATED;
                this->exitStatus_ = WEXITSTATUS(status);
            } else if(WIFSIGNALED(status)) {
                this->state_ = TERMINATED;
                this->exitStatus_ = WTERMSIG(status) + 128;
            } else if(WIFSTOPPED(status)) {
                this->state_ = STOPPED;
                this->exitStatus_ = WSTOPSIG(status) + 128;
            } else if(WIFCONTINUED(status)) {
                this->state_ = RUNNING;
            }

            if(this->state_ == TERMINATED) {
                this->pid_ = -1;
            }
        }
    }
    return this->exitStatus_;
}

// #####################
// ##     JobImpl     ##
// #####################

bool JobImpl::restoreStdin() {
    if(this->oldStdin > -1 && this->hasOwnership()) {
        dup2(this->oldStdin, STDIN_FILENO);
        close(this->oldStdin);
        return true;
    }
    return false;
}

void JobImpl::send(int sigNum, bool group) const {
    pid_t pid = this->getPid(0);
    if(group && pid == getpgid(pid)) {
        if(this->state != Proc::TERMINATED) {
            kill(-pid, sigNum);
        }
        return;
    }
    for(unsigned int i = 0; i < this->procSize; i++) {
        this->procs[i].send(sigNum);
    }
}

int JobImpl::wait(bool nonblocking) {
    if(!hasOwnership()) {
        return -1;
    }
    if(!this->available()) {
        return this->procs[this->procSize - 1].exitStatus();
    }

    unsigned int terminateCount = 0;
    unsigned int lastStatus = 0;
    for(unsigned int i = 0; i < this->procSize; i++) {
        auto &proc = this->procs[i];
        int s = proc.wait(nonblocking);
        if(proc.state() == Proc::TERMINATED) {
            terminateCount++;
            lastStatus = s;
        }
    }
    if(terminateCount == this->procSize) {
        this->state = Proc::TERMINATED;
    }
    return lastStatus;
}

// ######################
// ##     JobTable     ##
// ######################

void JobTable::attach(Job job, bool disowned) {
    if(job->getJobId() != 0) {
        return;
    }

    if(disowned) {
        this->entries.push_back(std::move(job));
        return;
    }

    auto pair = this->findEmptyEntry();
    this->entries.insert(this->beginJob() + pair.first, job);
    job->jobId = pair.second;
    this->latestEntry = std::move(job);
    this->jobSize++;
}

Job JobTable::detach(unsigned int jobId, bool remove) {
    auto iter = this->findEntryIter(jobId);
    if(iter == this->endJob()) {
        return nullptr;
    }
    auto job = *iter;
    this->detachByIter(iter);
    if(!remove) {
        this->entries.push_back(job);
    }
    return job;
}

JobTable::EntryIter JobTable::detachByIter(ConstEntryIter iter) {
    if(iter != this->entries.end()) {
        /**
         * convert const_iterator -> iterator
         */
        auto actual = this->entries.begin() + (iter - this->entries.cbegin());
        Job job = *actual;
        if(job->getJobId() > 0) {
            this->jobSize--;
        }
        job->jobId = 0;

        /**
         * in C++11, vector::erase accepts const_iterator.
         * but in libstdc++ 4.8, vector::erase(const_iterator) is not implemented.
         */
        auto next = this->entries.erase(actual);

        // change latest entry
        if(this->latestEntry == job) {
            this->latestEntry = nullptr;
            if(!this->entries.empty()) {
                this->latestEntry = this->entries.back();
            }
        }
        return next;
    }
    return this->entries.end();
}

void JobTable::updateStatus() {
    for(auto begin = this->entries.begin(); begin != this->entries.end();) {
        (*begin)->wait(true);
        if((*begin)->available()) {
            ++begin;
        } else {
            begin = this->detachByIter(begin);
        }
    }
}

std::pair<unsigned int, unsigned int> JobTable::findEmptyEntry() const {
    const unsigned int size = this->jobSize;
    if(size == 0) {
        return {0, 1};
    }

    if(this->entries.back()->jobId == size) {
        return {size, size + 1};
    }

    /**
     *  | 3 | 4 |
     *
     *  | 1 | 4 |
     *
     *  | 1 | 2 | 3 | 4 | 7 |
     */
    for(unsigned int i = 0; i < size; i++) {
        if(this->entries[i]->jobId != i + 1) {
            return {i, i + 1};  //FIXME: optimize lookup
        }
    }

    fatal("normally unreachable\n");
}

struct Comparator {
    bool operator()(const Job &x, unsigned int y) const {
        return x->getJobId() < y;
    }

    bool operator()(unsigned int x, const Job &y) const {
        return x < y->getJobId();
    }
};

JobTable::ConstEntryIter JobTable::findEntryIter(unsigned int jobId) const {
    if(jobId > 0) {
        auto iter = std::lower_bound(this->beginJob(), this->endJob(), jobId, Comparator());
        if(iter != this->endJob() && (*iter)->jobId == jobId) {
            return iter;
        }
    }
    return this->endJob();
}

} // namespace ydsh<|endoftext|>


<commit_before>#include "eval.hh"
#include "live.hh"
#include "utils.hh"
#include "gfx.hh"
#include "lex.hh"
#include <SDL2/SDL.h>
#include <GL/glew.h>
#include "imgui.hh"
#include "../thirdparty/imgui/imgui.h"

struct passed_data_t {
  struct frequency_data_t {
    bool on;
    uint64_t c;
    frequency_data_t() : c(0) {}
  };
  term_t *program;
  const std::string definition;
  std::map<double, frequency_data_t> frequencies; // _very_ sloppy but works
  passed_data_t(const std::string &definition)
    : program(nullptr)
    , definition(definition) {
  }
};

static bool g_done = false;
static SDL_AudioDeviceID g_dev = 0;
static std::string g_filename = "";
static char g_source[100000]; // stupid
static passed_data_t *g_passed_data = nullptr;
static std::vector<message_t> g_messages;
static std::vector<float> g_samples;
static float g_frequency = 261.626 /* C4 */, g_seconds = 1;
static int g_octave = 4;
static const std::map<int, std::pair<char, int>> key_notes = {
  { SDLK_a, { 'C', 0 } },
  { SDLK_w, { 'C', 1 } },
  { SDLK_s, { 'D', 0 } },
  { SDLK_e, { 'D', 1 } },
  { SDLK_d, { 'E', 0 } },
  { SDLK_f, { 'F', 0 } },
  { SDLK_t, { 'F', 1 } },
  { SDLK_g, { 'G', 0 } },
  { SDLK_y, { 'G', 1 } },
  { SDLK_h, { 'A', 0 } },
  { SDLK_u, { 'A', 1 } },
  { SDLK_j, { 'B', 0 } }
};

void replot();

static double note_to_freq(char note, int octave, int accidental_offset) {
  /* TODO static */ const std::map<char, int> semitone_offset = {
    { 'C', -9 },
    { 'D', -7 },
    { 'E', -5 },
    { 'F', -4 },
    { 'G', -2 },
    { 'A',  0 },
    { 'B',  2 }
  };
  int octave_diff = octave - 4, semitone_diff = semitone_offset.at(note)
    + accidental_offset;
  return 440. * pow(2., octave_diff) * pow(2., semitone_diff / 12.);
}

static void audio_callback(void *userdata, uint8_t *stream, int len) {
  passed_data_t *passed_data = (passed_data_t*)userdata;
  float *stream_ptr = (float*)stream;
  for (int i = 0; i < 4096; ++i) {
    *stream_ptr = 0;
    for (auto &freq_pair : passed_data->frequencies)
      if (freq_pair.second.on) {
        double t = (double)(freq_pair.second.c++) * 1. / 48000.;
        float value = (float)evaluate_definition(passed_data->program
            , passed_data->definition, freq_pair.first, t);
        *stream_ptr += 0.2f * value;
      }
    ++stream_ptr;
  }
}

static void init() {
  SDL_AudioSpec want, have;
  SDL_memset(&want, 0, sizeof(want));
  want.freq = 48000;
  want.format = AUDIO_F32;
  want.channels = 1;
  want.samples = 4096;
  want.callback = audio_callback;
  want.userdata = (void*)g_passed_data;
  g_dev = SDL_OpenAudioDevice(nullptr, 0, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE);
  if (g_dev == 0)
    die("failed to open audio device: %s", SDL_GetError());
  SDL_PauseAudioDevice(g_dev, 0);

  float s = 20.f / 255.f;
  glClearColor(s, s, s, 1.f);
}

static void update(double dt, double t) {
}

static void draw_gui() {
  if (ImGui::BeginMainMenuBar()) {
    // ImGui::PushStyleColor(ImGuiCol_Button,        r2v( 67,  96, 123));
    // ImGui::PushStyleColor(ImGuiCol_ButtonHovered, r2v( 75, 108, 138));
    // ImGui::PushStyleColor(ImGuiCol_ButtonActive,  r2v( 83, 119, 153));

    ImGui::Text("%s - sythin", g_filename.c_str());

    ImGui::EndMainMenuBar();
  }

  const float padding = 5;

  ImGui::SetNextWindowPos(ImVec2(padding, 25 + padding), ImGuiCond_Always);
  ImGui::SetNextWindowSize(ImVec2(ImGui::GetIO().DisplaySize.x * (1.f / 2.f)
        - padding * 1.5f, ImGui::GetIO().DisplaySize.y - 25 - padding * 2)
      , ImGuiCond_Always);

  ImGui::Begin("Source code", nullptr, ImGuiWindowFlags_NoResize
      | ImGuiWindowFlags_NoMove
      | ImGuiWindowFlags_NoTitleBar
      | ImGuiWindowFlags_NoCollapse);

  if (ImGui::Button("Save")) {
  }
  ImGui::SameLine();
  if (ImGui::Button("Compile")) {
  }

  ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]);
  ImGui::InputTextMultiline("##source", g_source, sizeof(g_source)
      , ImVec2(-1.f, -1.f)
      , ImGuiInputTextFlags_AllowTabInput);
  ImGui::PopFont();

  ImGui::ShowTestWindow(nullptr);

  ImGui::End();

  ImGui::SetNextWindowPos(ImVec2(padding * 0.5f + ImGui::GetIO().DisplaySize.x
        * (1.f / 2.f), 25 + padding), ImGuiCond_Always);
  ImGui::SetNextWindowSize(ImVec2(ImGui::GetIO().DisplaySize.x * (1.f / 2.f)
        - padding * 1.5f, ImGui::GetIO().DisplaySize.y - 25 - padding * 2)
      , ImGuiCond_Always);

  ImGui::Begin("Graph", nullptr, ImGuiWindowFlags_NoResize
      | ImGuiWindowFlags_NoMove
      | ImGuiWindowFlags_NoTitleBar
      | ImGuiWindowFlags_NoCollapse);

  ImGui::SliderFloat("seconds", &g_seconds, 0.1f, 5.0f, "%.3f");
  ImGui::SliderFloat("frequency", &g_frequency, 16.35f, 1975.53f, "%.3f", 2.f);

  if (ImGui::Button("Replot"))
    replot();

  ImGui::PlotLines("", g_samples.data()
      , g_samples.size(), 0, g_passed_data->definition.c_str(), -1.f, 1.f, ImVec2(0, 200));

  ImGui::End();
}

static void frame() {
  glClear(GL_COLOR_BUFFER_BIT);
  draw_gui();
}

static void key_event(unsigned long long key, bool down) {
  if (!down && key == SDLK_ESCAPE)
    g_done = true;

  if (key_notes.count(key)) {
    const std::pair<char, int> note = key_notes.at(key);
    double freq = note_to_freq(note.first, g_octave, note.second);
    g_passed_data->frequencies[freq].on = down;
    if (!down)
      g_passed_data->frequencies[freq].c = 0;
  }
  if (key >= SDLK_0 && key <= SDLK_9)
    g_octave = key - SDLK_0;
}

static void destroy() {
  SDL_CloseAudioDevice(g_dev);
}

void reload_file() {
  if (g_passed_data->program)
    delete g_passed_data->program;
  g_messages.clear();

  std::string source = read_file("test.sth");
  strncpy(g_source, source.c_str(), sizeof(g_source));

  g_passed_data->program = lex_parse_string(g_source);
  if (!g_passed_data->program)
    exit(1);

  validate_top_level_functions(g_passed_data->program, &g_messages);
  // for (const message_t &message : messages)
  //   printf("%s: %s\n", message_kind_to_string(message.kind).c_str()
  //       , message.content.c_str());

  replot();
}

void replot() {
  g_samples.clear();
  const float amplitude = 32760, sample_rate = 44100, scale = 1.f;
  for (uint64_t i = 0; i < (uint64_t)(sample_rate * g_seconds + 0.5f); i++)
    g_samples.push_back((float)evaluate_definition(g_passed_data->program
          , g_passed_data->definition, g_frequency
          , (double)i / (double)sample_rate) * scale);
}

void live(std::string _filename, const std::string &definition) {
  g_filename = _filename;

  g_passed_data = new passed_data_t(definition);
  reload_file();

  int window_width = 1200, window_height = (3. / 4.) * (double)window_width + 0.5;
  gfx_init("Sythin", window_width, window_height);

  gfx_main_loop(&g_done, init, frame, update, key_event, destroy);

  if (g_passed_data->program)
    delete g_passed_data->program;
}

<commit_msg>Add frequency to note<commit_after>#include "eval.hh"
#include "live.hh"
#include "utils.hh"
#include "gfx.hh"
#include "lex.hh"
#include <SDL2/SDL.h>
#include <GL/glew.h>
#include "imgui.hh"
#include "../thirdparty/imgui/imgui.h"

struct passed_data_t {
  struct frequency_data_t {
    bool on;
    uint64_t c;
    frequency_data_t() : c(0) {}
  };
  term_t *program;
  const std::string definition;
  std::map<double, frequency_data_t> frequencies; // _very_ sloppy but works
  passed_data_t(const std::string &definition)
    : program(nullptr)
    , definition(definition) {
  }
};

static bool g_done = false;
static SDL_AudioDeviceID g_dev = 0;
static std::string g_filename = "";
static char g_source[100000]; // stupid
static passed_data_t *g_passed_data = nullptr;
static std::vector<message_t> g_messages;
static std::vector<float> g_samples;
static float g_frequency = 55.f /* A1 */, g_seconds = 1;
static std::string g_frequency_to_note = "";
static int g_octave = 4;
static const std::map<int, std::pair<char, int>> key_notes = {
  { SDLK_a, { 'C', 0 } },
  { SDLK_w, { 'C', 1 } },
  { SDLK_s, { 'D', 0 } },
  { SDLK_e, { 'D', 1 } },
  { SDLK_d, { 'E', 0 } },
  { SDLK_f, { 'F', 0 } },
  { SDLK_t, { 'F', 1 } },
  { SDLK_g, { 'G', 0 } },
  { SDLK_y, { 'G', 1 } },
  { SDLK_h, { 'A', 0 } },
  { SDLK_u, { 'A', 1 } },
  { SDLK_j, { 'B', 0 } }
};

void replot();

static double note_to_freq(char note, int octave, int accidental_offset) {
  /* TODO static */ const std::map<char, int> semitone_offset = {
    { 'C', -9 },
    { 'D', -7 },
    { 'E', -5 },
    { 'F', -4 },
    { 'G', -2 },
    { 'A',  0 },
    { 'B',  2 }
  };
  int octave_diff = octave - 4, semitone_diff = semitone_offset.at(note)
    + accidental_offset;
  return 440. * pow(2., octave_diff) * pow(2., semitone_diff / 12.);
}

static void audio_callback(void *userdata, uint8_t *stream, int len) {
  passed_data_t *passed_data = (passed_data_t*)userdata;
  float *stream_ptr = (float*)stream;
  for (int i = 0; i < 4096; ++i) {
    *stream_ptr = 0;
    for (auto &freq_pair : passed_data->frequencies)
      if (freq_pair.second.on) {
        double t = (double)(freq_pair.second.c++) * 1. / 48000.;
        float value = (float)evaluate_definition(passed_data->program
            , passed_data->definition, freq_pair.first, t);
        *stream_ptr += 0.2f * value;
      }
    ++stream_ptr;
  }
}

static void init() {
  SDL_AudioSpec want, have;
  SDL_memset(&want, 0, sizeof(want));
  want.freq = 48000;
  want.format = AUDIO_F32;
  want.channels = 1;
  want.samples = 4096;
  want.callback = audio_callback;
  want.userdata = (void*)g_passed_data;
  g_dev = SDL_OpenAudioDevice(nullptr, 0, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE);
  if (g_dev == 0)
    die("failed to open audio device: %s", SDL_GetError());
  SDL_PauseAudioDevice(g_dev, 0);

  float s = 20.f / 255.f;
  glClearColor(s, s, s, 1.f);
}

static void update(double dt, double t) {
}

static void draw_gui() {
  if (ImGui::BeginMainMenuBar()) {
    // ImGui::PushStyleColor(ImGuiCol_Button,        r2v( 67,  96, 123));
    // ImGui::PushStyleColor(ImGuiCol_ButtonHovered, r2v( 75, 108, 138));
    // ImGui::PushStyleColor(ImGuiCol_ButtonActive,  r2v( 83, 119, 153));

    ImGui::Text("%s - sythin", g_filename.c_str());

    ImGui::EndMainMenuBar();
  }

  const float padding = 5;

  ImGui::SetNextWindowPos(ImVec2(padding, 25 + padding), ImGuiCond_Always);
  ImGui::SetNextWindowSize(ImVec2(ImGui::GetIO().DisplaySize.x * (1.f / 2.f)
        - padding * 1.5f, ImGui::GetIO().DisplaySize.y - 25 - padding * 2)
      , ImGuiCond_Always);

  ImGui::Begin("Source code", nullptr, ImGuiWindowFlags_NoResize
      | ImGuiWindowFlags_NoMove
      | ImGuiWindowFlags_NoTitleBar
      | ImGuiWindowFlags_NoCollapse);

  if (ImGui::Button("Save")) {
  }
  ImGui::SameLine();
  if (ImGui::Button("Compile")) {
  }

  ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]);
  ImGui::InputTextMultiline("##source", g_source, sizeof(g_source)
      , ImVec2(-1.f, -1.f)
      , ImGuiInputTextFlags_AllowTabInput);
  ImGui::PopFont();

  ImGui::ShowTestWindow(nullptr);

  ImGui::End();

  ImGui::SetNextWindowPos(ImVec2(padding * 0.5f + ImGui::GetIO().DisplaySize.x
        * (1.f / 2.f), 25 + padding), ImGuiCond_Always);
  ImGui::SetNextWindowSize(ImVec2(ImGui::GetIO().DisplaySize.x * (1.f / 2.f)
        - padding * 1.5f, ImGui::GetIO().DisplaySize.y - 25 - padding * 2)
      , ImGuiCond_Always);

  ImGui::Begin("Graph", nullptr, ImGuiWindowFlags_NoResize
      | ImGuiWindowFlags_NoMove
      | ImGuiWindowFlags_NoTitleBar
      | ImGuiWindowFlags_NoCollapse);

  ImGui::Text("Time");
  ImGui::SameLine(80);
  ImGui::SliderFloat("seconds", &g_seconds, 0.1f, 5.0f, "%.3f");

  ImGui::Text("Frequency");
  ImGui::SameLine(80);
  ImGui::SliderFloat("Hz", &g_frequency, 16.35f, 1975.53f, "%.3f", 2.f);

  ImGui::SameLine();
  ImGui::Text("%s", g_frequency_to_note.c_str());

  if (ImGui::Button("Replot"))
    replot();

  ImGui::PlotLines("", g_samples.data()
      , g_samples.size(), 0, g_passed_data->definition.c_str(), -1.f, 1.f, ImVec2(ImGui::GetContentRegionAvailWidth(), 200));

  ImGui::End();
}

static void frame() {
  glClear(GL_COLOR_BUFFER_BIT);
  draw_gui();
}

static void key_event(unsigned long long key, bool down) {
  if (!down && key == SDLK_ESCAPE)
    g_done = true;

  if (key_notes.count(key)) {
    const std::pair<char, int> note = key_notes.at(key);
    double freq = note_to_freq(note.first, g_octave, note.second);
    g_passed_data->frequencies[freq].on = down;
    if (!down)
      g_passed_data->frequencies[freq].c = 0;
  }
  if (key >= SDLK_0 && key <= SDLK_9)
    g_octave = key - SDLK_0;
}

static void destroy() {
  SDL_CloseAudioDevice(g_dev);
}

void reload_file() {
  if (g_passed_data->program)
    delete g_passed_data->program;
  g_messages.clear();

  std::string source = read_file("test.sth");
  strncpy(g_source, source.c_str(), sizeof(g_source));

  g_passed_data->program = lex_parse_string(g_source);
  if (!g_passed_data->program)
    exit(1);

  validate_top_level_functions(g_passed_data->program, &g_messages);
  // for (const message_t &message : messages)
  //   printf("%s: %s\n", message_kind_to_string(message.kind).c_str()
  //       , message.content.c_str());

  replot();
}

void replot() {
  g_samples.clear();
  const float amplitude = 32760, sample_rate = 48000, scale = 1.f;
  for (uint64_t i = 0; i < (uint64_t)(sample_rate * g_seconds + 0.5f); i++)
    g_samples.push_back((float)evaluate_definition(g_passed_data->program
          , g_passed_data->definition, g_frequency
          , (double)i / (double)sample_rate) * scale);

  std::vector<std::string> notes = {
    "C0", "C#0", "D0", "D#0", "E0", "F0", "F#0", "G0", "G#0", "A0", "A#0", "B0",
    "C1", "C#1", "D1", "D#1", "E1", "F1", "F#1", "G1", "G#1", "A1", "A#1", "B1",
    "C2", "C#2", "D2", "D#2", "E2", "F2", "F#2", "G2", "G#2", "A2", "A#2", "B2",
    "C3", "C#3", "D3", "D#3", "E3", "F3", "F#3", "G3", "G#3", "A3", "A#3", "B3",
    "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4",
    "C5", "C#5", "D5", "D#5", "E5", "F5", "F#5", "G5", "G#5", "A5", "A#5", "B5",
    "C6", "C#6", "D6", "D#6", "E6", "F6", "F#6", "G6", "G#6", "A6", "A#6", "B6",
    "C7", "C#7", "D7", "D#7", "E7", "F7", "F#7", "G7", "G#7", "A7", "A#7", "B7",
    "C8", "C#8", "D8", "D#8", "E8", "F8", "F#8", "G8", "G#8", "A8", "A#8", "B8",
    "C9", "C#9", "D9", "D#9", "E9", "F9", "F#9", "G9", "G#9", "A9", "A#9", "B9"
  };

  int A4_idx = 57, minus = 0, plus = 1, r_index = 0, cent_index = 0, side;
  double A4 = 440., frequency = A4, r = pow(2.0, 1.0 / 12.0)
    , cent = pow(2.0, 1.0 / 1200.0), input = g_frequency;

  if (input >= frequency) {
    while (input >= r * frequency) {
      frequency = r * frequency;
      ++r_index;
    }
    while (input > cent * frequency) {
      frequency = cent * frequency;
      ++cent_index;
    }
    if ((cent * frequency - input) < (input - frequency))
      ++cent_index;
    if (cent_index > 50) {
      ++r_index;
      cent_index = 100 - cent_index;
      side = (cent_index != 0) ? minus : plus;
    } else
      side = plus;
  } else {
    while (input <= frequency / r) {
      frequency = frequency / r;
      --r_index;
    }
    while (input < frequency / cent) {
      frequency /= cent;
      ++cent_index;
    }
    if ((input - frequency / cent) < (frequency - input))
      ++cent_index;
    if (cent_index >= 50) {
      --r_index;
      cent_index = 100 - cent_index;
      side = plus;
    } else
      side = (cent_index != 0) ? minus : plus;
  }

  g_frequency_to_note = notes[A4_idx + r_index];
  g_frequency_to_note += (side == plus) ? " + " : " - ";
  g_frequency_to_note += std::to_string(cent_index) + " cents";
}

void live(std::string _filename, const std::string &definition) {
  g_filename = _filename;

  g_passed_data = new passed_data_t(definition);
  reload_file();

  int window_width = 1200, window_height = (3. / 4.) * (double)window_width + 0.5;
  gfx_init("Sythin", window_width, window_height);

  gfx_main_loop(&g_done, init, frame, update, key_event, destroy);

  if (g_passed_data->program)
    delete g_passed_data->program;
}

<|endoftext|>


<commit_before>/**
 * This file is part of Slideshow.
 * Copyright (C) 2008-2012 David Sveningsson <ext@sidvind.com>
 *
 * Slideshow is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Slideshow 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Slideshow.  If not, see <http://www.gnu.org/licenses/>.
 */

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

#include "log.hpp"
#include "ptr.h"
#include "exception.h"
#include <stdarg.h>
#include <cstdlib>
#include <cstring>
#include <memory> /* for auto_ptr */
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <portable/asprintf.h>
#include <portable/file.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef WIN32
#	include "win32.h"
#endif

#ifdef HAVE_SYSLOG
#	include <syslog.h>
int syslog_severity[5] = {
	LOG_DEBUG,
	LOG_INFO,
	LOG_NOTICE,
	LOG_WARNING,
	LOG_ERR
};
#endif /* HAVE_SYSLOG */

typedef std::vector<std::pair<Destination*, Severity>> vector;
typedef vector::iterator iterator;

static vector destinations;

FileDestination::FileDestination(const char* filename)
	: FileDestination(fopen(filename, "a")){

}

FileDestination::FileDestination(FILE* fp)
	: _fp(fp)
	, _autoclose(false) {

	if ( !fp ){
		fprintf(stderr, "Failed to read fp! Fatal error!\n");
		exit(1);
	}
}

FileDestination::~FileDestination(){
	if ( _autoclose ){
		fclose(_fp);
	}
}
void FileDestination::write(const char* content, const char* decorated) const {
	fputs(decorated, _fp);
	fflush(_fp);
}

FIFODestination::FIFODestination(const char* filename)
	: _filename(NULL)
	, _fp(NULL) {

	_filename = strdup(filename);
	mkfifo(filename, 0600);

	FILE* fp = fopen(filename, "w");
	if ( !fp ){
		fprintf(stderr, "Failed to open logfile '%s' ! Fatal error!\n", filename);
		exit(1);
	}
}

FIFODestination::~FIFODestination(){
	fclose(_fp);
	unlink(_filename);
	free(_filename);
}
void FIFODestination::write(const char* content, const char* decorated) const {
	fputs(decorated, _fp);
	fflush(_fp);
}

SocketDestination::SocketDestination(int socket)
	: _socket(socket) {

}

SocketDestination::~SocketDestination(){
	close(_socket);
}

void SocketDestination::write(const char* content, const char* decorated) const {
	send(_socket, decorated, strlen(decorated), 0);
}

#ifdef HAVE_SYSLOG
SyslogDestination::SyslogDestination(){
	/* @todo only a single instance of syslog may be opened */
	openlog(PACKAGE, 0, LOG_DAEMON);
}
SyslogDestination::~SyslogDestination(){
	closelog();
}
void SyslogDestination::write(const char* content, const char* decorated) const {
	syslog(syslog_severity[severity], content);
}
#endif /* HAVE_SYSLOG */

UDSServer::UDSServer(const char* filename)
	: _filename(NULL)
	, _socket(-1) {

	_filename = strdup(filename);

	struct sockaddr_un address;
	socklen_t address_length;

	_socket = socket(PF_UNIX, SOCK_STREAM, 0);

	unlink(filename);
	address.sun_family = AF_UNIX;
	address_length = (socklen_t)sizeof(address.sun_family) +
		(socklen_t)sprintf(address.sun_path, "%s", filename);

	bind(_socket, (struct sockaddr *) &address, address_length);
	listen(_socket, 5);
}

UDSServer::~UDSServer(){
	unlink(_filename);
	free(_filename);
}

bool UDSServer::accept(struct timeval *timeout) const {
	fd_set rfds;
	FD_ZERO(&rfds);
	FD_SET(_socket, &rfds);

	if ( select(_socket+1, &rfds, NULL, NULL, timeout) <= 0 ){
		return false;
	}

	int client = ::accept(_socket, NULL, NULL);
	Log::add_destination(new SocketDestination(client));

	return true;
}

namespace Log {

	static char *timestring(char *buffer, int bufferlen);
	static const char* severity_string(Severity severity);

	void initialize(){

	}

	void cleanup(){
		for ( iterator it = destinations.begin(); it != destinations.end(); ++it ){
			delete it->first;
		}
		destinations.clear();
	}

	void add_destination(Destination* dst, Severity severity){
		destinations.push_back(std::pair<Destination*, Severity>(dst, severity));
	}

	void message(Severity severity, const char* fmt, ...){
		va_list ap;
		va_start(ap, fmt);
		vmessage(severity, fmt, ap);
		va_end(ap);
	}

	void vmessage(Severity severity, const char* fmt, va_list ap){
		static char buf[255]; /* this isn't thread-safe anyway, might as well make it static */
		char* tmp;

		vasprintf(&tmp, fmt, ap);
		Ptr<char> content(tmp);

		asprintf(&tmp, "(%s) [%s] %s", severity_string(severity), timestring(buf, 255), content.get());
		Ptr<char> decorated(tmp);

		for ( iterator it = destinations.begin(); it != destinations.end(); ++it ){
			if ( severity < it->second ) continue;
			Destination* dst = it->first;
			dst->write(content.get(), decorated.get());
		}
	}

	char* timestring(char *buffer, int bufferlen) {
		time_t t = time(NULL);
		struct tm* nt;
#ifdef WIN32
		nt = new struct tm;
		localtime_s(nt, &t);
#else
		nt = localtime(&t);
#endif
		strftime(buffer, bufferlen, "%Y-%m-%d %H:%M:%S", nt);
#ifdef WIN32
		delete nt;
#endif
		return buffer;
	}

	const char* severity_string(Severity severity){
		switch ( severity ){
		case Log_Debug: return "DD";
		case Log_Verbose: return "--";
		case Log_Info: return "  ";
		case Log_Warning: return "WW";
		case Log_Fatal: return "!!";
		}
		return NULL;
	}

	void debug(const char* fmt, ...){
		va_list ap;
		va_start(ap, fmt);
		vmessage(Log_Debug, fmt, ap);
		va_end(ap);
	}

	void verbose(const char* fmt, ...){
		va_list ap;
		va_start(ap, fmt);
		vmessage(Log_Verbose, fmt, ap);
		va_end(ap);

	}

	void info(const char* fmt, ...){
		va_list ap;
		va_start(ap, fmt);
		vmessage(Log_Info, fmt, ap);
		va_end(ap);

	}

	void warning(const char* fmt, ...){
		va_list ap;
		va_start(ap, fmt);
		vmessage(Log_Warning, fmt, ap);
		va_end(ap);

	}

	void fatal(const char* fmt, ...){
		va_list ap;
		va_start(ap, fmt);
		vmessage(Log_Fatal, fmt, ap);
		va_end(ap);

	}

}

extern "C" void log_message(enum Severity severity, const char* fmt, ...){
	va_list ap;
	va_start(ap, fmt);
	log_vmessage(severity, fmt, ap);
	va_end(ap);
}

extern "C" void log_vmessage(enum Severity severity, const char* fmt, va_list ap){
	Log::vmessage(severity, fmt, ap);
}
<commit_msg>daemon: print errors<commit_after>/**
 * This file is part of Slideshow.
 * Copyright (C) 2008-2012 David Sveningsson <ext@sidvind.com>
 *
 * Slideshow is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Slideshow 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Slideshow.  If not, see <http://www.gnu.org/licenses/>.
 */

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

#include "log.hpp"
#include "ptr.h"
#include "exception.h"
#include <stdarg.h>
#include <cstdlib>
#include <cstring>
#include <memory> /* for auto_ptr */
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <portable/asprintf.h>
#include <portable/file.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef WIN32
#	include "win32.h"
#endif

#ifdef HAVE_SYSLOG
#	include <syslog.h>
int syslog_severity[5] = {
	LOG_DEBUG,
	LOG_INFO,
	LOG_NOTICE,
	LOG_WARNING,
	LOG_ERR
};
#endif /* HAVE_SYSLOG */

typedef std::vector<std::pair<Destination*, Severity>> vector;
typedef vector::iterator iterator;

static vector destinations;

FileDestination::FileDestination(const char* filename)
	: FileDestination(fopen(filename, "a")){

}

FileDestination::FileDestination(FILE* fp)
	: _fp(fp)
	, _autoclose(false) {

	if ( !fp ){
		fprintf(stderr, "Failed to read fp! Fatal error!\n");
		exit(1);
	}
}

FileDestination::~FileDestination(){
	if ( _autoclose ){
		fclose(_fp);
	}
}
void FileDestination::write(const char* content, const char* decorated) const {
	fputs(decorated, _fp);
	fflush(_fp);
}

FIFODestination::FIFODestination(const char* filename)
	: _filename(NULL)
	, _fp(NULL) {

	_filename = strdup(filename);
	mkfifo(filename, 0600);

	FILE* fp = fopen(filename, "w");
	if ( !fp ){
		fprintf(stderr, "Failed to open logfile '%s' ! Fatal error!\n", filename);
		exit(1);
	}
}

FIFODestination::~FIFODestination(){
	fclose(_fp);
	unlink(_filename);
	free(_filename);
}
void FIFODestination::write(const char* content, const char* decorated) const {
	fputs(decorated, _fp);
	fflush(_fp);
}

SocketDestination::SocketDestination(int socket)
	: _socket(socket) {

}

SocketDestination::~SocketDestination(){
	close(_socket);
}

void SocketDestination::write(const char* content, const char* decorated) const {
	send(_socket, decorated, strlen(decorated), 0);
}

#ifdef HAVE_SYSLOG
SyslogDestination::SyslogDestination(){
	/* @todo only a single instance of syslog may be opened */
	openlog(PACKAGE, 0, LOG_DAEMON);
}
SyslogDestination::~SyslogDestination(){
	closelog();
}
void SyslogDestination::write(const char* content, const char* decorated) const {
	syslog(syslog_severity[severity], content);
}
#endif /* HAVE_SYSLOG */

UDSServer::UDSServer(const char* filename)
	: _filename(NULL)
	, _socket(-1) {

	_filename = strdup(filename);

	struct sockaddr_un address;
	socklen_t address_length;

	_socket = socket(PF_UNIX, SOCK_STREAM, 0);
	if ( _socket == -1 ){
		fprintf(stderr, "socket error %d: %s\n", errno, strerror(errno));
	}

	unlink(filename);
	address.sun_family = AF_UNIX;
	address_length = (socklen_t)sizeof(address.sun_family) +
		(socklen_t)sprintf(address.sun_path, "%s", filename);

	printf("listening on %s\n", filename);
	if ( bind(_socket, (struct sockaddr *) &address, address_length) == -1 ){
		fprintf(stderr, "bind error %d: %s\n", errno, strerror(errno));
	}
	if ( listen(_socket, 5) == -1 ){
		fprintf(stderr, "listen error %d: %s\n", errno, strerror(errno));
	}
}

UDSServer::~UDSServer(){
	unlink(_filename);
	free(_filename);
}

bool UDSServer::accept(struct timeval *timeout) const {
	fd_set rfds;
	FD_ZERO(&rfds);
	FD_SET(_socket, &rfds);

	if ( select(_socket+1, &rfds, NULL, NULL, timeout) <= 0 ){
		return false;
	}

	int client = ::accept(_socket, NULL, NULL);
	Log::add_destination(new SocketDestination(client));

	return true;
}

namespace Log {

	static char *timestring(char *buffer, int bufferlen);
	static const char* severity_string(Severity severity);

	void initialize(){

	}

	void cleanup(){
		for ( iterator it = destinations.begin(); it != destinations.end(); ++it ){
			delete it->first;
		}
		destinations.clear();
	}

	void add_destination(Destination* dst, Severity severity){
		destinations.push_back(std::pair<Destination*, Severity>(dst, severity));
	}

	void message(Severity severity, const char* fmt, ...){
		va_list ap;
		va_start(ap, fmt);
		vmessage(severity, fmt, ap);
		va_end(ap);
	}

	void vmessage(Severity severity, const char* fmt, va_list ap){
		static char buf[255]; /* this isn't thread-safe anyway, might as well make it static */
		char* tmp;

		vasprintf(&tmp, fmt, ap);
		Ptr<char> content(tmp);

		asprintf(&tmp, "(%s) [%s] %s", severity_string(severity), timestring(buf, 255), content.get());
		Ptr<char> decorated(tmp);

		for ( iterator it = destinations.begin(); it != destinations.end(); ++it ){
			if ( severity < it->second ) continue;
			Destination* dst = it->first;
			dst->write(content.get(), decorated.get());
		}
	}

	char* timestring(char *buffer, int bufferlen) {
		time_t t = time(NULL);
		struct tm* nt;
#ifdef WIN32
		nt = new struct tm;
		localtime_s(nt, &t);
#else
		nt = localtime(&t);
#endif
		strftime(buffer, bufferlen, "%Y-%m-%d %H:%M:%S", nt);
#ifdef WIN32
		delete nt;
#endif
		return buffer;
	}

	const char* severity_string(Severity severity){
		switch ( severity ){
		case Log_Debug: return "DD";
		case Log_Verbose: return "--";
		case Log_Info: return "  ";
		case Log_Warning: return "WW";
		case Log_Fatal: return "!!";
		}
		return NULL;
	}

	void debug(const char* fmt, ...){
		va_list ap;
		va_start(ap, fmt);
		vmessage(Log_Debug, fmt, ap);
		va_end(ap);
	}

	void verbose(const char* fmt, ...){
		va_list ap;
		va_start(ap, fmt);
		vmessage(Log_Verbose, fmt, ap);
		va_end(ap);

	}

	void info(const char* fmt, ...){
		va_list ap;
		va_start(ap, fmt);
		vmessage(Log_Info, fmt, ap);
		va_end(ap);

	}

	void warning(const char* fmt, ...){
		va_list ap;
		va_start(ap, fmt);
		vmessage(Log_Warning, fmt, ap);
		va_end(ap);

	}

	void fatal(const char* fmt, ...){
		va_list ap;
		va_start(ap, fmt);
		vmessage(Log_Fatal, fmt, ap);
		va_end(ap);

	}

}

extern "C" void log_message(enum Severity severity, const char* fmt, ...){
	va_list ap;
	va_start(ap, fmt);
	log_vmessage(severity, fmt, ap);
	va_end(ap);
}

extern "C" void log_vmessage(enum Severity severity, const char* fmt, va_list ap){
	Log::vmessage(severity, fmt, ap);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <string>
#include <uv.h>

#include "log.h"

#include <iomanip>

using std::endl;
using std::ostream;
using std::ofstream;
using std::string;
using std::dec;
using std::setw;

class NullLogger : public Logger {
public:
  NullLogger()
  {
    //
  }

  virtual Logger* prefix(const char *file, int line) override
  {
    return this;
  }

  virtual ostream& stream() override
  {
    return unopened;
  }

private:
  ofstream unopened;
};

class FileLogger : public Logger {
public:
  FileLogger(const char *filename) : log_stream{filename, std::ios::out | std::ios::app}
  {
    prefix(__FILE__, __LINE__);
    log_stream << "FileLogger opened." << endl;
  }

  virtual Logger* prefix(const char *file, int line) override
  {
    log_stream << "[" << setw(15) << file << ":" << setw(3) << dec << line << "] ";
    return this;
  }

  virtual ostream& stream() override
  {
    return log_stream;
  }

private:
  ofstream log_stream;
};

static uv_key_t current_logger_key;
static NullLogger the_null_logger;
static uv_once_t make_key_once = UV_ONCE_INIT;

static void make_key()
{
  uv_key_create(&current_logger_key);
}

Logger* Logger::current()
{
  uv_once(&make_key_once, &make_key);

  Logger* logger = (Logger*) uv_key_get(&current_logger_key);

  if (logger == nullptr) {
    uv_key_set(&current_logger_key, (void*) &the_null_logger);
    logger = &the_null_logger;
  }

  return logger;
}

static void replace_logger(const Logger *new_logger)
{
  Logger *prior = Logger::current();
  if (prior != &the_null_logger) {
    delete prior;
  }

  uv_key_set(&current_logger_key, (void*) new_logger);
}

void Logger::to_file(const char *filename)
{
  replace_logger(new FileLogger(filename));
}

void Logger::disable()
{
  replace_logger(&the_null_logger);
}

string plural(long quantity, const string &singular_form, const string &plural_form)
{
  string result("");
  result += quantity;
  result += " ";

  if (quantity == 1) {
    result += singular_form;
  } else {
    result += plural_form;
  }

  return result;
}

string plural(long quantity, const string &singular_form)
{
  string plural_form(singular_form + "s");
  return plural(quantity, singular_form, plural_form);
}
<commit_msg>Fix that other build warning while I'm here<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <uv.h>

#include "log.h"

#include <iomanip>

using std::endl;
using std::ostream;
using std::ofstream;
using std::string;
using std::to_string;
using std::dec;
using std::setw;

class NullLogger : public Logger {
public:
  NullLogger()
  {
    //
  }

  virtual Logger* prefix(const char *file, int line) override
  {
    return this;
  }

  virtual ostream& stream() override
  {
    return unopened;
  }

private:
  ofstream unopened;
};

class FileLogger : public Logger {
public:
  FileLogger(const char *filename) : log_stream{filename, std::ios::out | std::ios::app}
  {
    prefix(__FILE__, __LINE__);
    log_stream << "FileLogger opened." << endl;
  }

  virtual Logger* prefix(const char *file, int line) override
  {
    log_stream << "[" << setw(15) << file << ":" << setw(3) << dec << line << "] ";
    return this;
  }

  virtual ostream& stream() override
  {
    return log_stream;
  }

private:
  ofstream log_stream;
};

static uv_key_t current_logger_key;
static NullLogger the_null_logger;
static uv_once_t make_key_once = UV_ONCE_INIT;

static void make_key()
{
  uv_key_create(&current_logger_key);
}

Logger* Logger::current()
{
  uv_once(&make_key_once, &make_key);

  Logger* logger = (Logger*) uv_key_get(&current_logger_key);

  if (logger == nullptr) {
    uv_key_set(&current_logger_key, (void*) &the_null_logger);
    logger = &the_null_logger;
  }

  return logger;
}

static void replace_logger(const Logger *new_logger)
{
  Logger *prior = Logger::current();
  if (prior != &the_null_logger) {
    delete prior;
  }

  uv_key_set(&current_logger_key, (void*) new_logger);
}

void Logger::to_file(const char *filename)
{
  replace_logger(new FileLogger(filename));
}

void Logger::disable()
{
  replace_logger(&the_null_logger);
}

string plural(long quantity, const string &singular_form, const string &plural_form)
{
  string result("");
  result += to_string(quantity);
  result += " ";

  if (quantity == 1) {
    result += singular_form;
  } else {
    result += plural_form;
  }

  return result;
}

string plural(long quantity, const string &singular_form)
{
  string plural_form(singular_form + "s");
  return plural(quantity, singular_form, plural_form);
}
<|endoftext|>


<commit_before>/****************************************************************************
 *    Copyright (C) 2017-2019 Savoir-faire Linux Inc.                       *
 *   Author : Nicolas Jäger <nicolas.jager@savoirfairelinux.com>            *
 *   Author : Sébastien Blin <sebastien.blin@savoirfairelinux.com>          *
 *                                                                          *
 *   This library 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 library 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 General Public License      *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 ***************************************************************************/
#include "api/lrc.h"

#include <locale>

#ifndef _MSC_VER
#include <unistd.h>
#else
#include "../../daemon/MSVC/unistd.h"
#endif // !_MSC_VER

#include "call_const.h"

// Models and database
#include "api/avmodel.h"
#include "api/behaviorcontroller.h"
#include "api/datatransfermodel.h"
#include "api/newaccountmodel.h"
#include "callbackshandler.h"
#include "dbus/callmanager.h"
#include "dbus/configurationmanager.h"
#include "dbus/instancemanager.h"
#include "dbus/configurationmanager.h"
#include "authority/storagehelper.h"

namespace lrc
{

using namespace api;

// To judge whether the call is finished or not depending on callState
bool isFinished(const QString& callState);

class LrcPimpl
{

public:
    LrcPimpl(Lrc& linked, MigrationCb& willMigrateCb, MigrationCb& didMigrateCb);

    const Lrc& linked;
    std::unique_ptr<BehaviorController> behaviorController;
    std::unique_ptr<CallbacksHandler> callbackHandler;
    std::unique_ptr<NewAccountModel> accountModel;
    std::unique_ptr<DataTransferModel> dataTransferModel;
    std::unique_ptr<AVModel> AVModel_;

};

Lrc::Lrc(MigrationCb willDoMigrationCb, MigrationCb didDoMigrationCb)
{
    // Replace locale for timestamps
    std::locale::global(std::locale(""));
    // Ensure Daemon is running/loaded (especially on non-DBus platforms)
    // before instantiating LRC and its members
    InstanceManager::instance();
    lrcPimpl_ = std::make_unique<LrcPimpl>(*this, willDoMigrationCb, didDoMigrationCb);
}

Lrc::~Lrc()
{
    //Unregister from the daemon
    InstanceManagerInterface& instance = InstanceManager::instance();
    Q_NOREPLY instance.Unregister(getpid());
#ifndef ENABLE_LIBWRAP
    instance.connection().disconnectFromBus(instance.connection().baseService());
#endif //ENABLE_LIBWRAP
}

NewAccountModel&
Lrc::getAccountModel() const
{
    return *lrcPimpl_->accountModel;
}

BehaviorController&
Lrc::getBehaviorController() const
{
    return *lrcPimpl_->behaviorController;
}

DataTransferModel&
Lrc::getDataTransferModel() const
{
    return *lrcPimpl_->dataTransferModel;
}

AVModel&
Lrc::getAVModel() const
{
    return *lrcPimpl_->AVModel_;
}

void
Lrc::connectivityChanged() const
{
    ConfigurationManager::instance().connectivityChanged();
}

bool
Lrc::isConnected()
{
#ifdef ENABLE_LIBWRAP
    return true;
#else
    return ConfigurationManager::instance().connection().isConnected();
#endif
}

bool
Lrc::dbusIsValid()
{
#ifdef ENABLE_LIBWRAP
    return true;
#else
    return ConfigurationManager::instance().isValid();
#endif
}

void
Lrc::subscribeToDebugReceived()
{
    lrcPimpl_->callbackHandler->subscribeToDebugReceived();
}

std::vector<std::string>
Lrc::activeCalls()
{
    QStringList callLists = CallManager::instance().getCallList();
    std::vector<std::string> result;
    result.reserve(callLists.size());
    for (const auto &call : callLists) {
        MapStringString callDetails = CallManager::instance().getCallDetails(call);
        if(!isFinished(callDetails[QString(DRing::Call::Details::CALL_STATE)]))
            result.emplace_back(call.toStdString());
    }
    return result;
}

std::vector<std::string>
Lrc::getCalls()
{
    QStringList callLists = CallManager::instance().getCallList();
    std::vector<std::string> result;
    result.reserve(callLists.size());
    for (const auto &call : callLists) {
        result.emplace_back(call.toStdString());
    }
    return result;
}

std::vector<std::string>
Lrc::getConferences()
{
    QStringList conferencesList = CallManager::instance().getConferenceList();
    std::vector<std::string> result;
    result.reserve(conferencesList.size());
    for (const auto &conf : conferencesList) {
        result.emplace_back(conf.toStdString());
    }
    return result;
}

std::vector<std::string>
Lrc::getConferenceSubcalls(const std::string& cid)
{
    QStringList callList = CallManager::instance().getParticipantList(cid.c_str());
    std::vector<std::string> result;
    result.reserve(callList.size());
    foreach(const auto& callId, callList) {
        result.emplace_back(callId.toStdString());
    }
    return result;
}

bool
isFinished(const QString& callState)
{
    if (callState == QLatin1String(DRing::Call::StateEvent::HUNGUP) ||
        callState == QLatin1String(DRing::Call::StateEvent::BUSY) ||
        callState == QLatin1String(DRing::Call::StateEvent::PEER_BUSY) ||
        callState == QLatin1String(DRing::Call::StateEvent::FAILURE) ||
        callState == QLatin1String(DRing::Call::StateEvent::INACTIVE) ||
        callState == QLatin1String(DRing::Call::StateEvent::OVER)) {
        return true;
    }
    return false;
}

LrcPimpl::LrcPimpl(Lrc& linked, MigrationCb& willMigrateCb, MigrationCb& didMigrateCb)
: linked(linked)
, behaviorController(std::make_unique<BehaviorController>())
, callbackHandler(std::make_unique<CallbacksHandler>(linked))
, accountModel(std::make_unique<NewAccountModel>(linked, *callbackHandler, *behaviorController, willMigrateCb, didMigrateCb))
, dataTransferModel {std::make_unique<DataTransferModel>()}
, AVModel_ {std::make_unique<AVModel>(*callbackHandler)}
{
}

} // namespace lrc
<commit_msg>locale: disable for libwrap because it breaks the daemon<commit_after>/****************************************************************************
 *    Copyright (C) 2017-2019 Savoir-faire Linux Inc.                       *
 *   Author : Nicolas Jäger <nicolas.jager@savoirfairelinux.com>            *
 *   Author : Sébastien Blin <sebastien.blin@savoirfairelinux.com>          *
 *                                                                          *
 *   This library 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 library 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 General Public License      *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 ***************************************************************************/
#include "api/lrc.h"

#include <locale>

#ifndef _MSC_VER
#include <unistd.h>
#else
#include "../../daemon/MSVC/unistd.h"
#endif // !_MSC_VER

#include "call_const.h"

// Models and database
#include "api/avmodel.h"
#include "api/behaviorcontroller.h"
#include "api/datatransfermodel.h"
#include "api/newaccountmodel.h"
#include "callbackshandler.h"
#include "dbus/callmanager.h"
#include "dbus/configurationmanager.h"
#include "dbus/instancemanager.h"
#include "dbus/configurationmanager.h"
#include "authority/storagehelper.h"

namespace lrc
{

using namespace api;

// To judge whether the call is finished or not depending on callState
bool isFinished(const QString& callState);

class LrcPimpl
{

public:
    LrcPimpl(Lrc& linked, MigrationCb& willMigrateCb, MigrationCb& didMigrateCb);

    const Lrc& linked;
    std::unique_ptr<BehaviorController> behaviorController;
    std::unique_ptr<CallbacksHandler> callbackHandler;
    std::unique_ptr<NewAccountModel> accountModel;
    std::unique_ptr<DataTransferModel> dataTransferModel;
    std::unique_ptr<AVModel> AVModel_;

};

Lrc::Lrc(MigrationCb willDoMigrationCb, MigrationCb didDoMigrationCb)
{
#ifndef ENABLE_LIBWRAP
    // Replace locale for timestamps
    std::locale::global(std::locale(""));
#endif
    // Ensure Daemon is running/loaded (especially on non-DBus platforms)
    // before instantiating LRC and its members
    InstanceManager::instance();
    lrcPimpl_ = std::make_unique<LrcPimpl>(*this, willDoMigrationCb, didDoMigrationCb);
}

Lrc::~Lrc()
{
    //Unregister from the daemon
    InstanceManagerInterface& instance = InstanceManager::instance();
    Q_NOREPLY instance.Unregister(getpid());
#ifndef ENABLE_LIBWRAP
    instance.connection().disconnectFromBus(instance.connection().baseService());
#endif //ENABLE_LIBWRAP
}

NewAccountModel&
Lrc::getAccountModel() const
{
    return *lrcPimpl_->accountModel;
}

BehaviorController&
Lrc::getBehaviorController() const
{
    return *lrcPimpl_->behaviorController;
}

DataTransferModel&
Lrc::getDataTransferModel() const
{
    return *lrcPimpl_->dataTransferModel;
}

AVModel&
Lrc::getAVModel() const
{
    return *lrcPimpl_->AVModel_;
}

void
Lrc::connectivityChanged() const
{
    ConfigurationManager::instance().connectivityChanged();
}

bool
Lrc::isConnected()
{
#ifdef ENABLE_LIBWRAP
    return true;
#else
    return ConfigurationManager::instance().connection().isConnected();
#endif
}

bool
Lrc::dbusIsValid()
{
#ifdef ENABLE_LIBWRAP
    return true;
#else
    return ConfigurationManager::instance().isValid();
#endif
}

void
Lrc::subscribeToDebugReceived()
{
    lrcPimpl_->callbackHandler->subscribeToDebugReceived();
}

std::vector<std::string>
Lrc::activeCalls()
{
    QStringList callLists = CallManager::instance().getCallList();
    std::vector<std::string> result;
    result.reserve(callLists.size());
    for (const auto &call : callLists) {
        MapStringString callDetails = CallManager::instance().getCallDetails(call);
        if(!isFinished(callDetails[QString(DRing::Call::Details::CALL_STATE)]))
            result.emplace_back(call.toStdString());
    }
    return result;
}

std::vector<std::string>
Lrc::getCalls()
{
    QStringList callLists = CallManager::instance().getCallList();
    std::vector<std::string> result;
    result.reserve(callLists.size());
    for (const auto &call : callLists) {
        result.emplace_back(call.toStdString());
    }
    return result;
}

std::vector<std::string>
Lrc::getConferences()
{
    QStringList conferencesList = CallManager::instance().getConferenceList();
    std::vector<std::string> result;
    result.reserve(conferencesList.size());
    for (const auto &conf : conferencesList) {
        result.emplace_back(conf.toStdString());
    }
    return result;
}

std::vector<std::string>
Lrc::getConferenceSubcalls(const std::string& cid)
{
    QStringList callList = CallManager::instance().getParticipantList(cid.c_str());
    std::vector<std::string> result;
    result.reserve(callList.size());
    foreach(const auto& callId, callList) {
        result.emplace_back(callId.toStdString());
    }
    return result;
}

bool
isFinished(const QString& callState)
{
    if (callState == QLatin1String(DRing::Call::StateEvent::HUNGUP) ||
        callState == QLatin1String(DRing::Call::StateEvent::BUSY) ||
        callState == QLatin1String(DRing::Call::StateEvent::PEER_BUSY) ||
        callState == QLatin1String(DRing::Call::StateEvent::FAILURE) ||
        callState == QLatin1String(DRing::Call::StateEvent::INACTIVE) ||
        callState == QLatin1String(DRing::Call::StateEvent::OVER)) {
        return true;
    }
    return false;
}

LrcPimpl::LrcPimpl(Lrc& linked, MigrationCb& willMigrateCb, MigrationCb& didMigrateCb)
: linked(linked)
, behaviorController(std::make_unique<BehaviorController>())
, callbackHandler(std::make_unique<CallbacksHandler>(linked))
, accountModel(std::make_unique<NewAccountModel>(linked, *callbackHandler, *behaviorController, willMigrateCb, didMigrateCb))
, dataTransferModel {std::make_unique<DataTransferModel>()}
, AVModel_ {std::make_unique<AVModel>(*callbackHandler)}
{
}

} // namespace lrc
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

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

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

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

*/

#include "libtorrent/pch.hpp"

#include "libtorrent/lsd.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/http_tracker_connection.hpp"

#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <asio/ip/host_name.hpp>
#include <asio/ip/multicast.hpp>
#include <boost/thread/mutex.hpp>
#include <cstdlib>
#include <boost/config.hpp>

using boost::bind;
using namespace libtorrent;

namespace libtorrent
{
	// defined in broadcast_socket.cpp
	address guess_local_address(asio::io_service&);
}

lsd::lsd(io_service& ios, address const& listen_interface
	, peer_callback_t const& cb)
	: m_callback(cb)
	, m_retry_count(0)
	, m_socket(ios, udp::endpoint(address_v4::from_string("239.192.152.143"), 6771)
		, bind(&lsd::on_announce, self(), _1, _2, _3))
	, m_broadcast_timer(ios)
	, m_disabled(false)
{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log.open("lsd.log", std::ios::in | std::ios::out | std::ios::trunc);
#endif
}

lsd::~lsd() {}

void lsd::announce(sha1_hash const& ih, int listen_port)
{
	if (m_disabled) return;

	std::stringstream btsearch;
	btsearch << "BT-SEARCH * HTTP/1.1\r\n"
		"Host: 239.192.152.143:6771\r\n"
		"Port: " << listen_port << "\r\n"
		"Infohash: " << ih << "\r\n"
		"\r\n\r\n";
	std::string const& msg = btsearch.str();

	m_retry_count = 0;
	asio::error_code ec;
	m_socket.send(msg.c_str(), int(msg.size()), ec);
	if (ec)
	{
		m_disabled = true;
		return;
	}

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " ==> announce: ih: " << ih << " port: " << listen_port << std::endl;
#endif

	m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count));
	m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
}

void lsd::resend_announce(asio::error_code const& e, std::string msg) try
{
	if (e) return;

	asio::error_code ec;
	m_socket.send(msg.c_str(), int(msg.size()), ec);

	++m_retry_count;
	if (m_retry_count >= 5)
		return;

	m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count));
	m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
}
catch (std::exception&)
{}

void lsd::on_announce(udp::endpoint const& from, char* buffer
	, std::size_t bytes_transferred)
{
	using namespace libtorrent::detail;

	http_parser p;

	bool error = false;
	p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred)
		, error);

	if (!p.header_finished() || error)
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: incomplete HTTP message\n";
#endif
		return;
	}

	if (p.method() != "bt-search")
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid HTTP method: " << p.method() << std::endl;
#endif
		return;
	}

	std::string const& port_str = p.header("port");
	if (port_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing port" << std::endl;
#endif
		return;
	}

	std::string const& ih_str = p.header("infohash");
	if (ih_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing infohash" << std::endl;
#endif
		return;
	}

	sha1_hash ih(0);
	std::istringstream ih_sstr(ih_str);
	ih_sstr >> ih;
	int port = atoi(port_str.c_str());

	if (!ih.is_all_zeros() && port != 0)
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		m_log << time_now_string()
			<< " *** incoming local announce " << from.address()
			<< ":" << port << " ih: " << ih << std::endl;
#endif
		// we got an announce, pass it on through the callback
		try { m_callback(tcp::endpoint(from.address(), port), ih); }
		catch (std::exception&) {}
	}
}

void lsd::close()
{
	m_socket.close();
	m_broadcast_timer.cancel();
	m_disabled = true;
	m_callback.clear();
}

<commit_msg>made lsd build without exception support<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

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

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

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

*/

#include "libtorrent/pch.hpp"

#include "libtorrent/lsd.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/http_tracker_connection.hpp"

#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <asio/ip/host_name.hpp>
#include <asio/ip/multicast.hpp>
#include <boost/thread/mutex.hpp>
#include <cstdlib>
#include <boost/config.hpp>

using boost::bind;
using namespace libtorrent;

namespace libtorrent
{
	// defined in broadcast_socket.cpp
	address guess_local_address(asio::io_service&);
}

lsd::lsd(io_service& ios, address const& listen_interface
	, peer_callback_t const& cb)
	: m_callback(cb)
	, m_retry_count(0)
	, m_socket(ios, udp::endpoint(address_v4::from_string("239.192.152.143"), 6771)
		, bind(&lsd::on_announce, self(), _1, _2, _3))
	, m_broadcast_timer(ios)
	, m_disabled(false)
{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log.open("lsd.log", std::ios::in | std::ios::out | std::ios::trunc);
#endif
}

lsd::~lsd() {}

void lsd::announce(sha1_hash const& ih, int listen_port)
{
	if (m_disabled) return;

	std::stringstream btsearch;
	btsearch << "BT-SEARCH * HTTP/1.1\r\n"
		"Host: 239.192.152.143:6771\r\n"
		"Port: " << listen_port << "\r\n"
		"Infohash: " << ih << "\r\n"
		"\r\n\r\n";
	std::string const& msg = btsearch.str();

	m_retry_count = 0;
	asio::error_code ec;
	m_socket.send(msg.c_str(), int(msg.size()), ec);
	if (ec)
	{
		m_disabled = true;
		return;
	}

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " ==> announce: ih: " << ih << " port: " << listen_port << std::endl;
#endif

	m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count), ec);
	m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
}

void lsd::resend_announce(asio::error_code const& e, std::string msg)
{
	if (e) return;

	asio::error_code ec;
	m_socket.send(msg.c_str(), int(msg.size()), ec);

	++m_retry_count;
	if (m_retry_count >= 5)
		return;

	m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count), ec);
	m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
}

void lsd::on_announce(udp::endpoint const& from, char* buffer
	, std::size_t bytes_transferred)
{
	using namespace libtorrent::detail;

	http_parser p;

	bool error = false;
	p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred)
		, error);

	if (!p.header_finished() || error)
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: incomplete HTTP message\n";
#endif
		return;
	}

	if (p.method() != "bt-search")
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid HTTP method: " << p.method() << std::endl;
#endif
		return;
	}

	std::string const& port_str = p.header("port");
	if (port_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing port" << std::endl;
#endif
		return;
	}

	std::string const& ih_str = p.header("infohash");
	if (ih_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing infohash" << std::endl;
#endif
		return;
	}

	sha1_hash ih(0);
	std::istringstream ih_sstr(ih_str);
	ih_sstr >> ih;
	int port = atoi(port_str.c_str());

	if (!ih.is_all_zeros() && port != 0)
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		m_log << time_now_string()
			<< " *** incoming local announce " << from.address()
			<< ":" << port << " ih: " << ih << std::endl;
#endif
		// we got an announce, pass it on through the callback
#ifndef BOOST_NO_EXCEPTIONS
		try {
#endif
			m_callback(tcp::endpoint(from.address(), port), ih);
#ifndef BOOST_NO_EXCEPTIONS
		}
		catch (std::exception&) {}
#endif
	}
}

void lsd::close()
{
	m_socket.close();
	asio::error_code ec;
	m_broadcast_timer.cancel(ec);
	m_disabled = true;
	m_callback.clear();
}

<|endoftext|>


<commit_before>#include <assert.h>
#include <iostream>

// fte includes
#include "fte/fte.h"
#include "tests/dfas.h"

// ffx includes
#include "ffx/ffx.h"

// ranking includes
#include "fte/ranking/dfa.h"

int main(int argc, char **argv) {
  // fte example
  fte::Key K = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; // 128 bits, in hex
  fte::FTE fteObj = fte::FTE(VALID_DFA_5, 16,
                             VALID_DFA_1, 128,
                             K);
  std::string X = "Hello, Word!";
  std::string Y = fteObj.encrypt(X);
  std::string Z = fteObj.decrypt(Y);

  std::cout << "fte:" << std::endl;
  std::cout << "- X: " << X << std::endl;
  std::cout << "- Y: " << Y << std::endl;
  std::cout << "- Z: " << Z << std::endl;

  assert(X == Z);
}
<commit_msg>removal of stray headers<commit_after>#include <assert.h>
#include <iostream>

// fte includes
#include "fte/fte.h"
#include "tests/dfas.h"

int main(int argc, char **argv) {
  // fte example
  fte::Key K = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; // 128 bits, in hex
  fte::FTE fteObj = fte::FTE(VALID_DFA_5, 16,
                             VALID_DFA_1, 128,
                             K);
  std::string X = "Hello, Word!";
  std::string Y = fteObj.encrypt(X);
  std::string Z = fteObj.decrypt(Y);

  std::cout << "fte:" << std::endl;
  std::cout << "- X: " << X << std::endl;
  std::cout << "- Y: " << Y << std::endl;
  std::cout << "- Z: " << Z << std::endl;

  assert(X == Z);
}
<|endoftext|>


<commit_before>/*
 *  Copyright (C) 2014  Mario Alviano (mario@alviano.net)
 *
 *  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 "AbstractSolver.h"
#include "SatSolver.h"
#include "PseudoBooleanSolver.h"
#include "MaxSatSolver.h"
#include "utils/trace.h"

#include <utils/Options.h>

#include <errno.h>
#include <signal.h>
#include <zlib.h>

#include <string>
#include <iostream>
#include <fpu_control.h>

using namespace aspino;
using namespace std;

static Glucose::EnumOption option_mode("MAIN", "mode", "How to interpret input.\n", "asp|sat|maxsat|pbs");
static Glucose::IntOption option_n("MAIN", "n", "Number of desired solutions. Non-positive integers are interpreted as unbounded.\n", 1, Glucose::IntRange(0, INT32_MAX));

static aspino::AbstractSolver* solver;

static void SIGINT_interrupt(int) { solver->interrupt(); }

static Glucose::IntOption opt_size_lbd_queue("SUK", "szLBDQueue", "The size of moving average for LBD (restarts)", 50, Glucose::IntRange(10, INT32_MAX));

int main(int argc, char** argv)
{
    signal(SIGINT, SIGINT_interrupt);
    signal(SIGTERM, SIGINT_interrupt);

    Glucose::setUsageHelp(
        "Solve ASP or SAT problems read from STDIN or provided as command-line argument.\n\n"
        "usage: %s [flags] [input-file]\n");

#if defined(__linux__)
    fpu_control_t oldcw, newcw;
    _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw);
    //printf("c WARNING: for repeatability, setting FPU to use double precision\n");
#endif

    Glucose::IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", INT32_MAX, Glucose::IntRange(0, INT32_MAX));
    Glucose::IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", INT32_MAX, Glucose::IntRange(0, INT32_MAX));

//    gflags::ParseCommandLineFlags(&argc, &argv, true);

    Glucose::parseOptions(argc, argv, true);

    if(strcmp(option_mode, "asp") == 0)
//        solver = new AspSolver();
        { cerr << "ASP is not currently supported." << endl; exit(-1); }
    else if(strcmp(option_mode, "sat") == 0)
        solver = new SatSolver();
    else if(strcmp(option_mode, "maxsat") == 0)
        solver = new MaxSatSolver();
    else if(strcmp(option_mode, "pbs") == 0)
        solver = new PseudoBooleanSolver();
    else
        assert(0);

    if(argc > 2) {
        cerr << "Extra argument: " << argv[2] << endl;
        solver->exit(-1);
    }

    gzFile in = argc == 1 ? gzdopen(0, "rb") : gzopen(argv[1], "rb");
    solver->parse(in);
    gzclose(in);

    solver->eliminate(true);
    if(!solver->okay()) {
        cout << "UNSATISFIABLE" << endl;
        solver->exit(20);
    }

    lbool ret = solver->solve(option_n);

#ifndef SAFE_EXIT
    solver->exit(ret == l_True ? 10 : ret == l_False ? 20 : 0);     // (faster than "return", which will invoke the destructor for 'Solver')
#else
    delete solver;
    return (ret == l_True ? 10 : ret == l_False ? 20 : 0);
#endif
}<commit_msg>Remove useless flag.<commit_after>/*
 *  Copyright (C) 2014  Mario Alviano (mario@alviano.net)
 *
 *  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 "AbstractSolver.h"
#include "SatSolver.h"
#include "PseudoBooleanSolver.h"
#include "MaxSatSolver.h"
#include "utils/trace.h"

#include <utils/Options.h>

#include <errno.h>
#include <signal.h>
#include <zlib.h>

#include <string>
#include <iostream>
#include <fpu_control.h>

using namespace aspino;
using namespace std;

static Glucose::EnumOption option_mode("MAIN", "mode", "How to interpret input.\n", "asp|sat|maxsat|pbs");
static Glucose::IntOption option_n("MAIN", "n", "Number of desired solutions. Non-positive integers are interpreted as unbounded.\n", 1, Glucose::IntRange(0, INT32_MAX));

static aspino::AbstractSolver* solver;

static void SIGINT_interrupt(int) { solver->interrupt(); }

int main(int argc, char** argv)
{
    signal(SIGINT, SIGINT_interrupt);
    signal(SIGTERM, SIGINT_interrupt);

    Glucose::setUsageHelp(
        "Solve ASP or SAT problems read from STDIN or provided as command-line argument.\n\n"
        "usage: %s [flags] [input-file]\n");

#if defined(__linux__)
    fpu_control_t oldcw, newcw;
    _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw);
    //printf("c WARNING: for repeatability, setting FPU to use double precision\n");
#endif

    Glucose::IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", INT32_MAX, Glucose::IntRange(0, INT32_MAX));
    Glucose::IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", INT32_MAX, Glucose::IntRange(0, INT32_MAX));

//    gflags::ParseCommandLineFlags(&argc, &argv, true);

    Glucose::parseOptions(argc, argv, true);

    if(strcmp(option_mode, "asp") == 0)
//        solver = new AspSolver();
        { cerr << "ASP is not currently supported." << endl; exit(-1); }
    else if(strcmp(option_mode, "sat") == 0)
        solver = new SatSolver();
    else if(strcmp(option_mode, "maxsat") == 0)
        solver = new MaxSatSolver();
    else if(strcmp(option_mode, "pbs") == 0)
        solver = new PseudoBooleanSolver();
    else
        assert(0);

    if(argc > 2) {
        cerr << "Extra argument: " << argv[2] << endl;
        solver->exit(-1);
    }

    gzFile in = argc == 1 ? gzdopen(0, "rb") : gzopen(argv[1], "rb");
    solver->parse(in);
    gzclose(in);

    solver->eliminate(true);
    if(!solver->okay()) {
        cout << "UNSATISFIABLE" << endl;
        solver->exit(20);
    }

    lbool ret = solver->solve(option_n);

#ifndef SAFE_EXIT
    solver->exit(ret == l_True ? 10 : ret == l_False ? 20 : 0);     // (faster than "return", which will invoke the destructor for 'Solver')
#else
    delete solver;
    return (ret == l_True ? 10 : ret == l_False ? 20 : 0);
#endif
}<|endoftext|>


<commit_before>#include "../vendor/gc/include/gc.h"
#include "../vendor/gc/include/gc_cpp.h"
#include "../vendor/gc/include/gc_allocator.h"

#include <cstdarg>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>

#include<sys/stat.h>
#include<sys/types.h>

#include "array.h"
#include "string.h"
#include "fancy_exception.h"
#include "number.h"
#include "errors.h"
#include "utils.h"
#include "parser/parser.h"
#include "bootstrap/includes.h"
#include "bootstrap/core_classes.h"

using namespace std;
using namespace fancy;

extern int yyparse();
extern void yyrestart(FILE*);

string get_load_path(int argc, char **argv)
{
  for(int i = 1; i < argc; i++) {
    if(strcmp(argv[i], "-I") == 0) {
      return string(argv[i+1]);
    }
  }
  return "."; // current dir
}

bool output_sexp(int argc, char **argv) {
  for(int i = 1; i < argc; i++) {
    if(strcmp(argv[i], "--sexp") == 0) {
      return true;
    }
  }
  return false;
}

int prepare_argv(int argc, char **argv)
{
  int argv_size = 0;
  // set command line arguments in global ARGV variable as Array
  Array* args_arr = new Array();
  for(int i = 1; i < argc; i++) {
    string arg(argv[i]);
    // skip -I + root loadpath arg
    if(arg == "-I") {
      i++;
      continue;
    }
    // skip --sexp option
    if(arg == "--sexp") {
      continue;
    }
    args_arr->insert(FancyString::from_value(arg));
    argv_size++;
  }
  global_scope->define("ARGV", args_arr);
  return argv_size;
}

string filename(int argc, char **argv)
{
  for(int i = 1; i < argc; i++) {
    if(argv[i][0] == '-') {
      i++;
      continue;
    }
    return string(argv[i]);
  }
  return "";
}

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

  fancy::parser::output_sexp = output_sexp(argc, argv);
  fancy::parser::load_path.push_back(get_load_path(argc, argv));
  fancy::bootstrap::init_core_classes();
  fancy::bootstrap::init_global_objects();
  fancy::bootstrap::init_global_scope();
  fancy::Number::init_cache();

  string boot_file = "boot.fnc";
  string stdlib_path = get_load_path(argc, argv) + "/lib";
  fancy::parser::load_path.push_back(stdlib_path);

  int argv_size = prepare_argv(argc, argv);
  // now, load boot.fnc
  bool tmp = fancy::parser::output_sexp;
  fancy::parser::output_sexp = false; // just for booting phase
  fancy::parser::parse_file(boot_file);
  fancy::parser::output_sexp = tmp;

  try {
    string file = filename(argc, argv);
    if(file != "") {
      fancy::parser::parse_file(file);
    } else {
      if(argv_size == 0) {
        parser::parse_stdin();
      }
    }
  } catch(UnknownIdentifierError &ex) {
    cout << "Error:" << endl;
  }

  // cout << "heap size: " << GC_get_bytes_since_gc() << endl;
  // GC_gcollect();
  // cout << "heap size after collect: " << GC_get_bytes_since_gc() << endl;
  // cout << "Completed " << GC_gc_no << " collections" <<endl;
  // cout << "Heap size is " << GC_get_heap_size() << endl;

  return 0;
}

<commit_msg>Uncommented explicit GC_gcollect() at end of main().<commit_after>#include "../vendor/gc/include/gc.h"
#include "../vendor/gc/include/gc_cpp.h"
#include "../vendor/gc/include/gc_allocator.h"

#include <cstdarg>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>

#include<sys/stat.h>
#include<sys/types.h>

#include "array.h"
#include "string.h"
#include "fancy_exception.h"
#include "number.h"
#include "errors.h"
#include "utils.h"
#include "parser/parser.h"
#include "bootstrap/includes.h"
#include "bootstrap/core_classes.h"

using namespace std;
using namespace fancy;

extern int yyparse();
extern void yyrestart(FILE*);

string get_load_path(int argc, char **argv)
{
  for(int i = 1; i < argc; i++) {
    if(strcmp(argv[i], "-I") == 0) {
      return string(argv[i+1]);
    }
  }
  return "."; // current dir
}

bool output_sexp(int argc, char **argv) {
  for(int i = 1; i < argc; i++) {
    if(strcmp(argv[i], "--sexp") == 0) {
      return true;
    }
  }
  return false;
}

int prepare_argv(int argc, char **argv)
{
  int argv_size = 0;
  // set command line arguments in global ARGV variable as Array
  Array* args_arr = new Array();
  for(int i = 1; i < argc; i++) {
    string arg(argv[i]);
    // skip -I + root loadpath arg
    if(arg == "-I") {
      i++;
      continue;
    }
    // skip --sexp option
    if(arg == "--sexp") {
      continue;
    }
    args_arr->insert(FancyString::from_value(arg));
    argv_size++;
  }
  global_scope->define("ARGV", args_arr);
  return argv_size;
}

string filename(int argc, char **argv)
{
  for(int i = 1; i < argc; i++) {
    if(argv[i][0] == '-') {
      i++;
      continue;
    }
    return string(argv[i]);
  }
  return "";
}

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

  fancy::parser::output_sexp = output_sexp(argc, argv);
  fancy::parser::load_path.push_back(get_load_path(argc, argv));
  fancy::bootstrap::init_core_classes();
  fancy::bootstrap::init_global_objects();
  fancy::bootstrap::init_global_scope();
  fancy::Number::init_cache();

  string boot_file = "boot.fnc";
  string stdlib_path = get_load_path(argc, argv) + "/lib";
  fancy::parser::load_path.push_back(stdlib_path);

  int argv_size = prepare_argv(argc, argv);
  // now, load boot.fnc
  bool tmp = fancy::parser::output_sexp;
  fancy::parser::output_sexp = false; // just for booting phase
  fancy::parser::parse_file(boot_file);
  fancy::parser::output_sexp = tmp;

  try {
    string file = filename(argc, argv);
    if(file != "") {
      fancy::parser::parse_file(file);
    } else {
      if(argv_size == 0) {
        parser::parse_stdin();
      }
    }
  } catch(UnknownIdentifierError &ex) {
    cout << "Error:" << endl;
  }

  // cout << "heap size: " << GC_get_bytes_since_gc() << endl;
  GC_gcollect();
  // cout << "heap size after collect: " << GC_get_bytes_since_gc() << endl;
  // cout << "Completed " << GC_gc_no << " collections" <<endl;
  // cout << "Heap size is " << GC_get_heap_size() << endl;

  return 0;
}

<|endoftext|>


<commit_before>#include <sys/resource.h>
#include "config/cmd_args.hpp"
#include "utils.hpp"
#include "arch/arch.hpp"
#include "server.hpp"
#include "side_executable.hpp"
#include "logger.hpp"

int main(int argc, char *argv[]) {
    // Before we do anything, we look at the first argument and
    // consider running a different executable (such as
    // ./rethinkdb-extract).

    consider_execve_side_executable(argc, argv, "extract");

    install_generic_crash_handler();

#ifndef NDEBUG
    rlimit core_limit;
    core_limit.rlim_cur = RLIM_INFINITY;
    core_limit.rlim_max = RLIM_INFINITY;
    setrlimit(RLIMIT_CORE, &core_limit);
#endif

    // Parse command line arguments
    cmd_config_t config;
    parse_cmd_args(argc, argv, &config);

    // Open log file if necessary
    if (config.log_file_name[0]) {
        log_file = fopen(config.log_file_name, "w");
    }

    // Initial CPU message to start server
    struct server_starter_t :
        public cpu_message_t
    {
        cmd_config_t *cmd_config;
        thread_pool_t *thread_pool;
        void on_cpu_switch() {
            server_t *s = new server_t(cmd_config, thread_pool);
            s->do_start();
        }
    } starter;
    starter.cmd_config = &config;

    // Run the server
    thread_pool_t thread_pool(config.n_workers);
    starter.thread_pool = &thread_pool;
    thread_pool.run(&starter);

    logINF("Server is shut down.\n");

    // Close the log file if necessary.
    if (config.log_file_name[0]) {
        fclose(log_file);
        log_file = stderr;
    }

    return 0;
}
<commit_msg>Comments in main.cc<commit_after>#include <sys/resource.h>
#include "config/cmd_args.hpp"
#include "utils.hpp"
#include "arch/arch.hpp"
#include "server.hpp"
#include "side_executable.hpp"
#include "logger.hpp"

int main(int argc, char *argv[]) {
    // Before we do anything, we look at the first argument and
    // consider running a different executable (such as
    // ./rethinkdb-extract).

    consider_execve_side_executable(argc, argv, "extract");

    install_generic_crash_handler();

#ifndef NDEBUG
    rlimit core_limit;
    core_limit.rlim_cur = RLIM_INFINITY;
    core_limit.rlim_max = RLIM_INFINITY;
    setrlimit(RLIMIT_CORE, &core_limit);
#endif

    // Parse command line arguments
    cmd_config_t config;
    parse_cmd_args(argc, argv, &config);

    // Open log file if necessary
    if (config.log_file_name[0]) {
        log_file = fopen(config.log_file_name, "w");
    }

    // Initial CPU message to start server
    struct server_starter_t :
        public cpu_message_t
    {
        cmd_config_t *cmd_config;
        thread_pool_t *thread_pool;
        void on_cpu_switch() {
            server_t *s = new server_t(cmd_config, thread_pool);
            s->do_start();
        }
    } starter;
    starter.cmd_config = &config;

    // Run the server.
    thread_pool_t thread_pool(config.n_workers);
    starter.thread_pool = &thread_pool;
    thread_pool.run(&starter);

    logINF("Server is shut down.\n");

    // Close the log file if necessary.
    if (config.log_file_name[0]) {
        fclose(log_file);
        log_file = stderr;
    }

    return 0;
}
<|endoftext|>


<commit_before>#define GLEW_STATIC // Easier debugging
#include <GL/glew.h>
#include <GL/gl.h>
#include <SDL2/SDL.h>
#include <iostream>
#include <memory>

#define RUN_GRAPHICS_DISPLAY 0x00;

#include "GameWorld.h"

/*
 * SDL timers run in separate threads.  In the timer thread
 * push an event onto the event queue.  This event signifies
 * to call display() from the thread in which the OpenGL
 * context was created.
 */
Uint32 display(Uint32 interval, void *param) {
  SDL_Event event;
  event.type = SDL_USEREVENT;
  event.user.code = RUN_GRAPHICS_DISPLAY;
  event.user.data1 = 0;
  event.user.data2 = 0;
  SDL_PushEvent(&event);
  return interval;
}

struct SDLWindowDeleter {
  inline void operator()(SDL_Window* window) {
    SDL_DestroyWindow(window);
  }
};

void Draw(const std::shared_ptr<SDL_Window> window) {
  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

  // Don't forget to swap the buffers
  SDL_GL_SwapWindow(window.get());
}

std::shared_ptr<SDL_Window> InitWorld() {
  Uint32 width = 640;
  Uint32 height = 480;
  SDL_Window * _window;
  std::shared_ptr<SDL_Window> window;

  // Glew will later ensure that OpenGL 3 *is* supported
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);

  // Do double buffering in GL
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

  // Initialise SDL - when using C/C++ it's common to have to
  // initialise libraries by calling a function within them.
  if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_TIMER)<0) {
    std::cout << "Failed to initialise SDL: " << SDL_GetError() << std::endl;
    return nullptr;
  }

  // When we close a window quit the SDL application
  atexit(SDL_Quit);

  // Create a new window with an OpenGL surface
  _window = SDL_CreateWindow("CI224 - Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
  if (!window) {
    std::cout << "Failed to create SDL window: " << SDL_GetError() << std::endl;
    return nullptr;
  }

  SDL_GLContext glContext = SDL_GL_CreateContext(window.get());
  if (!glContext) {
    std::cout << "Failed to create OpenGL context: " << SDL_GetError() << std::endl;
    return nullptr;
  }

  // Initialise GLEW - an easy way to ensure OpenGl 3.0+
  // The *must* be done after we have set the video mode - otherwise we have no
  // OpenGL context to test.
  glewInit();
  if (!glewIsSupported("GL_VERSION_3_0")) {
    std::cerr << "OpenGL 3.0 not available" << std::endl;
    return nullptr;
  }

  window.reset(_window, SDL_DestroyWindow);
  return window;
}

int main(int argc, char ** argv) {
  Uint32 delay = 1000/60; // in milliseconds

  auto window = InitWorld();
  auto game_world = std::make_shared<GameWorld>();
  if(!window) {
    SDL_Quit();
  }

  // Call the function "display" every delay milliseconds
  SDL_AddTimer(delay, display, NULL);

  // Add the main event loop
  SDL_Event event;
  while (SDL_WaitEvent(&event)) {
    switch (event.type) {
    case SDL_QUIT:
      SDL_Quit();
      break;
    case SDL_USEREVENT:
      Draw(window);
      break;
    default:
      break;
    }
  }
}
<commit_msg>Some occurances of window should have been _window.<commit_after>#define GLEW_STATIC // Easier debugging
#include <GL/glew.h>
#include <GL/gl.h>
#include <SDL2/SDL.h>
#include <iostream>
#include <memory>

#define RUN_GRAPHICS_DISPLAY 0x00;

#include "GameWorld.h"

/*
 * SDL timers run in separate threads.  In the timer thread
 * push an event onto the event queue.  This event signifies
 * to call display() from the thread in which the OpenGL
 * context was created.
 */
Uint32 tick(Uint32 interval, void *param) {
  SDL_Event event;
  event.type = SDL_USEREVENT;
  event.user.code = RUN_GRAPHICS_DISPLAY;
  event.user.data1 = 0;
  event.user.data2 = 0;
  SDL_PushEvent(&event);
  return interval;
}

struct SDLWindowDeleter {
  inline void operator()(SDL_Window* window) {
    SDL_DestroyWindow(window);
  }
};

void Draw(const std::shared_ptr<SDL_Window> window) {
  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

  // Don't forget to swap the buffers
  SDL_GL_SwapWindow(window.get());
}

std::shared_ptr<SDL_Window> InitWorld() {
  Uint32 width = 640;
  Uint32 height = 480;
  SDL_Window * _window;
  std::shared_ptr<SDL_Window> window;

  // Glew will later ensure that OpenGL 3 *is* supported
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);

  // Do double buffering in GL
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

  // Initialise SDL - when using C/C++ it's common to have to
  // initialise libraries by calling a function within them.
  if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_TIMER)<0) {
    std::cout << "Failed to initialise SDL: " << SDL_GetError() << std::endl;
    return nullptr;
  }

  // When we close a window quit the SDL application
  atexit(SDL_Quit);

  // Create a new window with an OpenGL surface
  _window = SDL_CreateWindow("CI224 - Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
  if (!_window) {
    std::cout << "Failed to create SDL window: " << SDL_GetError() << std::endl;
    return nullptr;
  }

  SDL_GLContext glContext = SDL_GL_CreateContext(_window);
  if (!glContext) {
    std::cout << "Failed to create OpenGL context: " << SDL_GetError() << std::endl;
    return nullptr;
  }

  // Initialise GLEW - an easy way to ensure OpenGl 3.0+
  // The *must* be done after we have set the video mode - otherwise we have no
  // OpenGL context to test.
  glewInit();
  if (!glewIsSupported("GL_VERSION_3_0")) {
    std::cerr << "OpenGL 3.0 not available" << std::endl;
    return nullptr;
  }

  window.reset(_window, SDL_DestroyWindow);
  return window;
}

int main(int argc, char ** argv) {
  Uint32 delay = 1000/60; // in milliseconds

  auto window = InitWorld();
  auto game_world = std::make_shared<GameWorld>();
  if(!window) {
    SDL_Quit();
  }

  // Call the function "tick" every delay milliseconds
  SDL_AddTimer(delay, tick, NULL);

  // Add the main event loop
  SDL_Event event;
  while (SDL_WaitEvent(&event)) {
    switch (event.type) {
    case SDL_QUIT:
      SDL_Quit();
      break;
    case SDL_USEREVENT:
      Draw(window);
      break;
    default:
      break;
    }
  }
}
<|endoftext|>