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

#include "graph.h"

#include <assert.h>
#include <stdio.h>

#include "build_log.h"
#include "depfile_parser.h"
#include "deps_log.h"
#include "disk_interface.h"
#include "explain.h"
#include "manifest_parser.h"
#include "metrics.h"
#include "state.h"
#include "util.h"

bool Node::Stat(DiskInterface* disk_interface) {
  METRIC_RECORD("node stat");
  mtime_ = disk_interface->Stat(path_);
  return mtime_ > 0;
}

void Rule::AddBinding(const string& key, const EvalString& val) {
  bindings_[key] = val;
}

const EvalString* Rule::GetBinding(const string& key) const {
  map<string, EvalString>::const_iterator i = bindings_.find(key);
  if (i == bindings_.end())
    return NULL;
  return &i->second;
}

// static
bool Rule::IsReservedBinding(const string& var) {
  return var == "command" ||
      var == "depfile" ||
      var == "description" ||
      var == "deps" ||
      var == "generator" ||
      var == "pool" ||
      var == "restat" ||
      var == "rspfile" ||
      var == "rspfile_content";
}

bool DependencyScan::RecomputeDirty(Edge* edge, string* err) {
  bool dirty = false;
  edge->outputs_ready_ = true;
  edge->deps_missing_ = false;

  if (!dep_loader_.LoadDeps(edge, err)) {
    if (!err->empty())
      return false;
    // Failed to load dependency info: rebuild to regenerate it.
    dirty = edge->deps_missing_ = true;
  }

  // Visit all inputs; we're dirty if any of the inputs are dirty.
  Node* most_recent_input = NULL;
  for (vector<Node*>::iterator i = edge->inputs_.begin();
       i != edge->inputs_.end(); ++i) {
    if ((*i)->StatIfNecessary(disk_interface_)) {
      if (Edge* in_edge = (*i)->in_edge()) {
        if (!RecomputeDirty(in_edge, err))
          return false;
      } else {
        // This input has no in-edge; it is dirty if it is missing.
        if (!(*i)->exists())
          EXPLAIN("%s has no in-edge and is missing", (*i)->path().c_str());
        (*i)->set_dirty(!(*i)->exists());
      }
    }

    // If an input is not ready, neither are our outputs.
    if (Edge* in_edge = (*i)->in_edge()) {
      if (!in_edge->outputs_ready_)
        edge->outputs_ready_ = false;
    }

    if (!edge->is_order_only(i - edge->inputs_.begin())) {
      // If a regular input is dirty (or missing), we're dirty.
      // Otherwise consider mtime.
      if ((*i)->dirty()) {
        EXPLAIN("%s is dirty", (*i)->path().c_str());
        dirty = true;
      } else {
        if (!most_recent_input || (*i)->mtime() > most_recent_input->mtime()) {
          most_recent_input = *i;
        }
      }
    }
  }

  // We may also be dirty due to output state: missing outputs, out of
  // date outputs, etc.  Visit all outputs and determine whether they're dirty.
  if (!dirty)
    dirty = RecomputeOutputsDirty(edge, most_recent_input);

  // Finally, visit each output to mark off that we've visited it, and update
  // their dirty state if necessary.
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    (*i)->StatIfNecessary(disk_interface_);
    if (dirty)
      (*i)->MarkDirty();
  }

  // If an edge is dirty, its outputs are normally not ready.  (It's
  // possible to be clean but still not be ready in the presence of
  // order-only inputs.)
  // But phony edges with no inputs have nothing to do, so are always
  // ready.
  if (dirty && !(edge->is_phony() && edge->inputs_.empty()))
    edge->outputs_ready_ = false;

  return true;
}

bool DependencyScan::RecomputeOutputsDirty(Edge* edge,
                                           Node* most_recent_input) {
  string command = edge->EvaluateCommand(true);
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    (*i)->StatIfNecessary(disk_interface_);
    if (RecomputeOutputDirty(edge, most_recent_input, command, *i))
      return true;
  }
  return false;
}

bool DependencyScan::RecomputeOutputDirty(Edge* edge,
                                          Node* most_recent_input,
                                          const string& command,
                                          Node* output) {
  if (edge->is_phony()) {
    // Phony edges don't write any output.  Outputs are only dirty if
    // there are no inputs and we're missing the output.
    return edge->inputs_.empty() && !output->exists();
  }

  BuildLog::LogEntry* entry = 0;

  // Dirty if we're missing the output.
  if (!output->exists()) {
    EXPLAIN("output %s doesn't exist", output->path().c_str());
    return true;
  }

  // Dirty if the output is older than the input.
  if (most_recent_input && output->mtime() < most_recent_input->mtime()) {
    TimeStamp output_mtime = output->mtime();

    // If this is a restat rule, we may have cleaned the output with a restat
    // rule in a previous run and stored the most recent input mtime in the
    // build log.  Use that mtime instead, so that the file will only be
    // considered dirty if an input was modified since the previous run.
    bool used_restat = false;
    if (edge->GetBindingBool("restat") && build_log() &&
        (entry = build_log()->LookupByOutput(output->path()))) {
      output_mtime = entry->restat_mtime;
      used_restat = true;
    }

    if (output_mtime < most_recent_input->mtime()) {
      EXPLAIN("%soutput %s older than most recent input %s "
              "(%d vs %d)",
              used_restat ? "restat of " : "", output->path().c_str(),
              most_recent_input->path().c_str(),
              output_mtime, most_recent_input->mtime());
      return true;
    }
  }

  // May also be dirty due to the command changing since the last build.
  // But if this is a generator rule, the command changing does not make us
  // dirty.
  if (!edge->GetBindingBool("generator") && build_log()) {
    if (entry || (entry = build_log()->LookupByOutput(output->path()))) {
      if (BuildLog::LogEntry::HashCommand(command) != entry->command_hash) {
        EXPLAIN("command line changed for %s", output->path().c_str());
        return true;
      }
    }
    if (!entry) {
      EXPLAIN("command line not found in log for %s", output->path().c_str());
      return true;
    }
  }

  return false;
}

bool Edge::AllInputsReady() const {
  for (vector<Node*>::const_iterator i = inputs_.begin();
       i != inputs_.end(); ++i) {
    if ((*i)->in_edge() && !(*i)->in_edge()->outputs_ready())
      return false;
  }
  return true;
}

/// An Env for an Edge, providing $in and $out.
struct EdgeEnv : public Env {
  explicit EdgeEnv(Edge* edge) : edge_(edge) {}
  virtual string LookupVariable(const string& var);

  /// Given a span of Nodes, construct a list of paths suitable for a command
  /// line.
  string MakePathList(vector<Node*>::iterator begin,
                      vector<Node*>::iterator end,
                      char sep);

  Edge* edge_;
};

string EdgeEnv::LookupVariable(const string& var) {
  if (var == "in" || var == "in_newline") {
    int explicit_deps_count = edge_->inputs_.size() - edge_->implicit_deps_ -
      edge_->order_only_deps_;
    return MakePathList(edge_->inputs_.begin(),
                        edge_->inputs_.begin() + explicit_deps_count,
                        var == "in" ? ' ' : '\n');
  } else if (var == "out") {
    return MakePathList(edge_->outputs_.begin(),
                        edge_->outputs_.end(),
                        ' ');
  }

  // See notes on BindingEnv::LookupWithFallback.
  const EvalString* eval = edge_->rule_->GetBinding(var);
  return edge_->env_->LookupWithFallback(var, eval, this);
}

string EdgeEnv::MakePathList(vector<Node*>::iterator begin,
                             vector<Node*>::iterator end,
                             char sep) {
  string result;
  for (vector<Node*>::iterator i = begin; i != end; ++i) {
    if (!result.empty())
      result.push_back(sep);
    const string& path = (*i)->path();
    if (path.find(" ") != string::npos) {
      result.append("\"");
      result.append(path);
      result.append("\"");
    } else {
      result.append(path);
    }
  }
  return result;
}

string Edge::EvaluateCommand(bool incl_rsp_file) {
  string command = GetBinding("command");
  if (incl_rsp_file) {
    string rspfile_content = GetBinding("rspfile_content");
    if (!rspfile_content.empty())
      command += ";rspfile=" + rspfile_content;
  }
  return command;
}

string Edge::GetBinding(const string& key) {
  EdgeEnv env(this);
  return env.LookupVariable(key);
}

bool Edge::GetBindingBool(const string& key) {
  return !GetBinding(key).empty();
}

void Edge::Dump(const char* prefix) const {
  printf("%s[ ", prefix);
  for (vector<Node*>::const_iterator i = inputs_.begin();
       i != inputs_.end() && *i != NULL; ++i) {
    printf("%s ", (*i)->path().c_str());
  }
  printf("--%s-> ", rule_->name().c_str());
  for (vector<Node*>::const_iterator i = outputs_.begin();
       i != outputs_.end() && *i != NULL; ++i) {
    printf("%s ", (*i)->path().c_str());
  }
  if (pool_) {
    if (!pool_->name().empty()) {
      printf("(in pool '%s')", pool_->name().c_str());
    }
  } else {
    printf("(null pool?)");
  }
  printf("] 0x%p\n", this);
}

bool Edge::is_phony() const {
  return rule_ == &State::kPhonyRule;
}

void Node::Dump(const char* prefix) const {
  printf("%s <%s 0x%p> mtime: %d%s, (:%s), ",
         prefix, path().c_str(), this,
         mtime(), mtime() ? "" : " (:missing)",
         dirty() ? " dirty" : " clean");
  if (in_edge()) {
    in_edge()->Dump("in-edge: ");
  } else {
    printf("no in-edge\n");
  }
  printf(" out edges:\n");
  for (vector<Edge*>::const_iterator e = out_edges().begin();
       e != out_edges().end() && *e != NULL; ++e) {
    (*e)->Dump(" +- ");
  }
}

bool ImplicitDepLoader::LoadDeps(Edge* edge, string* err) {
  string deps_type = edge->GetBinding("deps");
  if (!deps_type.empty()) {
    if (!LoadDepsFromLog(edge, err)) {
      if (!err->empty())
        return false;
      return false;
    }
    return true;
  }

  string depfile = edge->GetBinding("depfile");
  if (!depfile.empty()) {
    if (!LoadDepFile(edge, depfile, err)) {
      if (!err->empty())
        return false;
      EXPLAIN("depfile '%s' is missing", depfile.c_str());
      return false;
    }
    return true;
  }

  // No deps to load.
  return true;
}

bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path,
                                    string* err) {
  METRIC_RECORD("depfile load");
  string content = disk_interface_->ReadFile(path, err);
  if (!err->empty()) {
    *err = "loading '" + path + "': " + *err;
    return false;
  }
  // On a missing depfile: return false and empty *err.
  if (content.empty())
    return false;

  DepfileParser depfile;
  string depfile_err;
  if (!depfile.Parse(&content, &depfile_err)) {
    *err = path + ": " + depfile_err;
    return false;
  }

  // Check that this depfile matches the edge's output.
  Node* first_output = edge->outputs_[0];
  StringPiece opath = StringPiece(first_output->path());
  if (opath != depfile.out_) {
    *err = "expected depfile '" + path + "' to mention '" +
        first_output->path() + "', got '" + depfile.out_.AsString() + "'";
    return false;
  }

  // Preallocate space in edge->inputs_ to be filled in below.
  vector<Node*>::iterator implicit_dep =
      PreallocateSpace(edge, depfile.ins_.size());

  // Add all its in-edges.
  for (vector<StringPiece>::iterator i = depfile.ins_.begin();
       i != depfile.ins_.end(); ++i, ++implicit_dep) {
    if (!CanonicalizePath(const_cast<char*>(i->str_), &i->len_, err))
      return false;

    Node* node = state_->GetNode(*i);
    *implicit_dep = node;
    node->AddOutEdge(edge);
    CreatePhonyInEdge(node);
  }

  return true;
}

bool ImplicitDepLoader::LoadDepsFromLog(Edge* edge, string* err) {
  // NOTE: deps are only supported for single-target edges.
  Node* output = edge->outputs_[0];
  DepsLog::Deps* deps = deps_log_->GetDeps(output);
  if (!deps) {
    EXPLAIN("deps for '%s' are missing", output->path().c_str());
    return false;
  }

  // Deps are invalid if the output is newer than the deps.
  if (output->mtime() > deps->mtime) {
    EXPLAIN("stored deps info out of date for for '%s' (%d vs %d)",
            output->path().c_str(), deps->mtime, output->mtime());
    return false;
  }

  vector<Node*>::iterator implicit_dep =
      PreallocateSpace(edge, deps->node_count);
  for (int i = 0; i < deps->node_count; ++i, ++implicit_dep) {
    Node* node = deps->nodes[i];
    *implicit_dep = node;
    node->AddOutEdge(edge);
    CreatePhonyInEdge(node);
  }
  return true;
}

vector<Node*>::iterator ImplicitDepLoader::PreallocateSpace(Edge* edge,
                                                            int count) {
  edge->inputs_.insert(edge->inputs_.end() - edge->order_only_deps_,
                       (size_t)count, 0);
  edge->implicit_deps_ += count;
  return edge->inputs_.end() - edge->order_only_deps_ - count;
}

void ImplicitDepLoader::CreatePhonyInEdge(Node* node) {
  if (node->in_edge())
    return;

  Edge* phony_edge = state_->AddEdge(&State::kPhonyRule);
  node->set_in_edge(phony_edge);
  phony_edge->outputs_.push_back(node);

  // RecomputeDirty might not be called for phony_edge if a previous call
  // to RecomputeDirty had caused the file to be stat'ed.  Because previous
  // invocations of RecomputeDirty would have seen this node without an
  // input edge (and therefore ready), we have to set outputs_ready_ to true
  // to avoid a potential stuck build.  If we do call RecomputeDirty for
  // this node, it will simply set outputs_ready_ to the correct value.
  phony_edge->outputs_ready_ = true;
}
<commit_msg>Simplify.<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "graph.h"

#include <assert.h>
#include <stdio.h>

#include "build_log.h"
#include "depfile_parser.h"
#include "deps_log.h"
#include "disk_interface.h"
#include "explain.h"
#include "manifest_parser.h"
#include "metrics.h"
#include "state.h"
#include "util.h"

bool Node::Stat(DiskInterface* disk_interface) {
  METRIC_RECORD("node stat");
  mtime_ = disk_interface->Stat(path_);
  return mtime_ > 0;
}

void Rule::AddBinding(const string& key, const EvalString& val) {
  bindings_[key] = val;
}

const EvalString* Rule::GetBinding(const string& key) const {
  map<string, EvalString>::const_iterator i = bindings_.find(key);
  if (i == bindings_.end())
    return NULL;
  return &i->second;
}

// static
bool Rule::IsReservedBinding(const string& var) {
  return var == "command" ||
      var == "depfile" ||
      var == "description" ||
      var == "deps" ||
      var == "generator" ||
      var == "pool" ||
      var == "restat" ||
      var == "rspfile" ||
      var == "rspfile_content";
}

bool DependencyScan::RecomputeDirty(Edge* edge, string* err) {
  bool dirty = false;
  edge->outputs_ready_ = true;
  edge->deps_missing_ = false;

  if (!dep_loader_.LoadDeps(edge, err)) {
    if (!err->empty())
      return false;
    // Failed to load dependency info: rebuild to regenerate it.
    dirty = edge->deps_missing_ = true;
  }

  // Visit all inputs; we're dirty if any of the inputs are dirty.
  Node* most_recent_input = NULL;
  for (vector<Node*>::iterator i = edge->inputs_.begin();
       i != edge->inputs_.end(); ++i) {
    if ((*i)->StatIfNecessary(disk_interface_)) {
      if (Edge* in_edge = (*i)->in_edge()) {
        if (!RecomputeDirty(in_edge, err))
          return false;
      } else {
        // This input has no in-edge; it is dirty if it is missing.
        if (!(*i)->exists())
          EXPLAIN("%s has no in-edge and is missing", (*i)->path().c_str());
        (*i)->set_dirty(!(*i)->exists());
      }
    }

    // If an input is not ready, neither are our outputs.
    if (Edge* in_edge = (*i)->in_edge()) {
      if (!in_edge->outputs_ready_)
        edge->outputs_ready_ = false;
    }

    if (!edge->is_order_only(i - edge->inputs_.begin())) {
      // If a regular input is dirty (or missing), we're dirty.
      // Otherwise consider mtime.
      if ((*i)->dirty()) {
        EXPLAIN("%s is dirty", (*i)->path().c_str());
        dirty = true;
      } else {
        if (!most_recent_input || (*i)->mtime() > most_recent_input->mtime()) {
          most_recent_input = *i;
        }
      }
    }
  }

  // We may also be dirty due to output state: missing outputs, out of
  // date outputs, etc.  Visit all outputs and determine whether they're dirty.
  if (!dirty)
    dirty = RecomputeOutputsDirty(edge, most_recent_input);

  // Finally, visit each output to mark off that we've visited it, and update
  // their dirty state if necessary.
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    (*i)->StatIfNecessary(disk_interface_);
    if (dirty)
      (*i)->MarkDirty();
  }

  // If an edge is dirty, its outputs are normally not ready.  (It's
  // possible to be clean but still not be ready in the presence of
  // order-only inputs.)
  // But phony edges with no inputs have nothing to do, so are always
  // ready.
  if (dirty && !(edge->is_phony() && edge->inputs_.empty()))
    edge->outputs_ready_ = false;

  return true;
}

bool DependencyScan::RecomputeOutputsDirty(Edge* edge,
                                           Node* most_recent_input) {
  string command = edge->EvaluateCommand(true);
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    (*i)->StatIfNecessary(disk_interface_);
    if (RecomputeOutputDirty(edge, most_recent_input, command, *i))
      return true;
  }
  return false;
}

bool DependencyScan::RecomputeOutputDirty(Edge* edge,
                                          Node* most_recent_input,
                                          const string& command,
                                          Node* output) {
  if (edge->is_phony()) {
    // Phony edges don't write any output.  Outputs are only dirty if
    // there are no inputs and we're missing the output.
    return edge->inputs_.empty() && !output->exists();
  }

  BuildLog::LogEntry* entry = 0;

  // Dirty if we're missing the output.
  if (!output->exists()) {
    EXPLAIN("output %s doesn't exist", output->path().c_str());
    return true;
  }

  // Dirty if the output is older than the input.
  if (most_recent_input && output->mtime() < most_recent_input->mtime()) {
    TimeStamp output_mtime = output->mtime();

    // If this is a restat rule, we may have cleaned the output with a restat
    // rule in a previous run and stored the most recent input mtime in the
    // build log.  Use that mtime instead, so that the file will only be
    // considered dirty if an input was modified since the previous run.
    bool used_restat = false;
    if (edge->GetBindingBool("restat") && build_log() &&
        (entry = build_log()->LookupByOutput(output->path()))) {
      output_mtime = entry->restat_mtime;
      used_restat = true;
    }

    if (output_mtime < most_recent_input->mtime()) {
      EXPLAIN("%soutput %s older than most recent input %s "
              "(%d vs %d)",
              used_restat ? "restat of " : "", output->path().c_str(),
              most_recent_input->path().c_str(),
              output_mtime, most_recent_input->mtime());
      return true;
    }
  }

  // May also be dirty due to the command changing since the last build.
  // But if this is a generator rule, the command changing does not make us
  // dirty.
  if (!edge->GetBindingBool("generator") && build_log()) {
    if (entry || (entry = build_log()->LookupByOutput(output->path()))) {
      if (BuildLog::LogEntry::HashCommand(command) != entry->command_hash) {
        EXPLAIN("command line changed for %s", output->path().c_str());
        return true;
      }
    }
    if (!entry) {
      EXPLAIN("command line not found in log for %s", output->path().c_str());
      return true;
    }
  }

  return false;
}

bool Edge::AllInputsReady() const {
  for (vector<Node*>::const_iterator i = inputs_.begin();
       i != inputs_.end(); ++i) {
    if ((*i)->in_edge() && !(*i)->in_edge()->outputs_ready())
      return false;
  }
  return true;
}

/// An Env for an Edge, providing $in and $out.
struct EdgeEnv : public Env {
  explicit EdgeEnv(Edge* edge) : edge_(edge) {}
  virtual string LookupVariable(const string& var);

  /// Given a span of Nodes, construct a list of paths suitable for a command
  /// line.
  string MakePathList(vector<Node*>::iterator begin,
                      vector<Node*>::iterator end,
                      char sep);

  Edge* edge_;
};

string EdgeEnv::LookupVariable(const string& var) {
  if (var == "in" || var == "in_newline") {
    int explicit_deps_count = edge_->inputs_.size() - edge_->implicit_deps_ -
      edge_->order_only_deps_;
    return MakePathList(edge_->inputs_.begin(),
                        edge_->inputs_.begin() + explicit_deps_count,
                        var == "in" ? ' ' : '\n');
  } else if (var == "out") {
    return MakePathList(edge_->outputs_.begin(),
                        edge_->outputs_.end(),
                        ' ');
  }

  // See notes on BindingEnv::LookupWithFallback.
  const EvalString* eval = edge_->rule_->GetBinding(var);
  return edge_->env_->LookupWithFallback(var, eval, this);
}

string EdgeEnv::MakePathList(vector<Node*>::iterator begin,
                             vector<Node*>::iterator end,
                             char sep) {
  string result;
  for (vector<Node*>::iterator i = begin; i != end; ++i) {
    if (!result.empty())
      result.push_back(sep);
    const string& path = (*i)->path();
    if (path.find(" ") != string::npos) {
      result.append("\"");
      result.append(path);
      result.append("\"");
    } else {
      result.append(path);
    }
  }
  return result;
}

string Edge::EvaluateCommand(bool incl_rsp_file) {
  string command = GetBinding("command");
  if (incl_rsp_file) {
    string rspfile_content = GetBinding("rspfile_content");
    if (!rspfile_content.empty())
      command += ";rspfile=" + rspfile_content;
  }
  return command;
}

string Edge::GetBinding(const string& key) {
  EdgeEnv env(this);
  return env.LookupVariable(key);
}

bool Edge::GetBindingBool(const string& key) {
  return !GetBinding(key).empty();
}

void Edge::Dump(const char* prefix) const {
  printf("%s[ ", prefix);
  for (vector<Node*>::const_iterator i = inputs_.begin();
       i != inputs_.end() && *i != NULL; ++i) {
    printf("%s ", (*i)->path().c_str());
  }
  printf("--%s-> ", rule_->name().c_str());
  for (vector<Node*>::const_iterator i = outputs_.begin();
       i != outputs_.end() && *i != NULL; ++i) {
    printf("%s ", (*i)->path().c_str());
  }
  if (pool_) {
    if (!pool_->name().empty()) {
      printf("(in pool '%s')", pool_->name().c_str());
    }
  } else {
    printf("(null pool?)");
  }
  printf("] 0x%p\n", this);
}

bool Edge::is_phony() const {
  return rule_ == &State::kPhonyRule;
}

void Node::Dump(const char* prefix) const {
  printf("%s <%s 0x%p> mtime: %d%s, (:%s), ",
         prefix, path().c_str(), this,
         mtime(), mtime() ? "" : " (:missing)",
         dirty() ? " dirty" : " clean");
  if (in_edge()) {
    in_edge()->Dump("in-edge: ");
  } else {
    printf("no in-edge\n");
  }
  printf(" out edges:\n");
  for (vector<Edge*>::const_iterator e = out_edges().begin();
       e != out_edges().end() && *e != NULL; ++e) {
    (*e)->Dump(" +- ");
  }
}

bool ImplicitDepLoader::LoadDeps(Edge* edge, string* err) {
  string deps_type = edge->GetBinding("deps");
  if (!deps_type.empty())
    return LoadDepsFromLog(edge, err);

  string depfile = edge->GetBinding("depfile");
  if (!depfile.empty())
    return LoadDepFile(edge, depfile, err);

  // No deps to load.
  return true;
}

bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path,
                                    string* err) {
  METRIC_RECORD("depfile load");
  string content = disk_interface_->ReadFile(path, err);
  if (!err->empty()) {
    *err = "loading '" + path + "': " + *err;
    return false;
  }
  // On a missing depfile: return false and empty *err.
  if (content.empty()) {
    EXPLAIN("depfile '%s' is missing", path.c_str());
    return false;
  }

  DepfileParser depfile;
  string depfile_err;
  if (!depfile.Parse(&content, &depfile_err)) {
    *err = path + ": " + depfile_err;
    return false;
  }

  // Check that this depfile matches the edge's output.
  Node* first_output = edge->outputs_[0];
  StringPiece opath = StringPiece(first_output->path());
  if (opath != depfile.out_) {
    *err = "expected depfile '" + path + "' to mention '" +
        first_output->path() + "', got '" + depfile.out_.AsString() + "'";
    return false;
  }

  // Preallocate space in edge->inputs_ to be filled in below.
  vector<Node*>::iterator implicit_dep =
      PreallocateSpace(edge, depfile.ins_.size());

  // Add all its in-edges.
  for (vector<StringPiece>::iterator i = depfile.ins_.begin();
       i != depfile.ins_.end(); ++i, ++implicit_dep) {
    if (!CanonicalizePath(const_cast<char*>(i->str_), &i->len_, err))
      return false;

    Node* node = state_->GetNode(*i);
    *implicit_dep = node;
    node->AddOutEdge(edge);
    CreatePhonyInEdge(node);
  }

  return true;
}

bool ImplicitDepLoader::LoadDepsFromLog(Edge* edge, string* err) {
  // NOTE: deps are only supported for single-target edges.
  Node* output = edge->outputs_[0];
  DepsLog::Deps* deps = deps_log_->GetDeps(output);
  if (!deps) {
    EXPLAIN("deps for '%s' are missing", output->path().c_str());
    return false;
  }

  // Deps are invalid if the output is newer than the deps.
  if (output->mtime() > deps->mtime) {
    EXPLAIN("stored deps info out of date for for '%s' (%d vs %d)",
            output->path().c_str(), deps->mtime, output->mtime());
    return false;
  }

  vector<Node*>::iterator implicit_dep =
      PreallocateSpace(edge, deps->node_count);
  for (int i = 0; i < deps->node_count; ++i, ++implicit_dep) {
    Node* node = deps->nodes[i];
    *implicit_dep = node;
    node->AddOutEdge(edge);
    CreatePhonyInEdge(node);
  }
  return true;
}

vector<Node*>::iterator ImplicitDepLoader::PreallocateSpace(Edge* edge,
                                                            int count) {
  edge->inputs_.insert(edge->inputs_.end() - edge->order_only_deps_,
                       (size_t)count, 0);
  edge->implicit_deps_ += count;
  return edge->inputs_.end() - edge->order_only_deps_ - count;
}

void ImplicitDepLoader::CreatePhonyInEdge(Node* node) {
  if (node->in_edge())
    return;

  Edge* phony_edge = state_->AddEdge(&State::kPhonyRule);
  node->set_in_edge(phony_edge);
  phony_edge->outputs_.push_back(node);

  // RecomputeDirty might not be called for phony_edge if a previous call
  // to RecomputeDirty had caused the file to be stat'ed.  Because previous
  // invocations of RecomputeDirty would have seen this node without an
  // input edge (and therefore ready), we have to set outputs_ready_ to true
  // to avoid a potential stuck build.  If we do call RecomputeDirty for
  // this node, it will simply set outputs_ready_ to the correct value.
  phony_edge->outputs_ready_ = true;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, Yahoo Inc. All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */

#include <vector>

#include "graph.h"

struct EdgeSorter {
  const Graph & graph_;
  EdgeSorter(const Graph & g) : graph_(g) { }

  bool operator () (const Graph::edge_descriptor & a,
      const Graph::edge_descriptor & b) const {
    return graph_[a] < graph_[b];
  }
};

void contextSort(Graph & g) {
  typedef std::pair< Graph::edge_iterator, Graph::edge_iterator > Pair;
  Pair p = boost::edges(g);
  std::vector< Graph::edge_descriptor > edges(p.first, p.second);
  std::sort(std::begin(edges), std::end(edges), EdgeSorter(g));

  const size_t size = edges.size();

  for (size_t i = 0; i < size; ++i) {
    const Graph::edge_descriptor a = edges[i];
    for (size_t j = i + 1; j < size; ++j) {
      const Graph::edge_descriptor b = edges[j];
      if (g[a].contains(g[b])) {
        const Context r = g[b];
        edges.push_back(add_edge(target(a, g), target(b, g), r, g).first);
      }
    }
  }

  reverse(std::begin(edges), std::end(edges));

  size_t newSize = edges.size();
  size_t additionalSize = newSize - size;

  for (size_t i = 0; i < additionalSize; ++i) {
    const Graph::edge_descriptor a = edges[i];
    for (size_t j = i + 1; j < newSize; ++j) {
      const Graph::edge_descriptor b = edges[j];
      if (target(a, g) == target(b, g)) {
        remove_edge(b, g);
        edges.erase(std::begin(edges) + j);
        --newSize;
        if (j < additionalSize) {
          --additionalSize;
        }
      }
    }
  }
}
<commit_msg>we need to sort the edges<commit_after>/*
 * Copyright (c) 2015, Yahoo Inc. All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */

#include <vector>

#include "graph.h"

struct EdgeSorter {
  const Graph & graph_;
  EdgeSorter(const Graph & g) : graph_(g) { }

  bool operator () (const Graph::edge_descriptor & a,
      const Graph::edge_descriptor & b) const {
    return graph_[a] < graph_[b];
  }
};

void contextSort(Graph & g) {
  typedef std::pair< Graph::edge_iterator, Graph::edge_iterator > Pair;
  Pair p = boost::edges(g);
  std::vector< Graph::edge_descriptor > edges(p.first, p.second);
  std::sort(std::begin(edges), std::end(edges), EdgeSorter(g));

  const size_t size = edges.size();

  for (size_t i = 0; i < size; ++i) {
    const Graph::edge_descriptor a = edges[i];
    for (size_t j = i + 1; j < size; ++j) {
      const Graph::edge_descriptor b = edges[j];
      const Context r = g[b];
      if (g[a].contains(g[b])) {
        edges.push_back(add_edge(target(a, g), target(b, g), r, g).first);
      } else {
        edges.push_back(add_edge(*vertices(g).first, target(b, g), r, g).first);
      }
    }
  }

  reverse(std::begin(edges), std::end(edges));

  size_t newSize = edges.size();
  size_t additionalSize = newSize - size;

  for (size_t i = 0; i < additionalSize; ++i) {
    const Graph::edge_descriptor a = edges[i];
    for (size_t j = i + 1; j < newSize; ++j) {
      const Graph::edge_descriptor b = edges[j];
      if (target(a, g) == target(b, g)) {
        remove_edge(b, g);
        edges.erase(std::begin(edges) + j);
        --newSize;
        if (j < additionalSize) {
          --additionalSize;
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2013-2014 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>

#include "help.hpp"

void budget::help_module::handle(const std::vector<std::string>&){
    std::cout << "Usage: budget                                                     Display the overview of the current month" << std::endl << std::endl;

    std::cout << "       budget account [show]                                      Show the current accounts" << std::endl;
    std::cout << "       budget account all                                         Show all the accounts" << std::endl;
    std::cout << "       budget account add                                         Add a new account" << std::endl;
    std::cout << "       budget account delete (id)                                 Delete the given account" << std::endl;
    std::cout << "       budget account edit (id)                                   Edit the given account" << std::endl;
    std::cout << "       budget account migrate                                     Merge two accounts together" << std::endl << std::endl;
    std::cout << "       budget account archive                                     Archive the current accounts to start new accounts" << std::endl << std::endl;

    std::cout << "       budget expense [show]                                      Display the expenses of the current month" << std::endl;
    std::cout << "       budget expense show (month) (year)                         Display the expenses of the specified month of the specified year" << std::endl;
    std::cout << "       budget expense all                                         Display all the expenses" << std::endl;
    std::cout << "       budget expense add                                         Add a new expense" << std::endl;
    std::cout << "       budget expense add (template name)                         Add a new expense from a template or create a new template" << std::endl;
    std::cout << "       budget expense delete (id)                                 Remove completely the expense with the given id" << std::endl;
    std::cout << "       budget expense edit (id)                                   Modify the expense with the given id" << std::endl << std::endl;
    std::cout << "       budget expense template                                    Display the templates" << std::endl << std::endl;

    std::cout << "       budget earning [earnings]                                  Display the earnings of the current month" << std::endl;
    std::cout << "       budget earning show (month) (year)                         Display the earnings of the specified month of the specified year" << std::endl;
    std::cout << "       budget earning all                                         Display all the earnings" << std::endl;
    std::cout << "       budget earning add                                         Add a new earning" << std::endl;
    std::cout << "       budget earning delete (id)                                 Remove completely the earning with the given id" << std::endl;
    std::cout << "       budget earning edit (id)                                   Modify the earning with the given id" << std::endl << std::endl;

    std::cout << "       budget overview [month]                                    Display the overvew of the current month" << std::endl;
    std::cout << "       budget overview month (month) (year)                       Display the overvew of the specified month of the current year" << std::endl;
    std::cout << "       budget overview year (year)                                Display the overvew of the specified year" << std::endl;
    std::cout << "       budget overview aggregate                                  Display the aggregated expenses for the current year" << std::endl;
    std::cout << "       budget overview aggregate year (year)                      Display the aggregated expenses for the given year" << std::endl << std::endl;

    std::cout << "       budget recurring [show]                                    Display the recurring expenses" << std::endl;
    std::cout << "       budget recurring add                                       Add a new recurring expense" << std::endl;
    std::cout << "       budget recurring delete (id)                               Remove completely the recurring expense with the given id" << std::endl;
    std::cout << "       budget recurring edit (id)                                 Modify the recurring expense with the given id" << std::endl << std::endl;

    std::cout << "       budget fortune [status]                                    Display the status of the fortune checks" << std::endl;
    std::cout << "       budget fortune list                                        Display the list of all the fortune checks" << std::endl;
    std::cout << "       budget fortune check                                       Create a new fortune check" << std::endl;
    std::cout << "       budget fortune edit (id)                                   Edit a fortune check" << std::endl;
    std::cout << "       budget fortune delete (id)                                 Delete a fortune check" << std::endl << std::endl;

    std::cout << "       budget objective [status]                                  Show the status of the objectives for the current year" << std::endl;
    std::cout << "       budget objective list                                      List all the defined objectives" << std::endl;
    std::cout << "       budget objective add                                       Add a new objective" << std::endl;
    std::cout << "       budget objective edit (id)                                 Edit an objective" << std::endl;
    std::cout << "       budget objective delete (id)                               Delete an objective" << std::endl;

    std::cout << "       budget wish [status]                                       Show the status of the wishes" << std::endl;
    std::cout << "       budget wish list                                           List all the wishes" << std::endl;
    std::cout << "       budget wish estimate                                       Estimate the best date to buy something" << std::endl;
    std::cout << "       budget wish add                                            Add a new wish" << std::endl;
    std::cout << "       budget wish edit (id)                                      Edit a wish" << std::endl;
    std::cout << "       budget wish delete (id)                                    Delete a wish" << std::endl;

    std::cout << "       budget debt [list]                                         Display the unpaid debts" << std::endl;
    std::cout << "       budget debt all                                            Display all debts" << std::endl;
    std::cout << "       budget debt paid (id)                                      Mark the given debt as paid" << std::endl;
    std::cout << "       budget debt delete (id)                                    Delete the given debt" << std::endl;
    std::cout << "       budget debt edit (id)                                      Edit the given debt" << std::endl << std::endl;

    std::cout << "       budget versioning save                                     Commit the budget directory changes with Git" << std::endl;
    std::cout << "       budget versioning sync                                     Pull the remote changes on the budget directory with Git and push" << std::endl;

    std::cout << "       budget report [monthly]                                    Display monthly report in form of bar plot" << std::endl;

    std::cout << "       budget gc                                                  Make sure all IDs are contiguous" << std::endl;
}
<commit_msg>Complete help<commit_after>//=======================================================================
// Copyright (c) 2013-2014 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>

#include "help.hpp"

void budget::help_module::handle(const std::vector<std::string>&){
    std::cout << "Usage: budget                                                     Display the overview of the current month" << std::endl << std::endl;

    std::cout << "       budget account [show]                                      Show the current accounts" << std::endl;
    std::cout << "       budget account all                                         Show all the accounts" << std::endl;
    std::cout << "       budget account add                                         Add a new account" << std::endl;
    std::cout << "       budget account delete (id)                                 Delete the given account" << std::endl;
    std::cout << "       budget account edit (id)                                   Edit the given account" << std::endl;
    std::cout << "       budget account migrate                                     Merge two accounts together" << std::endl << std::endl;
    std::cout << "       budget account archive                                     Archive the current accounts to start new accounts" << std::endl << std::endl;

    std::cout << "       budget expense [show]                                      Display the expenses of the current month" << std::endl;
    std::cout << "       budget expense show (month) (year)                         Display the expenses of the specified month of the specified year" << std::endl;
    std::cout << "       budget expense all                                         Display all the expenses" << std::endl;
    std::cout << "       budget expense add                                         Add a new expense" << std::endl;
    std::cout << "       budget expense add (template name)                         Add a new expense from a template or create a new template" << std::endl;
    std::cout << "       budget expense delete (id)                                 Remove completely the expense with the given id" << std::endl;
    std::cout << "       budget expense edit (id)                                   Modify the expense with the given id" << std::endl << std::endl;
    std::cout << "       budget expense template                                    Display the templates" << std::endl << std::endl;

    std::cout << "       budget earning [earnings]                                  Display the earnings of the current month" << std::endl;
    std::cout << "       budget earning show (month) (year)                         Display the earnings of the specified month of the specified year" << std::endl;
    std::cout << "       budget earning all                                         Display all the earnings" << std::endl;
    std::cout << "       budget earning add                                         Add a new earning" << std::endl;
    std::cout << "       budget earning delete (id)                                 Remove completely the earning with the given id" << std::endl;
    std::cout << "       budget earning edit (id)                                   Modify the earning with the given id" << std::endl << std::endl;

    std::cout << "       budget overview [month]                                    Display the overvew of the current month" << std::endl;
    std::cout << "       budget overview month (month) (year)                       Display the overvew of the specified month of the current year" << std::endl;
    std::cout << "       budget overview year (year)                                Display the overvew of the specified year" << std::endl;
    std::cout << "       budget overview aggregate                                  Display the aggregated expenses for the current year" << std::endl;
    std::cout << "       budget overview aggregate year (year)                      Display the aggregated expenses for the given year" << std::endl << std::endl;

    std::cout << "       budget recurring [show]                                    Display the recurring expenses" << std::endl;
    std::cout << "       budget recurring add                                       Add a new recurring expense" << std::endl;
    std::cout << "       budget recurring delete (id)                               Remove completely the recurring expense with the given id" << std::endl;
    std::cout << "       budget recurring edit (id)                                 Modify the recurring expense with the given id" << std::endl << std::endl;

    std::cout << "       budget fortune [status]                                    Display the status of the fortune checks" << std::endl;
    std::cout << "       budget fortune list                                        Display the list of all the fortune checks" << std::endl;
    std::cout << "       budget fortune check                                       Create a new fortune check" << std::endl;
    std::cout << "       budget fortune edit (id)                                   Edit a fortune check" << std::endl;
    std::cout << "       budget fortune delete (id)                                 Delete a fortune check" << std::endl << std::endl;

    std::cout << "       budget objective [status]                                  Show the status of the objectives for the current year" << std::endl;
    std::cout << "       budget objective list                                      List all the defined objectives" << std::endl;
    std::cout << "       budget objective add                                       Add a new objective" << std::endl;
    std::cout << "       budget objective edit (id)                                 Edit an objective" << std::endl;
    std::cout << "       budget objective delete (id)                               Delete an objective" << std::endl;

    std::cout << "       budget wish [status]                                       Show the status of the wishes" << std::endl;
    std::cout << "       budget wish list                                           List all the wishes" << std::endl;
    std::cout << "       budget wish estimate                                       Estimate the best date to buy something" << std::endl;
    std::cout << "       budget wish add                                            Add a new wish" << std::endl;
    std::cout << "       budget wish edit (id)                                      Edit a wish" << std::endl;
    std::cout << "       budget wish delete (id)                                    Delete a wish" << std::endl;

    std::cout << "       budget debt [list]                                         Display the unpaid debts" << std::endl;
    std::cout << "       budget debt all                                            Display all debts" << std::endl;
    std::cout << "       budget debt paid (id)                                      Mark the given debt as paid" << std::endl;
    std::cout << "       budget debt delete (id)                                    Delete the given debt" << std::endl;
    std::cout << "       budget debt edit (id)                                      Edit the given debt" << std::endl << std::endl;

    std::cout << "       budget versioning save                                     Commit the budget directory changes with Git" << std::endl;
    std::cout << "       budget versioning sync                                     Pull the remote changes on the budget directory with Git and push" << std::endl;

    std::cout << "       budget report [monthly]                                    Display monthly report in form of bar plot" << std::endl;
    std::cout << "       budget report account [monthly]                            Display monthly report of a specific account in form of bar plot" << std::endl;

    std::cout << "       budget gc                                                  Make sure all IDs are contiguous" << std::endl;
}
<|endoftext|>


<commit_before>#ifndef HEADER_GUARD_HOOKS_H
#define HEADER_GUARD_HOOKS_H

#include "contents.hh"

namespace vick {

/*!
 * \file hooks.hh
 *
 * \brief Defines how to hook processes in with one another so that one
 *        action will always accompany another.
 *
 * proc_hook(hook) will call all the functions added in add_hook(hook,
 *void(*)())
 *
 */

/*!
 * \brief Distinguishes normal unsigned ints from being confused as
 * hooks.
 */
using hook_t = unsigned int;

namespace hook {

extern hook_t save;
extern hook_t refresh;
extern hook_t mode_enter;
extern hook_t open_file;
extern hook_t contents_created;
extern hook_t contents_deleted;

/*!
 * \brief Generates a unique hook id
 *
 * This id is made at runtime and is not thread safe.
 */
hook_t gen();
/*!
 * \brief Calls all the functions associated to the hook given
 *
 * To associate a function with a hook use add()
 */
void proc(hook_t, contents&);
/*!
 * \brief Associates the function given with a hook
 *
 * The function argumen is guarenteed to be called whenever
 * proc_hook() is called with the same hook as this method is called
 * with.
 *
 * There can be multiple functions for a certain hook.  They will be
 * called in the order they were added with add()
 */
void add(hook_t, void (*)(contents&));

}
}

#endif
<commit_msg>Add spaces between method documentation<commit_after>#ifndef HEADER_GUARD_HOOKS_H
#define HEADER_GUARD_HOOKS_H

#include "contents.hh"

namespace vick {

/*!
 * \file hooks.hh
 *
 * \brief Defines how to hook processes in with one another so that one
 *        action will always accompany another.
 *
 * proc_hook(hook) will call all the functions added in add_hook(hook,
 *void(*)())
 *
 */

/*!
 * \brief Distinguishes normal unsigned ints from being confused as
 * hooks.
 */
using hook_t = unsigned int;

namespace hook {

extern hook_t save;
extern hook_t refresh;
extern hook_t mode_enter;
extern hook_t open_file;
extern hook_t contents_created;
extern hook_t contents_deleted;

/*!
 * \brief Generates a unique hook id
 *
 * This id is made at runtime and is not thread safe.
 */
hook_t gen();

/*!
 * \brief Calls all the functions associated to the hook given
 *
 * To associate a function with a hook use add()
 */
void proc(hook_t, contents&);

/*!
 * \brief Associates the function given with a hook
 *
 * The function argumen is guarenteed to be called whenever
 * proc_hook() is called with the same hook as this method is called
 * with.
 *
 * There can be multiple functions for a certain hook.  They will be
 * called in the order they were added with add()
 */
void add(hook_t, void (*)(contents&));

}
}

#endif
<|endoftext|>


<commit_before>#include <allegro.h>
#ifdef ALLEGRO_WINDOWS
#include <winalleg.h>
#endif

#ifndef ALLEGRO_WINDOWS
#include <signal.h>
#include <string.h>
#endif

#include "globals.h"
#include "init.h"
#include <pthread.h>
#include "network/network.h"

#include <ostream>
#include "dumb/include/dumb.h"
#include "dumb/include/aldumb.h"
#include "loadpng/loadpng.h"
#include "util/bitmap.h"
#include "configuration.h"

using namespace std;

volatile int Global::speed_counter = 0;
volatile int Global::second_counter = 0;

/* the original engine was running at 90 ticks per second, but we dont
 * need to render that fast, so TICS_PER_SECOND is really fps and
 * LOGIC_MULTIPLIER will be used to adjust the speed counter to its
 * original value.
 */
static const int TICS_PER_SECOND = 40;
const double Global::LOGIC_MULTIPLIER = (double) 90 / (double) TICS_PER_SECOND;

pthread_mutex_t Global::loading_screen_mutex;
bool Global::done_loading = false;

const int Global::WINDOWED = GFX_AUTODETECT_WINDOWED;
const int Global::FULLSCREEN = GFX_AUTODETECT_FULLSCREEN;

void inc_speed_counter() {
	Global::speed_counter += 1;
}
END_OF_FUNCTION( inc_speed_counter );

void inc_second_counter() {
	Global::second_counter += 1;
}
END_OF_FUNCTION( inc_second_counter );

#ifndef ALLEGRO_WINDOWS
static void handleSigPipe( int i, siginfo_t * sig, void * data ){
}

/*
static void handleSigUsr1( int i, siginfo_t * sig, void * data ){
	pthread_exit( NULL );
}
*/
#endif

static void registerSignals(){
#ifndef ALLEGRO_WINDOWS
	struct sigaction action;
	memset( &action, 0, sizeof(struct sigaction) );
	action.sa_sigaction = handleSigPipe;
	sigaction( SIGPIPE, &action, NULL );
	/*
	action.sa_sigaction = handleSigUsr1;
	sigaction( SIGUSR1, &action, NULL );
	*/
#endif
}

bool Global::init( int gfx ){

	ostream & out = Global::debug( 0 );
	out << "-- BEGIN init --" << endl;
	out << "Allegro version: " << ALLEGRO_VERSION_STR << endl;
	out <<"Allegro init: "<<allegro_init()<<endl;
	out <<"Install timer: "<<install_timer()<<endl;

	set_volume_per_voice( 0 );
	out<<"Install sound: "<<install_sound( DIGI_AUTODETECT, MIDI_NONE, "" )<<endl;

	loadpng_init();

        Bitmap::SCALE_X = GFX_X;
        Bitmap::SCALE_Y = GFX_Y;

        const int sx = 640;
        const int sy = 480;

	out<<"Install keyboard: "<<install_keyboard()<<endl;
	out<<"Install mouse: "<<install_mouse()<<endl;
	set_color_depth( 16 );
	out<<"Set gfx mode: " << Bitmap::setGraphicsMode( gfx, sx, sy ) <<endl;

	LOCK_VARIABLE( speed_counter );
	LOCK_VARIABLE( second_counter );
	LOCK_FUNCTION( (void *)inc_speed_counter );
	LOCK_FUNCTION( (void *)inc_second_counter );
	out<<"Install game timer: "<<install_int_ex( inc_speed_counter, BPS_TO_TIMER( TICS_PER_SECOND ) )<<endl;
	out<<"Install second timer: "<<install_int_ex( inc_second_counter, BPS_TO_TIMER( 1 ) )<<endl;
	srand( time( NULL ) );
	set_display_switch_mode( SWITCH_BACKGROUND );

	atexit( &dumb_exit );
	atexit( Network::closeAll );
	dumb_register_packfiles();

	registerSignals();

	Network::init();

	Configuration::loadConfigurations();

	pthread_mutex_init( &Global::loading_screen_mutex, NULL );

	out<<"-- END init --"<<endl;

	/*
	Bitmap::Screen = new Bitmap( screen );
	if ( ! Bitmap::Screen ){
		return false;
	}
	*/
	return true;
}
<commit_msg>add close hook. the game segfaults currently<commit_after>#include <allegro.h>
#ifdef ALLEGRO_WINDOWS
#include <winalleg.h>
#endif

#ifndef ALLEGRO_WINDOWS
#include <signal.h>
#include <string.h>
#endif

#include "globals.h"
#include "init.h"
#include <pthread.h>
#include "network/network.h"

#include <ostream>
#include "dumb/include/dumb.h"
#include "dumb/include/aldumb.h"
#include "loadpng/loadpng.h"
#include "util/bitmap.h"
#include "configuration.h"

using namespace std;

volatile int Global::speed_counter = 0;
volatile int Global::second_counter = 0;

/* the original engine was running at 90 ticks per second, but we dont
 * need to render that fast, so TICS_PER_SECOND is really fps and
 * LOGIC_MULTIPLIER will be used to adjust the speed counter to its
 * original value.
 */
static const int TICS_PER_SECOND = 40;
const double Global::LOGIC_MULTIPLIER = (double) 90 / (double) TICS_PER_SECOND;

pthread_mutex_t Global::loading_screen_mutex;
bool Global::done_loading = false;

const int Global::WINDOWED = GFX_AUTODETECT_WINDOWED;
const int Global::FULLSCREEN = GFX_AUTODETECT_FULLSCREEN;

void inc_speed_counter() {
	Global::speed_counter += 1;
}
END_OF_FUNCTION( inc_speed_counter );

void inc_second_counter() {
	Global::second_counter += 1;
}
END_OF_FUNCTION( inc_second_counter );

#ifndef ALLEGRO_WINDOWS
static void handleSigPipe( int i, siginfo_t * sig, void * data ){
}

/*
static void handleSigUsr1( int i, siginfo_t * sig, void * data ){
	pthread_exit( NULL );
}
*/
#endif

static void registerSignals(){
#ifndef ALLEGRO_WINDOWS
	struct sigaction action;
	memset( &action, 0, sizeof(struct sigaction) );
	action.sa_sigaction = handleSigPipe;
	sigaction( SIGPIPE, &action, NULL );
	/*
	action.sa_sigaction = handleSigUsr1;
	sigaction( SIGUSR1, &action, NULL );
	*/
#endif
}

static void close_paintown(){
    exit(0);
}
END_OF_FUNCTION(close_paintown)

bool Global::init( int gfx ){

	ostream & out = Global::debug( 0 );
	out << "-- BEGIN init --" << endl;
	out << "Allegro version: " << ALLEGRO_VERSION_STR << endl;
	out <<"Allegro init: "<<allegro_init()<<endl;
	out <<"Install timer: "<<install_timer()<<endl;

	set_volume_per_voice( 0 );
	out<<"Install sound: "<<install_sound( DIGI_AUTODETECT, MIDI_NONE, "" )<<endl;

	loadpng_init();

        Bitmap::SCALE_X = GFX_X;
        Bitmap::SCALE_Y = GFX_Y;

        const int sx = 640;
        const int sy = 480;

	out<<"Install keyboard: "<<install_keyboard()<<endl;
	out<<"Install mouse: "<<install_mouse()<<endl;
	set_color_depth( 16 );
	out<<"Set gfx mode: " << Bitmap::setGraphicsMode( gfx, sx, sy ) <<endl;

	LOCK_VARIABLE( speed_counter );
	LOCK_VARIABLE( second_counter );
	LOCK_FUNCTION( (void *)inc_speed_counter );
	LOCK_FUNCTION( (void *)inc_second_counter );
	out<<"Install game timer: "<<install_int_ex( inc_speed_counter, BPS_TO_TIMER( TICS_PER_SECOND ) )<<endl;
	out<<"Install second timer: "<<install_int_ex( inc_second_counter, BPS_TO_TIMER( 1 ) )<<endl;
	srand( time( NULL ) );
	set_display_switch_mode( SWITCH_BACKGROUND );

        LOCK_FUNCTION(close_paintown);
        set_close_button_callback(close_paintown);

	atexit( &dumb_exit );
	atexit( Network::closeAll );
	dumb_register_packfiles();

	registerSignals();

	Network::init();

	Configuration::loadConfigurations();

	pthread_mutex_init( &Global::loading_screen_mutex, NULL );

	out<<"-- END init --"<<endl;

	/*
	Bitmap::Screen = new Bitmap( screen );
	if ( ! Bitmap::Screen ){
		return false;
	}
	*/
	return true;
}
<|endoftext|>


<commit_before>#include "json.hpp"

using namespace std;

ptree json_decode(string s) {

  ptree p;

  std::istringstream ss (s);
  try {
    read_json (ss,p);
  }
  catch (exception e) {
    cerr << "*CRITICAL: CANNOT PARSE/MALFORMED JSON '" << s << "'" << endl;
  }
}

std::string json_escape(const std::string& input) {
    std::ostringstream ss;
    for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) {
        switch (*iter) {
            case '\\': ss << "\\\\"; break;
            case '"': ss << "\\\""; break;
            case '/': ss << "\\/"; break;
            case '\b': ss << "\\b"; break;
            case '\f': ss << "\\f"; break;
            case '\n': ss << "\\n"; break;
            case '\r': ss << "\\r"; break;
            case '\t': ss << "\\t"; break;
            default: ss << *iter; break;
        }
    }
    return ss.str();
}
<commit_msg>Mods on json_decode<commit_after>#include "json.hpp"

using namespace std;

ptree json_decode(string s) {

  ptree* p = new ptree();

  std::istringstream ss (s);
  try {
    read_json (ss,*p);
  }
  catch (exception e) {
    cerr << "*CRITICAL: CANNOT PARSE/MALFORMED JSON '" << s << "'" << endl;
  }
  return *p;
}

std::string json_escape(const std::string& input) {
    std::ostringstream ss;
    for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) {
        switch (*iter) {
            case '\\': ss << "\\\\"; break;
            case '"': ss << "\\\""; break;
            case '/': ss << "\\/"; break;
            case '\b': ss << "\\b"; break;
            case '\f': ss << "\\f"; break;
            case '\n': ss << "\\n"; break;
            case '\r': ss << "\\r"; break;
            case '\t': ss << "\\t"; break;
            default: ss << *iter; break;
        }
    }
    return ss.str();
}
<|endoftext|>


<commit_before>/*
  Copyright (C) 2002 by Marten Svanfeldt
                        Anders Stenberg

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 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
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"

#include "csgeom/vector3.h"
#include "csutil/objreg.h"
#include "csutil/ref.h"
#include "csutil/scf.h"
#include "csutil/stringreader.h"
#include "iutil/databuff.h"
#include "iutil/document.h"
#include "iutil/string.h"
#include "ivaria/reporter.h"
#include "ivideo/graph3d.h"
#include "ivideo/shader/shader.h"

#include "glshader_cgfp.h"

CS_PLUGIN_NAMESPACE_BEGIN(GLShaderCg)
{

CS_LEAKGUARD_IMPLEMENT (csShaderGLCGFP);

void csShaderGLCGFP::Activate()
{
  if (pswrap)
  {
    pswrap->Activate ();
    return;
  }

  csShaderGLCGCommon::Activate();
}

void csShaderGLCGFP::Deactivate()
{
  if (pswrap)
  {
    pswrap->Deactivate ();
    return;
  }

  csShaderGLCGCommon::Deactivate();
}

void csShaderGLCGFP::SetupState (const CS::Graphics::RenderMesh* mesh,
                                 CS::Graphics::RenderMeshModes& modes,
                                 const csShaderVariableStack& stack)
{
  if (pswrap)
  {
    pswrap->SetupState (mesh, modes, stack);
    return;
  }

  csShaderGLCGCommon::SetupState (mesh, modes, stack);
}

void csShaderGLCGFP::ResetState()
{
  if (pswrap)
  {
    pswrap->ResetState ();
    return;
  }
  csShaderGLCGCommon::ResetState();
}

bool csShaderGLCGFP::Compile ()
{
  if (!shaderPlug->enableFP) return false;

  csRef<iDataBuffer> programBuffer = GetProgramData();
  if (!programBuffer.IsValid())
    return false;
  csString programStr;
  programStr.Append ((char*)programBuffer->GetData(), programBuffer->GetSize());

  size_t i;

  // See if we want to wrap through the PS plugin
  // (psplg will be 0 if wrapping isn't wanted)
  if (shaderPlug->psplg)
  {
    ArgumentArray args;
    shaderPlug->GetProfileCompilerArgs ("fragment", shaderPlug->psProfile,
      args);
    for (i = 0; i < compilerArgs.GetSize(); i++)
      args.Push (compilerArgs[i]);
    args.Push (0);
    program = cgCreateProgram (shaderPlug->context, CG_SOURCE,
      programStr, shaderPlug->psProfile,
      !entrypoint.IsEmpty() ? entrypoint : "main", args.GetArray());

    if (!program)
      return false;

    pswrap = shaderPlug->psplg->CreateProgram ("fp");

    if (!pswrap)
      return false;

    csArray<csShaderVarMapping> mappings;

    for (i = 0; i < variablemap.GetSize (); i++)
    {
      // Get the Cg parameter
      CGparameter parameter = cgGetNamedParameter (
	program, variablemap[i].destination);
      // Check if it's found, and just skip it if not.
      if (!parameter)
        continue;
      if (!cgIsParameterReferenced (parameter))
	continue;
      // Make sure it's a C-register
      CGresource resource = cgGetParameterResource (parameter);
      if (resource == CG_C)
      {
        // Get the register number, and create a mapping
        csString regnum;
        regnum.Format ("c%lu", cgGetParameterResourceIndex (parameter));
        mappings.Push (csShaderVarMapping (variablemap[i].name, regnum));
      }
    }

    if (pswrap->Load (0, cgGetProgramString (program, CG_COMPILED_PROGRAM),
      mappings))
    {
      bool ret = pswrap->Compile ();
      if (shaderPlug->debugDump)
        DoDebugDump();
      return ret;
    }
    else
    {
      return false;
    }
  }
  else
  {
    csStringArray testForUnused;
    csStringReader lines (programStr);
    while (lines.HasMoreLines())
    {
      csString line;
      lines.GetLine (line);
      if (line.StartsWith ("//@@UNUSED? "))
      {
        line.DeleteAt (0, 12);
        testForUnused.Push (line);
      }
    }

    if (testForUnused.GetSize() > 0)
    {
      /* A list of unused variables to test for has been given. Test piecemeal
       * which variables are really unused */
      csSet<csString> allNewUnusedParams;
      size_t step = 8;
      size_t offset = 0;
      while (offset < testForUnused.GetSize())
      {
        unusedParams.DeleteAll();
        for (size_t i = 0; i < offset; i++)
          unusedParams.Add (testForUnused[i]);
        for (size_t i = offset+step; i < testForUnused.GetSize(); i++)
          unusedParams.Add (testForUnused[i]);
	if (DefaultLoadProgram (0, programStr, CG_GL_FRAGMENT,
	  shaderPlug->maxProfileFragment, loadIgnoreErrors))
	{
	  csSet<csString> newUnusedParams;
	  CollectUnusedParameters (newUnusedParams);
	  for (size_t i = 0; i < step; i++)
	  {
	    if (offset+i >= testForUnused.GetSize()) break;
	    const char* s = testForUnused[offset+i];
	    if (newUnusedParams.Contains (s))
	      allNewUnusedParams.Add (s);
	  }
	}

        offset += step;
      }
      unusedParams = allNewUnusedParams;
    }
    else
    {
      unusedParams.DeleteAll();
    }
    if (!DefaultLoadProgram (0, programStr, CG_GL_FRAGMENT,
      shaderPlug->maxProfileFragment, loadLoadToGL))
      return false;
    /* Compile twice to be able to filter out unused vertex2fragment stuff on
     * pass 2.
     * @@@ FIXME: two passes are not always needed.
     */
    CollectUnusedParameters (unusedParams);
    return DefaultLoadProgram (this, programStr, CG_GL_FRAGMENT,
      shaderPlug->maxProfileFragment);
  }

  return true;
}

int csShaderGLCGFP::ResolveTU (const char* binding)
{
  int newTU = -1;
  if (program)
  {
    CGparameter parameter = cgGetNamedParameter (program, binding);
    if (parameter)
    {
      if ((cgGetParameterBaseResource (parameter) == CG_TEXUNIT0) ||
	(cgGetParameterBaseResource (parameter) == CG_TEX0))
      {
	newTU = cgGetParameterResourceIndex (parameter);
      }
    }
  }

  return newTU;
}

}
CS_PLUGIN_NAMESPACE_END(GLShaderCg)
<commit_msg>Don't bind textures which aren't actually used<commit_after>/*
  Copyright (C) 2002 by Marten Svanfeldt
                        Anders Stenberg

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 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
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"

#include "csgeom/vector3.h"
#include "csutil/objreg.h"
#include "csutil/ref.h"
#include "csutil/scf.h"
#include "csutil/stringreader.h"
#include "iutil/databuff.h"
#include "iutil/document.h"
#include "iutil/string.h"
#include "ivaria/reporter.h"
#include "ivideo/graph3d.h"
#include "ivideo/shader/shader.h"

#include "glshader_cgfp.h"

CS_PLUGIN_NAMESPACE_BEGIN(GLShaderCg)
{

CS_LEAKGUARD_IMPLEMENT (csShaderGLCGFP);

void csShaderGLCGFP::Activate()
{
  if (pswrap)
  {
    pswrap->Activate ();
    return;
  }

  csShaderGLCGCommon::Activate();
}

void csShaderGLCGFP::Deactivate()
{
  if (pswrap)
  {
    pswrap->Deactivate ();
    return;
  }

  csShaderGLCGCommon::Deactivate();
}

void csShaderGLCGFP::SetupState (const CS::Graphics::RenderMesh* mesh,
                                 CS::Graphics::RenderMeshModes& modes,
                                 const csShaderVariableStack& stack)
{
  if (pswrap)
  {
    pswrap->SetupState (mesh, modes, stack);
    return;
  }

  csShaderGLCGCommon::SetupState (mesh, modes, stack);
}

void csShaderGLCGFP::ResetState()
{
  if (pswrap)
  {
    pswrap->ResetState ();
    return;
  }
  csShaderGLCGCommon::ResetState();
}

bool csShaderGLCGFP::Compile ()
{
  if (!shaderPlug->enableFP) return false;

  csRef<iDataBuffer> programBuffer = GetProgramData();
  if (!programBuffer.IsValid())
    return false;
  csString programStr;
  programStr.Append ((char*)programBuffer->GetData(), programBuffer->GetSize());

  size_t i;

  // See if we want to wrap through the PS plugin
  // (psplg will be 0 if wrapping isn't wanted)
  if (shaderPlug->psplg)
  {
    ArgumentArray args;
    shaderPlug->GetProfileCompilerArgs ("fragment", shaderPlug->psProfile,
      args);
    for (i = 0; i < compilerArgs.GetSize(); i++)
      args.Push (compilerArgs[i]);
    args.Push (0);
    program = cgCreateProgram (shaderPlug->context, CG_SOURCE,
      programStr, shaderPlug->psProfile,
      !entrypoint.IsEmpty() ? entrypoint : "main", args.GetArray());

    if (!program)
      return false;

    pswrap = shaderPlug->psplg->CreateProgram ("fp");

    if (!pswrap)
      return false;

    csArray<csShaderVarMapping> mappings;

    for (i = 0; i < variablemap.GetSize (); i++)
    {
      // Get the Cg parameter
      CGparameter parameter = cgGetNamedParameter (
	program, variablemap[i].destination);
      // Check if it's found, and just skip it if not.
      if (!parameter)
        continue;
      if (!cgIsParameterReferenced (parameter))
	continue;
      // Make sure it's a C-register
      CGresource resource = cgGetParameterResource (parameter);
      if (resource == CG_C)
      {
        // Get the register number, and create a mapping
        csString regnum;
        regnum.Format ("c%lu", cgGetParameterResourceIndex (parameter));
        mappings.Push (csShaderVarMapping (variablemap[i].name, regnum));
      }
    }

    if (pswrap->Load (0, cgGetProgramString (program, CG_COMPILED_PROGRAM),
      mappings))
    {
      bool ret = pswrap->Compile ();
      if (shaderPlug->debugDump)
        DoDebugDump();
      return ret;
    }
    else
    {
      return false;
    }
  }
  else
  {
    csStringArray testForUnused;
    csStringReader lines (programStr);
    while (lines.HasMoreLines())
    {
      csString line;
      lines.GetLine (line);
      if (line.StartsWith ("//@@UNUSED? "))
      {
        line.DeleteAt (0, 12);
        testForUnused.Push (line);
      }
    }

    if (testForUnused.GetSize() > 0)
    {
      /* A list of unused variables to test for has been given. Test piecemeal
       * which variables are really unused */
      csSet<csString> allNewUnusedParams;
      size_t step = 8;
      size_t offset = 0;
      while (offset < testForUnused.GetSize())
      {
        unusedParams.DeleteAll();
        for (size_t i = 0; i < offset; i++)
          unusedParams.Add (testForUnused[i]);
        for (size_t i = offset+step; i < testForUnused.GetSize(); i++)
          unusedParams.Add (testForUnused[i]);
	if (DefaultLoadProgram (0, programStr, CG_GL_FRAGMENT,
	  shaderPlug->maxProfileFragment, loadIgnoreErrors))
	{
	  csSet<csString> newUnusedParams;
	  CollectUnusedParameters (newUnusedParams);
	  for (size_t i = 0; i < step; i++)
	  {
	    if (offset+i >= testForUnused.GetSize()) break;
	    const char* s = testForUnused[offset+i];
	    if (newUnusedParams.Contains (s))
	      allNewUnusedParams.Add (s);
	  }
	}

        offset += step;
      }
      unusedParams = allNewUnusedParams;
    }
    else
    {
      unusedParams.DeleteAll();
    }
    if (!DefaultLoadProgram (0, programStr, CG_GL_FRAGMENT,
      shaderPlug->maxProfileFragment, loadLoadToGL))
      return false;
    /* Compile twice to be able to filter out unused vertex2fragment stuff on
     * pass 2.
     * @@@ FIXME: two passes are not always needed.
     */
    CollectUnusedParameters (unusedParams);
    return DefaultLoadProgram (this, programStr, CG_GL_FRAGMENT,
      shaderPlug->maxProfileFragment);
  }

  return true;
}

int csShaderGLCGFP::ResolveTU (const char* binding)
{
  int newTU = -1;
  if (program)
  {
    CGparameter parameter = cgGetNamedParameter (program, binding);
    if (parameter)
    {
      CGresource baseRes = cgGetParameterBaseResource (parameter);
      if (((baseRes == CG_TEXUNIT0) || (baseRes == CG_TEX0))
          && (cgIsParameterUsed (parameter, program)
            || cgIsParameterReferenced (parameter)))
      {
	newTU = cgGetParameterResourceIndex (parameter);
      }
    }
  }

  return newTU;
}

}
CS_PLUGIN_NAMESPACE_END(GLShaderCg)
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

typedef tuple<int, int> edge;
typedef tuple<int, int, int> uvc;

int N, M;
vector<edge> V[310];

bool subroutine(uvc e) {
  int u0 = get<0>(e);
  edge edge0 = edge(get<1>(e), get<2>(e));
  int u1 = get<1>(e);
  edge edge1 = edge(get<0>(e), -get<2>(e));
  // Make an dfs tree without (u0, edge0) and (u1, edge1).
  stack<edge> S;
  S.push(edge(0, 0));
  int height[310];
  fill(height, height+310, -1);
  uvc parent[310];
  parent[0] = uvc(-1, 0, -1);
  while (!S.empty()) {
    int now = get<0>(S.top());
    int h = get<1>(S.top());
    S.pop();
    if (height[now] == -1) {
      height[now] = h;
      for (auto x : V[now]) {
        if ((now == u0 && x == edge0) || (now == u1 && x == edge1)) {
          continue;
        }
        int dst = get<0>(x);
        int cost = h + get<1>(x);
        if (height[dst] == -1) {
          parent[dst] = uvc(now, dst, cost);
          S.push(edge(dst, cost));
        }
      }
    }
  }
  for (auto i = 0; i < N; ++i) {
    for (auto x : V[i]) {
      int j = get<0>(x);
      int cost = get<1>(x);
      if (height[j] - height[i] != cost) {
        return false;
      }
    }
  }
  return true;
}

int main () {
  cin >> N >> M;
  for (auto i = 0; i < M; ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    --a;
    --b;
    V[a].push_back(edge(b, c));
    V[b].push_back(edge(a, -c));
  }
  // Make an initial dfs tree.
  stack<edge> S;
  S.push(edge(0, 0));
  int height[310];
  fill(height, height+310, -1);
  uvc parent[310];
  parent[0] = uvc(-1, 0, -1);
  while (!S.empty()) {
    int now = get<0>(S.top());
    int h = get<1>(S.top());
    S.pop();
    if (height[now] == -1) {
      // cerr << now << " " << h << endl;
      height[now] = h;
      for (auto x : V[now]) {
        int dst = get<0>(x);
        int cost = h + get<1>(x);
        if (height[dst] == -1) {
          parent[dst] = uvc(now, dst, cost);
          S.push(edge(dst, cost));
        }
      }
    }
  }
  bool initial_ok = true;
  vector<uvc> forbid;
  for (auto i = 0; i < N; ++i) {
    for (auto x : V[i]) {
      int j = get<0>(x);
      int cost = get<1>(x);
      if (height[j] - height[i] != cost) {
        cerr << "height[" << j << "] - height[" << i << "] = "
             << height[j] << " - " << height[i]
             << " != " << cost << endl;
        initial_ok = false;
        int now = i;
        while (now != 0) {
          forbid.push_back(parent[now]);
          now = get<0>(parent[now]);
        }
        now = j;
        while (now != 0) {
          forbid.push_back(parent[now]);
          now = get<0>(parent[now]);
        }
        break;
      }
    }
    if (!initial_ok) break;
  }
  if (initial_ok) {
    cout << "Yes" << endl;
    return 0;
  }
  for (auto e : forbid) {
    if (subroutine(e)) {
      cout << "Yes" << endl;
      return 0;
    }
  }
  cout << "No" << endl;
  return 0;
}
<commit_msg>tried C.cpp to 'C'<commit_after>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

typedef tuple<int, int> edge;
typedef tuple<int, int, int> uvc;

int N, M;
vector<edge> V[310];

bool subroutine(uvc e) {
  int u0 = get<0>(e);
  edge edge0 = edge(get<1>(e), get<2>(e));
  int u1 = get<1>(e);
  edge edge1 = edge(get<0>(e), -get<2>(e));
  cerr << u0 << " " << u1 << " is not used." << endl;
  // Make an dfs tree without (u0, edge0) and (u1, edge1).
  stack<edge> S;
  S.push(edge(0, 0));
  int height[310];
  fill(height, height+310, -1);
  uvc parent[310];
  parent[0] = uvc(-1, 0, -1);
  while (!S.empty()) {
    int now = get<0>(S.top());
    int h = get<1>(S.top());
    S.pop();
    if (height[now] == -1) {
      height[now] = h;
      for (auto x : V[now]) {
        if ((now == u0 && x == edge0) || (now == u1 && x == edge1)) {
          continue;
        }
        int dst = get<0>(x);
        int cost = h + get<1>(x);
        if (height[dst] == -1) {
          parent[dst] = uvc(now, dst, cost);
          S.push(edge(dst, cost));
        }
      }
    }
  }
  for (auto i = 0; i < N; ++i) {
    for (auto x : V[i]) {
      int j = get<0>(x);
      int cost = get<1>(x);
      if (height[j] - height[i] != cost) {
        cerr << "height[" << j << "] - height[" << i << "] = "
             << height[j] << " - " << height[i]
             << " != " << cost << endl;
        return false;
      }
    }
  }
  return true;
}

int main () {
  cin >> N >> M;
  for (auto i = 0; i < M; ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    --a;
    --b;
    V[a].push_back(edge(b, c));
    V[b].push_back(edge(a, -c));
  }
  // Make an initial dfs tree.
  stack<edge> S;
  S.push(edge(0, 0));
  int height[310];
  fill(height, height+310, -1);
  uvc parent[310];
  parent[0] = uvc(-1, 0, -1);
  while (!S.empty()) {
    int now = get<0>(S.top());
    int h = get<1>(S.top());
    S.pop();
    if (height[now] == -1) {
      // cerr << now << " " << h << endl;
      height[now] = h;
      for (auto x : V[now]) {
        int dst = get<0>(x);
        int cost = h + get<1>(x);
        if (height[dst] == -1) {
          parent[dst] = uvc(now, dst, cost);
          S.push(edge(dst, cost));
        }
      }
    }
  }
  bool initial_ok = true;
  vector<uvc> forbid;
  for (auto i = 0; i < N; ++i) {
    for (auto x : V[i]) {
      int j = get<0>(x);
      int cost = get<1>(x);
      if (height[j] - height[i] != cost) {
        cerr << "height[" << j << "] - height[" << i << "] = "
             << height[j] << " - " << height[i]
             << " != " << cost << endl;
        initial_ok = false;
        int now = i;
        while (now != 0) {
          forbid.push_back(parent[now]);
          now = get<0>(parent[now]);
        }
        now = j;
        while (now != 0) {
          forbid.push_back(parent[now]);
          now = get<0>(parent[now]);
        }
        break;
      }
    }
    if (!initial_ok) break;
  }
  if (initial_ok) {
    cout << "Yes" << endl;
    return 0;
  }
  for (auto e : forbid) {
    if (subroutine(e)) {
      cout << "Yes" << endl;
      return 0;
    }
  }
  cout << "No" << endl;
  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: dlelstnr.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: tl $ $Date: 2001-02-27 14:53:05 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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 Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _DLELSTNR_HXX_
#define _DLELSTNR_HXX_

#include <cppuhelper/weak.hxx>

#ifndef _COM_SUN_STAR_LINGUISTIC2_XDICTIONARYLISTEVENTLISTENER_HPP_
#include <com/sun/star/linguistic2/XDictionaryListEventListener.hpp>
#endif
#ifndef _COM_SUN_STAR_LINGUISTIC2_XLINGUSERVICEEVENTLISTENER_HPP_
#include <com/sun/star/linguistic2/XLinguServiceEventListener.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XTERMINATELISTENER_HPP_
#include <com/sun/star/frame/XTerminateListener.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XDESKTOP_HPP_
#include <com/sun/star/frame/XDesktop.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx> // helper for implementations
#endif

namespace com { namespace sun { namespace star {
    namespace linguistic2 {
        class XDictionaryList;
        class XLinguServiceManager;
    }
    namespace frame {
        class XTerminateListener;
    }
} } }

///////////////////////////////////////////////////////////////////////////
// SwLinguServiceEventListener
// is a EventListener that triggers spellchecking
// and hyphenation when relevant changes (to the
// dictionaries of the dictionary list, or properties) were made.
//

class SwLinguServiceEventListener :
    public cppu::WeakImplHelper2
    <
        com::sun::star::linguistic2::XLinguServiceEventListener,
        com::sun::star::frame::XTerminateListener
    >
{
    com::sun::star::uno::Reference<
        com::sun::star::frame::XDesktop >                   xDesktop;
    com::sun::star::uno::Reference<
        com::sun::star::linguistic2::XLinguServiceManager > xLngSvcMgr;

    // disallow use of copy-constructor and assignment operator
    SwLinguServiceEventListener(const SwLinguServiceEventListener &);
    SwLinguServiceEventListener & operator = (const SwLinguServiceEventListener &);

public:
    SwLinguServiceEventListener();
    virtual ~SwLinguServiceEventListener();

    // XEventListener
    virtual void SAL_CALL disposing(
            const ::com::sun::star::lang::EventObject& rEventObj )
        throw(::com::sun::star::uno::RuntimeException);

    // XDictionaryListEventListener
    virtual void    SAL_CALL processDictionaryListEvent(
            const ::com::sun::star::linguistic2::DictionaryListEvent& rDicListEvent)
        throw( ::com::sun::star::uno::RuntimeException );

    // XLinguServiceEventListener
    virtual void SAL_CALL processLinguServiceEvent(
            const ::com::sun::star::linguistic2::LinguServiceEvent& rLngSvcEvent )
        throw(::com::sun::star::uno::RuntimeException);

    // XTerminateListener
    virtual void SAL_CALL queryTermination(
            const ::com::sun::star::lang::EventObject& rEventObj )
        throw(::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL notifyTermination(
            const ::com::sun::star::lang::EventObject& rEventObj )
        throw(::com::sun::star::uno::RuntimeException);
};

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.4.1454); FILE MERGED 2005/09/05 13:35:50 rt 1.4.1454.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dlelstnr.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 01:40:15 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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 Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _DLELSTNR_HXX_
#define _DLELSTNR_HXX_

#include <cppuhelper/weak.hxx>

#ifndef _COM_SUN_STAR_LINGUISTIC2_XDICTIONARYLISTEVENTLISTENER_HPP_
#include <com/sun/star/linguistic2/XDictionaryListEventListener.hpp>
#endif
#ifndef _COM_SUN_STAR_LINGUISTIC2_XLINGUSERVICEEVENTLISTENER_HPP_
#include <com/sun/star/linguistic2/XLinguServiceEventListener.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XTERMINATELISTENER_HPP_
#include <com/sun/star/frame/XTerminateListener.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XDESKTOP_HPP_
#include <com/sun/star/frame/XDesktop.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx> // helper for implementations
#endif

namespace com { namespace sun { namespace star {
    namespace linguistic2 {
        class XDictionaryList;
        class XLinguServiceManager;
    }
    namespace frame {
        class XTerminateListener;
    }
} } }

///////////////////////////////////////////////////////////////////////////
// SwLinguServiceEventListener
// is a EventListener that triggers spellchecking
// and hyphenation when relevant changes (to the
// dictionaries of the dictionary list, or properties) were made.
//

class SwLinguServiceEventListener :
    public cppu::WeakImplHelper2
    <
        com::sun::star::linguistic2::XLinguServiceEventListener,
        com::sun::star::frame::XTerminateListener
    >
{
    com::sun::star::uno::Reference<
        com::sun::star::frame::XDesktop >                   xDesktop;
    com::sun::star::uno::Reference<
        com::sun::star::linguistic2::XLinguServiceManager > xLngSvcMgr;

    // disallow use of copy-constructor and assignment operator
    SwLinguServiceEventListener(const SwLinguServiceEventListener &);
    SwLinguServiceEventListener & operator = (const SwLinguServiceEventListener &);

public:
    SwLinguServiceEventListener();
    virtual ~SwLinguServiceEventListener();

    // XEventListener
    virtual void SAL_CALL disposing(
            const ::com::sun::star::lang::EventObject& rEventObj )
        throw(::com::sun::star::uno::RuntimeException);

    // XDictionaryListEventListener
    virtual void    SAL_CALL processDictionaryListEvent(
            const ::com::sun::star::linguistic2::DictionaryListEvent& rDicListEvent)
        throw( ::com::sun::star::uno::RuntimeException );

    // XLinguServiceEventListener
    virtual void SAL_CALL processLinguServiceEvent(
            const ::com::sun::star::linguistic2::LinguServiceEvent& rLngSvcEvent )
        throw(::com::sun::star::uno::RuntimeException);

    // XTerminateListener
    virtual void SAL_CALL queryTermination(
            const ::com::sun::star::lang::EventObject& rEventObj )
        throw(::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL notifyTermination(
            const ::com::sun::star::lang::EventObject& rEventObj )
        throw(::com::sun::star::uno::RuntimeException);
};

#endif

<|endoftext|>


<commit_before><commit_msg>提高兼容性<commit_after><|endoftext|>


<commit_before><commit_msg>Minor update.<commit_after><|endoftext|>


<commit_before>// -*- c++ -*-

/*!
 *
 * Copyright (C) 2012 Jolla Ltd.
 *
 * Contact: Mohammed Hassan <mohammed.hassan@jollamobile.com>
 * Author: Andres Gomez <agomez@igalia.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 Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "simple-model.h"

#include <GriloRegistry>
#include <GriloBrowse>
#include <GriloMedia>

#include <QVariant>

SimpleModel::SimpleModel(QObject *parent) :
    GriloModel(parent),
    m_grlRegistry(0),
    m_grlBrowse(0)
{
    m_grlRegistry = new GriloRegistry();
    // Not nice that we have to call this ...
    m_grlRegistry->componentComplete();
    m_grlRegistry->loadPluginById("grl-filesystem");

    m_grlBrowse = new GriloBrowse();
    m_grlBrowse->setSource("grl-filesystem");
    m_grlBrowse->setRegistry(m_grlRegistry);

    QVariantList metaDataKeys;
    metaDataKeys.append(QVariant(GriloDataSource::Title));

    QVariantList typeFilter;
    typeFilter.append(QVariant(GriloDataSource::Audio));

    m_grlBrowse->setMetadataKeys(metaDataKeys);
    m_grlBrowse->setTypeFilter(typeFilter);

    QObject::connect(m_grlBrowse, SIGNAL(baseMediaChanged()), m_grlBrowse, SLOT(refresh()));

    setSource(m_grlBrowse);
}

SimpleModel::~SimpleModel()
{
    if (m_grlBrowse) {
        delete m_grlBrowse;
    }

    if (m_grlRegistry) {
        delete m_grlRegistry;
    }
}

QVariant SimpleModel::data(const QModelIndex& index, int role) const
{
    if (index.row() < 0 || index.row() >= rowCount()) {
        return QVariant();
    }

    switch (role) {
    case GriloModel::MediaRole:
        return QVariant::fromValue(get(index.row()));
    case Qt::DisplayRole:
        return qobject_cast<GriloMedia*>(get(index.row()))->title();
    }

    return QVariant();
}

void SimpleModel::onItemClicked(const QModelIndex& index)
{
    QVariant mediaVariant = data(index, GriloModel::MediaRole);

    GriloMedia *media = mediaVariant.value<GriloMedia*>();
    if (!media) {
        return;
    }

    if (media->isContainer()) {
        m_grlBrowse->setBaseMedia(media->serialize());
        qWarning() << media->serialize();
    }
}
<commit_msg>[example] Removed left qWarning<commit_after>// -*- c++ -*-

/*!
 *
 * Copyright (C) 2012 Jolla Ltd.
 *
 * Contact: Mohammed Hassan <mohammed.hassan@jollamobile.com>
 * Author: Andres Gomez <agomez@igalia.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 Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "simple-model.h"

#include <GriloRegistry>
#include <GriloBrowse>
#include <GriloMedia>

#include <QVariant>

SimpleModel::SimpleModel(QObject *parent) :
    GriloModel(parent),
    m_grlRegistry(0),
    m_grlBrowse(0)
{
    m_grlRegistry = new GriloRegistry();
    // Not nice that we have to call this ...
    m_grlRegistry->componentComplete();
    m_grlRegistry->loadPluginById("grl-filesystem");

    m_grlBrowse = new GriloBrowse();
    m_grlBrowse->setSource("grl-filesystem");
    m_grlBrowse->setRegistry(m_grlRegistry);

    QVariantList metaDataKeys;
    metaDataKeys.append(QVariant(GriloDataSource::Title));

    QVariantList typeFilter;
    typeFilter.append(QVariant(GriloDataSource::Audio));

    m_grlBrowse->setMetadataKeys(metaDataKeys);
    m_grlBrowse->setTypeFilter(typeFilter);

    QObject::connect(m_grlBrowse, SIGNAL(baseMediaChanged()), m_grlBrowse, SLOT(refresh()));

    setSource(m_grlBrowse);
}

SimpleModel::~SimpleModel()
{
    if (m_grlBrowse) {
        delete m_grlBrowse;
    }

    if (m_grlRegistry) {
        delete m_grlRegistry;
    }
}

QVariant SimpleModel::data(const QModelIndex& index, int role) const
{
    if (index.row() < 0 || index.row() >= rowCount()) {
        return QVariant();
    }

    switch (role) {
    case GriloModel::MediaRole:
        return QVariant::fromValue(get(index.row()));
    case Qt::DisplayRole:
        return qobject_cast<GriloMedia*>(get(index.row()))->title();
    }

    return QVariant();
}

void SimpleModel::onItemClicked(const QModelIndex& index)
{
    QVariant mediaVariant = data(index, GriloModel::MediaRole);

    GriloMedia *media = mediaVariant.value<GriloMedia*>();
    if (!media) {
        return;
    }

    if (media->isContainer()) {
        m_grlBrowse->setBaseMedia(media->serialize());
    }
}
<|endoftext|>