Example #1
0
Res ParseValueStringOrMap(const Context* ctx,
                          Config* cfg,
                          const Json::Value& val,
                          const string& equals_string,
                          const string& separator_string,
                          string* out) {
  if (val.isString()) {
    *out = val.asString();
  } else if (val.isArray()) {
    // Evaluate as a lisp expression.
    Res err = EvalToString(ctx, cfg, val, out);
    if (!err.Ok()) {
      err.AppendDetail("in ParseValueStringOrMap(): array eval of '" +
                       val.toStyledString() + "'");
      return err;
    }
  } else if (val.isObject()) {
    // Evaluate as a named-value map.
    bool done_first = false;
    out->clear();
    for (Json::Value::iterator it = val.begin(); it != val.end(); ++it) {
      if (!it.key().isString()) {
        return Res(ERR_PARSE,
                   "ParseValueStringOrMap(): key is not a string: '" +
                   it.key().toStyledString());
      }
      const Json::Value& map_val = *it;
      string result;
      Res err = EvalToString(ctx, cfg, map_val, &result);
      if (!err.Ok()) {
        err.AppendDetail("in ParseValueStringOrMap(): key '" +
                         it.key().toStyledString() + "'");
        return err;
      }
      if (done_first) {
        *out += separator_string;
      }
      *out += it.key().asString();
      *out += equals_string;
      *out += result;
      done_first = true;
    }
  }
  return Res(OK);
}
Example #2
0
void ExitIfError(const Res& res, const Context& context) {
  if (res.Ok()) {
    return;
  }

  if (res.value() == ERR_SHOW_USAGE) {
    PrintUsage();
    exit(1);
  }

  fprintf(stderr, "dmb error\n");
  fprintf(stderr, "%s\n", res.ToString().c_str());

  if (context.log_verbose()) {
    context.LogAllTargets();
  }

  exit(1);
}
Example #3
0
// DepHash(src_file) = Hash(src_file) + sum(for d in deps: DepHash(d))
//
// The include_chain helps us avoid infinite recursion in case of
// include cycles.
Res AccumulateSrcFileDepHash(const Target* t, const Context* context,
                             const string& src_path, const string& inc_dirs_str,
                             std::set<string>* included,
                             Hash* dep_hash) {
    if (included->find(src_path) != included->end()) {
        // Recursive include; we've already visited this file.  Don't
        // recurse infinitely!
        *dep_hash << src_path;
        return Res(OK);
    }

    // Insert src_path into the include chain, and remove it before we
    // return.
    struct AutoInsertRemove {
    public:
        AutoInsertRemove(std::set<string>* included, const string& file) :
            included_(included), file_(file) {
            included_->insert(file_);
        }
        ~AutoInsertRemove() {
            included_->erase(file_);
        }
    private:
        std::set<string>* included_;
        const string& file_;
    };
    AutoInsertRemove auto_insert_remove(included, src_path);

    Hash content_hash;
    Res res = context->ComputeOrGetFileContentHash(src_path, &content_hash);
    if (!res.Ok()) {
        return res;
    }

    // Check to see if we've already computed this dep hash.
    HashCache<Hash>* dep_hash_cache = context->GetDepHashCache();
    assert(dep_hash_cache);
    Hash dep_cache_key;
    dep_cache_key << "dep_cache_key" << src_path << content_hash << inc_dirs_str;
    Hash cached_dep_hash;
    if (dep_hash_cache->Get(dep_cache_key, &cached_dep_hash)) {
        *dep_hash << cached_dep_hash;
        return Res(OK);
    }

    // Compute the dep hash.
    Hash computed_dep_hash;
    computed_dep_hash << content_hash;

    vector<string> includes;
    res = GetIncludes(t, context, src_path, inc_dirs_str, &includes);
    if (!res.Ok()) {
        return res;
    }

    for (size_t i = 0; i < includes.size(); i++) {
        res = AccumulateSrcFileDepHash(t, context, includes[i], inc_dirs_str,
                                       included, &computed_dep_hash);
        if (!res.Ok()) {
            return res;
        }
    }

    // Write the computed hash back to the cache, for re-use.
    dep_hash_cache->Insert(dep_cache_key, computed_dep_hash);
    *dep_hash << computed_dep_hash;

    return Res(OK);
}
Example #4
0
Res GetIncludes(const Target* t, const Context* context,
                const string& src_path, const string& inc_dirs_str,
                vector<string>* includes) {
    Hash src_hash;
    Res res = context->ComputeOrGetFileContentHash(src_path, &src_hash);
    if (!res.Ok()) {
        return res;
    }

    Hash deps_file_id;
    deps_file_id << "includes" << src_hash << inc_dirs_str;

    ObjectStore* ostore = context->GetObjectStore();
    FILE* fp = ostore->Read(deps_file_id);
    if (fp) {
        // Read the deps file.
        static const int BUFSIZE = 1000;
        char linebuf[BUFSIZE];
        while (fgets(linebuf, BUFSIZE, fp)) {
            if (linebuf[0] == '\r' || linebuf[0] == '\n' || linebuf[0] == '#') {
                // Skip.
                continue;
            }
            int len = strlen(linebuf);

            // Trim.
            while (len >= 0 && (linebuf[len - 1] == '\n' ||
                                linebuf[len - 1] == '\r')) {
                linebuf[len - 1] = 0;
                len--;
            }

            includes->push_back(linebuf);
        }
        fclose(fp);
    } else {
        // Scan the source file.
        FILE* fp_src = fopen(src_path.c_str(), "rb");
        if (!fp_src) {
            return Res(ERR_FILE_ERROR, "Couldn't open file for include scanning: " +
                       src_path);
        }

        string src_dir = FilenamePathPart(src_path);
        static const int BUFSIZE = 1000;
        char linebuf[BUFSIZE];
        string header_file;
        string header_path;
        bool is_quoted = false;
        while (fgets(linebuf, BUFSIZE, fp_src)) {
            if (ParseIncludeLine(linebuf, &header_file, &is_quoted)) {
                if (FindHeader(src_dir, t, context, header_file, is_quoted,
                               &header_path)) {
                    includes->push_back(header_path);
                }
            }
        }
        fclose(fp_src);

        // Write the deps file.
        FILE* fp = ostore->Write(deps_file_id);
        if (!fp) {
            context->LogVerbose("Unable to write deps to ostore for file: " +
                                src_path);
        } else {
            fprintf(fp, "# includes %s\n", src_path.c_str());
            for (size_t i = 0; i < includes->size(); i++) {
                const string& header_path = (*includes)[i];
                bool ok =
                    (fwrite(header_path.c_str(), header_path.size(), 1, fp) == 1) &&
                    (fputc('\n', fp) != EOF);
                if (!ok) {
                    fclose(fp);
                    return Res(ERR_FILE_ERROR, "Error writing to deps file for " +
                               src_path);
                }
            }
            fclose(fp);
        }
    }

    return Res(OK);
}