summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Rosdahl <joel@rosdahl.net>2019-08-02 00:04:30 +0200
committerJoel Rosdahl <joel@rosdahl.net>2019-08-14 21:42:33 +0200
commitf5795cdbc0703d80ab21f39c49bb2384ea2429ba (patch)
treec1a18e6743bd8875284cb45b36c2db6399c6371b
parent80ff3c27a787973dc6284b1d6f85a236f573a866 (diff)
downloadccache-f5795cdbc0703d80ab21f39c49bb2384ea2429ba.tar.gz
Run clang-format on all code to follow the new code style
If you end up on this commit when running “git blame ...”, it’s probably a good idea to use “git blame -w ...” to ignore whitespace changes.
-rw-r--r--.editorconfig2
-rw-r--r--src/args.cpp443
-rw-r--r--src/ccache.cpp7203
-rw-r--r--src/ccache.hpp358
-rw-r--r--src/cleanup.cpp385
-rw-r--r--src/common_header.cpp264
-rw-r--r--src/common_header.hpp54
-rw-r--r--src/compopt.cpp317
-rw-r--r--src/compopt.hpp20
-rw-r--r--src/compr_none.cpp60
-rw-r--r--src/compr_zstd.cpp223
-rw-r--r--src/compress.cpp215
-rw-r--r--src/compression.cpp64
-rw-r--r--src/compression.hpp107
-rw-r--r--src/conf.cpp738
-rw-r--r--src/conf.hpp102
-rw-r--r--src/confitems.cpp463
-rw-r--r--src/confitems.hpp65
-rw-r--r--src/counters.cpp56
-rw-r--r--src/counters.hpp15
-rw-r--r--src/decompr_none.cpp58
-rw-r--r--src/decompr_zstd.cpp161
-rw-r--r--src/envtoconfitems.hpp9
-rw-r--r--src/execute.cpp666
-rw-r--r--src/exitfn.cpp84
-rw-r--r--src/hash.cpp192
-rw-r--r--src/hash.hpp37
-rw-r--r--src/hashutil.cpp451
-rw-r--r--src/hashutil.hpp33
-rw-r--r--src/int_bytes_conversion.hpp109
-rw-r--r--src/language.cpp216
-rw-r--r--src/language.hpp10
-rw-r--r--src/lockfile.cpp329
-rw-r--r--src/macroskip.hpp26
-rw-r--r--src/manifest.cpp1298
-rw-r--r--src/manifest.hpp10
-rw-r--r--src/result.cpp1146
-rw-r--r--src/result.hpp14
-rw-r--r--src/stats.cpp1007
-rw-r--r--src/system.hpp24
-rw-r--r--src/unify.cpp369
-rw-r--r--src/unify.hpp2
-rw-r--r--src/util.cpp2506
-rw-r--r--unittest/framework.cpp426
-rw-r--r--unittest/framework.hpp243
-rw-r--r--unittest/main.cpp95
-rw-r--r--unittest/test_args.cpp258
-rw-r--r--unittest/test_argument_processing.cpp731
-rw-r--r--unittest/test_compopt.cpp50
-rw-r--r--unittest/test_compr_none.cpp56
-rw-r--r--unittest/test_compr_zstd.cpp144
-rw-r--r--unittest/test_conf.cpp846
-rw-r--r--unittest/test_counters.cpp36
-rw-r--r--unittest/test_hash.cpp116
-rw-r--r--unittest/test_hashutil.cpp322
-rw-r--r--unittest/test_lockfile.cpp40
-rw-r--r--unittest/test_stats.cpp30
-rw-r--r--unittest/test_util.cpp248
-rw-r--r--unittest/util.cpp27
-rw-r--r--unittest/util.hpp6
60 files changed, 11791 insertions, 11794 deletions
diff --git a/.editorconfig b/.editorconfig
index da20c97f..8f4a31e1 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -6,7 +6,7 @@ insert_final_newline = true
charset = utf-8
[*.{c,cpp,h,hpp}]
-indent_style = tab
+indent_style = space
indent_size = 2
[*.{bash,py}]
diff --git a/src/args.cpp b/src/args.cpp
index 9ff7d5c3..deb4309d 100644
--- a/src/args.cpp
+++ b/src/args.cpp
@@ -19,116 +19,116 @@
#include "ccache.hpp"
-struct args *
-args_init(int init_argc, const char * const*init_args)
+struct args*
+args_init(int init_argc, const char* const* init_args)
{
- struct args *args = (struct args *)x_malloc(sizeof(struct args));
- args->argc = 0;
- args->argv = (char **)x_malloc(sizeof(char *));
- args->argv[0] = NULL;
- for (int i = 0; i < init_argc; i++) {
- args_add(args, init_args[i]);
- }
- return args;
+ struct args* args = (struct args*)x_malloc(sizeof(struct args));
+ args->argc = 0;
+ args->argv = (char**)x_malloc(sizeof(char*));
+ args->argv[0] = NULL;
+ for (int i = 0; i < init_argc; i++) {
+ args_add(args, init_args[i]);
+ }
+ return args;
}
-struct args *
-args_init_from_string(const char *command)
+struct args*
+args_init_from_string(const char* command)
{
- char *p = x_strdup(command);
- char *q = p;
- char *word, *saveptr = NULL;
- struct args *args = args_init(0, NULL);
- while ((word = strtok_r(q, " \t\r\n", &saveptr))) {
- args_add(args, word);
- q = NULL;
- }
-
- free(p);
- return args;
+ char* p = x_strdup(command);
+ char* q = p;
+ char *word, *saveptr = NULL;
+ struct args* args = args_init(0, NULL);
+ while ((word = strtok_r(q, " \t\r\n", &saveptr))) {
+ args_add(args, word);
+ q = NULL;
+ }
+
+ free(p);
+ return args;
}
-struct args *
-args_init_from_gcc_atfile(const char *filename)
+struct args*
+args_init_from_gcc_atfile(const char* filename)
{
- char *argtext;
- if (!(argtext = read_text_file(filename, 0))) {
- return NULL;
- }
-
- struct args *args = args_init(0, NULL);
- char *pos = argtext;
- char* argbuf = static_cast<char*>(x_malloc(strlen(argtext) + 1));
- char *argpos = argbuf;
-
- // Used to track quoting state; if \0, we are not inside quotes. Otherwise
- // stores the quoting character that started it, for matching the end quote.
- char quoting = '\0';
-
- while (1) {
- switch (*pos) {
- case '\\':
- pos++;
- if (*pos == '\0') {
- continue;
- }
- break;
-
- case '\"':
- case '\'':
- if (quoting != '\0') {
- if (quoting == *pos) {
- quoting = '\0';
- pos++;
- continue;
- } else {
- break;
- }
- } else {
- quoting = *pos;
- pos++;
- continue;
- }
-
- case '\n':
- case '\r':
- case '\t':
- case ' ':
- if (quoting) {
- break;
- }
- // Fall through.
-
- case '\0':
- // End of token
- *argpos = '\0';
- if (argbuf[0] != '\0') {
- args_add(args, argbuf);
- }
- argpos = argbuf;
- if (*pos == '\0') {
- goto out;
- } else {
- pos++;
- continue;
- }
- }
-
- *argpos = *pos;
- pos++;
- argpos++;
- }
+ char* argtext;
+ if (!(argtext = read_text_file(filename, 0))) {
+ return NULL;
+ }
+
+ struct args* args = args_init(0, NULL);
+ char* pos = argtext;
+ char* argbuf = static_cast<char*>(x_malloc(strlen(argtext) + 1));
+ char* argpos = argbuf;
+
+ // Used to track quoting state; if \0, we are not inside quotes. Otherwise
+ // stores the quoting character that started it, for matching the end quote.
+ char quoting = '\0';
+
+ while (1) {
+ switch (*pos) {
+ case '\\':
+ pos++;
+ if (*pos == '\0') {
+ continue;
+ }
+ break;
+
+ case '\"':
+ case '\'':
+ if (quoting != '\0') {
+ if (quoting == *pos) {
+ quoting = '\0';
+ pos++;
+ continue;
+ } else {
+ break;
+ }
+ } else {
+ quoting = *pos;
+ pos++;
+ continue;
+ }
+
+ case '\n':
+ case '\r':
+ case '\t':
+ case ' ':
+ if (quoting) {
+ break;
+ }
+ // Fall through.
+
+ case '\0':
+ // End of token
+ *argpos = '\0';
+ if (argbuf[0] != '\0') {
+ args_add(args, argbuf);
+ }
+ argpos = argbuf;
+ if (*pos == '\0') {
+ goto out;
+ } else {
+ pos++;
+ continue;
+ }
+ }
+
+ *argpos = *pos;
+ pos++;
+ argpos++;
+ }
out:
- free(argbuf);
- free(argtext);
- return args;
+ free(argbuf);
+ free(argtext);
+ return args;
}
-struct args *
-args_copy(struct args *args)
+struct args*
+args_copy(struct args* args)
{
- return args_init(args->argc, args->argv);
+ return args_init(args->argc, args->argv);
}
// Insert all arguments in src into dest at position index. If replace is true,
@@ -138,178 +138,175 @@ args_copy(struct args *args)
// src is consumed by this operation and should not be freed or used again by
// the caller.
void
-args_insert(struct args *dest, int index, struct args *src, bool replace)
+args_insert(struct args* dest, int index, struct args* src, bool replace)
{
- // Adjustments made if we are replacing or shifting the element currently at
- // dest->argv[index].
- int offset = replace ? 1 : 0;
-
- if (replace) {
- free(dest->argv[index]);
- }
-
- if (src->argc == 0) {
- if (replace) {
- // Have to shift everything down by 1 since we replaced with an empty
- // list.
- for (int i = index; i < dest->argc; i++) {
- dest->argv[i] = dest->argv[i + 1];
- }
- dest->argc--;
- }
- args_free(src);
- return;
- }
-
- if (src->argc == 1 && replace) {
- // Trivial case; replace with 1 element.
- dest->argv[index] = src->argv[0];
- src->argc = 0;
- args_free(src);
- return;
- }
-
- dest->argv = (char **)x_realloc(
- dest->argv,
- (src->argc + dest->argc + 1 - offset) * sizeof(char *));
-
- // Shift arguments over.
- for (int i = dest->argc; i >= index + offset; i--) {
- dest->argv[i + src->argc - offset] = dest->argv[i];
- }
-
- // Copy the new arguments into place.
- for (int i = 0; i < src->argc; i++) {
- dest->argv[i + index] = src->argv[i];
- }
-
- dest->argc += src->argc - offset;
- src->argc = 0;
- args_free(src);
+ // Adjustments made if we are replacing or shifting the element currently at
+ // dest->argv[index].
+ int offset = replace ? 1 : 0;
+
+ if (replace) {
+ free(dest->argv[index]);
+ }
+
+ if (src->argc == 0) {
+ if (replace) {
+ // Have to shift everything down by 1 since we replaced with an empty
+ // list.
+ for (int i = index; i < dest->argc; i++) {
+ dest->argv[i] = dest->argv[i + 1];
+ }
+ dest->argc--;
+ }
+ args_free(src);
+ return;
+ }
+
+ if (src->argc == 1 && replace) {
+ // Trivial case; replace with 1 element.
+ dest->argv[index] = src->argv[0];
+ src->argc = 0;
+ args_free(src);
+ return;
+ }
+
+ dest->argv = (char**)x_realloc(
+ dest->argv, (src->argc + dest->argc + 1 - offset) * sizeof(char*));
+
+ // Shift arguments over.
+ for (int i = dest->argc; i >= index + offset; i--) {
+ dest->argv[i + src->argc - offset] = dest->argv[i];
+ }
+
+ // Copy the new arguments into place.
+ for (int i = 0; i < src->argc; i++) {
+ dest->argv[i + index] = src->argv[i];
+ }
+
+ dest->argc += src->argc - offset;
+ src->argc = 0;
+ args_free(src);
}
void
-args_free(struct args *args)
+args_free(struct args* args)
{
- if (!args) {
- return;
- }
- for (int i = 0; i < args->argc; ++i) {
- if (args->argv[i]) {
- free(args->argv[i]);
- }
- }
- free(args->argv);
- free(args);
+ if (!args) {
+ return;
+ }
+ for (int i = 0; i < args->argc; ++i) {
+ if (args->argv[i]) {
+ free(args->argv[i]);
+ }
+ }
+ free(args->argv);
+ free(args);
}
void
-args_add(struct args *args, const char *s)
+args_add(struct args* args, const char* s)
{
- args->argv = (char **)x_realloc(args->argv,
- (args->argc + 2) * sizeof(char *));
- args->argv[args->argc] = x_strdup(s);
- args->argc++;
- args->argv[args->argc] = NULL;
+ args->argv = (char**)x_realloc(args->argv, (args->argc + 2) * sizeof(char*));
+ args->argv[args->argc] = x_strdup(s);
+ args->argc++;
+ args->argv[args->argc] = NULL;
}
// Add all arguments in to_append to args.
void
-args_extend(struct args *args, struct args *to_append)
+args_extend(struct args* args, struct args* to_append)
{
- for (int i = 0; i < to_append->argc; i++) {
- args_add(args, to_append->argv[i]);
- }
+ for (int i = 0; i < to_append->argc; i++) {
+ args_add(args, to_append->argv[i]);
+ }
}
// Pop the last element off the args list.
void
-args_pop(struct args *args, int n)
+args_pop(struct args* args, int n)
{
- while (n--) {
- args->argc--;
- free(args->argv[args->argc]);
- args->argv[args->argc] = NULL;
- }
+ while (n--) {
+ args->argc--;
+ free(args->argv[args->argc]);
+ args->argv[args->argc] = NULL;
+ }
}
// Set argument at given index.
void
-args_set(struct args *args, int index, const char *value)
+args_set(struct args* args, int index, const char* value)
{
- assert(index < args->argc);
- free(args->argv[index]);
- args->argv[index] = x_strdup(value);
+ assert(index < args->argc);
+ free(args->argv[index]);
+ args->argv[index] = x_strdup(value);
}
// Remove the first element of the argument list.
void
-args_remove_first(struct args *args)
+args_remove_first(struct args* args)
{
- free(args->argv[0]);
- memmove(&args->argv[0], &args->argv[1], args->argc * sizeof(args->argv[0]));
- args->argc--;
+ free(args->argv[0]);
+ memmove(&args->argv[0], &args->argv[1], args->argc * sizeof(args->argv[0]));
+ args->argc--;
}
// Add an argument into the front of the argument list.
void
-args_add_prefix(struct args *args, const char *s)
+args_add_prefix(struct args* args, const char* s)
{
- args->argv = (char **)x_realloc(args->argv,
- (args->argc + 2) * sizeof(char *));
- memmove(&args->argv[1], &args->argv[0],
- (args->argc+1) * sizeof(args->argv[0]));
- args->argv[0] = x_strdup(s);
- args->argc++;
+ args->argv = (char**)x_realloc(args->argv, (args->argc + 2) * sizeof(char*));
+ memmove(
+ &args->argv[1], &args->argv[0], (args->argc + 1) * sizeof(args->argv[0]));
+ args->argv[0] = x_strdup(s);
+ args->argc++;
}
// Strip any arguments beginning with the specified prefix.
void
-args_strip(struct args *args, const char *prefix)
+args_strip(struct args* args, const char* prefix)
{
- for (int i = 0; i < args->argc;) {
- if (str_startswith(args->argv[i], prefix)) {
- free(args->argv[i]);
- memmove(&args->argv[i],
- &args->argv[i+1],
- (args->argc - i) * sizeof(args->argv[i]));
- args->argc--;
- } else {
- i++;
- }
- }
+ for (int i = 0; i < args->argc;) {
+ if (str_startswith(args->argv[i], prefix)) {
+ free(args->argv[i]);
+ memmove(&args->argv[i],
+ &args->argv[i + 1],
+ (args->argc - i) * sizeof(args->argv[i]));
+ args->argc--;
+ } else {
+ i++;
+ }
+ }
}
// Format args to a space-separated string. Does not quote spaces. Caller
// frees.
-char *
-args_to_string(const struct args *args)
+char*
+args_to_string(const struct args* args)
{
- unsigned size = 0;
- for (char **p = args->argv; *p; p++) {
- size += strlen(*p) + 1;
- }
-
- char* result = static_cast<char*>(x_malloc(size + 1));
- int pos = 0;
- for (char **p = args->argv; *p; p++) {
- pos += sprintf(&result[pos], "%s ", *p);
- }
- result[pos - 1] = '\0';
- return result;
+ unsigned size = 0;
+ for (char** p = args->argv; *p; p++) {
+ size += strlen(*p) + 1;
+ }
+
+ char* result = static_cast<char*>(x_malloc(size + 1));
+ int pos = 0;
+ for (char** p = args->argv; *p; p++) {
+ pos += sprintf(&result[pos], "%s ", *p);
+ }
+ result[pos - 1] = '\0';
+ return result;
}
// Returns true if args1 equals args2, else false.
bool
-args_equal(const struct args *args1, const struct args *args2)
+args_equal(const struct args* args1, const struct args* args2)
{
- if (args1->argc != args2->argc) {
- return false;
- }
- for (int i = 0; i < args1->argc; i++) {
- if (!str_eq(args1->argv[i], args2->argv[i])) {
- return false;
- }
- }
- return true;
+ if (args1->argc != args2->argc) {
+ return false;
+ }
+ for (int i = 0; i < args1->argc; i++) {
+ if (!str_eq(args1->argv[i], args2->argv[i])) {
+ return false;
+ }
+ }
+ return true;
}
diff --git a/src/ccache.cpp b/src/ccache.cpp
index 32e0477c..74207601 100644
--- a/src/ccache.cpp
+++ b/src/ccache.cpp
@@ -18,137 +18,154 @@
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "ccache.hpp"
+
#include "compopt.hpp"
#ifdef HAVE_GETOPT_LONG
-#include <getopt.h>
+# include <getopt.h>
#else
-#include "third_party/getopt_long.h"
+# include "third_party/getopt_long.h"
#endif
#include "hash.hpp"
-#include "third_party/hashtable.h"
-#include "third_party/hashtable_itr.h"
#include "hashutil.hpp"
#include "language.hpp"
#include "manifest.hpp"
#include "result.hpp"
#include "unify.hpp"
+#include "third_party/hashtable.h"
+#include "third_party/hashtable_itr.h"
+
#define STRINGIFY(x) #x
#define TO_STRING(x) STRINGIFY(x)
// Global variables used by other compilation units.
-extern struct conf *conf;
-extern char *primary_config_path;
-extern char *secondary_config_path;
-extern char *current_working_dir;
-extern char *stats_file;
+extern struct conf* conf;
+extern char* primary_config_path;
+extern char* secondary_config_path;
+extern char* current_working_dir;
+extern char* stats_file;
extern unsigned lock_staleness_limit;
-static const char VERSION_TEXT[] =
- MYNAME " version %s\n"
- "\n"
- "Copyright (C) 2002-2007 Andrew Tridgell\n"
- "Copyright (C) 2009-2019 Joel Rosdahl and other contributors\n"
- "\n"
- "See <https://ccache.dev/credits.html> for a complete list of contributors.\n"
- "\n"
- "This program is free software; you can redistribute it and/or modify it under\n"
- "the terms of the GNU General Public License as published by the Free Software\n"
- "Foundation; either version 3 of the License, or (at your option) any later\n"
- "version.\n";
+static const char VERSION_TEXT[] = MYNAME
+ " version %s\n"
+ "\n"
+ "Copyright (C) 2002-2007 Andrew Tridgell\n"
+ "Copyright (C) 2009-2019 Joel Rosdahl and other contributors\n"
+ "\n"
+ "See <https://ccache.dev/credits.html> for a complete list of "
+ "contributors.\n"
+ "\n"
+ "This program is free software; you can redistribute it and/or modify it "
+ "under\n"
+ "the terms of the GNU General Public License as published by the Free "
+ "Software\n"
+ "Foundation; either version 3 of the License, or (at your option) any "
+ "later\n"
+ "version.\n";
static const char USAGE_TEXT[] =
- "Usage:\n"
- " " MYNAME " [options]\n"
- " " MYNAME " compiler [compiler options]\n"
- " compiler [compiler options] (via symbolic link)\n"
- "\n"
- "Common options:\n"
- " -c, --cleanup delete old files and recalculate size counters\n"
- " (normally not needed as this is done\n"
- " automatically)\n"
- " -C, --clear clear the cache completely (except configuration)\n"
- " -F, --max-files=N set maximum number of files in cache to N (use 0\n"
- " for no limit)\n"
- " -M, --max-size=SIZE set maximum size of cache to SIZE (use 0 for no\n"
- " limit); available suffixes: k, M, G, T (decimal)\n"
- " and Ki, Mi, Gi, Ti (binary); default suffix: G\n"
- " -x, --show-compression show compression statistics\n"
- " -p, --show-config show current configuration options in\n"
- " human-readable format\n"
- " -s, --show-stats show summary of configuration and statistics\n"
- " counters in human-readable format\n"
- " -z, --zero-stats zero statistics counters\n"
- "\n"
- " -h, --help print this help text\n"
- " -V, --version print version and copyright information\n"
- "\n"
- "Options for scripting or debugging:\n"
- " --dump-manifest=PATH dump manifest file at PATH in text format\n"
- " -k, --get-config=K print the value of configuration key K\n"
- " --hash-file=PATH print the hash (160 bit BLAKE2b) of the file at\n"
- " PATH\n"
- " --print-stats print statistics counter IDs and corresponding\n"
- " values in machine-parsable format\n"
- " -o, --set-config=K=V set configuration item K to value V\n"
- "\n"
- "See also <https://ccache.dev>.\n";
+ "Usage:\n"
+ " " MYNAME
+ " [options]\n"
+ " " MYNAME
+ " compiler [compiler options]\n"
+ " compiler [compiler options] (via symbolic link)\n"
+ "\n"
+ "Common options:\n"
+ " -c, --cleanup delete old files and recalculate size "
+ "counters\n"
+ " (normally not needed as this is done\n"
+ " automatically)\n"
+ " -C, --clear clear the cache completely (except "
+ "configuration)\n"
+ " -F, --max-files=N set maximum number of files in cache to N "
+ "(use 0\n"
+ " for no limit)\n"
+ " -M, --max-size=SIZE set maximum size of cache to SIZE (use 0 "
+ "for no\n"
+ " limit); available suffixes: k, M, G, T "
+ "(decimal)\n"
+ " and Ki, Mi, Gi, Ti (binary); default "
+ "suffix: G\n"
+ " -x, --show-compression show compression statistics\n"
+ " -p, --show-config show current configuration options in\n"
+ " human-readable format\n"
+ " -s, --show-stats show summary of configuration and "
+ "statistics\n"
+ " counters in human-readable format\n"
+ " -z, --zero-stats zero statistics counters\n"
+ "\n"
+ " -h, --help print this help text\n"
+ " -V, --version print version and copyright information\n"
+ "\n"
+ "Options for scripting or debugging:\n"
+ " --dump-manifest=PATH dump manifest file at PATH in text format\n"
+ " -k, --get-config=K print the value of configuration key K\n"
+ " --hash-file=PATH print the hash (160 bit BLAKE2b) of the "
+ "file at\n"
+ " PATH\n"
+ " --print-stats print statistics counter IDs and "
+ "corresponding\n"
+ " values in machine-parsable format\n"
+ " -o, --set-config=K=V set configuration item K to value V\n"
+ "\n"
+ "See also <https://ccache.dev>.\n";
// Global configuration data.
-struct conf *conf = NULL;
+struct conf* conf = NULL;
// Where to write configuration changes.
-char *primary_config_path = NULL;
+char* primary_config_path = NULL;
// Secondary, read-only configuration file (if any).
-char *secondary_config_path = NULL;
+char* secondary_config_path = NULL;
// Current working directory taken from $PWD, or getcwd() if $PWD is bad.
-char *current_working_dir = NULL;
+char* current_working_dir = NULL;
// The original argument list.
-static struct args *orig_args;
+static struct args* orig_args;
// The source file.
-static char *input_file;
+static char* input_file;
// The output file being compiled to.
-static char *output_obj;
+static char* output_obj;
// The path to the dependency file (implicit or specified with -MF).
-static char *output_dep;
+static char* output_dep;
// The path to the coverage file (implicit when using -ftest-coverage).
-static char *output_cov;
+static char* output_cov;
// The path to the stack usage (implicit when using -fstack-usage).
-static char *output_su;
+static char* output_su;
// Diagnostic generation information (clang). Contains pathname if not NULL.
-static char *output_dia;
+static char* output_dia;
// Split dwarf information (GCC 4.8 and up). Contains pathname if not NULL.
-static char *output_dwo;
+static char* output_dwo;
// Language to use for the compilation target (see language.c).
-static const char *actual_language;
+static const char* actual_language;
// Array for storing -arch options.
#define MAX_ARCH_ARGS 10
static size_t arch_args_size = 0;
-static char *arch_args[MAX_ARCH_ARGS] = {NULL};
+static char* arch_args[MAX_ARCH_ARGS] = {NULL};
// Name (represented as a struct digest) of the file containing the cached
// result.
-static struct digest *cached_result_name;
+static struct digest* cached_result_name;
// Full path to the file containing the result
// (cachedir/a/b/cdef[...]-size.result).
-static char *cached_result_path;
+static char* cached_result_path;
// Full path to the file containing the manifest
// (cachedir/a/b/cdef[...]-size.manifest).
-static char *manifest_path;
+static char* manifest_path;
// Time of compilation. Used to see if include files have changed after
// compilation.
@@ -156,13 +173,13 @@ time_t time_of_compilation;
// Files included by the preprocessor and their hashes. Key: file path. Value:
// struct digest.
-static struct hashtable *included_files = NULL;
+static struct hashtable* included_files = NULL;
// Uses absolute path for some include files.
static bool has_absolute_include_headers = false;
// List of headers to ignore.
-static char **ignore_headers;
+static char** ignore_headers;
// Size of headers to ignore list.
static size_t ignore_headers_len;
@@ -190,7 +207,7 @@ static bool generating_diagnostics;
static bool seen_split_dwarf;
// Relocating debuginfo in the format old=new.
-static char **debug_prefix_maps = NULL;
+static char** debug_prefix_maps = NULL;
// Size of debug_prefix_maps list.
static size_t debug_prefix_maps_len = 0;
@@ -199,23 +216,23 @@ static size_t debug_prefix_maps_len = 0;
static bool profile_arcs;
// Name of the custom profile directory (default: object dirname).
-static char *profile_dir;
+static char* profile_dir;
// The name of the temporary preprocessed file.
-static char *i_tmpfile;
+static char* i_tmpfile;
// Are we compiling a .i or .ii file directly?
static bool direct_i_file;
// The name of the cpp stderr file.
-static char *cpp_stderr;
+static char* cpp_stderr;
// Full path to the statistics file in the subdirectory where the cached result
// belongs (<cache_dir>/<x>/stats).
-char *stats_file = NULL;
+char* stats_file = NULL;
// The stats file to use for the manifest.
-static char *manifest_stats_file;
+static char* manifest_stats_file;
// Whether the output is a precompiled header.
bool output_is_precompiled_header = false;
@@ -229,7 +246,7 @@ static bool profile_use = false;
static bool profile_generate = false;
// Sanitize blacklist
-static char **sanitize_blacklists = NULL;
+static char** sanitize_blacklists = NULL;
// Size of sanitize_blacklists
static size_t sanitize_blacklists_len = 0;
@@ -239,23 +256,21 @@ static size_t sanitize_blacklists_len = 0;
static bool using_precompiled_header = false;
// The .gch/.pch/.pth file used for compilation.
-static char *included_pch_file = NULL;
+static char* included_pch_file = NULL;
// How long (in microseconds) to wait before breaking a stale lock.
unsigned lock_staleness_limit = 2000000;
-enum fromcache_call_mode {
- FROMCACHE_DIRECT_MODE,
- FROMCACHE_CPP_MODE
-};
+enum fromcache_call_mode { FROMCACHE_DIRECT_MODE, FROMCACHE_CPP_MODE };
-struct pending_tmp_file {
- char *path;
- struct pending_tmp_file *next;
+struct pending_tmp_file
+{
+ char* path;
+ struct pending_tmp_file* next;
};
// Temporary files to remove at program exit.
-static struct pending_tmp_file *pending_tmp_files = NULL;
+static struct pending_tmp_file* pending_tmp_files = NULL;
#ifndef _WIN32
static sigset_t fatal_signal_set;
@@ -273,75 +288,73 @@ static pid_t compiler_pid = 0;
static const char HASH_PREFIX[] = "3";
static void
-add_prefix(struct args *args, char *prefix_command)
+add_prefix(struct args* args, char* prefix_command)
{
- if (str_eq(prefix_command, "")) {
- return;
- }
-
- struct args *prefix = args_init(0, NULL);
- char *e = x_strdup(prefix_command);
- char *saveptr = NULL;
- for (char *tok = strtok_r(e, " ", &saveptr);
- tok;
- tok = strtok_r(NULL, " ", &saveptr)) {
- char *p;
-
- p = find_executable(tok, MYNAME);
- if (!p) {
- fatal("%s: %s", tok, strerror(errno));
- }
-
- args_add(prefix, p);
- free(p);
- }
- free(e);
-
- cc_log("Using command-line prefix %s", prefix_command);
- for (int i = prefix->argc; i != 0; i--) {
- args_add_prefix(args, prefix->argv[i-1]);
- }
- args_free(prefix);
+ if (str_eq(prefix_command, "")) {
+ return;
+ }
+
+ struct args* prefix = args_init(0, NULL);
+ char* e = x_strdup(prefix_command);
+ char* saveptr = NULL;
+ for (char* tok = strtok_r(e, " ", &saveptr); tok;
+ tok = strtok_r(NULL, " ", &saveptr)) {
+ char* p;
+
+ p = find_executable(tok, MYNAME);
+ if (!p) {
+ fatal("%s: %s", tok, strerror(errno));
+ }
+
+ args_add(prefix, p);
+ free(p);
+ }
+ free(e);
+
+ cc_log("Using command-line prefix %s", prefix_command);
+ for (int i = prefix->argc; i != 0; i--) {
+ args_add_prefix(args, prefix->argv[i - 1]);
+ }
+ args_free(prefix);
}
-
static void failed(void) ATTR_NORETURN;
// Something went badly wrong - just execute the real compiler.
static void
failed(void)
{
- assert(orig_args);
+ assert(orig_args);
- args_strip(orig_args, "--ccache-");
- add_prefix(orig_args, conf->prefix_command);
+ args_strip(orig_args, "--ccache-");
+ add_prefix(orig_args, conf->prefix_command);
- cc_log("Failed; falling back to running the real compiler");
- cc_log_argv("Executing ", orig_args->argv);
- exitfn_call();
- execv(orig_args->argv[0], orig_args->argv);
- fatal("execv of %s failed: %s", orig_args->argv[0], strerror(errno));
+ cc_log("Failed; falling back to running the real compiler");
+ cc_log_argv("Executing ", orig_args->argv);
+ exitfn_call();
+ execv(orig_args->argv[0], orig_args->argv);
+ fatal("execv of %s failed: %s", orig_args->argv[0], strerror(errno));
}
-static const char *
+static const char*
temp_dir()
{
- static char *path = NULL;
- if (path) {
- return path; // Memoize
- }
- path = conf->temporary_dir;
- if (str_eq(path, "")) {
- path = format("%s/tmp", conf->cache_dir);
- }
- return path;
+ static char* path = NULL;
+ if (path) {
+ return path; // Memoize
+ }
+ path = conf->temporary_dir;
+ if (str_eq(path, "")) {
+ path = format("%s/tmp", conf->cache_dir);
+ }
+ return path;
}
void
block_signals(void)
{
#ifndef _WIN32
- sigprocmask(SIG_BLOCK, &fatal_signal_set, NULL);
+ sigprocmask(SIG_BLOCK, &fatal_signal_set, NULL);
#endif
}
@@ -349,470 +362,474 @@ void
unblock_signals(void)
{
#ifndef _WIN32
- sigset_t empty;
- sigemptyset(&empty);
- sigprocmask(SIG_SETMASK, &empty, NULL);
+ sigset_t empty;
+ sigemptyset(&empty);
+ sigprocmask(SIG_SETMASK, &empty, NULL);
#endif
}
static void
-add_pending_tmp_file(const char *path)
+add_pending_tmp_file(const char* path)
{
- block_signals();
- auto e = static_cast<pending_tmp_file*>(x_malloc(sizeof(pending_tmp_file)));
- e->path = x_strdup(path);
- e->next = pending_tmp_files;
- pending_tmp_files = e;
- unblock_signals();
+ block_signals();
+ auto e = static_cast<pending_tmp_file*>(x_malloc(sizeof(pending_tmp_file)));
+ e->path = x_strdup(path);
+ e->next = pending_tmp_files;
+ pending_tmp_files = e;
+ unblock_signals();
}
static void
do_clean_up_pending_tmp_files(void)
{
- struct pending_tmp_file *p = pending_tmp_files;
- while (p) {
- // Can't call tmp_unlink here since its cc_log calls aren't signal safe.
- unlink(p->path);
- p = p->next;
- // Leak p->path and p here because clean_up_pending_tmp_files needs to be
- // signal safe.
- }
+ struct pending_tmp_file* p = pending_tmp_files;
+ while (p) {
+ // Can't call tmp_unlink here since its cc_log calls aren't signal safe.
+ unlink(p->path);
+ p = p->next;
+ // Leak p->path and p here because clean_up_pending_tmp_files needs to be
+ // signal safe.
+ }
}
static void
clean_up_pending_tmp_files(void)
{
- block_signals();
- do_clean_up_pending_tmp_files();
- unblock_signals();
+ block_signals();
+ do_clean_up_pending_tmp_files();
+ unblock_signals();
}
#ifndef _WIN32
static void
signal_handler(int signum)
{
- // Unregister handler for this signal so that we can send the signal to
- // ourselves at the end of the handler.
- signal(signum, SIG_DFL);
-
- // If ccache was killed explicitly, then bring the compiler subprocess (if
- // any) with us as well.
- if (signum == SIGTERM
- && compiler_pid != 0
- && waitpid(compiler_pid, NULL, WNOHANG) == 0) {
- kill(compiler_pid, signum);
- }
-
- do_clean_up_pending_tmp_files();
-
- if (compiler_pid != 0) {
- // Wait for compiler subprocess to exit before we snuff it.
- waitpid(compiler_pid, NULL, 0);
- }
-
- // Resend signal to ourselves to exit properly after returning from the
- // handler.
- kill(getpid(), signum);
+ // Unregister handler for this signal so that we can send the signal to
+ // ourselves at the end of the handler.
+ signal(signum, SIG_DFL);
+
+ // If ccache was killed explicitly, then bring the compiler subprocess (if
+ // any) with us as well.
+ if (signum == SIGTERM && compiler_pid != 0
+ && waitpid(compiler_pid, NULL, WNOHANG) == 0) {
+ kill(compiler_pid, signum);
+ }
+
+ do_clean_up_pending_tmp_files();
+
+ if (compiler_pid != 0) {
+ // Wait for compiler subprocess to exit before we snuff it.
+ waitpid(compiler_pid, NULL, 0);
+ }
+
+ // Resend signal to ourselves to exit properly after returning from the
+ // handler.
+ kill(getpid(), signum);
}
static void
register_signal_handler(int signum)
{
- struct sigaction act;
- memset(&act, 0, sizeof(act));
- act.sa_handler = signal_handler;
- act.sa_mask = fatal_signal_set;
-#ifdef SA_RESTART
- act.sa_flags = SA_RESTART;
-#endif
- sigaction(signum, &act, NULL);
+ struct sigaction act;
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = signal_handler;
+ act.sa_mask = fatal_signal_set;
+# ifdef SA_RESTART
+ act.sa_flags = SA_RESTART;
+# endif
+ sigaction(signum, &act, NULL);
}
static void
set_up_signal_handlers(void)
{
- sigemptyset(&fatal_signal_set);
- sigaddset(&fatal_signal_set, SIGINT);
- sigaddset(&fatal_signal_set, SIGTERM);
-#ifdef SIGHUP
- sigaddset(&fatal_signal_set, SIGHUP);
-#endif
-#ifdef SIGQUIT
- sigaddset(&fatal_signal_set, SIGQUIT);
-#endif
-
- register_signal_handler(SIGINT);
- register_signal_handler(SIGTERM);
-#ifdef SIGHUP
- register_signal_handler(SIGHUP);
-#endif
-#ifdef SIGQUIT
- register_signal_handler(SIGQUIT);
-#endif
+ sigemptyset(&fatal_signal_set);
+ sigaddset(&fatal_signal_set, SIGINT);
+ sigaddset(&fatal_signal_set, SIGTERM);
+# ifdef SIGHUP
+ sigaddset(&fatal_signal_set, SIGHUP);
+# endif
+# ifdef SIGQUIT
+ sigaddset(&fatal_signal_set, SIGQUIT);
+# endif
+
+ register_signal_handler(SIGINT);
+ register_signal_handler(SIGTERM);
+# ifdef SIGHUP
+ register_signal_handler(SIGHUP);
+# endif
+# ifdef SIGQUIT
+ register_signal_handler(SIGQUIT);
+# endif
}
#endif // _WIN32
static void
clean_up_internal_tempdir(void)
{
- time_t now = time(NULL);
- struct stat st;
- if (x_stat(conf->cache_dir, &st) != 0 || st.st_mtime + 3600 >= now) {
- // No cleanup needed.
- return;
- }
-
- update_mtime(conf->cache_dir);
-
- DIR *dir = opendir(temp_dir());
- if (!dir) {
- return;
- }
-
- struct dirent *entry;
- while ((entry = readdir(dir))) {
- if (str_eq(entry->d_name, ".") || str_eq(entry->d_name, "..")) {
- continue;
- }
-
- char *path = format("%s/%s", temp_dir(), entry->d_name);
- if (x_lstat(path, &st) == 0 && st.st_mtime + 3600 < now) {
- tmp_unlink(path);
- }
- free(path);
- }
-
- closedir(dir);
+ time_t now = time(NULL);
+ struct stat st;
+ if (x_stat(conf->cache_dir, &st) != 0 || st.st_mtime + 3600 >= now) {
+ // No cleanup needed.
+ return;
+ }
+
+ update_mtime(conf->cache_dir);
+
+ DIR* dir = opendir(temp_dir());
+ if (!dir) {
+ return;
+ }
+
+ struct dirent* entry;
+ while ((entry = readdir(dir))) {
+ if (str_eq(entry->d_name, ".") || str_eq(entry->d_name, "..")) {
+ continue;
+ }
+
+ char* path = format("%s/%s", temp_dir(), entry->d_name);
+ if (x_lstat(path, &st) == 0 && st.st_mtime + 3600 < now) {
+ tmp_unlink(path);
+ }
+ free(path);
+ }
+
+ closedir(dir);
}
static void
-fclose_exitfn(void *context)
+fclose_exitfn(void* context)
{
- fclose((FILE *)context);
+ fclose((FILE*)context);
}
static void
-dump_debug_log_buffer_exitfn(void *context)
+dump_debug_log_buffer_exitfn(void* context)
{
- if (!conf->debug) {
- return;
- }
+ if (!conf->debug) {
+ return;
+ }
- char *path = format("%s.ccache-log", (const char *)context);
- cc_dump_debug_log_buffer(path);
- free(path);
+ char* path = format("%s.ccache-log", (const char*)context);
+ cc_dump_debug_log_buffer(path);
+ free(path);
}
static void
-init_hash_debug(struct hash *hash, const char *obj_path, char type,
- const char *section_name, FILE *debug_text_file)
+init_hash_debug(struct hash* hash,
+ const char* obj_path,
+ char type,
+ const char* section_name,
+ FILE* debug_text_file)
{
- if (!conf->debug) {
- return;
- }
-
- char *path = format("%s.ccache-input-%c", obj_path, type);
- FILE *debug_binary_file = fopen(path, "wb");
- if (debug_binary_file) {
- hash_enable_debug(hash, section_name, debug_binary_file, debug_text_file);
- exitfn_add(fclose_exitfn, debug_binary_file);
- } else {
- cc_log("Failed to open %s: %s", path, strerror(errno));
- }
- free(path);
+ if (!conf->debug) {
+ return;
+ }
+
+ char* path = format("%s.ccache-input-%c", obj_path, type);
+ FILE* debug_binary_file = fopen(path, "wb");
+ if (debug_binary_file) {
+ hash_enable_debug(hash, section_name, debug_binary_file, debug_text_file);
+ exitfn_add(fclose_exitfn, debug_binary_file);
+ } else {
+ cc_log("Failed to open %s: %s", path, strerror(errno));
+ }
+ free(path);
}
static enum guessed_compiler
-guess_compiler(const char *path)
+guess_compiler(const char* path)
{
- char *name = x_basename(path);
- enum guessed_compiler result = GUESSED_UNKNOWN;
- if (strstr(name, "clang")) {
- result = GUESSED_CLANG;
- } else if (strstr(name, "gcc") || strstr(name, "g++")) {
- result = GUESSED_GCC;
- } else if (strstr(name, "nvcc")) {
- result = GUESSED_NVCC;
- } else if (str_eq(name, "pump") || str_eq(name, "distcc-pump")) {
- result = GUESSED_PUMP;
- }
- free(name);
- return result;
+ char* name = x_basename(path);
+ enum guessed_compiler result = GUESSED_UNKNOWN;
+ if (strstr(name, "clang")) {
+ result = GUESSED_CLANG;
+ } else if (strstr(name, "gcc") || strstr(name, "g++")) {
+ result = GUESSED_GCC;
+ } else if (strstr(name, "nvcc")) {
+ result = GUESSED_NVCC;
+ } else if (str_eq(name, "pump") || str_eq(name, "distcc-pump")) {
+ result = GUESSED_PUMP;
+ }
+ free(name);
+ return result;
}
-static char *
+static char*
get_current_working_dir(void)
{
- if (!current_working_dir) {
- char *cwd = get_cwd();
- if (cwd) {
- current_working_dir = x_realpath(cwd);
- free(cwd);
- }
- if (!current_working_dir) {
- cc_log("Unable to determine current working directory: %s",
- strerror(errno));
- failed();
- }
- }
- return current_working_dir;
+ if (!current_working_dir) {
+ char* cwd = get_cwd();
+ if (cwd) {
+ current_working_dir = x_realpath(cwd);
+ free(cwd);
+ }
+ if (!current_working_dir) {
+ cc_log("Unable to determine current working directory: %s",
+ strerror(errno));
+ failed();
+ }
+ }
+ return current_working_dir;
}
// This function hashes an include file and stores the path and hash in the
// global included_files variable. If the include file is a PCH, cpp_hash is
// also updated. Takes over ownership of path.
static void
-remember_include_file(char *path, struct hash *cpp_hash, bool system,
- struct hash *depend_mode_hash)
+remember_include_file(char* path,
+ struct hash* cpp_hash,
+ bool system,
+ struct hash* depend_mode_hash)
{
- struct hash *fhash = NULL;
- bool is_pch = false;
-
- size_t path_len = strlen(path);
- if (path_len >= 2 && (path[0] == '<' && path[path_len - 1] == '>')) {
- // Typically <built-in> or <command-line>.
- goto out;
- }
-
- if (str_eq(path, input_file)) {
- // Don't remember the input file.
- goto out;
- }
-
- if (system && (conf->sloppiness & SLOPPY_SYSTEM_HEADERS)) {
- // Don't remember this system header.
- goto out;
- }
-
- if (hashtable_search(included_files, path)) {
- // Already known include file.
- goto out;
- }
+ struct hash* fhash = NULL;
+ bool is_pch = false;
+
+ size_t path_len = strlen(path);
+ if (path_len >= 2 && (path[0] == '<' && path[path_len - 1] == '>')) {
+ // Typically <built-in> or <command-line>.
+ goto out;
+ }
+
+ if (str_eq(path, input_file)) {
+ // Don't remember the input file.
+ goto out;
+ }
+
+ if (system && (conf->sloppiness & SLOPPY_SYSTEM_HEADERS)) {
+ // Don't remember this system header.
+ goto out;
+ }
+
+ if (hashtable_search(included_files, path)) {
+ // Already known include file.
+ goto out;
+ }
#ifdef _WIN32
- {
- // stat fails on directories on win32.
- DWORD attributes = GetFileAttributes(path);
- if (attributes != INVALID_FILE_ATTRIBUTES &&
- attributes & FILE_ATTRIBUTE_DIRECTORY) {
- goto out;
- }
- }
+ {
+ // stat fails on directories on win32.
+ DWORD attributes = GetFileAttributes(path);
+ if (attributes != INVALID_FILE_ATTRIBUTES
+ && attributes & FILE_ATTRIBUTE_DIRECTORY) {
+ goto out;
+ }
+ }
#endif
- struct stat st;
- if (x_stat(path, &st) != 0) {
- goto failure;
- }
- if (S_ISDIR(st.st_mode)) {
- // Ignore directory, typically $PWD.
- goto out;
- }
- if (!S_ISREG(st.st_mode)) {
- // Device, pipe, socket or other strange creature.
- cc_log("Non-regular include file %s", path);
- goto failure;
- }
-
- // Canonicalize path for comparison; clang uses ./header.h.
- {
- char *canonical = path;
- size_t canonical_len = path_len;
- if (canonical[0] == '.' && canonical[1] == '/') {
- canonical += 2;
- canonical_len -= 2;
- }
-
- for (size_t i = 0; i < ignore_headers_len; i++) {
- char *ignore = ignore_headers[i];
- size_t ignore_len = strlen(ignore);
- if (ignore_len > canonical_len) {
- continue;
- }
- if (strncmp(canonical, ignore, ignore_len) == 0
- && (ignore[ignore_len-1] == DIR_DELIM_CH
- || canonical[ignore_len] == DIR_DELIM_CH
- || canonical[ignore_len] == '\0')) {
- goto out;
- }
- }
- }
-
- // The comparison using >= is intentional, due to a possible race between
- // starting compilation and writing the include file. See also the notes
- // under "Performance" in doc/MANUAL.adoc.
- if (!(conf->sloppiness & SLOPPY_INCLUDE_FILE_MTIME)
- && st.st_mtime >= time_of_compilation) {
- cc_log("Include file %s too new", path);
- goto failure;
- }
-
- // The same >= logic as above applies to the change time of the file.
- if (!(conf->sloppiness & SLOPPY_INCLUDE_FILE_CTIME)
- && st.st_ctime >= time_of_compilation) {
- cc_log("Include file %s ctime too new", path);
- goto failure;
- }
-
- // Let's hash the include file content.
- fhash = hash_init();
-
- is_pch = is_precompiled_header(path);
- if (is_pch) {
- if (!included_pch_file) {
- cc_log("Detected use of precompiled header: %s", path);
- }
- bool using_pch_sum = false;
- if (conf->pch_external_checksum) {
- // hash pch.sum instead of pch when it exists
- // to prevent hashing a very large .pch file every time
- char *pch_sum_path = format("%s.sum", path);
- if (x_stat(pch_sum_path, &st) == 0) {
- char *old_path = path;
- path = pch_sum_path;
- pch_sum_path = old_path;
- using_pch_sum = true;
- cc_log("Using pch.sum file %s", path);
- }
- free(pch_sum_path);
- }
-
- if (!hash_file(fhash, path)) {
- goto failure;
- }
- hash_delimiter(cpp_hash, using_pch_sum ? "pch_sum_hash" : "pch_hash");
- char pch_digest[DIGEST_STRING_BUFFER_SIZE];
- hash_result_as_string(fhash, pch_digest);
- hash_string(cpp_hash, pch_digest);
- }
-
- if (conf->direct_mode) {
- if (!is_pch) { // else: the file has already been hashed.
- char *source = NULL;
- size_t size;
- if (st.st_size > 0) {
- if (!read_file(path, st.st_size, &source, &size)) {
- goto failure;
- }
- } else {
- source = x_strdup("");
- size = 0;
- }
-
- int result = hash_source_code_string(conf, fhash, source, size, path);
- free(source);
- if (result & HASH_SOURCE_CODE_ERROR
- || result & HASH_SOURCE_CODE_FOUND_TIME) {
- goto failure;
- }
- }
-
- auto d = static_cast<digest*>(x_malloc(sizeof(digest)));
- hash_result_as_bytes(fhash, d);
- hashtable_insert(included_files, path, d);
- path = NULL; // Ownership transferred to included_files.
-
- if (depend_mode_hash) {
- hash_delimiter(depend_mode_hash, "include");
- char digest[DIGEST_STRING_BUFFER_SIZE];
- digest_as_string(d, digest);
- hash_string(depend_mode_hash, digest);
- }
- }
-
- goto out;
+ struct stat st;
+ if (x_stat(path, &st) != 0) {
+ goto failure;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ // Ignore directory, typically $PWD.
+ goto out;
+ }
+ if (!S_ISREG(st.st_mode)) {
+ // Device, pipe, socket or other strange creature.
+ cc_log("Non-regular include file %s", path);
+ goto failure;
+ }
+
+ // Canonicalize path for comparison; clang uses ./header.h.
+ {
+ char* canonical = path;
+ size_t canonical_len = path_len;
+ if (canonical[0] == '.' && canonical[1] == '/') {
+ canonical += 2;
+ canonical_len -= 2;
+ }
+
+ for (size_t i = 0; i < ignore_headers_len; i++) {
+ char* ignore = ignore_headers[i];
+ size_t ignore_len = strlen(ignore);
+ if (ignore_len > canonical_len) {
+ continue;
+ }
+ if (strncmp(canonical, ignore, ignore_len) == 0
+ && (ignore[ignore_len - 1] == DIR_DELIM_CH
+ || canonical[ignore_len] == DIR_DELIM_CH
+ || canonical[ignore_len] == '\0')) {
+ goto out;
+ }
+ }
+ }
+
+ // The comparison using >= is intentional, due to a possible race between
+ // starting compilation and writing the include file. See also the notes
+ // under "Performance" in doc/MANUAL.adoc.
+ if (!(conf->sloppiness & SLOPPY_INCLUDE_FILE_MTIME)
+ && st.st_mtime >= time_of_compilation) {
+ cc_log("Include file %s too new", path);
+ goto failure;
+ }
+
+ // The same >= logic as above applies to the change time of the file.
+ if (!(conf->sloppiness & SLOPPY_INCLUDE_FILE_CTIME)
+ && st.st_ctime >= time_of_compilation) {
+ cc_log("Include file %s ctime too new", path);
+ goto failure;
+ }
+
+ // Let's hash the include file content.
+ fhash = hash_init();
+
+ is_pch = is_precompiled_header(path);
+ if (is_pch) {
+ if (!included_pch_file) {
+ cc_log("Detected use of precompiled header: %s", path);
+ }
+ bool using_pch_sum = false;
+ if (conf->pch_external_checksum) {
+ // hash pch.sum instead of pch when it exists
+ // to prevent hashing a very large .pch file every time
+ char* pch_sum_path = format("%s.sum", path);
+ if (x_stat(pch_sum_path, &st) == 0) {
+ char* old_path = path;
+ path = pch_sum_path;
+ pch_sum_path = old_path;
+ using_pch_sum = true;
+ cc_log("Using pch.sum file %s", path);
+ }
+ free(pch_sum_path);
+ }
+
+ if (!hash_file(fhash, path)) {
+ goto failure;
+ }
+ hash_delimiter(cpp_hash, using_pch_sum ? "pch_sum_hash" : "pch_hash");
+ char pch_digest[DIGEST_STRING_BUFFER_SIZE];
+ hash_result_as_string(fhash, pch_digest);
+ hash_string(cpp_hash, pch_digest);
+ }
+
+ if (conf->direct_mode) {
+ if (!is_pch) { // else: the file has already been hashed.
+ char* source = NULL;
+ size_t size;
+ if (st.st_size > 0) {
+ if (!read_file(path, st.st_size, &source, &size)) {
+ goto failure;
+ }
+ } else {
+ source = x_strdup("");
+ size = 0;
+ }
+
+ int result = hash_source_code_string(conf, fhash, source, size, path);
+ free(source);
+ if (result & HASH_SOURCE_CODE_ERROR
+ || result & HASH_SOURCE_CODE_FOUND_TIME) {
+ goto failure;
+ }
+ }
+
+ auto d = static_cast<digest*>(x_malloc(sizeof(digest)));
+ hash_result_as_bytes(fhash, d);
+ hashtable_insert(included_files, path, d);
+ path = NULL; // Ownership transferred to included_files.
+
+ if (depend_mode_hash) {
+ hash_delimiter(depend_mode_hash, "include");
+ char digest[DIGEST_STRING_BUFFER_SIZE];
+ digest_as_string(d, digest);
+ hash_string(depend_mode_hash, digest);
+ }
+ }
+
+ goto out;
failure:
- if (conf->direct_mode) {
- cc_log("Disabling direct mode");
- conf->direct_mode = false;
- }
- // Fall through.
+ if (conf->direct_mode) {
+ cc_log("Disabling direct mode");
+ conf->direct_mode = false;
+ }
+ // Fall through.
out:
- hash_free(fhash);
- free(path);
+ hash_free(fhash);
+ free(path);
}
static void
-print_included_files(FILE *fp)
+print_included_files(FILE* fp)
{
- struct hashtable_itr *iter = hashtable_iterator(included_files);
- do {
- char* path = static_cast<char*>(hashtable_iterator_key(iter));
- fprintf(fp, "%s\n", path);
- } while (hashtable_iterator_advance(iter));
+ struct hashtable_itr* iter = hashtable_iterator(included_files);
+ do {
+ char* path = static_cast<char*>(hashtable_iterator_key(iter));
+ fprintf(fp, "%s\n", path);
+ } while (hashtable_iterator_advance(iter));
}
// Make a relative path from current working directory to path if path is under
// the base directory. Takes over ownership of path. Caller frees.
-static char *
-make_relative_path(char *path)
+static char*
+make_relative_path(char* path)
{
- if (str_eq(conf->base_dir, "") || !str_startswith(path, conf->base_dir)) {
- return path;
- }
+ if (str_eq(conf->base_dir, "") || !str_startswith(path, conf->base_dir)) {
+ return path;
+ }
#ifdef _WIN32
- if (path[0] == '/') {
- path++; // Skip leading slash.
- }
+ if (path[0] == '/') {
+ path++; // Skip leading slash.
+ }
#endif
- // x_realpath only works for existing paths, so if path doesn't exist, try
- // x_dirname(path) and assemble the path afterwards. We only bother to try
- // canonicalizing one of these two paths since a compiler path argument
- // typically only makes sense if path or x_dirname(path) exists.
- char *path_suffix = NULL;
- struct stat st;
- if (stat(path, &st) != 0) {
- // path doesn't exist.
- char *dir = x_dirname(path);
- // find the nearest existing directory in path
- while (stat(dir, &st) != 0) {
- char *parent_dir = x_dirname(dir);
- free(dir);
- dir = parent_dir;
- }
-
- // suffix is the remaining of the path, skip the first delimiter
- size_t dir_len = strlen(dir);
- if (path[dir_len] == '/' || path[dir_len] == '\\') {
- dir_len++;
- }
- path_suffix = x_strdup(&path[dir_len]);
- char *p = path;
- path = dir;
- free(p);
- }
-
- char *canon_path = x_realpath(path);
- if (canon_path) {
- free(path);
- char *relpath = get_relative_path(get_current_working_dir(), canon_path);
- free(canon_path);
- if (path_suffix) {
- path = format("%s/%s", relpath, path_suffix);
- free(relpath);
- free(path_suffix);
- return path;
- } else {
- return relpath;
- }
- } else {
- // path doesn't exist, so leave it as it is.
- free(path_suffix);
- return path;
- }
+ // x_realpath only works for existing paths, so if path doesn't exist, try
+ // x_dirname(path) and assemble the path afterwards. We only bother to try
+ // canonicalizing one of these two paths since a compiler path argument
+ // typically only makes sense if path or x_dirname(path) exists.
+ char* path_suffix = NULL;
+ struct stat st;
+ if (stat(path, &st) != 0) {
+ // path doesn't exist.
+ char* dir = x_dirname(path);
+ // find the nearest existing directory in path
+ while (stat(dir, &st) != 0) {
+ char* parent_dir = x_dirname(dir);
+ free(dir);
+ dir = parent_dir;
+ }
+
+ // suffix is the remaining of the path, skip the first delimiter
+ size_t dir_len = strlen(dir);
+ if (path[dir_len] == '/' || path[dir_len] == '\\') {
+ dir_len++;
+ }
+ path_suffix = x_strdup(&path[dir_len]);
+ char* p = path;
+ path = dir;
+ free(p);
+ }
+
+ char* canon_path = x_realpath(path);
+ if (canon_path) {
+ free(path);
+ char* relpath = get_relative_path(get_current_working_dir(), canon_path);
+ free(canon_path);
+ if (path_suffix) {
+ path = format("%s/%s", relpath, path_suffix);
+ free(relpath);
+ free(path_suffix);
+ return path;
+ } else {
+ return relpath;
+ }
+ } else {
+ // path doesn't exist, so leave it as it is.
+ free(path_suffix);
+ return path;
+ }
}
static void
init_included_files_table(void)
{
- // (This function may be called multiple times if several -arch options are
- // used.)
- if (!included_files) {
- included_files = create_hashtable(1000, hash_from_string, strings_equal);
- }
+ // (This function may be called multiple times if several -arch options are
+ // used.)
+ if (!included_files) {
+ included_files = create_hashtable(1000, hash_from_string, strings_equal);
+ }
}
// This function reads and hashes a file. While doing this, it also does these
@@ -823,779 +840,788 @@ init_included_files_table(void)
// - Stores the paths and hashes of included files in the global variable
// included_files.
static bool
-process_preprocessed_file(struct hash *hash, const char *path, bool pump)
+process_preprocessed_file(struct hash* hash, const char* path, bool pump)
{
- char *data;
- size_t size;
- if (!read_file(path, 0, &data, &size)) {
- return false;
- }
-
- ignore_headers = NULL;
- ignore_headers_len = 0;
- if (!str_eq(conf->ignore_headers_in_manifest, "")) {
- char *header, *p, *q, *saveptr = NULL;
- p = x_strdup(conf->ignore_headers_in_manifest);
- q = p;
- while ((header = strtok_r(q, PATH_DELIM, &saveptr))) {
- ignore_headers = static_cast<char**>(
- x_realloc(ignore_headers, (ignore_headers_len+1) * sizeof(char *)));
- ignore_headers[ignore_headers_len++] = x_strdup(header);
- q = NULL;
- }
- free(p);
- }
-
- init_included_files_table();
-
- char *cwd = gnu_getcwd();
-
- // Bytes between p and q are pending to be hashed.
- char *p = data;
- char *q = data;
- char *end = data + size;
-
- // There must be at least 7 characters (# 1 "x") left to potentially find an
- // include file path.
- while (q < end - 7) {
- // Check if we look at a line containing the file name of an included file.
- // At least the following formats exist (where N is a positive integer):
- //
- // GCC:
- //
- // # N "file"
- // # N "file" N
- // #pragma GCC pch_preprocess "file"
- //
- // HP's compiler:
- //
- // #line N "file"
- //
- // AIX's compiler:
- //
- // #line N "file"
- // #line N
- //
- // Note that there may be other lines starting with '#' left after
- // preprocessing as well, for instance "# pragma".
- if (q[0] == '#'
- // GCC:
- && ((q[1] == ' ' && q[2] >= '0' && q[2] <= '9')
- // GCC precompiled header:
- || (q[1] == 'p'
- && str_startswith(&q[2], "ragma GCC pch_preprocess "))
- // HP/AIX:
- || (q[1] == 'l' && q[2] == 'i' && q[3] == 'n' && q[4] == 'e'
- && q[5] == ' '))
- && (q == data || q[-1] == '\n')) {
- // Workarounds for preprocessor linemarker bugs in GCC version 6.
- if (q[2] == '3') {
- if (str_startswith(q, "# 31 \"<command-line>\"\n")) {
- // Bogus extra line with #31, after the regular #1: Ignore the whole
- // line, and continue parsing.
- hash_string_buffer(hash, p, q - p);
- while (q < end && *q != '\n') {
- q++;
- }
- q++;
- p = q;
- continue;
- } else if (str_startswith(q, "# 32 \"<command-line>\" 2\n")) {
- // Bogus wrong line with #32, instead of regular #1: Replace the line
- // number with the usual one.
- hash_string_buffer(hash, p, q - p);
- q += 1;
- q[0] = '#';
- q[1] = ' ';
- q[2] = '1';
- p = q;
- }
- }
-
- while (q < end && *q != '"' && *q != '\n') {
- q++;
- }
- if (q < end && *q == '\n') {
- // A newline before the quotation mark -> no match.
- continue;
- }
- q++;
- if (q >= end) {
- cc_log("Failed to parse included file path");
- free(data);
- free(cwd);
- return false;
- }
- // q points to the beginning of an include file path
- hash_string_buffer(hash, p, q - p);
- p = q;
- while (q < end && *q != '"') {
- q++;
- }
- // Look for preprocessor flags, after the "filename".
- bool system = false;
- char *r = q + 1;
- while (r < end && *r != '\n') {
- if (*r == '3') { // System header.
- system = true;
- }
- r++;
- }
- // p and q span the include file path.
- char *inc_path = x_strndup(p, q - p);
- if (!has_absolute_include_headers) {
- has_absolute_include_headers = is_absolute_path(inc_path);
- }
- inc_path = make_relative_path(inc_path);
-
- bool should_hash_inc_path = true;
- if (!conf->hash_dir) {
- if (str_startswith(inc_path, cwd) && str_endswith(inc_path, "//")) {
- // When compiling with -g or similar, GCC adds the absolute path to
- // CWD like this:
- //
- // # 1 "CWD//"
- //
- // If the user has opted out of including the CWD in the hash, don't
- // hash it. See also how debug_prefix_map is handled.
- should_hash_inc_path = false;
- }
- }
- if (should_hash_inc_path) {
- hash_string_buffer(hash, inc_path, strlen(inc_path));
- }
-
- remember_include_file(inc_path, hash, system, NULL);
- p = q; // Everything of interest between p and q has been hashed now.
- } else if (q[0] == '.' && q[1] == 'i' && q[2] == 'n' && q[3] == 'c'
- && q[4] == 'b' && q[5] == 'i' && q[6] == 'n') {
- // An assembler .inc bin (without the space) statement, which could be
- // part of inline assembly, refers to an external file. If the file
- // changes, the hash should change as well, but finding out what file to
- // hash is too hard for ccache, so just bail out.
- cc_log("Found unsupported .inc" "bin directive in source code");
- stats_update(STATS_UNSUPPORTED_DIRECTIVE);
- failed();
- } else if (pump && strncmp(q, "_________", 9) == 0) {
- // Unfortunately the distcc-pump wrapper outputs standard output lines:
- // __________Using distcc-pump from /usr/bin
- // __________Using # distcc servers in pump mode
- // __________Shutting down distcc-pump include server
- while (q < end && *q != '\n') {
- q++;
- }
- if (*q == '\n') {
- q++;
- }
- p = q;
- continue;
- } else {
- q++;
- }
- }
-
- hash_string_buffer(hash, p, (end - p));
- free(data);
- free(cwd);
-
- // Explicitly check the .gch/.pch/.pth file as Clang does not include any
- // mention of it in the preprocessed output.
- if (included_pch_file) {
- char *pch_path = x_strdup(included_pch_file);
- pch_path = make_relative_path(pch_path);
- hash_string(hash, pch_path);
- remember_include_file(pch_path, hash, false, NULL);
- }
-
- bool debug_included = getenv("CCACHE_DEBUG_INCLUDED");
- if (debug_included) {
- print_included_files(stdout);
- }
-
- return true;
+ char* data;
+ size_t size;
+ if (!read_file(path, 0, &data, &size)) {
+ return false;
+ }
+
+ ignore_headers = NULL;
+ ignore_headers_len = 0;
+ if (!str_eq(conf->ignore_headers_in_manifest, "")) {
+ char *header, *p, *q, *saveptr = NULL;
+ p = x_strdup(conf->ignore_headers_in_manifest);
+ q = p;
+ while ((header = strtok_r(q, PATH_DELIM, &saveptr))) {
+ ignore_headers = static_cast<char**>(
+ x_realloc(ignore_headers, (ignore_headers_len + 1) * sizeof(char*)));
+ ignore_headers[ignore_headers_len++] = x_strdup(header);
+ q = NULL;
+ }
+ free(p);
+ }
+
+ init_included_files_table();
+
+ char* cwd = gnu_getcwd();
+
+ // Bytes between p and q are pending to be hashed.
+ char* p = data;
+ char* q = data;
+ char* end = data + size;
+
+ // There must be at least 7 characters (# 1 "x") left to potentially find an
+ // include file path.
+ while (q < end - 7) {
+ // Check if we look at a line containing the file name of an included file.
+ // At least the following formats exist (where N is a positive integer):
+ //
+ // GCC:
+ //
+ // # N "file"
+ // # N "file" N
+ // #pragma GCC pch_preprocess "file"
+ //
+ // HP's compiler:
+ //
+ // #line N "file"
+ //
+ // AIX's compiler:
+ //
+ // #line N "file"
+ // #line N
+ //
+ // Note that there may be other lines starting with '#' left after
+ // preprocessing as well, for instance "# pragma".
+ if (q[0] == '#'
+ // GCC:
+ && ((q[1] == ' ' && q[2] >= '0' && q[2] <= '9')
+ // GCC precompiled header:
+ || (q[1] == 'p'
+ && str_startswith(&q[2], "ragma GCC pch_preprocess "))
+ // HP/AIX:
+ || (q[1] == 'l' && q[2] == 'i' && q[3] == 'n' && q[4] == 'e'
+ && q[5] == ' '))
+ && (q == data || q[-1] == '\n')) {
+ // Workarounds for preprocessor linemarker bugs in GCC version 6.
+ if (q[2] == '3') {
+ if (str_startswith(q, "# 31 \"<command-line>\"\n")) {
+ // Bogus extra line with #31, after the regular #1: Ignore the whole
+ // line, and continue parsing.
+ hash_string_buffer(hash, p, q - p);
+ while (q < end && *q != '\n') {
+ q++;
+ }
+ q++;
+ p = q;
+ continue;
+ } else if (str_startswith(q, "# 32 \"<command-line>\" 2\n")) {
+ // Bogus wrong line with #32, instead of regular #1: Replace the line
+ // number with the usual one.
+ hash_string_buffer(hash, p, q - p);
+ q += 1;
+ q[0] = '#';
+ q[1] = ' ';
+ q[2] = '1';
+ p = q;
+ }
+ }
+
+ while (q < end && *q != '"' && *q != '\n') {
+ q++;
+ }
+ if (q < end && *q == '\n') {
+ // A newline before the quotation mark -> no match.
+ continue;
+ }
+ q++;
+ if (q >= end) {
+ cc_log("Failed to parse included file path");
+ free(data);
+ free(cwd);
+ return false;
+ }
+ // q points to the beginning of an include file path
+ hash_string_buffer(hash, p, q - p);
+ p = q;
+ while (q < end && *q != '"') {
+ q++;
+ }
+ // Look for preprocessor flags, after the "filename".
+ bool system = false;
+ char* r = q + 1;
+ while (r < end && *r != '\n') {
+ if (*r == '3') { // System header.
+ system = true;
+ }
+ r++;
+ }
+ // p and q span the include file path.
+ char* inc_path = x_strndup(p, q - p);
+ if (!has_absolute_include_headers) {
+ has_absolute_include_headers = is_absolute_path(inc_path);
+ }
+ inc_path = make_relative_path(inc_path);
+
+ bool should_hash_inc_path = true;
+ if (!conf->hash_dir) {
+ if (str_startswith(inc_path, cwd) && str_endswith(inc_path, "//")) {
+ // When compiling with -g or similar, GCC adds the absolute path to
+ // CWD like this:
+ //
+ // # 1 "CWD//"
+ //
+ // If the user has opted out of including the CWD in the hash, don't
+ // hash it. See also how debug_prefix_map is handled.
+ should_hash_inc_path = false;
+ }
+ }
+ if (should_hash_inc_path) {
+ hash_string_buffer(hash, inc_path, strlen(inc_path));
+ }
+
+ remember_include_file(inc_path, hash, system, NULL);
+ p = q; // Everything of interest between p and q has been hashed now.
+ } else if (q[0] == '.' && q[1] == 'i' && q[2] == 'n' && q[3] == 'c'
+ && q[4] == 'b' && q[5] == 'i' && q[6] == 'n') {
+ // An assembler .inc bin (without the space) statement, which could be
+ // part of inline assembly, refers to an external file. If the file
+ // changes, the hash should change as well, but finding out what file to
+ // hash is too hard for ccache, so just bail out.
+ cc_log(
+ "Found unsupported .inc"
+ "bin directive in source code");
+ stats_update(STATS_UNSUPPORTED_DIRECTIVE);
+ failed();
+ } else if (pump && strncmp(q, "_________", 9) == 0) {
+ // Unfortunately the distcc-pump wrapper outputs standard output lines:
+ // __________Using distcc-pump from /usr/bin
+ // __________Using # distcc servers in pump mode
+ // __________Shutting down distcc-pump include server
+ while (q < end && *q != '\n') {
+ q++;
+ }
+ if (*q == '\n') {
+ q++;
+ }
+ p = q;
+ continue;
+ } else {
+ q++;
+ }
+ }
+
+ hash_string_buffer(hash, p, (end - p));
+ free(data);
+ free(cwd);
+
+ // Explicitly check the .gch/.pch/.pth file as Clang does not include any
+ // mention of it in the preprocessed output.
+ if (included_pch_file) {
+ char* pch_path = x_strdup(included_pch_file);
+ pch_path = make_relative_path(pch_path);
+ hash_string(hash, pch_path);
+ remember_include_file(pch_path, hash, false, NULL);
+ }
+
+ bool debug_included = getenv("CCACHE_DEBUG_INCLUDED");
+ if (debug_included) {
+ print_included_files(stdout);
+ }
+
+ return true;
}
// Replace absolute paths with relative paths in the provided dependency file.
static void
-use_relative_paths_in_depfile(const char *depfile)
+use_relative_paths_in_depfile(const char* depfile)
{
- if (str_eq(conf->base_dir, "")) {
- cc_log("Base dir not set, skip using relative paths");
- return; // nothing to do
- }
- if (!has_absolute_include_headers) {
- cc_log("No absolute path for included files found, skip using relative"
- " paths");
- return; // nothing to do
- }
-
- FILE *f;
- f = fopen(depfile, "r");
- if (!f) {
- cc_log("Cannot open dependency file: %s (%s)", depfile, strerror(errno));
- return;
- }
-
- char *tmp_file = format("%s.tmp", depfile);
- FILE *tmpf = create_tmp_file(&tmp_file, "w");
-
- bool result = false;
- char buf[10000];
- while (fgets(buf, sizeof(buf), f) && !ferror(tmpf)) {
- char *saveptr;
- char *token = strtok_r(buf, " \t", &saveptr);
- while (token) {
- char *relpath;
- if (is_absolute_path(token) && str_startswith(token, conf->base_dir)) {
- relpath = make_relative_path(x_strdup(token));
- result = true;
- } else {
- relpath = token;
- }
- if (token != buf) { // This is a dependency file.
- fputc(' ', tmpf);
- }
- fputs(relpath, tmpf);
- if (relpath != token) {
- free(relpath);
- }
- token = strtok_r(NULL, " \t", &saveptr);
- }
- }
-
- if (ferror(f)) {
- cc_log("Error reading dependency file: %s, skip relative path usage",
- depfile);
- result = false;
- goto out;
- }
- if (ferror(tmpf)) {
- cc_log("Error writing temporary dependency file: %s, skip relative path"
- " usage", tmp_file);
- result = false;
- goto out;
- }
+ if (str_eq(conf->base_dir, "")) {
+ cc_log("Base dir not set, skip using relative paths");
+ return; // nothing to do
+ }
+ if (!has_absolute_include_headers) {
+ cc_log(
+ "No absolute path for included files found, skip using relative"
+ " paths");
+ return; // nothing to do
+ }
+
+ FILE* f;
+ f = fopen(depfile, "r");
+ if (!f) {
+ cc_log("Cannot open dependency file: %s (%s)", depfile, strerror(errno));
+ return;
+ }
+
+ char* tmp_file = format("%s.tmp", depfile);
+ FILE* tmpf = create_tmp_file(&tmp_file, "w");
+
+ bool result = false;
+ char buf[10000];
+ while (fgets(buf, sizeof(buf), f) && !ferror(tmpf)) {
+ char* saveptr;
+ char* token = strtok_r(buf, " \t", &saveptr);
+ while (token) {
+ char* relpath;
+ if (is_absolute_path(token) && str_startswith(token, conf->base_dir)) {
+ relpath = make_relative_path(x_strdup(token));
+ result = true;
+ } else {
+ relpath = token;
+ }
+ if (token != buf) { // This is a dependency file.
+ fputc(' ', tmpf);
+ }
+ fputs(relpath, tmpf);
+ if (relpath != token) {
+ free(relpath);
+ }
+ token = strtok_r(NULL, " \t", &saveptr);
+ }
+ }
+
+ if (ferror(f)) {
+ cc_log("Error reading dependency file: %s, skip relative path usage",
+ depfile);
+ result = false;
+ goto out;
+ }
+ if (ferror(tmpf)) {
+ cc_log(
+ "Error writing temporary dependency file: %s, skip relative path"
+ " usage",
+ tmp_file);
+ result = false;
+ goto out;
+ }
out:
- fclose(tmpf);
- fclose(f);
- if (result) {
- if (x_rename(tmp_file, depfile) != 0) {
- cc_log("Error renaming dependency file: %s -> %s (%s), skip relative"
- " path usage", tmp_file, depfile, strerror(errno));
- result = false;
- } else {
- cc_log("Renamed dependency file: %s -> %s", tmp_file, depfile);
- }
- }
- if (!result) {
- cc_log("Removing temporary dependency file: %s", tmp_file);
- x_unlink(tmp_file);
- }
- free(tmp_file);
+ fclose(tmpf);
+ fclose(f);
+ if (result) {
+ if (x_rename(tmp_file, depfile) != 0) {
+ cc_log(
+ "Error renaming dependency file: %s -> %s (%s), skip relative"
+ " path usage",
+ tmp_file,
+ depfile,
+ strerror(errno));
+ result = false;
+ } else {
+ cc_log("Renamed dependency file: %s -> %s", tmp_file, depfile);
+ }
+ }
+ if (!result) {
+ cc_log("Removing temporary dependency file: %s", tmp_file);
+ x_unlink(tmp_file);
+ }
+ free(tmp_file);
}
// Extract the used includes from the dependency file. Note that we cannot
// distinguish system headers from other includes here.
-static struct digest *
-result_name_from_depfile(const char *depfile, struct hash *hash)
+static struct digest*
+result_name_from_depfile(const char* depfile, struct hash* hash)
{
- FILE *f = fopen(depfile, "r");
- if (!f) {
- cc_log("Cannot open dependency file %s: %s", depfile, strerror(errno));
- return NULL;
- }
-
- init_included_files_table();
-
- char buf[10000];
- while (fgets(buf, sizeof(buf), f) && !ferror(f)) {
- char *saveptr;
- char *token;
- for (token = strtok_r(buf, " \t\n", &saveptr);
- token;
- token = strtok_r(NULL, " \t\n", &saveptr)) {
- if (str_endswith(token, ":") || str_eq(token, "\\")) {
- continue;
- }
- if (!has_absolute_include_headers) {
- has_absolute_include_headers = is_absolute_path(token);
- }
- char *path = make_relative_path(x_strdup(token));
- remember_include_file(path, hash, false, hash);
- }
- }
-
- fclose(f);
-
- // Explicitly check the .gch/.pch/.pth file as it may not be mentioned in the
- // dependencies output.
- if (included_pch_file) {
- char *pch_path = x_strdup(included_pch_file);
- pch_path = make_relative_path(pch_path);
- hash_string(hash, pch_path);
- remember_include_file(pch_path, hash, false, NULL);
- }
-
- bool debug_included = getenv("CCACHE_DEBUG_INCLUDED");
- if (debug_included) {
- print_included_files(stdout);
- }
-
- auto d = static_cast<digest*>(x_malloc(sizeof(digest)));
- hash_result_as_bytes(hash, d);
- return d;
+ FILE* f = fopen(depfile, "r");
+ if (!f) {
+ cc_log("Cannot open dependency file %s: %s", depfile, strerror(errno));
+ return NULL;
+ }
+
+ init_included_files_table();
+
+ char buf[10000];
+ while (fgets(buf, sizeof(buf), f) && !ferror(f)) {
+ char* saveptr;
+ char* token;
+ for (token = strtok_r(buf, " \t\n", &saveptr); token;
+ token = strtok_r(NULL, " \t\n", &saveptr)) {
+ if (str_endswith(token, ":") || str_eq(token, "\\")) {
+ continue;
+ }
+ if (!has_absolute_include_headers) {
+ has_absolute_include_headers = is_absolute_path(token);
+ }
+ char* path = make_relative_path(x_strdup(token));
+ remember_include_file(path, hash, false, hash);
+ }
+ }
+
+ fclose(f);
+
+ // Explicitly check the .gch/.pch/.pth file as it may not be mentioned in the
+ // dependencies output.
+ if (included_pch_file) {
+ char* pch_path = x_strdup(included_pch_file);
+ pch_path = make_relative_path(pch_path);
+ hash_string(hash, pch_path);
+ remember_include_file(pch_path, hash, false, NULL);
+ }
+
+ bool debug_included = getenv("CCACHE_DEBUG_INCLUDED");
+ if (debug_included) {
+ print_included_files(stdout);
+ }
+
+ auto d = static_cast<digest*>(x_malloc(sizeof(digest)));
+ hash_result_as_bytes(hash, d);
+ return d;
}
// Send cached stderr, if any, to stderr.
static void
-send_cached_stderr(const char *path_stderr)
+send_cached_stderr(const char* path_stderr)
{
- int fd_stderr = open(path_stderr, O_RDONLY | O_BINARY);
- if (fd_stderr != -1) {
- copy_fd(fd_stderr, 2);
- close(fd_stderr);
- }
+ int fd_stderr = open(path_stderr, O_RDONLY | O_BINARY);
+ if (fd_stderr != -1) {
+ copy_fd(fd_stderr, 2);
+ close(fd_stderr);
+ }
}
// Create or update the manifest file.
static void
update_manifest_file(void)
{
- if (!conf->direct_mode
- || !included_files
- || conf->read_only
- || conf->read_only_direct) {
- return;
- }
-
- struct stat st;
- size_t old_size = 0; // in bytes
- if (stat(manifest_path, &st) == 0) {
- old_size = file_size(&st);
- }
-
- MTR_BEGIN("manifest", "manifest_put");
- cc_log("Adding result name to %s", manifest_path);
- if (manifest_put(manifest_path, cached_result_name, included_files)) {
- if (x_stat(manifest_path, &st) == 0) {
- stats_update_size(
- manifest_stats_file,
- file_size(&st) - old_size,
- old_size == 0 ? 1 : 0);
- }
- } else {
- cc_log("Failed to add result name to %s", manifest_path);
- }
- MTR_END("manifest", "manifest_put");
+ if (!conf->direct_mode || !included_files || conf->read_only
+ || conf->read_only_direct) {
+ return;
+ }
+
+ struct stat st;
+ size_t old_size = 0; // in bytes
+ if (stat(manifest_path, &st) == 0) {
+ old_size = file_size(&st);
+ }
+
+ MTR_BEGIN("manifest", "manifest_put");
+ cc_log("Adding result name to %s", manifest_path);
+ if (manifest_put(manifest_path, cached_result_name, included_files)) {
+ if (x_stat(manifest_path, &st) == 0) {
+ stats_update_size(
+ manifest_stats_file, file_size(&st) - old_size, old_size == 0 ? 1 : 0);
+ }
+ } else {
+ cc_log("Failed to add result name to %s", manifest_path);
+ }
+ MTR_END("manifest", "manifest_put");
}
static void
-update_cached_result_globals(struct digest *result_name)
+update_cached_result_globals(struct digest* result_name)
{
- char result_name_string[DIGEST_STRING_BUFFER_SIZE];
- digest_as_string(result_name, result_name_string);
- cached_result_name = result_name;
- cached_result_path = get_path_in_cache(result_name_string, ".result");
- stats_file = format("%s/%c/stats", conf->cache_dir, result_name_string[0]);
+ char result_name_string[DIGEST_STRING_BUFFER_SIZE];
+ digest_as_string(result_name, result_name_string);
+ cached_result_name = result_name;
+ cached_result_path = get_path_in_cache(result_name_string, ".result");
+ stats_file = format("%s/%c/stats", conf->cache_dir, result_name_string[0]);
}
// Run the real compiler and put the result in cache.
static void
-to_cache(struct args *args, struct hash *depend_mode_hash)
+to_cache(struct args* args, struct hash* depend_mode_hash)
{
- args_add(args, "-o");
- args_add(args, output_obj);
-
- if (conf->hard_link) {
- // Workaround for Clang bug where it overwrites an existing object file
- // when it's compiling an assembler file, see
- // <https://bugs.llvm.org/show_bug.cgi?id=39782>.
- x_unlink(output_obj);
- }
-
- if (generating_diagnostics) {
- args_add(args, "--serialize-diagnostics");
- args_add(args, output_dia);
- }
-
- // Turn off DEPENDENCIES_OUTPUT when running cc1, because otherwise it will
- // emit a line like this:
- //
- // tmp.stdout.vexed.732.o: /home/mbp/.ccache/tmp.stdout.vexed.732.i
- x_unsetenv("DEPENDENCIES_OUTPUT");
- x_unsetenv("SUNPRO_DEPENDENCIES");
-
- if (conf->run_second_cpp) {
- args_add(args, input_file);
- } else {
- args_add(args, i_tmpfile);
- }
-
- if (seen_split_dwarf) {
- // Remove any pre-existing .dwo file since we want to check if the compiler
- // produced one, intentionally not using x_unlink or tmp_unlink since we're
- // not interested in logging successful deletions or failures due to
- // non-existent .dwo files.
- if (unlink(output_dwo) == -1 && errno != ENOENT) {
- cc_log("Failed to unlink %s: %s", output_dwo, strerror(errno));
- stats_update(STATS_BADOUTPUTFILE);
- }
- }
-
- cc_log("Running real compiler");
- MTR_BEGIN("execute", "compiler");
- char *tmp_stdout;
- int tmp_stdout_fd;
- char *tmp_stderr;
- int tmp_stderr_fd;
- int status;
- if (!conf->depend_mode) {
- tmp_stdout = format("%s/tmp.stdout", temp_dir());
- tmp_stdout_fd = create_tmp_fd(&tmp_stdout);
- tmp_stderr = format("%s/tmp.stderr", temp_dir());
- tmp_stderr_fd = create_tmp_fd(&tmp_stderr);
- status = execute(args->argv, tmp_stdout_fd, tmp_stderr_fd, &compiler_pid);
- args_pop(args, 3);
- } else {
- // The cached result path is not known yet, use temporary files.
- tmp_stdout = format("%s/tmp.stdout", temp_dir());
- tmp_stdout_fd = create_tmp_fd(&tmp_stdout);
- tmp_stderr = format("%s/tmp.stderr", temp_dir());
- tmp_stderr_fd = create_tmp_fd(&tmp_stderr);
-
- // Use the original arguments (including dependency options) in depend
- // mode.
- assert(orig_args);
- struct args *depend_mode_args = args_copy(orig_args);
- args_strip(depend_mode_args, "--ccache-");
- add_prefix(depend_mode_args, conf->prefix_command);
-
- time_of_compilation = time(NULL);
- status = execute(
- depend_mode_args->argv, tmp_stdout_fd, tmp_stderr_fd, &compiler_pid);
- args_free(depend_mode_args);
- }
- MTR_END("execute", "compiler");
-
- struct stat st;
- if (x_stat(tmp_stdout, &st) != 0) {
- // The stdout file was removed - cleanup in progress? Better bail out.
- stats_update(STATS_MISSING);
- tmp_unlink(tmp_stdout);
- tmp_unlink(tmp_stderr);
- failed();
- }
-
- // distcc-pump outputs lines like this:
- // __________Using # distcc servers in pump mode
- if (st.st_size != 0 && guessed_compiler != GUESSED_PUMP) {
- cc_log("Compiler produced stdout");
- stats_update(STATS_STDOUT);
- tmp_unlink(tmp_stdout);
- tmp_unlink(tmp_stderr);
- failed();
- }
- tmp_unlink(tmp_stdout);
-
- // Merge stderr from the preprocessor (if any) and stderr from the real
- // compiler into tmp_stderr.
- if (cpp_stderr) {
- char *tmp_stderr2 = format("%s.2", tmp_stderr);
- if (x_rename(tmp_stderr, tmp_stderr2)) {
- cc_log("Failed to rename %s to %s: %s", tmp_stderr, tmp_stderr2,
- strerror(errno));
- failed();
- }
-
- int fd_cpp_stderr = open(cpp_stderr, O_RDONLY | O_BINARY);
- if (fd_cpp_stderr == -1) {
- cc_log("Failed opening %s: %s", cpp_stderr, strerror(errno));
- failed();
- }
-
- int fd_real_stderr = open(tmp_stderr2, O_RDONLY | O_BINARY);
- if (fd_real_stderr == -1) {
- cc_log("Failed opening %s: %s", tmp_stderr2, strerror(errno));
- failed();
- }
-
- int fd_result =
- open(tmp_stderr, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
- if (fd_result == -1) {
- cc_log("Failed opening %s: %s", tmp_stderr, strerror(errno));
- failed();
- }
-
- copy_fd(fd_cpp_stderr, fd_result);
- copy_fd(fd_real_stderr, fd_result);
- close(fd_cpp_stderr);
- close(fd_real_stderr);
- close(fd_result);
- tmp_unlink(tmp_stderr2);
- free(tmp_stderr2);
- }
-
- if (status != 0) {
- cc_log("Compiler gave exit status %d", status);
- stats_update(STATS_STATUS);
-
- int fd = open(tmp_stderr, O_RDONLY | O_BINARY);
- if (fd != -1) {
- // We can output stderr immediately instead of rerunning the compiler.
- copy_fd(fd, 2);
- close(fd);
- tmp_unlink(tmp_stderr);
-
- x_exit(status);
- }
-
- tmp_unlink(tmp_stderr);
- failed();
- }
-
- if (conf->depend_mode) {
- struct digest *result_name =
- result_name_from_depfile(output_dep, depend_mode_hash);
- if (!result_name) {
- failed();
- }
- update_cached_result_globals(result_name);
- }
-
- bool produce_dep_file =
- generating_dependencies && !str_eq(output_dep, "/dev/null");
-
- if (produce_dep_file) {
- use_relative_paths_in_depfile(output_dep);
- }
-
- if (stat(output_obj, &st) != 0) {
- cc_log("Compiler didn't produce an object file");
- stats_update(STATS_NOOUTPUT);
- failed();
- }
- if (st.st_size == 0) {
- cc_log("Compiler produced an empty object file");
- stats_update(STATS_EMPTYOUTPUT);
- failed();
- }
-
- if (x_stat(tmp_stderr, &st) != 0) {
- stats_update(STATS_ERROR);
- failed();
- }
- struct result_files *result_files = result_files_init();
- if (st.st_size > 0) {
- result_files_add(result_files, tmp_stderr, RESULT_STDERR_NAME);
- }
- result_files_add(result_files, output_obj, ".o");
- if (generating_dependencies) {
- result_files_add(result_files, output_dep, ".d");
- }
- if (generating_coverage) {
- result_files_add(result_files, output_cov, ".gcno");
- }
- if (generating_stackusage) {
- result_files_add(result_files, output_su, ".su");
- }
- if (generating_diagnostics) {
- result_files_add(result_files, output_dia, ".dia");
- }
- if (seen_split_dwarf && stat(output_dwo, &st) == 0) {
- // Only copy .dwo file if it was created by the compiler (GCC and Clang
- // behave differently e.g. for "-gsplit-dwarf -g1").
- result_files_add(result_files, output_dwo, ".dwo");
- }
- struct stat orig_dest_st;
- bool orig_dest_existed = stat(cached_result_path, &orig_dest_st) == 0;
- result_put(cached_result_path, result_files);
- result_files_free(result_files);
-
- cc_log("Stored in cache: %s", cached_result_path);
-
- if (x_stat(cached_result_path, &st) != 0) {
- stats_update(STATS_ERROR);
- failed();
- }
- stats_update_size(
- stats_file,
- file_size(&st) - (orig_dest_existed ? file_size(&orig_dest_st) : 0),
- orig_dest_existed ? 0 : 1);
-
- MTR_END("file", "file_put");
-
- stats_update(STATS_TOCACHE);
-
- // Make sure we have a CACHEDIR.TAG in the cache part of cache_dir. This can
- // be done almost anywhere, but we might as well do it near the end as we
- // save the stat call if we exit early.
- {
- char *first_level_dir = x_dirname(stats_file);
- if (create_cachedirtag(first_level_dir) != 0) {
- cc_log("Failed to create %s/CACHEDIR.TAG (%s)\n",
- first_level_dir, strerror(errno));
- stats_update(STATS_ERROR);
- failed();
- }
- free(first_level_dir);
-
- // Remove any CACHEDIR.TAG on the cache_dir level where it was located in
- // previous ccache versions.
- if (getpid() % 1000 == 0) {
- char *path = format("%s/CACHEDIR.TAG", conf->cache_dir);
- x_unlink(path);
- free(path);
- }
- }
-
- // Everything OK.
- send_cached_stderr(tmp_stderr);
- tmp_unlink(tmp_stderr);
-
- update_manifest_file();
-
- free(tmp_stderr);
- free(tmp_stdout);
+ args_add(args, "-o");
+ args_add(args, output_obj);
+
+ if (conf->hard_link) {
+ // Workaround for Clang bug where it overwrites an existing object file
+ // when it's compiling an assembler file, see
+ // <https://bugs.llvm.org/show_bug.cgi?id=39782>.
+ x_unlink(output_obj);
+ }
+
+ if (generating_diagnostics) {
+ args_add(args, "--serialize-diagnostics");
+ args_add(args, output_dia);
+ }
+
+ // Turn off DEPENDENCIES_OUTPUT when running cc1, because otherwise it will
+ // emit a line like this:
+ //
+ // tmp.stdout.vexed.732.o: /home/mbp/.ccache/tmp.stdout.vexed.732.i
+ x_unsetenv("DEPENDENCIES_OUTPUT");
+ x_unsetenv("SUNPRO_DEPENDENCIES");
+
+ if (conf->run_second_cpp) {
+ args_add(args, input_file);
+ } else {
+ args_add(args, i_tmpfile);
+ }
+
+ if (seen_split_dwarf) {
+ // Remove any pre-existing .dwo file since we want to check if the compiler
+ // produced one, intentionally not using x_unlink or tmp_unlink since we're
+ // not interested in logging successful deletions or failures due to
+ // non-existent .dwo files.
+ if (unlink(output_dwo) == -1 && errno != ENOENT) {
+ cc_log("Failed to unlink %s: %s", output_dwo, strerror(errno));
+ stats_update(STATS_BADOUTPUTFILE);
+ }
+ }
+
+ cc_log("Running real compiler");
+ MTR_BEGIN("execute", "compiler");
+ char* tmp_stdout;
+ int tmp_stdout_fd;
+ char* tmp_stderr;
+ int tmp_stderr_fd;
+ int status;
+ if (!conf->depend_mode) {
+ tmp_stdout = format("%s/tmp.stdout", temp_dir());
+ tmp_stdout_fd = create_tmp_fd(&tmp_stdout);
+ tmp_stderr = format("%s/tmp.stderr", temp_dir());
+ tmp_stderr_fd = create_tmp_fd(&tmp_stderr);
+ status = execute(args->argv, tmp_stdout_fd, tmp_stderr_fd, &compiler_pid);
+ args_pop(args, 3);
+ } else {
+ // The cached result path is not known yet, use temporary files.
+ tmp_stdout = format("%s/tmp.stdout", temp_dir());
+ tmp_stdout_fd = create_tmp_fd(&tmp_stdout);
+ tmp_stderr = format("%s/tmp.stderr", temp_dir());
+ tmp_stderr_fd = create_tmp_fd(&tmp_stderr);
+
+ // Use the original arguments (including dependency options) in depend
+ // mode.
+ assert(orig_args);
+ struct args* depend_mode_args = args_copy(orig_args);
+ args_strip(depend_mode_args, "--ccache-");
+ add_prefix(depend_mode_args, conf->prefix_command);
+
+ time_of_compilation = time(NULL);
+ status = execute(
+ depend_mode_args->argv, tmp_stdout_fd, tmp_stderr_fd, &compiler_pid);
+ args_free(depend_mode_args);
+ }
+ MTR_END("execute", "compiler");
+
+ struct stat st;
+ if (x_stat(tmp_stdout, &st) != 0) {
+ // The stdout file was removed - cleanup in progress? Better bail out.
+ stats_update(STATS_MISSING);
+ tmp_unlink(tmp_stdout);
+ tmp_unlink(tmp_stderr);
+ failed();
+ }
+
+ // distcc-pump outputs lines like this:
+ // __________Using # distcc servers in pump mode
+ if (st.st_size != 0 && guessed_compiler != GUESSED_PUMP) {
+ cc_log("Compiler produced stdout");
+ stats_update(STATS_STDOUT);
+ tmp_unlink(tmp_stdout);
+ tmp_unlink(tmp_stderr);
+ failed();
+ }
+ tmp_unlink(tmp_stdout);
+
+ // Merge stderr from the preprocessor (if any) and stderr from the real
+ // compiler into tmp_stderr.
+ if (cpp_stderr) {
+ char* tmp_stderr2 = format("%s.2", tmp_stderr);
+ if (x_rename(tmp_stderr, tmp_stderr2)) {
+ cc_log("Failed to rename %s to %s: %s",
+ tmp_stderr,
+ tmp_stderr2,
+ strerror(errno));
+ failed();
+ }
+
+ int fd_cpp_stderr = open(cpp_stderr, O_RDONLY | O_BINARY);
+ if (fd_cpp_stderr == -1) {
+ cc_log("Failed opening %s: %s", cpp_stderr, strerror(errno));
+ failed();
+ }
+
+ int fd_real_stderr = open(tmp_stderr2, O_RDONLY | O_BINARY);
+ if (fd_real_stderr == -1) {
+ cc_log("Failed opening %s: %s", tmp_stderr2, strerror(errno));
+ failed();
+ }
+
+ int fd_result =
+ open(tmp_stderr, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ if (fd_result == -1) {
+ cc_log("Failed opening %s: %s", tmp_stderr, strerror(errno));
+ failed();
+ }
+
+ copy_fd(fd_cpp_stderr, fd_result);
+ copy_fd(fd_real_stderr, fd_result);
+ close(fd_cpp_stderr);
+ close(fd_real_stderr);
+ close(fd_result);
+ tmp_unlink(tmp_stderr2);
+ free(tmp_stderr2);
+ }
+
+ if (status != 0) {
+ cc_log("Compiler gave exit status %d", status);
+ stats_update(STATS_STATUS);
+
+ int fd = open(tmp_stderr, O_RDONLY | O_BINARY);
+ if (fd != -1) {
+ // We can output stderr immediately instead of rerunning the compiler.
+ copy_fd(fd, 2);
+ close(fd);
+ tmp_unlink(tmp_stderr);
+
+ x_exit(status);
+ }
+
+ tmp_unlink(tmp_stderr);
+ failed();
+ }
+
+ if (conf->depend_mode) {
+ struct digest* result_name =
+ result_name_from_depfile(output_dep, depend_mode_hash);
+ if (!result_name) {
+ failed();
+ }
+ update_cached_result_globals(result_name);
+ }
+
+ bool produce_dep_file =
+ generating_dependencies && !str_eq(output_dep, "/dev/null");
+
+ if (produce_dep_file) {
+ use_relative_paths_in_depfile(output_dep);
+ }
+
+ if (stat(output_obj, &st) != 0) {
+ cc_log("Compiler didn't produce an object file");
+ stats_update(STATS_NOOUTPUT);
+ failed();
+ }
+ if (st.st_size == 0) {
+ cc_log("Compiler produced an empty object file");
+ stats_update(STATS_EMPTYOUTPUT);
+ failed();
+ }
+
+ if (x_stat(tmp_stderr, &st) != 0) {
+ stats_update(STATS_ERROR);
+ failed();
+ }
+ struct result_files* result_files = result_files_init();
+ if (st.st_size > 0) {
+ result_files_add(result_files, tmp_stderr, RESULT_STDERR_NAME);
+ }
+ result_files_add(result_files, output_obj, ".o");
+ if (generating_dependencies) {
+ result_files_add(result_files, output_dep, ".d");
+ }
+ if (generating_coverage) {
+ result_files_add(result_files, output_cov, ".gcno");
+ }
+ if (generating_stackusage) {
+ result_files_add(result_files, output_su, ".su");
+ }
+ if (generating_diagnostics) {
+ result_files_add(result_files, output_dia, ".dia");
+ }
+ if (seen_split_dwarf && stat(output_dwo, &st) == 0) {
+ // Only copy .dwo file if it was created by the compiler (GCC and Clang
+ // behave differently e.g. for "-gsplit-dwarf -g1").
+ result_files_add(result_files, output_dwo, ".dwo");
+ }
+ struct stat orig_dest_st;
+ bool orig_dest_existed = stat(cached_result_path, &orig_dest_st) == 0;
+ result_put(cached_result_path, result_files);
+ result_files_free(result_files);
+
+ cc_log("Stored in cache: %s", cached_result_path);
+
+ if (x_stat(cached_result_path, &st) != 0) {
+ stats_update(STATS_ERROR);
+ failed();
+ }
+ stats_update_size(stats_file,
+ file_size(&st)
+ - (orig_dest_existed ? file_size(&orig_dest_st) : 0),
+ orig_dest_existed ? 0 : 1);
+
+ MTR_END("file", "file_put");
+
+ stats_update(STATS_TOCACHE);
+
+ // Make sure we have a CACHEDIR.TAG in the cache part of cache_dir. This can
+ // be done almost anywhere, but we might as well do it near the end as we
+ // save the stat call if we exit early.
+ {
+ char* first_level_dir = x_dirname(stats_file);
+ if (create_cachedirtag(first_level_dir) != 0) {
+ cc_log("Failed to create %s/CACHEDIR.TAG (%s)\n",
+ first_level_dir,
+ strerror(errno));
+ stats_update(STATS_ERROR);
+ failed();
+ }
+ free(first_level_dir);
+
+ // Remove any CACHEDIR.TAG on the cache_dir level where it was located in
+ // previous ccache versions.
+ if (getpid() % 1000 == 0) {
+ char* path = format("%s/CACHEDIR.TAG", conf->cache_dir);
+ x_unlink(path);
+ free(path);
+ }
+ }
+
+ // Everything OK.
+ send_cached_stderr(tmp_stderr);
+ tmp_unlink(tmp_stderr);
+
+ update_manifest_file();
+
+ free(tmp_stderr);
+ free(tmp_stdout);
}
// Find the result name by running the compiler in preprocessor mode and
// hashing the result.
-static struct digest *
-get_result_name_from_cpp(struct args *args, struct hash *hash)
+static struct digest*
+get_result_name_from_cpp(struct args* args, struct hash* hash)
{
- time_of_compilation = time(NULL);
-
- char *path_stderr = NULL;
- char *path_stdout;
- int status;
- if (direct_i_file) {
- // We are compiling a .i or .ii file - that means we can skip the cpp stage
- // and directly form the correct i_tmpfile.
- path_stdout = input_file;
- status = 0;
- } else {
- // Run cpp on the input file to obtain the .i.
-
- // Limit the basename to 10 characters in order to cope with filesystem with
- // small maximum filename length limits.
- char *input_base = x_basename(input_file);
- char *tmp = strchr(input_base, '.');
- if (tmp) {
- *tmp = 0;
- }
- if (strlen(input_base) > 10) {
- input_base[10] = 0;
- }
-
- path_stdout = format("%s/%s.stdout", temp_dir(), input_base);
- free(input_base);
- int path_stdout_fd = create_tmp_fd(&path_stdout);
- add_pending_tmp_file(path_stdout);
-
- path_stderr = format("%s/tmp.cpp_stderr", temp_dir());
- int path_stderr_fd = create_tmp_fd(&path_stderr);
- add_pending_tmp_file(path_stderr);
-
- int args_added = 2;
- args_add(args, "-E");
- if (conf->keep_comments_cpp) {
- args_add(args, "-C");
- args_added = 3;
- }
- args_add(args, input_file);
- add_prefix(args, conf->prefix_command_cpp);
- cc_log("Running preprocessor");
- MTR_BEGIN("execute", "preprocessor");
- status = execute(args->argv, path_stdout_fd, path_stderr_fd, &compiler_pid);
- MTR_END("execute", "preprocessor");
- args_pop(args, args_added);
- }
-
- if (status != 0) {
- cc_log("Preprocessor gave exit status %d", status);
- stats_update(STATS_PREPROCESSOR);
- failed();
- }
-
- if (conf->unify) {
- // When we are doing the unifying tricks we need to include the input file
- // name in the hash to get the warnings right.
- hash_delimiter(hash, "unifyfilename");
- hash_string(hash, input_file);
-
- hash_delimiter(hash, "unifycpp");
-
- bool debug_unify = getenv("CCACHE_DEBUG_UNIFY");
- if (unify_hash(hash, path_stdout, debug_unify) != 0) {
- stats_update(STATS_ERROR);
- cc_log("Failed to unify %s", path_stdout);
- failed();
- }
- } else {
- hash_delimiter(hash, "cpp");
- if (!process_preprocessed_file(hash, path_stdout,
- guessed_compiler == GUESSED_PUMP)) {
- stats_update(STATS_ERROR);
- failed();
- }
- }
-
- hash_delimiter(hash, "cppstderr");
- if (!direct_i_file && !hash_file(hash, path_stderr)) {
- fatal("Failed to open %s: %s", path_stderr, strerror(errno));
- }
-
- if (direct_i_file) {
- i_tmpfile = input_file;
- } else {
- // i_tmpfile needs the proper cpp_extension for the compiler to do its
- // thing correctly
- i_tmpfile = format("%s.%s", path_stdout, conf->cpp_extension);
- x_rename(path_stdout, i_tmpfile);
- add_pending_tmp_file(i_tmpfile);
- }
-
- if (conf->run_second_cpp) {
- free(path_stderr);
- } else {
- // If we are using the CPP trick, we need to remember this stderr data and
- // output it just before the main stderr from the compiler pass.
- cpp_stderr = path_stderr;
- hash_delimiter(hash, "runsecondcpp");
- hash_string(hash, "false");
- }
-
- auto name = static_cast<digest*>(x_malloc(sizeof(digest)));
- hash_result_as_bytes(hash, name);
- return name;
+ time_of_compilation = time(NULL);
+
+ char* path_stderr = NULL;
+ char* path_stdout;
+ int status;
+ if (direct_i_file) {
+ // We are compiling a .i or .ii file - that means we can skip the cpp stage
+ // and directly form the correct i_tmpfile.
+ path_stdout = input_file;
+ status = 0;
+ } else {
+ // Run cpp on the input file to obtain the .i.
+
+ // Limit the basename to 10 characters in order to cope with filesystem with
+ // small maximum filename length limits.
+ char* input_base = x_basename(input_file);
+ char* tmp = strchr(input_base, '.');
+ if (tmp) {
+ *tmp = 0;
+ }
+ if (strlen(input_base) > 10) {
+ input_base[10] = 0;
+ }
+
+ path_stdout = format("%s/%s.stdout", temp_dir(), input_base);
+ free(input_base);
+ int path_stdout_fd = create_tmp_fd(&path_stdout);
+ add_pending_tmp_file(path_stdout);
+
+ path_stderr = format("%s/tmp.cpp_stderr", temp_dir());
+ int path_stderr_fd = create_tmp_fd(&path_stderr);
+ add_pending_tmp_file(path_stderr);
+
+ int args_added = 2;
+ args_add(args, "-E");
+ if (conf->keep_comments_cpp) {
+ args_add(args, "-C");
+ args_added = 3;
+ }
+ args_add(args, input_file);
+ add_prefix(args, conf->prefix_command_cpp);
+ cc_log("Running preprocessor");
+ MTR_BEGIN("execute", "preprocessor");
+ status = execute(args->argv, path_stdout_fd, path_stderr_fd, &compiler_pid);
+ MTR_END("execute", "preprocessor");
+ args_pop(args, args_added);
+ }
+
+ if (status != 0) {
+ cc_log("Preprocessor gave exit status %d", status);
+ stats_update(STATS_PREPROCESSOR);
+ failed();
+ }
+
+ if (conf->unify) {
+ // When we are doing the unifying tricks we need to include the input file
+ // name in the hash to get the warnings right.
+ hash_delimiter(hash, "unifyfilename");
+ hash_string(hash, input_file);
+
+ hash_delimiter(hash, "unifycpp");
+
+ bool debug_unify = getenv("CCACHE_DEBUG_UNIFY");
+ if (unify_hash(hash, path_stdout, debug_unify) != 0) {
+ stats_update(STATS_ERROR);
+ cc_log("Failed to unify %s", path_stdout);
+ failed();
+ }
+ } else {
+ hash_delimiter(hash, "cpp");
+ if (!process_preprocessed_file(
+ hash, path_stdout, guessed_compiler == GUESSED_PUMP)) {
+ stats_update(STATS_ERROR);
+ failed();
+ }
+ }
+
+ hash_delimiter(hash, "cppstderr");
+ if (!direct_i_file && !hash_file(hash, path_stderr)) {
+ fatal("Failed to open %s: %s", path_stderr, strerror(errno));
+ }
+
+ if (direct_i_file) {
+ i_tmpfile = input_file;
+ } else {
+ // i_tmpfile needs the proper cpp_extension for the compiler to do its
+ // thing correctly
+ i_tmpfile = format("%s.%s", path_stdout, conf->cpp_extension);
+ x_rename(path_stdout, i_tmpfile);
+ add_pending_tmp_file(i_tmpfile);
+ }
+
+ if (conf->run_second_cpp) {
+ free(path_stderr);
+ } else {
+ // If we are using the CPP trick, we need to remember this stderr data and
+ // output it just before the main stderr from the compiler pass.
+ cpp_stderr = path_stderr;
+ hash_delimiter(hash, "runsecondcpp");
+ hash_string(hash, "false");
+ }
+
+ auto name = static_cast<digest*>(x_malloc(sizeof(digest)));
+ hash_result_as_bytes(hash, name);
+ return name;
}
// Hash mtime or content of a file, or the output of a command, according to
// the CCACHE_COMPILERCHECK setting.
static void
-hash_compiler(struct hash *hash, struct stat *st, const char *path,
+hash_compiler(struct hash* hash,
+ struct stat* st,
+ const char* path,
bool allow_command)
{
- if (str_eq(conf->compiler_check, "none")) {
- // Do nothing.
- } else if (str_eq(conf->compiler_check, "mtime")) {
- hash_delimiter(hash, "cc_mtime");
- hash_int(hash, st->st_size);
- hash_int(hash, st->st_mtime);
- } else if (str_startswith(conf->compiler_check, "string:")) {
- hash_delimiter(hash, "cc_hash");
- hash_string(hash, conf->compiler_check + strlen("string:"));
- } else if (str_eq(conf->compiler_check, "content") || !allow_command) {
- hash_delimiter(hash, "cc_content");
- hash_file(hash, path);
- } else { // command string
- bool ok = hash_multicommand_output(
- hash, conf->compiler_check, orig_args->argv[0]);
- if (!ok) {
- fatal("Failure running compiler check command: %s", conf->compiler_check);
- }
- }
+ if (str_eq(conf->compiler_check, "none")) {
+ // Do nothing.
+ } else if (str_eq(conf->compiler_check, "mtime")) {
+ hash_delimiter(hash, "cc_mtime");
+ hash_int(hash, st->st_size);
+ hash_int(hash, st->st_mtime);
+ } else if (str_startswith(conf->compiler_check, "string:")) {
+ hash_delimiter(hash, "cc_hash");
+ hash_string(hash, conf->compiler_check + strlen("string:"));
+ } else if (str_eq(conf->compiler_check, "content") || !allow_command) {
+ hash_delimiter(hash, "cc_content");
+ hash_file(hash, path);
+ } else { // command string
+ bool ok =
+ hash_multicommand_output(hash, conf->compiler_check, orig_args->argv[0]);
+ if (!ok) {
+ fatal("Failure running compiler check command: %s", conf->compiler_check);
+ }
+ }
}
// Hash the host compiler(s) invoked by nvcc.
@@ -1604,498 +1630,485 @@ hash_compiler(struct hash *hash, struct stat *st, const char *path,
// with -ccbin/--compiler-bindir. If they are NULL, the compilers are looked up
// in PATH instead.
static void
-hash_nvcc_host_compiler(struct hash *hash, struct stat *ccbin_st,
- const char *ccbin)
+hash_nvcc_host_compiler(struct hash* hash,
+ struct stat* ccbin_st,
+ const char* ccbin)
{
- // From <http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html>:
- //
- // "[...] Specify the directory in which the compiler executable resides.
- // The host compiler executable name can be also specified to ensure that
- // the correct host compiler is selected."
- //
- // and
- //
- // "On all platforms, the default host compiler executable (gcc and g++ on
- // Linux, clang and clang++ on Mac OS X, and cl.exe on Windows) found in
- // the current execution search path will be used".
-
- if (!ccbin || S_ISDIR(ccbin_st->st_mode)) {
+ // From <http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html>:
+ //
+ // "[...] Specify the directory in which the compiler executable resides.
+ // The host compiler executable name can be also specified to ensure that
+ // the correct host compiler is selected."
+ //
+ // and
+ //
+ // "On all platforms, the default host compiler executable (gcc and g++ on
+ // Linux, clang and clang++ on Mac OS X, and cl.exe on Windows) found in
+ // the current execution search path will be used".
+
+ if (!ccbin || S_ISDIR(ccbin_st->st_mode)) {
#if defined(__APPLE__)
- const char *compilers[] = {"clang", "clang++"};
+ const char* compilers[] = {"clang", "clang++"};
#elif defined(_WIN32)
- const char *compilers[] = {"cl.exe"};
+ const char* compilers[] = {"cl.exe"};
#else
- const char *compilers[] = {"gcc", "g++"};
+ const char* compilers[] = {"gcc", "g++"};
#endif
- for (size_t i = 0; i < ARRAY_SIZE(compilers); i++) {
- if (ccbin) {
- char *path = format("%s/%s", ccbin, compilers[i]);
- struct stat st;
- if (stat(path, &st) == 0) {
- hash_compiler(hash, &st, path, false);
- }
- free(path);
- } else {
- char *path = find_executable(compilers[i], MYNAME);
- if (path) {
- struct stat st;
- x_stat(path, &st);
- hash_compiler(hash, &st, ccbin, false);
- free(path);
- }
- }
- }
- } else {
- hash_compiler(hash, ccbin_st, ccbin, false);
- }
+ for (size_t i = 0; i < ARRAY_SIZE(compilers); i++) {
+ if (ccbin) {
+ char* path = format("%s/%s", ccbin, compilers[i]);
+ struct stat st;
+ if (stat(path, &st) == 0) {
+ hash_compiler(hash, &st, path, false);
+ }
+ free(path);
+ } else {
+ char* path = find_executable(compilers[i], MYNAME);
+ if (path) {
+ struct stat st;
+ x_stat(path, &st);
+ hash_compiler(hash, &st, ccbin, false);
+ free(path);
+ }
+ }
+ }
+ } else {
+ hash_compiler(hash, ccbin_st, ccbin, false);
+ }
}
// Update a hash with information common for the direct and preprocessor modes.
static void
-hash_common_info(struct args *args, struct hash *hash)
+hash_common_info(struct args* args, struct hash* hash)
{
- hash_string(hash, HASH_PREFIX);
+ hash_string(hash, HASH_PREFIX);
- // We have to hash the extension, as a .i file isn't treated the same by the
- // compiler as a .ii file.
- hash_delimiter(hash, "ext");
- hash_string(hash, conf->cpp_extension);
+ // We have to hash the extension, as a .i file isn't treated the same by the
+ // compiler as a .ii file.
+ hash_delimiter(hash, "ext");
+ hash_string(hash, conf->cpp_extension);
#ifdef _WIN32
- const char *ext = strrchr(args->argv[0], '.');
- char full_path_win_ext[MAX_PATH + 1] = {0};
- add_exe_ext_if_no_to_fullpath(full_path_win_ext, MAX_PATH, ext,
- args->argv[0]);
- const char *full_path = full_path_win_ext;
+ const char* ext = strrchr(args->argv[0], '.');
+ char full_path_win_ext[MAX_PATH + 1] = {0};
+ add_exe_ext_if_no_to_fullpath(
+ full_path_win_ext, MAX_PATH, ext, args->argv[0]);
+ const char* full_path = full_path_win_ext;
#else
- const char *full_path = args->argv[0];
+ const char* full_path = args->argv[0];
#endif
- struct stat st;
- if (x_stat(full_path, &st) != 0) {
- stats_update(STATS_COMPILER);
- failed();
- }
-
- // Hash information about the compiler.
- hash_compiler(hash, &st, args->argv[0], true);
-
- // Also hash the compiler name as some compilers use hard links and behave
- // differently depending on the real name.
- hash_delimiter(hash, "cc_name");
- char *base = x_basename(args->argv[0]);
- hash_string(hash, base);
- free(base);
-
- if (!(conf->sloppiness & SLOPPY_LOCALE)) {
- // Hash environment variables that may affect localization of compiler
- // warning messages.
- const char *envvars[] = {
- "LANG",
- "LC_ALL",
- "LC_CTYPE",
- "LC_MESSAGES",
- NULL
- };
- for (const char **p = envvars; *p; ++p) {
- char *v = getenv(*p);
- if (v) {
- hash_delimiter(hash, *p);
- hash_string(hash, v);
- }
- }
- }
-
- // Possibly hash the current working directory.
- if (generating_debuginfo && conf->hash_dir) {
- char *cwd = gnu_getcwd();
- for (size_t i = 0; i < debug_prefix_maps_len; i++) {
- char *map = debug_prefix_maps[i];
- char *sep = strchr(map, '=');
- if (sep) {
- char *old_path = x_strndup(map, sep - map);
- char* new_path = static_cast<char*>(x_strdup(sep + 1));
- cc_log(
- "Relocating debuginfo CWD %s from %s to %s",
- cwd,
- old_path,
- new_path);
- if (str_startswith(cwd, old_path)) {
- char *dir = format("%s%s", new_path, cwd + strlen(old_path));
- free(cwd);
- cwd = dir;
- }
- free(old_path);
- free(new_path);
- }
- }
- if (cwd) {
- cc_log("Hashing CWD %s", cwd);
- hash_delimiter(hash, "cwd");
- hash_string(hash, cwd);
- free(cwd);
- }
- }
-
- if (seen_split_dwarf) {
- // When using -gsplit-dwarf, object files include a link to the
- // corresponding .dwo file based on the target object filename, so we need
- // to include the target filename in the hash to avoid handing out an
- // object file with an incorrect .dwo link.
- hash_delimiter(hash, "filename");
- hash_string(hash, x_basename(output_obj));
- }
-
- // Possibly hash the coverage data file path.
- if (generating_coverage && profile_arcs) {
- char *dir = x_dirname(output_obj);
- if (profile_dir) {
- dir = x_strdup(profile_dir);
- } else {
- char *real_dir = x_realpath(dir);
- free(dir);
- dir = real_dir;
- }
- if (dir) {
- char *base_name = x_basename(output_obj);
- char *p = remove_extension(base_name);
- free(base_name);
- char *gcda_path = format("%s/%s.gcda", dir, p);
- cc_log("Hashing coverage path %s", gcda_path);
- free(p);
- hash_delimiter(hash, "gcda");
- hash_string(hash, gcda_path);
- free(dir);
- }
- }
-
- // Possibly hash the sanitize blacklist file path.
- for (size_t i = 0; i < sanitize_blacklists_len; i++) {
- char *sanitize_blacklist = sanitize_blacklists[i];
- cc_log("Hashing sanitize blacklist %s", sanitize_blacklist);
- hash_delimiter(hash, "sanitizeblacklist");
- if (!hash_file(hash, sanitize_blacklist)) {
- stats_update(STATS_BADEXTRAFILE);
- failed();
- }
- }
-
- if (!str_eq(conf->extra_files_to_hash, "")) {
- char *p = x_strdup(conf->extra_files_to_hash);
- char *q = p;
- char *path;
- char *saveptr = NULL;
- while ((path = strtok_r(q, PATH_DELIM, &saveptr))) {
- cc_log("Hashing extra file %s", path);
- hash_delimiter(hash, "extrafile");
- if (!hash_file(hash, path)) {
- stats_update(STATS_BADEXTRAFILE);
- failed();
- }
- q = NULL;
- }
- free(p);
- }
-
- // Possibly hash GCC_COLORS (for color diagnostics).
- if (guessed_compiler == GUESSED_GCC) {
- const char *gcc_colors = getenv("GCC_COLORS");
- if (gcc_colors) {
- hash_delimiter(hash, "gcccolors");
- hash_string(hash, gcc_colors);
- }
- }
+ struct stat st;
+ if (x_stat(full_path, &st) != 0) {
+ stats_update(STATS_COMPILER);
+ failed();
+ }
+
+ // Hash information about the compiler.
+ hash_compiler(hash, &st, args->argv[0], true);
+
+ // Also hash the compiler name as some compilers use hard links and behave
+ // differently depending on the real name.
+ hash_delimiter(hash, "cc_name");
+ char* base = x_basename(args->argv[0]);
+ hash_string(hash, base);
+ free(base);
+
+ if (!(conf->sloppiness & SLOPPY_LOCALE)) {
+ // Hash environment variables that may affect localization of compiler
+ // warning messages.
+ const char* envvars[] = {"LANG", "LC_ALL", "LC_CTYPE", "LC_MESSAGES", NULL};
+ for (const char** p = envvars; *p; ++p) {
+ char* v = getenv(*p);
+ if (v) {
+ hash_delimiter(hash, *p);
+ hash_string(hash, v);
+ }
+ }
+ }
+
+ // Possibly hash the current working directory.
+ if (generating_debuginfo && conf->hash_dir) {
+ char* cwd = gnu_getcwd();
+ for (size_t i = 0; i < debug_prefix_maps_len; i++) {
+ char* map = debug_prefix_maps[i];
+ char* sep = strchr(map, '=');
+ if (sep) {
+ char* old_path = x_strndup(map, sep - map);
+ char* new_path = static_cast<char*>(x_strdup(sep + 1));
+ cc_log(
+ "Relocating debuginfo CWD %s from %s to %s", cwd, old_path, new_path);
+ if (str_startswith(cwd, old_path)) {
+ char* dir = format("%s%s", new_path, cwd + strlen(old_path));
+ free(cwd);
+ cwd = dir;
+ }
+ free(old_path);
+ free(new_path);
+ }
+ }
+ if (cwd) {
+ cc_log("Hashing CWD %s", cwd);
+ hash_delimiter(hash, "cwd");
+ hash_string(hash, cwd);
+ free(cwd);
+ }
+ }
+
+ if (seen_split_dwarf) {
+ // When using -gsplit-dwarf, object files include a link to the
+ // corresponding .dwo file based on the target object filename, so we need
+ // to include the target filename in the hash to avoid handing out an
+ // object file with an incorrect .dwo link.
+ hash_delimiter(hash, "filename");
+ hash_string(hash, x_basename(output_obj));
+ }
+
+ // Possibly hash the coverage data file path.
+ if (generating_coverage && profile_arcs) {
+ char* dir = x_dirname(output_obj);
+ if (profile_dir) {
+ dir = x_strdup(profile_dir);
+ } else {
+ char* real_dir = x_realpath(dir);
+ free(dir);
+ dir = real_dir;
+ }
+ if (dir) {
+ char* base_name = x_basename(output_obj);
+ char* p = remove_extension(base_name);
+ free(base_name);
+ char* gcda_path = format("%s/%s.gcda", dir, p);
+ cc_log("Hashing coverage path %s", gcda_path);
+ free(p);
+ hash_delimiter(hash, "gcda");
+ hash_string(hash, gcda_path);
+ free(dir);
+ }
+ }
+
+ // Possibly hash the sanitize blacklist file path.
+ for (size_t i = 0; i < sanitize_blacklists_len; i++) {
+ char* sanitize_blacklist = sanitize_blacklists[i];
+ cc_log("Hashing sanitize blacklist %s", sanitize_blacklist);
+ hash_delimiter(hash, "sanitizeblacklist");
+ if (!hash_file(hash, sanitize_blacklist)) {
+ stats_update(STATS_BADEXTRAFILE);
+ failed();
+ }
+ }
+
+ if (!str_eq(conf->extra_files_to_hash, "")) {
+ char* p = x_strdup(conf->extra_files_to_hash);
+ char* q = p;
+ char* path;
+ char* saveptr = NULL;
+ while ((path = strtok_r(q, PATH_DELIM, &saveptr))) {
+ cc_log("Hashing extra file %s", path);
+ hash_delimiter(hash, "extrafile");
+ if (!hash_file(hash, path)) {
+ stats_update(STATS_BADEXTRAFILE);
+ failed();
+ }
+ q = NULL;
+ }
+ free(p);
+ }
+
+ // Possibly hash GCC_COLORS (for color diagnostics).
+ if (guessed_compiler == GUESSED_GCC) {
+ const char* gcc_colors = getenv("GCC_COLORS");
+ if (gcc_colors) {
+ hash_delimiter(hash, "gcccolors");
+ hash_string(hash, gcc_colors);
+ }
+ }
}
// Update a hash sum with information specific to the direct and preprocessor
// modes and calculate the result name. Returns the result name on success,
// otherwise NULL. Caller frees.
-static struct digest *
-calculate_result_name(struct args *args, struct hash *hash, int direct_mode)
+static struct digest*
+calculate_result_name(struct args* args, struct hash* hash, int direct_mode)
{
- bool found_ccbin = false;
-
- hash_delimiter(hash, "result version");
- hash_int(hash, RESULT_VERSION);
-
- if (direct_mode) {
- hash_delimiter(hash, "manifest version");
- hash_int(hash, MANIFEST_VERSION);
- }
-
- // clang will emit warnings for unused linker flags, so we shouldn't skip
- // those arguments.
- int is_clang =
- guessed_compiler == GUESSED_CLANG || guessed_compiler == GUESSED_UNKNOWN;
-
- // First the arguments.
- for (int i = 1; i < args->argc; i++) {
- // -L doesn't affect compilation (except for clang).
- if (i < args->argc-1 && str_eq(args->argv[i], "-L") && !is_clang) {
- i++;
- continue;
- }
- if (str_startswith(args->argv[i], "-L") && !is_clang) {
- continue;
- }
-
- // -Wl,... doesn't affect compilation (except for clang).
- if (str_startswith(args->argv[i], "-Wl,") && !is_clang) {
- continue;
- }
-
- // The -fdebug-prefix-map option may be used in combination with
- // CCACHE_BASEDIR to reuse results across different directories. Skip using
- // the value of the option from hashing but still hash the existence of the
- // option.
- if (str_startswith(args->argv[i], "-fdebug-prefix-map=")) {
- hash_delimiter(hash, "arg");
- hash_string(hash, "-fdebug-prefix-map=");
- continue;
- }
- if (str_startswith(args->argv[i], "-ffile-prefix-map=")) {
- hash_delimiter(hash, "arg");
- hash_string(hash, "-ffile-prefix-map=");
- continue;
- }
- if (str_startswith(args->argv[i], "-fmacro-prefix-map=")) {
- hash_delimiter(hash, "arg");
- hash_string(hash, "-fmacro-prefix-map=");
- continue;
- }
-
- // When using the preprocessor, some arguments don't contribute to the
- // hash. The theory is that these arguments will change the output of -E if
- // they are going to have any effect at all. For precompiled headers this
- // might not be the case.
- if (!direct_mode && !output_is_precompiled_header
- && !using_precompiled_header) {
- if (compopt_affects_cpp(args->argv[i])) {
- if (compopt_takes_arg(args->argv[i])) {
- i++;
- }
- continue;
- }
- if (compopt_short(compopt_affects_cpp, args->argv[i])) {
- continue;
- }
- }
-
- // If we're generating dependencies, we make sure to skip the filename of
- // the dependency file, since it doesn't impact the output.
- if (generating_dependencies) {
- if (str_startswith(args->argv[i], "-Wp,")) {
- if (str_startswith(args->argv[i], "-Wp,-MD,")
- && !strchr(args->argv[i] + 8, ',')) {
- hash_string_buffer(hash, args->argv[i], 8);
- continue;
- } else if (str_startswith(args->argv[i], "-Wp,-MMD,")
- && !strchr(args->argv[i] + 9, ',')) {
- hash_string_buffer(hash, args->argv[i], 9);
- continue;
- }
- } else if (str_startswith(args->argv[i], "-MF")) {
- // In either case, hash the "-MF" part.
- hash_delimiter(hash, "arg");
- hash_string_buffer(hash, args->argv[i], 3);
-
- if (!str_eq(output_dep, "/dev/null")) {
- bool separate_argument = (strlen(args->argv[i]) == 3);
- if (separate_argument) {
- // Next argument is dependency name, so skip it.
- i++;
- }
- }
- continue;
- }
- }
-
- char *p = NULL;
- if (str_startswith(args->argv[i], "-specs=")) {
- p = args->argv[i] + 7;
- } else if (str_startswith(args->argv[i], "--specs=")) {
- p = args->argv[i] + 8;
- }
-
- struct stat st;
- if (p && x_stat(p, &st) == 0) {
- // If given an explicit specs file, then hash that file, but don't
- // include the path to it in the hash.
- hash_delimiter(hash, "specs");
- hash_compiler(hash, &st, p, false);
- continue;
- }
-
- if (str_startswith(args->argv[i], "-fplugin=")
- && x_stat(args->argv[i] + 9, &st) == 0) {
- hash_delimiter(hash, "plugin");
- hash_compiler(hash, &st, args->argv[i] + 9, false);
- continue;
- }
-
- if (str_eq(args->argv[i], "-Xclang")
- && i + 3 < args->argc
- && str_eq(args->argv[i+1], "-load")
- && str_eq(args->argv[i+2], "-Xclang")
- && x_stat(args->argv[i+3], &st) == 0) {
- hash_delimiter(hash, "plugin");
- hash_compiler(hash, &st, args->argv[i+3], false);
- i += 3;
- continue;
- }
-
- if ((str_eq(args->argv[i], "-ccbin")
- || str_eq(args->argv[i], "--compiler-bindir"))
- && i + 1 < args->argc
- && x_stat(args->argv[i+1], &st) == 0) {
- found_ccbin = true;
- hash_delimiter(hash, "ccbin");
- hash_nvcc_host_compiler(hash, &st, args->argv[i+1]);
- i++;
- continue;
- }
-
- // All other arguments are included in the hash.
- hash_delimiter(hash, "arg");
- hash_string(hash, args->argv[i]);
- if (i + 1 < args->argc && compopt_takes_arg(args->argv[i])) {
- i++;
- hash_delimiter(hash, "arg");
- hash_string(hash, args->argv[i]);
- }
- }
-
- // Make results with dependency file /dev/null different from those without
- // it.
- if (generating_dependencies && str_eq(output_dep, "/dev/null")) {
- hash_delimiter(hash, "/dev/null dependency file");
- }
-
- if (!found_ccbin && str_eq(actual_language, "cu")) {
- hash_nvcc_host_compiler(hash, NULL, NULL);
- }
-
- // For profile generation (-fprofile-arcs, -fprofile-generate):
- // - hash profile directory
- //
- // For profile usage (-fprofile-use):
- // - hash profile data
- //
- // -fbranch-probabilities and -fvpt usage is covered by
- // -fprofile-generate/-fprofile-use.
- //
- // The profile directory can be specified as an argument to
- // -fprofile-generate=, -fprofile-use= or -fprofile-dir=.
- if (profile_generate) {
- if (!profile_dir) {
- profile_dir = get_cwd();
- }
- cc_log("Adding profile directory %s to our hash", profile_dir);
- hash_delimiter(hash, "-fprofile-dir");
- hash_string(hash, profile_dir);
- }
-
- if (profile_use) {
- // Calculate gcda name.
- if (!profile_dir) {
- profile_dir = get_cwd();
- }
- char *base_name = remove_extension(output_obj);
- char *gcda_name = format("%s/%s.gcda", profile_dir, base_name);
- cc_log("Adding profile data %s to our hash", gcda_name);
- // Add the gcda to our hash.
- hash_delimiter(hash, "-fprofile-use");
- hash_file(hash, gcda_name);
- free(base_name);
- free(gcda_name);
- }
-
- // Adding -arch to hash since cpp output is affected.
- for (size_t i = 0; i < arch_args_size; ++i) {
- hash_delimiter(hash, "-arch");
- hash_string(hash, arch_args[i]);
- }
-
- struct digest *result_name = NULL;
- if (direct_mode) {
- // Hash environment variables that affect the preprocessor output.
- const char *envvars[] = {
- "CPATH",
- "C_INCLUDE_PATH",
- "CPLUS_INCLUDE_PATH",
- "OBJC_INCLUDE_PATH",
- "OBJCPLUS_INCLUDE_PATH", // clang
- NULL
- };
- for (const char **p = envvars; *p; ++p) {
- char *v = getenv(*p);
- if (v) {
- hash_delimiter(hash, *p);
- hash_string(hash, v);
- }
- }
-
- if (!(conf->sloppiness & SLOPPY_FILE_MACRO)) {
- // The source code file or an include file may contain __FILE__, so make
- // sure that the hash is unique for the file name.
- hash_delimiter(hash, "inputfile");
- hash_string(hash, input_file);
- }
-
- hash_delimiter(hash, "sourcecode");
- int result = hash_source_code_file(conf, hash, input_file);
- if (result & HASH_SOURCE_CODE_ERROR) {
- failed();
- }
- if (result & HASH_SOURCE_CODE_FOUND_TIME) {
- cc_log("Disabling direct mode");
- conf->direct_mode = false;
- return NULL;
- }
-
- char manifest_name_string[DIGEST_STRING_BUFFER_SIZE];
- hash_result_as_string(hash, manifest_name_string);
- manifest_path = get_path_in_cache(manifest_name_string, ".manifest");
- manifest_stats_file =
- format("%s/%c/stats", conf->cache_dir, manifest_name_string[0]);
-
- cc_log("Looking for result name in %s", manifest_path);
- MTR_BEGIN("manifest", "manifest_get");
- result_name = manifest_get(conf, manifest_path);
- MTR_END("manifest", "manifest_get");
- if (result_name) {
- cc_log("Got result name from manifest");
- } else {
- cc_log("Did not find result name in manifest");
- }
- } else {
- if (arch_args_size == 0) {
- result_name = get_result_name_from_cpp(args, hash);
- cc_log("Got result name from preprocessor");
- } else {
- args_add(args, "-arch");
- for (size_t i = 0; i < arch_args_size; ++i) {
- args_add(args, arch_args[i]);
- result_name = get_result_name_from_cpp(args, hash);
- cc_log("Got result name from preprocessor with -arch %s",
- arch_args[i]);
- if (i != arch_args_size - 1) {
- free(result_name);
- result_name = NULL;
- }
- args_pop(args, 1);
- }
- args_pop(args, 1);
- }
- if (generating_dependencies) {
- // Nothing is actually created with -MF /dev/null
- if (!str_eq(output_dep, "/dev/null")) {
- cc_log("Preprocessor created %s", output_dep);
- }
- }
- }
-
- return result_name;
+ bool found_ccbin = false;
+
+ hash_delimiter(hash, "result version");
+ hash_int(hash, RESULT_VERSION);
+
+ if (direct_mode) {
+ hash_delimiter(hash, "manifest version");
+ hash_int(hash, MANIFEST_VERSION);
+ }
+
+ // clang will emit warnings for unused linker flags, so we shouldn't skip
+ // those arguments.
+ int is_clang =
+ guessed_compiler == GUESSED_CLANG || guessed_compiler == GUESSED_UNKNOWN;
+
+ // First the arguments.
+ for (int i = 1; i < args->argc; i++) {
+ // -L doesn't affect compilation (except for clang).
+ if (i < args->argc - 1 && str_eq(args->argv[i], "-L") && !is_clang) {
+ i++;
+ continue;
+ }
+ if (str_startswith(args->argv[i], "-L") && !is_clang) {
+ continue;
+ }
+
+ // -Wl,... doesn't affect compilation (except for clang).
+ if (str_startswith(args->argv[i], "-Wl,") && !is_clang) {
+ continue;
+ }
+
+ // The -fdebug-prefix-map option may be used in combination with
+ // CCACHE_BASEDIR to reuse results across different directories. Skip using
+ // the value of the option from hashing but still hash the existence of the
+ // option.
+ if (str_startswith(args->argv[i], "-fdebug-prefix-map=")) {
+ hash_delimiter(hash, "arg");
+ hash_string(hash, "-fdebug-prefix-map=");
+ continue;
+ }
+ if (str_startswith(args->argv[i], "-ffile-prefix-map=")) {
+ hash_delimiter(hash, "arg");
+ hash_string(hash, "-ffile-prefix-map=");
+ continue;
+ }
+ if (str_startswith(args->argv[i], "-fmacro-prefix-map=")) {
+ hash_delimiter(hash, "arg");
+ hash_string(hash, "-fmacro-prefix-map=");
+ continue;
+ }
+
+ // When using the preprocessor, some arguments don't contribute to the
+ // hash. The theory is that these arguments will change the output of -E if
+ // they are going to have any effect at all. For precompiled headers this
+ // might not be the case.
+ if (!direct_mode && !output_is_precompiled_header
+ && !using_precompiled_header) {
+ if (compopt_affects_cpp(args->argv[i])) {
+ if (compopt_takes_arg(args->argv[i])) {
+ i++;
+ }
+ continue;
+ }
+ if (compopt_short(compopt_affects_cpp, args->argv[i])) {
+ continue;
+ }
+ }
+
+ // If we're generating dependencies, we make sure to skip the filename of
+ // the dependency file, since it doesn't impact the output.
+ if (generating_dependencies) {
+ if (str_startswith(args->argv[i], "-Wp,")) {
+ if (str_startswith(args->argv[i], "-Wp,-MD,")
+ && !strchr(args->argv[i] + 8, ',')) {
+ hash_string_buffer(hash, args->argv[i], 8);
+ continue;
+ } else if (str_startswith(args->argv[i], "-Wp,-MMD,")
+ && !strchr(args->argv[i] + 9, ',')) {
+ hash_string_buffer(hash, args->argv[i], 9);
+ continue;
+ }
+ } else if (str_startswith(args->argv[i], "-MF")) {
+ // In either case, hash the "-MF" part.
+ hash_delimiter(hash, "arg");
+ hash_string_buffer(hash, args->argv[i], 3);
+
+ if (!str_eq(output_dep, "/dev/null")) {
+ bool separate_argument = (strlen(args->argv[i]) == 3);
+ if (separate_argument) {
+ // Next argument is dependency name, so skip it.
+ i++;
+ }
+ }
+ continue;
+ }
+ }
+
+ char* p = NULL;
+ if (str_startswith(args->argv[i], "-specs=")) {
+ p = args->argv[i] + 7;
+ } else if (str_startswith(args->argv[i], "--specs=")) {
+ p = args->argv[i] + 8;
+ }
+
+ struct stat st;
+ if (p && x_stat(p, &st) == 0) {
+ // If given an explicit specs file, then hash that file, but don't
+ // include the path to it in the hash.
+ hash_delimiter(hash, "specs");
+ hash_compiler(hash, &st, p, false);
+ continue;
+ }
+
+ if (str_startswith(args->argv[i], "-fplugin=")
+ && x_stat(args->argv[i] + 9, &st) == 0) {
+ hash_delimiter(hash, "plugin");
+ hash_compiler(hash, &st, args->argv[i] + 9, false);
+ continue;
+ }
+
+ if (str_eq(args->argv[i], "-Xclang") && i + 3 < args->argc
+ && str_eq(args->argv[i + 1], "-load")
+ && str_eq(args->argv[i + 2], "-Xclang")
+ && x_stat(args->argv[i + 3], &st) == 0) {
+ hash_delimiter(hash, "plugin");
+ hash_compiler(hash, &st, args->argv[i + 3], false);
+ i += 3;
+ continue;
+ }
+
+ if ((str_eq(args->argv[i], "-ccbin")
+ || str_eq(args->argv[i], "--compiler-bindir"))
+ && i + 1 < args->argc && x_stat(args->argv[i + 1], &st) == 0) {
+ found_ccbin = true;
+ hash_delimiter(hash, "ccbin");
+ hash_nvcc_host_compiler(hash, &st, args->argv[i + 1]);
+ i++;
+ continue;
+ }
+
+ // All other arguments are included in the hash.
+ hash_delimiter(hash, "arg");
+ hash_string(hash, args->argv[i]);
+ if (i + 1 < args->argc && compopt_takes_arg(args->argv[i])) {
+ i++;
+ hash_delimiter(hash, "arg");
+ hash_string(hash, args->argv[i]);
+ }
+ }
+
+ // Make results with dependency file /dev/null different from those without
+ // it.
+ if (generating_dependencies && str_eq(output_dep, "/dev/null")) {
+ hash_delimiter(hash, "/dev/null dependency file");
+ }
+
+ if (!found_ccbin && str_eq(actual_language, "cu")) {
+ hash_nvcc_host_compiler(hash, NULL, NULL);
+ }
+
+ // For profile generation (-fprofile-arcs, -fprofile-generate):
+ // - hash profile directory
+ //
+ // For profile usage (-fprofile-use):
+ // - hash profile data
+ //
+ // -fbranch-probabilities and -fvpt usage is covered by
+ // -fprofile-generate/-fprofile-use.
+ //
+ // The profile directory can be specified as an argument to
+ // -fprofile-generate=, -fprofile-use= or -fprofile-dir=.
+ if (profile_generate) {
+ if (!profile_dir) {
+ profile_dir = get_cwd();
+ }
+ cc_log("Adding profile directory %s to our hash", profile_dir);
+ hash_delimiter(hash, "-fprofile-dir");
+ hash_string(hash, profile_dir);
+ }
+
+ if (profile_use) {
+ // Calculate gcda name.
+ if (!profile_dir) {
+ profile_dir = get_cwd();
+ }
+ char* base_name = remove_extension(output_obj);
+ char* gcda_name = format("%s/%s.gcda", profile_dir, base_name);
+ cc_log("Adding profile data %s to our hash", gcda_name);
+ // Add the gcda to our hash.
+ hash_delimiter(hash, "-fprofile-use");
+ hash_file(hash, gcda_name);
+ free(base_name);
+ free(gcda_name);
+ }
+
+ // Adding -arch to hash since cpp output is affected.
+ for (size_t i = 0; i < arch_args_size; ++i) {
+ hash_delimiter(hash, "-arch");
+ hash_string(hash, arch_args[i]);
+ }
+
+ struct digest* result_name = NULL;
+ if (direct_mode) {
+ // Hash environment variables that affect the preprocessor output.
+ const char* envvars[] = {"CPATH",
+ "C_INCLUDE_PATH",
+ "CPLUS_INCLUDE_PATH",
+ "OBJC_INCLUDE_PATH",
+ "OBJCPLUS_INCLUDE_PATH", // clang
+ NULL};
+ for (const char** p = envvars; *p; ++p) {
+ char* v = getenv(*p);
+ if (v) {
+ hash_delimiter(hash, *p);
+ hash_string(hash, v);
+ }
+ }
+
+ if (!(conf->sloppiness & SLOPPY_FILE_MACRO)) {
+ // The source code file or an include file may contain __FILE__, so make
+ // sure that the hash is unique for the file name.
+ hash_delimiter(hash, "inputfile");
+ hash_string(hash, input_file);
+ }
+
+ hash_delimiter(hash, "sourcecode");
+ int result = hash_source_code_file(conf, hash, input_file);
+ if (result & HASH_SOURCE_CODE_ERROR) {
+ failed();
+ }
+ if (result & HASH_SOURCE_CODE_FOUND_TIME) {
+ cc_log("Disabling direct mode");
+ conf->direct_mode = false;
+ return NULL;
+ }
+
+ char manifest_name_string[DIGEST_STRING_BUFFER_SIZE];
+ hash_result_as_string(hash, manifest_name_string);
+ manifest_path = get_path_in_cache(manifest_name_string, ".manifest");
+ manifest_stats_file =
+ format("%s/%c/stats", conf->cache_dir, manifest_name_string[0]);
+
+ cc_log("Looking for result name in %s", manifest_path);
+ MTR_BEGIN("manifest", "manifest_get");
+ result_name = manifest_get(conf, manifest_path);
+ MTR_END("manifest", "manifest_get");
+ if (result_name) {
+ cc_log("Got result name from manifest");
+ } else {
+ cc_log("Did not find result name in manifest");
+ }
+ } else {
+ if (arch_args_size == 0) {
+ result_name = get_result_name_from_cpp(args, hash);
+ cc_log("Got result name from preprocessor");
+ } else {
+ args_add(args, "-arch");
+ for (size_t i = 0; i < arch_args_size; ++i) {
+ args_add(args, arch_args[i]);
+ result_name = get_result_name_from_cpp(args, hash);
+ cc_log("Got result name from preprocessor with -arch %s", arch_args[i]);
+ if (i != arch_args_size - 1) {
+ free(result_name);
+ result_name = NULL;
+ }
+ args_pop(args, 1);
+ }
+ args_pop(args, 1);
+ }
+ if (generating_dependencies) {
+ // Nothing is actually created with -MF /dev/null
+ if (!str_eq(output_dep, "/dev/null")) {
+ cc_log("Preprocessor created %s", output_dep);
+ }
+ }
+ }
+
+ return result_name;
}
// Try to return the compile result from cache. If we can return from cache
@@ -2103,1392 +2116,1383 @@ calculate_result_name(struct args *args, struct hash *hash, int direct_mode)
static void
from_cache(enum fromcache_call_mode mode, bool put_result_in_manifest)
{
- // The user might be disabling cache hits.
- if (conf->recache) {
- return;
- }
-
- // If we're using Clang, we can't trust a precompiled header object based on
- // running the preprocessor since clang will produce a fatal error when the
- // precompiled header is used and one of the included files has an updated
- // timestamp:
- //
- // file 'foo.h' has been modified since the precompiled header 'foo.pch'
- // was built
- if ((guessed_compiler == GUESSED_CLANG || guessed_compiler == GUESSED_UNKNOWN)
- && output_is_precompiled_header
- && mode == FROMCACHE_CPP_MODE) {
- cc_log("Not considering cached precompiled header in preprocessor mode");
- return;
- }
-
- MTR_BEGIN("cache", "from_cache");
-
- // (If mode != FROMCACHE_DIRECT_MODE, the dependency file is created by gcc.)
- bool produce_dep_file =
- generating_dependencies && mode == FROMCACHE_DIRECT_MODE
- && !str_eq(output_dep, "/dev/null");
-
- MTR_BEGIN("file", "file_get");
-
- // Get result from cache.
- char *tmp_stderr = format("%s/tmp.stderr", temp_dir());
- int tmp_stderr_fd = create_tmp_fd(&tmp_stderr);
- close(tmp_stderr_fd);
-
- struct result_files *result_files = result_files_init();
- if (!str_eq(output_obj, "/dev/null")) {
- result_files_add(result_files, output_obj, ".o");
- if (seen_split_dwarf) {
- result_files_add(result_files, output_dwo, ".dwo");
- }
- }
- result_files_add(result_files, tmp_stderr, RESULT_STDERR_NAME);
- if (produce_dep_file) {
- result_files_add(result_files, output_dep, ".d");
- }
- if (generating_coverage) {
- result_files_add(result_files, output_cov, ".gcno");
- }
- if (generating_stackusage) {
- result_files_add(result_files, output_su, ".su");
- }
- if (generating_diagnostics) {
- result_files_add(result_files, output_dia, ".dia");
- }
- bool ok = result_get(cached_result_path, result_files);
- result_files_free(result_files);
- if (!ok) {
- cc_log("Failed to get result from cache");
- tmp_unlink(tmp_stderr);
- free(tmp_stderr);
- return;
- }
-
- MTR_END("file", "file_get");
-
- send_cached_stderr(tmp_stderr);
-
- if (put_result_in_manifest) {
- update_manifest_file();
- }
-
- tmp_unlink(tmp_stderr);
- free(tmp_stderr);
-
- // Log the cache hit.
- switch (mode) {
- case FROMCACHE_DIRECT_MODE:
- cc_log("Succeeded getting cached result");
- stats_update(STATS_CACHEHIT_DIR);
- break;
-
- case FROMCACHE_CPP_MODE:
- cc_log("Succeeded getting cached result");
- stats_update(STATS_CACHEHIT_CPP);
- break;
- }
-
- MTR_END("cache", "from_cache");
-
- // And exit with the right status code.
- x_exit(0);
+ // The user might be disabling cache hits.
+ if (conf->recache) {
+ return;
+ }
+
+ // If we're using Clang, we can't trust a precompiled header object based on
+ // running the preprocessor since clang will produce a fatal error when the
+ // precompiled header is used and one of the included files has an updated
+ // timestamp:
+ //
+ // file 'foo.h' has been modified since the precompiled header 'foo.pch'
+ // was built
+ if ((guessed_compiler == GUESSED_CLANG || guessed_compiler == GUESSED_UNKNOWN)
+ && output_is_precompiled_header && mode == FROMCACHE_CPP_MODE) {
+ cc_log("Not considering cached precompiled header in preprocessor mode");
+ return;
+ }
+
+ MTR_BEGIN("cache", "from_cache");
+
+ // (If mode != FROMCACHE_DIRECT_MODE, the dependency file is created by gcc.)
+ bool produce_dep_file = generating_dependencies
+ && mode == FROMCACHE_DIRECT_MODE
+ && !str_eq(output_dep, "/dev/null");
+
+ MTR_BEGIN("file", "file_get");
+
+ // Get result from cache.
+ char* tmp_stderr = format("%s/tmp.stderr", temp_dir());
+ int tmp_stderr_fd = create_tmp_fd(&tmp_stderr);
+ close(tmp_stderr_fd);
+
+ struct result_files* result_files = result_files_init();
+ if (!str_eq(output_obj, "/dev/null")) {
+ result_files_add(result_files, output_obj, ".o");
+ if (seen_split_dwarf) {
+ result_files_add(result_files, output_dwo, ".dwo");
+ }
+ }
+ result_files_add(result_files, tmp_stderr, RESULT_STDERR_NAME);
+ if (produce_dep_file) {
+ result_files_add(result_files, output_dep, ".d");
+ }
+ if (generating_coverage) {
+ result_files_add(result_files, output_cov, ".gcno");
+ }
+ if (generating_stackusage) {
+ result_files_add(result_files, output_su, ".su");
+ }
+ if (generating_diagnostics) {
+ result_files_add(result_files, output_dia, ".dia");
+ }
+ bool ok = result_get(cached_result_path, result_files);
+ result_files_free(result_files);
+ if (!ok) {
+ cc_log("Failed to get result from cache");
+ tmp_unlink(tmp_stderr);
+ free(tmp_stderr);
+ return;
+ }
+
+ MTR_END("file", "file_get");
+
+ send_cached_stderr(tmp_stderr);
+
+ if (put_result_in_manifest) {
+ update_manifest_file();
+ }
+
+ tmp_unlink(tmp_stderr);
+ free(tmp_stderr);
+
+ // Log the cache hit.
+ switch (mode) {
+ case FROMCACHE_DIRECT_MODE:
+ cc_log("Succeeded getting cached result");
+ stats_update(STATS_CACHEHIT_DIR);
+ break;
+
+ case FROMCACHE_CPP_MODE:
+ cc_log("Succeeded getting cached result");
+ stats_update(STATS_CACHEHIT_CPP);
+ break;
+ }
+
+ MTR_END("cache", "from_cache");
+
+ // And exit with the right status code.
+ x_exit(0);
}
// Find the real compiler. We just search the PATH to find an executable of the
// same name that isn't a link to ourselves.
static void
-find_compiler(char **argv)
+find_compiler(char** argv)
{
- // We might be being invoked like "ccache gcc -c foo.c".
- char *base = x_basename(argv[0]);
- if (same_executable_name(base, MYNAME)) {
- args_remove_first(orig_args);
- free(base);
- if (is_full_path(orig_args->argv[0])) {
- // A full path was given.
- return;
- }
- base = x_basename(orig_args->argv[0]);
- }
-
- // Support user override of the compiler.
- if (!str_eq(conf->compiler, "")) {
- base = conf->compiler;
- }
-
- char *compiler = find_executable(base, MYNAME);
- if (!compiler) {
- stats_update(STATS_COMPILER);
- fatal("Could not find compiler \"%s\" in PATH", base);
- }
- if (str_eq(compiler, argv[0])) {
- fatal("Recursive invocation (the name of the ccache binary must be \"%s\")",
- MYNAME);
- }
- orig_args->argv[0] = compiler;
+ // We might be being invoked like "ccache gcc -c foo.c".
+ char* base = x_basename(argv[0]);
+ if (same_executable_name(base, MYNAME)) {
+ args_remove_first(orig_args);
+ free(base);
+ if (is_full_path(orig_args->argv[0])) {
+ // A full path was given.
+ return;
+ }
+ base = x_basename(orig_args->argv[0]);
+ }
+
+ // Support user override of the compiler.
+ if (!str_eq(conf->compiler, "")) {
+ base = conf->compiler;
+ }
+
+ char* compiler = find_executable(base, MYNAME);
+ if (!compiler) {
+ stats_update(STATS_COMPILER);
+ fatal("Could not find compiler \"%s\" in PATH", base);
+ }
+ if (str_eq(compiler, argv[0])) {
+ fatal("Recursive invocation (the name of the ccache binary must be \"%s\")",
+ MYNAME);
+ }
+ orig_args->argv[0] = compiler;
}
bool
-is_precompiled_header(const char *path)
+is_precompiled_header(const char* path)
{
- const char *ext = get_extension(path);
- char *dir = x_dirname(path);
- const char *dir_ext = get_extension(dir);
- bool result =
- str_eq(ext, ".gch")
- || str_eq(ext, ".pch")
- || str_eq(ext, ".pth")
- || str_eq(dir_ext, ".gch"); // See "Precompiled Headers" in GCC docs.
- free(dir);
- return result;
+ const char* ext = get_extension(path);
+ char* dir = x_dirname(path);
+ const char* dir_ext = get_extension(dir);
+ bool result =
+ str_eq(ext, ".gch") || str_eq(ext, ".pch") || str_eq(ext, ".pth")
+ || str_eq(dir_ext, ".gch"); // See "Precompiled Headers" in GCC docs.
+ free(dir);
+ return result;
}
static bool
color_output_possible(void)
{
- const char *term_env = getenv("TERM");
- return isatty(STDERR_FILENO) && term_env && strcasecmp(term_env, "DUMB") != 0;
+ const char* term_env = getenv("TERM");
+ return isatty(STDERR_FILENO) && term_env && strcasecmp(term_env, "DUMB") != 0;
}
static bool
-detect_pch(const char *option, const char *arg, bool *found_pch)
+detect_pch(const char* option, const char* arg, bool* found_pch)
{
- struct stat st;
-
- // Try to be smart about detecting precompiled headers.
- char *pch_file = NULL;
- if (str_eq(option, "-include-pch") || str_eq(option, "-include-pth")) {
- if (stat(arg, &st) == 0) {
- cc_log("Detected use of precompiled header: %s", arg);
- pch_file = x_strdup(arg);
- }
- } else {
- char *gchpath = format("%s.gch", arg);
- if (stat(gchpath, &st) == 0) {
- cc_log("Detected use of precompiled header: %s", gchpath);
- pch_file = x_strdup(gchpath);
- } else {
- char *pchpath = format("%s.pch", arg);
- if (stat(pchpath, &st) == 0) {
- cc_log("Detected use of precompiled header: %s", pchpath);
- pch_file = x_strdup(pchpath);
- } else {
- // clang may use pretokenized headers.
- char *pthpath = format("%s.pth", arg);
- if (stat(pthpath, &st) == 0) {
- cc_log("Detected use of pretokenized header: %s", pthpath);
- pch_file = x_strdup(pthpath);
- }
- free(pthpath);
- }
- free(pchpath);
- }
- free(gchpath);
- }
-
- if (pch_file) {
- if (included_pch_file) {
- cc_log("Multiple precompiled headers used: %s and %s\n",
- included_pch_file, pch_file);
- stats_update(STATS_ARGS);
- return false;
- }
- included_pch_file = pch_file;
- *found_pch = true;
- }
- return true;
+ struct stat st;
+
+ // Try to be smart about detecting precompiled headers.
+ char* pch_file = NULL;
+ if (str_eq(option, "-include-pch") || str_eq(option, "-include-pth")) {
+ if (stat(arg, &st) == 0) {
+ cc_log("Detected use of precompiled header: %s", arg);
+ pch_file = x_strdup(arg);
+ }
+ } else {
+ char* gchpath = format("%s.gch", arg);
+ if (stat(gchpath, &st) == 0) {
+ cc_log("Detected use of precompiled header: %s", gchpath);
+ pch_file = x_strdup(gchpath);
+ } else {
+ char* pchpath = format("%s.pch", arg);
+ if (stat(pchpath, &st) == 0) {
+ cc_log("Detected use of precompiled header: %s", pchpath);
+ pch_file = x_strdup(pchpath);
+ } else {
+ // clang may use pretokenized headers.
+ char* pthpath = format("%s.pth", arg);
+ if (stat(pthpath, &st) == 0) {
+ cc_log("Detected use of pretokenized header: %s", pthpath);
+ pch_file = x_strdup(pthpath);
+ }
+ free(pthpath);
+ }
+ free(pchpath);
+ }
+ free(gchpath);
+ }
+
+ if (pch_file) {
+ if (included_pch_file) {
+ cc_log("Multiple precompiled headers used: %s and %s\n",
+ included_pch_file,
+ pch_file);
+ stats_update(STATS_ARGS);
+ return false;
+ }
+ included_pch_file = pch_file;
+ *found_pch = true;
+ }
+ return true;
}
// Process the compiler options into options suitable for passing to the
// preprocessor and the real compiler. The preprocessor options don't include
// -E; this is added later. Returns true on success, otherwise false.
bool
-cc_process_args(struct args *args, struct args **preprocessor_args,
- struct args **compiler_args)
+cc_process_args(struct args* args,
+ struct args** preprocessor_args,
+ struct args** compiler_args)
{
- bool found_c_opt = false;
- bool found_dc_opt = false;
- bool found_S_opt = false;
- bool found_pch = false;
- bool found_fpch_preprocess = false;
- const char *explicit_language = NULL; // As specified with -x.
- const char *file_language; // As deduced from file extension.
- const char *input_charset = NULL;
-
- // Is the dependency makefile name overridden with -MF?
- bool dependency_filename_specified = false;
-
- // Is the dependency makefile target name specified with -MT or -MQ?
- bool dependency_target_specified = false;
-
- // Is the dependency target name implicitly specified using
- // DEPENDENCIES_OUTPUT or SUNPRO_DEPENDENCIES?
- bool dependency_implicit_target_specified = false;
-
- // expanded_args is a copy of the original arguments given to the compiler
- // but with arguments from @file and similar constructs expanded. It's only
- // used as a temporary data structure to loop over.
- struct args *expanded_args = args_copy(args);
-
- // common_args contains all original arguments except:
- // * those that never should be passed to the preprocessor,
- // * those that only should be passed to the preprocessor (if run_second_cpp
- // is false), and
- // * dependency options (like -MD and friends).
- struct args *common_args = args_init(0, NULL);
-
- // cpp_args contains arguments that were not added to common_args, i.e. those
- // that should only be passed to the preprocessor if run_second_cpp is false.
- // If run_second_cpp is true, they will be passed to the compiler as well.
- struct args *cpp_args = args_init(0, NULL);
-
- // dep_args contains dependency options like -MD. They are only passed to the
- // preprocessor, never to the compiler.
- struct args *dep_args = args_init(0, NULL);
-
- // compiler_only_args contains arguments that should only be passed to the
- // compiler, not the preprocessor.
- struct args *compiler_only_args = args_init(0, NULL);
-
- bool found_color_diagnostics = false;
- bool found_directives_only = false;
- bool found_rewrite_includes = false;
-
- int argc = expanded_args->argc;
- char **argv = expanded_args->argv;
- args_add(common_args, argv[0]);
-
- bool result = true;
- for (int i = 1; i < argc; i++) {
- // The user knows best: just swallow the next arg.
- if (str_eq(argv[i], "--ccache-skip")) {
- i++;
- if (i == argc) {
- cc_log("--ccache-skip lacks an argument");
- result = false;
- goto out;
- }
- args_add(common_args, argv[i]);
- continue;
- }
-
- // Special case for -E.
- if (str_eq(argv[i], "-E")) {
- stats_update(STATS_PREPROCESSING);
- result = false;
- goto out;
- }
-
- // Handle "@file" argument.
- if (str_startswith(argv[i], "@") || str_startswith(argv[i], "-@")) {
- char *argpath = argv[i] + 1;
-
- if (argpath[-1] == '-') {
- ++argpath;
- }
- struct args *file_args = args_init_from_gcc_atfile(argpath);
- if (!file_args) {
- cc_log("Couldn't read arg file %s", argpath);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
-
- args_insert(expanded_args, i, file_args, true);
- argc = expanded_args->argc;
- argv = expanded_args->argv;
- i--;
- continue;
- }
-
- // Handle cuda "-optf" and "--options-file" argument.
- if (guessed_compiler == GUESSED_NVCC
- && (str_eq(argv[i], "-optf") || str_eq(argv[i], "--options-file"))) {
- if (i == argc - 1) {
- cc_log("Expected argument after %s", argv[i]);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
- ++i;
-
- // Argument is a comma-separated list of files.
- char *str_start = argv[i];
- char *str_end = strchr(str_start, ',');
- int index = i + 1;
-
- if (!str_end) {
- str_end = str_start + strlen(str_start);
- }
-
- while (str_end) {
- *str_end = '\0';
- struct args *file_args = args_init_from_gcc_atfile(str_start);
- if (!file_args) {
- cc_log("Couldn't read cuda options file %s", str_start);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
-
- int new_index = file_args->argc + index;
- args_insert(expanded_args, index, file_args, false);
- index = new_index;
- str_start = str_end;
- str_end = strchr(str_start, ',');
- }
-
- argc = expanded_args->argc;
- argv = expanded_args->argv;
- continue;
- }
-
- // These are always too hard.
- if (compopt_too_hard(argv[i]) || str_startswith(argv[i], "-fdump-")) {
- cc_log("Compiler option %s is unsupported", argv[i]);
- stats_update(STATS_UNSUPPORTED_OPTION);
- result = false;
- goto out;
- }
-
- // These are too hard in direct mode.
- if (conf->direct_mode && compopt_too_hard_for_direct_mode(argv[i])) {
- cc_log("Unsupported compiler option for direct mode: %s", argv[i]);
- conf->direct_mode = false;
- }
-
- // -Xarch_* options are too hard.
- if (str_startswith(argv[i], "-Xarch_")) {
- cc_log("Unsupported compiler option :%s", argv[i]);
- stats_update(STATS_UNSUPPORTED_OPTION);
- result = false;
- goto out;
- }
-
- // Handle -arch options.
- if (str_eq(argv[i], "-arch")) {
- if (arch_args_size == MAX_ARCH_ARGS - 1) {
- cc_log("Too many -arch compiler options; ccache supports at most %d",
- MAX_ARCH_ARGS);
- stats_update(STATS_UNSUPPORTED_OPTION);
- result = false;
- goto out;
- }
-
- ++i;
- arch_args[arch_args_size] = x_strdup(argv[i]); // It will leak.
- ++arch_args_size;
- if (arch_args_size == 2) {
- conf->run_second_cpp = true;
- }
- continue;
- }
-
- // Handle options that should not be passed to the preprocessor.
- if (compopt_affects_comp(argv[i])) {
- args_add(compiler_only_args, argv[i]);
- if (compopt_takes_arg(argv[i])) {
- if (i == argc - 1) {
- cc_log("Missing argument to %s", argv[i]);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
- args_add(compiler_only_args, argv[i + 1]);
- ++i;
- }
- continue;
- }
- if (compopt_prefix_affects_comp(argv[i])) {
- args_add(compiler_only_args, argv[i]);
- continue;
- }
-
- if (str_eq(argv[i], "-fpch-preprocess")
- || str_eq(argv[i], "-emit-pch")
- || str_eq(argv[i], "-emit-pth")) {
- found_fpch_preprocess = true;
- }
-
- // We must have -c.
- if (str_eq(argv[i], "-c")) {
- found_c_opt = true;
- continue;
- }
-
- // when using nvcc with separable compilation, -dc implies -c
- if ((str_eq(argv[i], "-dc") || str_eq(argv[i], "--device-c")) && guessed_compiler == GUESSED_NVCC) {
- found_dc_opt = true;
- continue;
- }
-
- // -S changes the default extension.
- if (str_eq(argv[i], "-S")) {
- args_add(common_args, argv[i]);
- found_S_opt = true;
- continue;
- }
-
- // Special handling for -x: remember the last specified language before the
- // input file and strip all -x options from the arguments.
- if (str_eq(argv[i], "-x")) {
- if (i == argc - 1) {
- cc_log("Missing argument to %s", argv[i]);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
- if (!input_file) {
- explicit_language = argv[i+1];
- }
- i++;
- continue;
- }
- if (str_startswith(argv[i], "-x")) {
- if (!input_file) {
- explicit_language = &argv[i][2];
- }
- continue;
- }
-
- // We need to work out where the output was meant to go.
- if (str_eq(argv[i], "-o")) {
- if (i == argc - 1) {
- cc_log("Missing argument to %s", argv[i]);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
- output_obj = make_relative_path(x_strdup(argv[i+1]));
- i++;
- continue;
- }
-
- // Alternate form of -o with no space. Nvcc does not support this.
- if (str_startswith(argv[i], "-o") && guessed_compiler != GUESSED_NVCC) {
- output_obj = make_relative_path(x_strdup(&argv[i][2]));
- continue;
- }
-
- if (str_startswith(argv[i], "-fdebug-prefix-map=")
- || str_startswith(argv[i], "-ffile-prefix-map=")) {
- debug_prefix_maps = static_cast<char**>(
- x_realloc(
- debug_prefix_maps,
- (debug_prefix_maps_len + 1) * sizeof(char *)));
- debug_prefix_maps[debug_prefix_maps_len++] =
- x_strdup(&argv[i][argv[i][2] == 'f' ? 18 : 19]);
- args_add(common_args, argv[i]);
- continue;
- }
-
- // Debugging is handled specially, so that we know if we can strip line
- // number info.
- if (str_startswith(argv[i], "-g")) {
- args_add(common_args, argv[i]);
-
- if (str_startswith(argv[i], "-gdwarf")) {
- // Selection of DWARF format (-gdwarf or -gdwarf-<version>) enables
- // debug info on level 2.
- generating_debuginfo = true;
- continue;
- }
-
- char last_char = argv[i][strlen(argv[i]) - 1];
- if (last_char == '0') {
- // "-g0", "-ggdb0" or similar: All debug information disabled.
- generating_debuginfo = false;
- generating_debuginfo_level_3 = false;
- } else {
- generating_debuginfo = true;
- if (last_char == '3') {
- generating_debuginfo_level_3 = true;
- }
- if (str_eq(argv[i], "-gsplit-dwarf")) {
- seen_split_dwarf = true;
- }
- }
- continue;
- }
-
- // These options require special handling, because they behave differently
- // with gcc -E, when the output file is not specified.
- if (str_eq(argv[i], "-MD") || str_eq(argv[i], "-MMD")) {
- generating_dependencies = true;
- args_add(dep_args, argv[i]);
- continue;
- }
- if (str_startswith(argv[i], "-MF")) {
- dependency_filename_specified = true;
- free(output_dep);
-
- char *arg;
- bool separate_argument = (strlen(argv[i]) == 3);
- if (separate_argument) {
- // -MF arg
- if (i == argc - 1) {
- cc_log("Missing argument to %s", argv[i]);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
- arg = argv[i + 1];
- i++;
- } else {
- // -MFarg
- arg = &argv[i][3];
- }
- output_dep = make_relative_path(x_strdup(arg));
- // Keep the format of the args the same.
- if (separate_argument) {
- args_add(dep_args, "-MF");
- args_add(dep_args, output_dep);
- } else {
- char *option = format("-MF%s", output_dep);
- args_add(dep_args, option);
- free(option);
- }
- continue;
- }
- if (str_startswith(argv[i], "-MQ") || str_startswith(argv[i], "-MT")) {
- dependency_target_specified = true;
-
- char *relpath;
- if (strlen(argv[i]) == 3) {
- // -MQ arg or -MT arg
- if (i == argc - 1) {
- cc_log("Missing argument to %s", argv[i]);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
- args_add(dep_args, argv[i]);
- relpath = make_relative_path(x_strdup(argv[i + 1]));
- args_add(dep_args, relpath);
- free(relpath);
- i++;
- } else {
- char *arg_opt = x_strndup(argv[i], 3);
- relpath = make_relative_path(x_strdup(argv[i] + 3));
- char *option = format("%s%s", arg_opt, relpath);
- args_add(dep_args, option);
- free(arg_opt);
- free(relpath);
- free(option);
- }
- continue;
- }
- if (str_eq(argv[i], "-fprofile-arcs")) {
- profile_arcs = true;
- args_add(common_args, argv[i]);
- continue;
- }
- if (str_eq(argv[i], "-ftest-coverage")) {
- generating_coverage = true;
- args_add(common_args, argv[i]);
- continue;
- }
- if (str_eq(argv[i], "-fstack-usage")) {
- generating_stackusage = true;
- args_add(common_args, argv[i]);
- continue;
- }
- if (str_eq(argv[i], "--coverage") // = -fprofile-arcs -ftest-coverage
- || str_eq(argv[i], "-coverage")) { // Undocumented but still works.
- profile_arcs = true;
- generating_coverage = true;
- args_add(common_args, argv[i]);
- continue;
- }
- if (str_startswith(argv[i], "-fprofile-dir=")) {
- profile_dir = x_strdup(argv[i] + 14);
- args_add(common_args, argv[i]);
- continue;
- }
- if (str_startswith(argv[i], "-fsanitize-blacklist=")) {
- sanitize_blacklists = static_cast<char**>(
- x_realloc(
- sanitize_blacklists,
- (sanitize_blacklists_len + 1) * sizeof(char *)));
- sanitize_blacklists[sanitize_blacklists_len++] = x_strdup(argv[i] + 21);
- args_add(common_args, argv[i]);
- continue;
- }
- if (str_startswith(argv[i], "--sysroot=")) {
- char *relpath = make_relative_path(x_strdup(argv[i] + 10));
- char *option = format("--sysroot=%s", relpath);
- args_add(common_args, option);
- free(relpath);
- free(option);
- continue;
- }
- // Alternate form of specifying sysroot without =
- if (str_eq(argv[i], "--sysroot")) {
- if (i == argc-1) {
- cc_log("Missing argument to %s", argv[i]);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
- args_add(common_args, argv[i]);
- char *relpath = make_relative_path(x_strdup(argv[i+1]));
- args_add(common_args, relpath);
- i++;
- free(relpath);
- continue;
- }
- // Alternate form of specifying target without =
- if (str_eq(argv[i], "-target")) {
- if (i == argc-1) {
- cc_log("Missing argument to %s", argv[i]);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
- args_add(common_args, argv[i]);
- args_add(common_args, argv[i+1]);
- i++;
- continue;
- }
- if (str_startswith(argv[i], "-Wp,")) {
- if (str_eq(argv[i], "-Wp,-P")
- || strstr(argv[i], ",-P,")
- || str_endswith(argv[i], ",-P")) {
- // -P removes preprocessor information in such a way that the object
- // file from compiling the preprocessed file will not be equal to the
- // object file produced when compiling without ccache.
- cc_log("Too hard option -Wp,-P detected");
- stats_update(STATS_UNSUPPORTED_OPTION);
- failed();
- } else if (str_startswith(argv[i], "-Wp,-MD,")
- && !strchr(argv[i] + 8, ',')) {
- generating_dependencies = true;
- dependency_filename_specified = true;
- free(output_dep);
- output_dep = make_relative_path(x_strdup(argv[i] + 8));
- args_add(dep_args, argv[i]);
- continue;
- } else if (str_startswith(argv[i], "-Wp,-MMD,")
- && !strchr(argv[i] + 9, ',')) {
- generating_dependencies = true;
- dependency_filename_specified = true;
- free(output_dep);
- output_dep = make_relative_path(x_strdup(argv[i] + 9));
- args_add(dep_args, argv[i]);
- continue;
- } else if (str_startswith(argv[i], "-Wp,-D")
- && !strchr(argv[i] + 6, ',')) {
- // Treat it like -D.
- args_add(cpp_args, argv[i] + 4);
- continue;
- } else if (str_eq(argv[i], "-Wp,-MP")
- || (strlen(argv[i]) > 8
- && str_startswith(argv[i], "-Wp,-M")
- && argv[i][7] == ','
- && (argv[i][6] == 'F'
- || argv[i][6] == 'Q'
- || argv[i][6] == 'T')
- && !strchr(argv[i] + 8, ','))) {
- // TODO: Make argument to MF/MQ/MT relative.
- args_add(dep_args, argv[i]);
- continue;
- } else if (conf->direct_mode) {
- // -Wp, can be used to pass too hard options to the preprocessor.
- // Hence, disable direct mode.
- cc_log("Unsupported compiler option for direct mode: %s", argv[i]);
- conf->direct_mode = false;
- }
-
- // Any other -Wp,* arguments are only relevant for the preprocessor.
- args_add(cpp_args, argv[i]);
- continue;
- }
- if (str_eq(argv[i], "-MP")) {
- args_add(dep_args, argv[i]);
- continue;
- }
-
- // Input charset needs to be handled specially.
- if (str_startswith(argv[i], "-finput-charset=")) {
- input_charset = argv[i];
- continue;
- }
-
- if (str_eq(argv[i], "--serialize-diagnostics")) {
- if (i == argc - 1) {
- cc_log("Missing argument to %s", argv[i]);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
- generating_diagnostics = true;
- output_dia = make_relative_path(x_strdup(argv[i+1]));
- i++;
- continue;
- }
-
- if (str_startswith(argv[i], "-fprofile-")) {
- char *arg = x_strdup(argv[i]);
- const char *arg_profile_dir = strchr(argv[i], '=');
- if (arg_profile_dir) {
- // Convert to absolute path.
- char *dir = x_realpath(arg_profile_dir + 1);
- if (!dir) {
- // Directory doesn't exist.
- dir = x_strdup(arg_profile_dir + 1);
- }
-
- // We can get a better hit rate by using the real path here.
- free(arg);
- char *option = x_strndup(argv[i], arg_profile_dir - argv[i]);
- arg = format("%s=%s", option, dir);
- cc_log("Rewriting %s to %s", argv[i], arg);
- free(option);
- free(dir);
- }
-
- bool supported_profile_option = false;
- if (str_startswith(argv[i], "-fprofile-generate")
- || str_eq(argv[i], "-fprofile-arcs")) {
- profile_generate = true;
- supported_profile_option = true;
- } else if (str_startswith(argv[i], "-fprofile-use")
- || str_eq(argv[i], "-fbranch-probabilities")) {
- profile_use = true;
- supported_profile_option = true;
- } else if (str_eq(argv[i], "-fprofile-dir")) {
- supported_profile_option = true;
- }
-
- if (supported_profile_option) {
- args_add(common_args, arg);
- free(arg);
-
- // If the profile directory has already been set, give up... Hard to
- // know what the user means, and what the compiler will do.
- if (arg_profile_dir && profile_dir) {
- cc_log("Profile directory already set; giving up");
- result = false;
- goto out;
- } else if (arg_profile_dir) {
- cc_log("Setting profile directory to %s", arg_profile_dir);
- profile_dir = x_strdup(arg_profile_dir);
- }
- continue;
- }
- cc_log("Unknown profile option: %s", argv[i]);
- free(arg);
- }
-
- if (str_eq(argv[i], "-fcolor-diagnostics")
- || str_eq(argv[i], "-fno-color-diagnostics")
- || str_eq(argv[i], "-fdiagnostics-color")
- || str_eq(argv[i], "-fdiagnostics-color=always")
- || str_eq(argv[i], "-fno-diagnostics-color")
- || str_eq(argv[i], "-fdiagnostics-color=never")) {
- args_add(common_args, argv[i]);
- found_color_diagnostics = true;
- continue;
- }
- if (str_eq(argv[i], "-fdiagnostics-color=auto")) {
- if (color_output_possible()) {
- // Output is redirected, so color output must be forced.
- args_add(common_args, "-fdiagnostics-color=always");
- cc_log("Automatically forcing colors");
- } else {
- args_add(common_args, argv[i]);
- }
- found_color_diagnostics = true;
- continue;
- }
-
- // GCC
- if (str_eq(argv[i], "-fdirectives-only")) {
- found_directives_only = true;
- continue;
- }
- // Clang
- if (str_eq(argv[i], "-frewrite-includes")) {
- found_rewrite_includes = true;
- continue;
- }
-
- if (conf->sloppiness & SLOPPY_CLANG_INDEX_STORE
- && str_eq(argv[i], "-index-store-path")) {
- // Xcode 9 or later calls Clang with this option. The given path includes
- // a UUID that might lead to cache misses, especially when cache is
- // shared among multiple users.
- i++;
- if (i <= argc - 1) {
- cc_log("Skipping argument -index-store-path %s", argv[i]);
- }
- continue;
- }
-
- // Options taking an argument that we may want to rewrite to relative paths
- // to get better hit rate. A secondary effect is that paths in the standard
- // error output produced by the compiler will be normalized.
- if (compopt_takes_path(argv[i])) {
- if (i == argc - 1) {
- cc_log("Missing argument to %s", argv[i]);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
-
- if (!detect_pch(argv[i], argv[i+1], &found_pch)) {
- result = false;
- goto out;
- }
-
- char *relpath = make_relative_path(x_strdup(argv[i+1]));
- if (compopt_affects_cpp(argv[i])) {
- args_add(cpp_args, argv[i]);
- args_add(cpp_args, relpath);
- } else {
- args_add(common_args, argv[i]);
- args_add(common_args, relpath);
- }
- free(relpath);
-
- i++;
- continue;
- }
-
- // Same as above but options with concatenated argument beginning with a
- // slash.
- if (argv[i][0] == '-') {
- char *slash_pos = strchr(argv[i], '/');
- if (slash_pos) {
- char *option = x_strndup(argv[i], slash_pos - argv[i]);
- if (compopt_takes_concat_arg(option) && compopt_takes_path(option)) {
- char *relpath = make_relative_path(x_strdup(slash_pos));
- char *new_option = format("%s%s", option, relpath);
- if (compopt_affects_cpp(option)) {
- args_add(cpp_args, new_option);
- } else {
- args_add(common_args, new_option);
- }
- free(new_option);
- free(relpath);
- free(option);
- continue;
- } else {
- free(option);
- }
- }
- }
-
- // Options that take an argument.
- if (compopt_takes_arg(argv[i])) {
- if (i == argc - 1) {
- cc_log("Missing argument to %s", argv[i]);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
-
- if (compopt_affects_cpp(argv[i])) {
- args_add(cpp_args, argv[i]);
- args_add(cpp_args, argv[i+1]);
- } else {
- args_add(common_args, argv[i]);
- args_add(common_args, argv[i+1]);
- }
-
- i++;
- continue;
- }
-
- // Other options.
- if (argv[i][0] == '-') {
- if (compopt_affects_cpp(argv[i])
- || compopt_prefix_affects_cpp(argv[i])) {
- args_add(cpp_args, argv[i]);
- } else {
- args_add(common_args, argv[i]);
- }
- continue;
- }
-
- // If an argument isn't a plain file then assume its an option, not an
- // input file. This allows us to cope better with unusual compiler options.
- //
- // Note that "/dev/null" is an exception that is sometimes used as an input
- // file when code is testing compiler flags.
- struct stat st;
- if (!str_eq(argv[i], "/dev/null")
- && (stat(argv[i], &st) != 0 || !S_ISREG(st.st_mode))) {
- cc_log("%s is not a regular file, not considering as input file",
- argv[i]);
- args_add(common_args, argv[i]);
- continue;
- }
-
- if (input_file) {
- if (language_for_file(argv[i])) {
- cc_log("Multiple input files: %s and %s", input_file, argv[i]);
- stats_update(STATS_MULTIPLE);
- } else if (!found_c_opt && !found_dc_opt) {
- cc_log("Called for link with %s", argv[i]);
- if (strstr(argv[i], "conftest.")) {
- stats_update(STATS_CONFTEST);
- } else {
- stats_update(STATS_LINK);
- }
- } else {
- cc_log("Unsupported source extension: %s", argv[i]);
- stats_update(STATS_SOURCELANG);
- }
- result = false;
- goto out;
- }
-
- // The source code file path gets put into the notes.
- if (generating_coverage) {
- input_file = x_strdup(argv[i]);
- continue;
- }
-
- if (is_symlink(argv[i])) {
- // Don't rewrite source file path if it's a symlink since
- // make_relative_path resolves symlinks using realpath(3) and this leads
- // to potentially choosing incorrect relative header files. See the
- // "symlink to source file" test.
- input_file = x_strdup(argv[i]);
- } else {
- // Rewrite to relative to increase hit rate.
- input_file = make_relative_path(x_strdup(argv[i]));
- }
- } // for
-
- if (generating_debuginfo && conf->unify) {
- cc_log("Generating debug info; disabling unify mode");
- conf->unify = false;
- }
-
- if (generating_debuginfo_level_3 && !conf->run_second_cpp) {
- cc_log("Generating debug info level 3; not compiling preprocessed code");
- conf->run_second_cpp = true;
- }
-
- // See <http://gcc.gnu.org/onlinedocs/cpp/Environment-Variables.html>.
- // Contrary to what the documentation seems to imply the compiler still
- // creates object files with these defined (confirmed with GCC 8.2.1), i.e.
- // they work as -MMD/-MD, not -MM/-M. These environment variables do nothing
- // on Clang.
- {
- char *dependencies_env = getenv("DEPENDENCIES_OUTPUT");
- bool using_sunpro_dependencies = false;
- if (!dependencies_env) {
- dependencies_env = getenv("SUNPRO_DEPENDENCIES");
- using_sunpro_dependencies = true;
- }
- if (dependencies_env) {
- generating_dependencies = true;
- dependency_filename_specified = true;
- char *saveptr = nullptr;
- char *abspath_file = strtok_r(dependencies_env, " ", &saveptr);
-
- free(output_dep);
- output_dep = make_relative_path(x_strdup(abspath_file));
-
- // specifying target object is optional.
- char *abspath_obj = strtok_r(nullptr, " ", &saveptr);
- if (abspath_obj) {
- // it's the "file target" form.
-
- dependency_target_specified = true;
- char *relpath_obj = make_relative_path(x_strdup(abspath_obj));
- // ensure compiler gets relative path.
- char *relpath_both = format("%s %s", output_dep, relpath_obj);
- if (using_sunpro_dependencies) {
- x_setenv("SUNPRO_DEPENDENCIES", relpath_both);
- } else {
- x_setenv("DEPENDENCIES_OUTPUT", relpath_both);
- }
- free(relpath_obj);
- free(relpath_both);
- } else {
- // it's the "file" form.
-
- dependency_implicit_target_specified = true;
- // ensure compiler gets relative path.
- if (using_sunpro_dependencies) {
- x_setenv("SUNPRO_DEPENDENCIES", output_dep);
- } else {
- x_setenv("DEPENDENCIES_OUTPUT", output_dep);
- }
- }
- }
- }
-
- if (!input_file) {
- cc_log("No input file found");
- stats_update(STATS_NOINPUT);
- result = false;
- goto out;
- }
-
- if (found_pch || found_fpch_preprocess) {
- using_precompiled_header = true;
- if (!(conf->sloppiness & SLOPPY_TIME_MACROS)) {
- cc_log("You have to specify \"time_macros\" sloppiness when using"
- " precompiled headers to get direct hits");
- cc_log("Disabling direct mode");
- stats_update(STATS_CANTUSEPCH);
- result = false;
- goto out;
- }
- }
-
- if (explicit_language && str_eq(explicit_language, "none")) {
- explicit_language = NULL;
- }
- file_language = language_for_file(input_file);
- if (explicit_language) {
- if (!language_is_supported(explicit_language)) {
- cc_log("Unsupported language: %s", explicit_language);
- stats_update(STATS_SOURCELANG);
- result = false;
- goto out;
- }
- actual_language = x_strdup(explicit_language);
- } else {
- actual_language = file_language;
- }
-
- output_is_precompiled_header =
- actual_language && strstr(actual_language, "-header");
-
- if (output_is_precompiled_header
- && !(conf->sloppiness & SLOPPY_PCH_DEFINES)) {
- cc_log("You have to specify \"pch_defines,time_macros\" sloppiness when"
- " creating precompiled headers");
- stats_update(STATS_CANTUSEPCH);
- result = false;
- goto out;
- }
-
- if (!found_c_opt && !found_dc_opt && !found_S_opt) {
- if (output_is_precompiled_header) {
- args_add(common_args, "-c");
- } else {
- cc_log("No -c option found");
- // I find that having a separate statistic for autoconf tests is useful,
- // as they are the dominant form of "called for link" in many cases.
- if (strstr(input_file, "conftest.")) {
- stats_update(STATS_CONFTEST);
- } else {
- stats_update(STATS_LINK);
- }
- result = false;
- goto out;
- }
- }
-
- if (!actual_language) {
- cc_log("Unsupported source extension: %s", input_file);
- stats_update(STATS_SOURCELANG);
- result = false;
- goto out;
- }
-
- if (!conf->run_second_cpp && str_eq(actual_language, "cu")) {
- cc_log("Using CUDA compiler; not compiling preprocessed code");
- conf->run_second_cpp = true;
- }
-
- direct_i_file = language_is_preprocessed(actual_language);
-
- if (output_is_precompiled_header && !conf->run_second_cpp) {
- // It doesn't work to create the .gch from preprocessed source.
- cc_log("Creating precompiled header; not compiling preprocessed code");
- conf->run_second_cpp = true;
- }
-
- if (str_eq(conf->cpp_extension, "")) {
- const char *p_language = p_language_for_language(actual_language);
- free(conf->cpp_extension);
- conf->cpp_extension = x_strdup(extension_for_language(p_language) + 1);
- }
-
- // Don't try to second guess the compilers heuristics for stdout handling.
- if (output_obj && str_eq(output_obj, "-")) {
- stats_update(STATS_OUTSTDOUT);
- cc_log("Output file is -");
- result = false;
- goto out;
- }
-
- if (!output_obj) {
- if (output_is_precompiled_header) {
- output_obj = format("%s.gch", input_file);
- } else {
- char extension = found_S_opt ? 's' : 'o';
- output_obj = x_basename(input_file);
- char *p = strrchr(output_obj, '.');
- if (!p) {
- reformat(&output_obj, "%s.%c", output_obj, extension);
- } else if (!p[1]) {
- reformat(&output_obj, "%s%c", output_obj, extension);
- } else {
- p[1] = extension;
- p[2] = 0;
- }
- }
- }
-
- if (seen_split_dwarf) {
- char *p = strrchr(output_obj, '.');
- if (!p || !p[1]) {
- cc_log("Badly formed object filename");
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
-
- char *base_name = remove_extension(output_obj);
- output_dwo = format("%s.dwo", base_name);
- free(base_name);
- }
-
- // Cope with -o /dev/null.
- struct stat st;
- if (!str_eq(output_obj, "/dev/null")
- && stat(output_obj, &st) == 0
- && !S_ISREG(st.st_mode)) {
- cc_log("Not a regular file: %s", output_obj);
- stats_update(STATS_BADOUTPUTFILE);
- result = false;
- goto out;
- }
-
- {
- char *output_dir = x_dirname(output_obj);
- if (stat(output_dir, &st) != 0 || !S_ISDIR(st.st_mode)) {
- cc_log("Directory does not exist: %s", output_dir);
- stats_update(STATS_BADOUTPUTFILE);
- result = false;
- free(output_dir);
- goto out;
- }
- free(output_dir);
- }
-
- // Some options shouldn't be passed to the real compiler when it compiles
- // preprocessed code:
- //
- // -finput-charset=XXX (otherwise conversion happens twice)
- // -x XXX (otherwise the wrong language is selected)
- if (input_charset) {
- args_add(cpp_args, input_charset);
- }
- if (found_pch) {
- args_add(cpp_args, "-fpch-preprocess");
- }
- if (explicit_language) {
- args_add(cpp_args, "-x");
- args_add(cpp_args, explicit_language);
- }
-
- // Since output is redirected, compilers will not color their output by
- // default, so force it explicitly if it would be otherwise done.
- if (!found_color_diagnostics && color_output_possible()) {
- if (guessed_compiler == GUESSED_CLANG) {
- if (!str_eq(actual_language, "assembler")) {
- args_add(common_args, "-fcolor-diagnostics");
- cc_log("Automatically enabling colors");
- }
- } else if (guessed_compiler == GUESSED_GCC) {
- // GCC has it since 4.9, but that'd require detecting what GCC version is
- // used for the actual compile. However it requires also GCC_COLORS to be
- // set (and not empty), so use that for detecting if GCC would use
- // colors.
- if (getenv("GCC_COLORS") && getenv("GCC_COLORS")[0] != '\0') {
- args_add(common_args, "-fdiagnostics-color");
- cc_log("Automatically enabling colors");
- }
- }
- }
-
- // Add flags for dependency generation only to the preprocessor command line.
- if (generating_dependencies) {
- if (!dependency_filename_specified) {
- char *base_name = remove_extension(output_obj);
- char *default_depfile_name = format("%s.d", base_name);
- free(base_name);
- args_add(dep_args, "-MF");
- args_add(dep_args, default_depfile_name);
- output_dep = make_relative_path(x_strdup(default_depfile_name));
- }
-
- if (!dependency_target_specified
- && !dependency_implicit_target_specified
- && !str_eq(get_extension(output_dep), ".o")) {
- args_add(dep_args, "-MQ");
- args_add(dep_args, output_obj);
- }
- }
- if (generating_coverage) {
- char *base_name = remove_extension(output_obj);
- char *default_covfile_name = format("%s.gcno", base_name);
- free(base_name);
- output_cov = make_relative_path(default_covfile_name);
- }
- if (generating_stackusage) {
- char *base_name = remove_extension(output_obj);
- char *default_sufile_name = format("%s.su", base_name);
- free(base_name);
- output_su = make_relative_path(default_sufile_name);
- }
-
- *compiler_args = args_copy(common_args);
- args_extend(*compiler_args, compiler_only_args);
-
- if (conf->run_second_cpp) {
- args_extend(*compiler_args, cpp_args);
- } else if (found_directives_only || found_rewrite_includes) {
- // Need to pass the macros and any other preprocessor directives again.
- args_extend(*compiler_args, cpp_args);
- if (found_directives_only) {
- args_add(cpp_args, "-fdirectives-only");
- // The preprocessed source code still needs some more preprocessing.
- args_add(*compiler_args, "-fpreprocessed");
- args_add(*compiler_args, "-fdirectives-only");
- }
- if (found_rewrite_includes) {
- args_add(cpp_args, "-frewrite-includes");
- // The preprocessed source code still needs some more preprocessing.
- args_add(*compiler_args, "-x");
- args_add(*compiler_args, actual_language);
- }
- } else if (explicit_language) {
- // Workaround for a bug in Apple's patched distcc -- it doesn't properly
- // reset the language specified with -x, so if -x is given, we have to
- // specify the preprocessed language explicitly.
- args_add(*compiler_args, "-x");
- args_add(*compiler_args, p_language_for_language(explicit_language));
- }
-
- if (found_c_opt) {
- args_add(*compiler_args, "-c");
- }
-
- if (found_dc_opt) {
- args_add(*compiler_args, "-dc");
- }
-
- for (size_t i = 0; i < arch_args_size; ++i) {
- args_add(*compiler_args, "-arch");
- args_add(*compiler_args, arch_args[i]);
- }
-
- // Only pass dependency arguments to the preprocessor since Intel's C++
- // compiler doesn't produce a correct .d file when compiling preprocessed
- // source.
- args_extend(cpp_args, dep_args);
-
- *preprocessor_args = args_copy(common_args);
- args_extend(*preprocessor_args, cpp_args);
+ bool found_c_opt = false;
+ bool found_dc_opt = false;
+ bool found_S_opt = false;
+ bool found_pch = false;
+ bool found_fpch_preprocess = false;
+ const char* explicit_language = NULL; // As specified with -x.
+ const char* file_language; // As deduced from file extension.
+ const char* input_charset = NULL;
+
+ // Is the dependency makefile name overridden with -MF?
+ bool dependency_filename_specified = false;
+
+ // Is the dependency makefile target name specified with -MT or -MQ?
+ bool dependency_target_specified = false;
+
+ // Is the dependency target name implicitly specified using
+ // DEPENDENCIES_OUTPUT or SUNPRO_DEPENDENCIES?
+ bool dependency_implicit_target_specified = false;
+
+ // expanded_args is a copy of the original arguments given to the compiler
+ // but with arguments from @file and similar constructs expanded. It's only
+ // used as a temporary data structure to loop over.
+ struct args* expanded_args = args_copy(args);
+
+ // common_args contains all original arguments except:
+ // * those that never should be passed to the preprocessor,
+ // * those that only should be passed to the preprocessor (if run_second_cpp
+ // is false), and
+ // * dependency options (like -MD and friends).
+ struct args* common_args = args_init(0, NULL);
+
+ // cpp_args contains arguments that were not added to common_args, i.e. those
+ // that should only be passed to the preprocessor if run_second_cpp is false.
+ // If run_second_cpp is true, they will be passed to the compiler as well.
+ struct args* cpp_args = args_init(0, NULL);
+
+ // dep_args contains dependency options like -MD. They are only passed to the
+ // preprocessor, never to the compiler.
+ struct args* dep_args = args_init(0, NULL);
+
+ // compiler_only_args contains arguments that should only be passed to the
+ // compiler, not the preprocessor.
+ struct args* compiler_only_args = args_init(0, NULL);
+
+ bool found_color_diagnostics = false;
+ bool found_directives_only = false;
+ bool found_rewrite_includes = false;
+
+ int argc = expanded_args->argc;
+ char** argv = expanded_args->argv;
+ args_add(common_args, argv[0]);
+
+ bool result = true;
+ for (int i = 1; i < argc; i++) {
+ // The user knows best: just swallow the next arg.
+ if (str_eq(argv[i], "--ccache-skip")) {
+ i++;
+ if (i == argc) {
+ cc_log("--ccache-skip lacks an argument");
+ result = false;
+ goto out;
+ }
+ args_add(common_args, argv[i]);
+ continue;
+ }
+
+ // Special case for -E.
+ if (str_eq(argv[i], "-E")) {
+ stats_update(STATS_PREPROCESSING);
+ result = false;
+ goto out;
+ }
+
+ // Handle "@file" argument.
+ if (str_startswith(argv[i], "@") || str_startswith(argv[i], "-@")) {
+ char* argpath = argv[i] + 1;
+
+ if (argpath[-1] == '-') {
+ ++argpath;
+ }
+ struct args* file_args = args_init_from_gcc_atfile(argpath);
+ if (!file_args) {
+ cc_log("Couldn't read arg file %s", argpath);
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+
+ args_insert(expanded_args, i, file_args, true);
+ argc = expanded_args->argc;
+ argv = expanded_args->argv;
+ i--;
+ continue;
+ }
+
+ // Handle cuda "-optf" and "--options-file" argument.
+ if (guessed_compiler == GUESSED_NVCC
+ && (str_eq(argv[i], "-optf") || str_eq(argv[i], "--options-file"))) {
+ if (i == argc - 1) {
+ cc_log("Expected argument after %s", argv[i]);
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+ ++i;
+
+ // Argument is a comma-separated list of files.
+ char* str_start = argv[i];
+ char* str_end = strchr(str_start, ',');
+ int index = i + 1;
+
+ if (!str_end) {
+ str_end = str_start + strlen(str_start);
+ }
+
+ while (str_end) {
+ *str_end = '\0';
+ struct args* file_args = args_init_from_gcc_atfile(str_start);
+ if (!file_args) {
+ cc_log("Couldn't read cuda options file %s", str_start);
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+
+ int new_index = file_args->argc + index;
+ args_insert(expanded_args, index, file_args, false);
+ index = new_index;
+ str_start = str_end;
+ str_end = strchr(str_start, ',');
+ }
+
+ argc = expanded_args->argc;
+ argv = expanded_args->argv;
+ continue;
+ }
+
+ // These are always too hard.
+ if (compopt_too_hard(argv[i]) || str_startswith(argv[i], "-fdump-")) {
+ cc_log("Compiler option %s is unsupported", argv[i]);
+ stats_update(STATS_UNSUPPORTED_OPTION);
+ result = false;
+ goto out;
+ }
+
+ // These are too hard in direct mode.
+ if (conf->direct_mode && compopt_too_hard_for_direct_mode(argv[i])) {
+ cc_log("Unsupported compiler option for direct mode: %s", argv[i]);
+ conf->direct_mode = false;
+ }
+
+ // -Xarch_* options are too hard.
+ if (str_startswith(argv[i], "-Xarch_")) {
+ cc_log("Unsupported compiler option :%s", argv[i]);
+ stats_update(STATS_UNSUPPORTED_OPTION);
+ result = false;
+ goto out;
+ }
+
+ // Handle -arch options.
+ if (str_eq(argv[i], "-arch")) {
+ if (arch_args_size == MAX_ARCH_ARGS - 1) {
+ cc_log("Too many -arch compiler options; ccache supports at most %d",
+ MAX_ARCH_ARGS);
+ stats_update(STATS_UNSUPPORTED_OPTION);
+ result = false;
+ goto out;
+ }
+
+ ++i;
+ arch_args[arch_args_size] = x_strdup(argv[i]); // It will leak.
+ ++arch_args_size;
+ if (arch_args_size == 2) {
+ conf->run_second_cpp = true;
+ }
+ continue;
+ }
+
+ // Handle options that should not be passed to the preprocessor.
+ if (compopt_affects_comp(argv[i])) {
+ args_add(compiler_only_args, argv[i]);
+ if (compopt_takes_arg(argv[i])) {
+ if (i == argc - 1) {
+ cc_log("Missing argument to %s", argv[i]);
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+ args_add(compiler_only_args, argv[i + 1]);
+ ++i;
+ }
+ continue;
+ }
+ if (compopt_prefix_affects_comp(argv[i])) {
+ args_add(compiler_only_args, argv[i]);
+ continue;
+ }
+
+ if (str_eq(argv[i], "-fpch-preprocess") || str_eq(argv[i], "-emit-pch")
+ || str_eq(argv[i], "-emit-pth")) {
+ found_fpch_preprocess = true;
+ }
+
+ // We must have -c.
+ if (str_eq(argv[i], "-c")) {
+ found_c_opt = true;
+ continue;
+ }
+
+ // when using nvcc with separable compilation, -dc implies -c
+ if ((str_eq(argv[i], "-dc") || str_eq(argv[i], "--device-c"))
+ && guessed_compiler == GUESSED_NVCC) {
+ found_dc_opt = true;
+ continue;
+ }
+
+ // -S changes the default extension.
+ if (str_eq(argv[i], "-S")) {
+ args_add(common_args, argv[i]);
+ found_S_opt = true;
+ continue;
+ }
+
+ // Special handling for -x: remember the last specified language before the
+ // input file and strip all -x options from the arguments.
+ if (str_eq(argv[i], "-x")) {
+ if (i == argc - 1) {
+ cc_log("Missing argument to %s", argv[i]);
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+ if (!input_file) {
+ explicit_language = argv[i + 1];
+ }
+ i++;
+ continue;
+ }
+ if (str_startswith(argv[i], "-x")) {
+ if (!input_file) {
+ explicit_language = &argv[i][2];
+ }
+ continue;
+ }
+
+ // We need to work out where the output was meant to go.
+ if (str_eq(argv[i], "-o")) {
+ if (i == argc - 1) {
+ cc_log("Missing argument to %s", argv[i]);
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+ output_obj = make_relative_path(x_strdup(argv[i + 1]));
+ i++;
+ continue;
+ }
+
+ // Alternate form of -o with no space. Nvcc does not support this.
+ if (str_startswith(argv[i], "-o") && guessed_compiler != GUESSED_NVCC) {
+ output_obj = make_relative_path(x_strdup(&argv[i][2]));
+ continue;
+ }
+
+ if (str_startswith(argv[i], "-fdebug-prefix-map=")
+ || str_startswith(argv[i], "-ffile-prefix-map=")) {
+ debug_prefix_maps = static_cast<char**>(x_realloc(
+ debug_prefix_maps, (debug_prefix_maps_len + 1) * sizeof(char*)));
+ debug_prefix_maps[debug_prefix_maps_len++] =
+ x_strdup(&argv[i][argv[i][2] == 'f' ? 18 : 19]);
+ args_add(common_args, argv[i]);
+ continue;
+ }
+
+ // Debugging is handled specially, so that we know if we can strip line
+ // number info.
+ if (str_startswith(argv[i], "-g")) {
+ args_add(common_args, argv[i]);
+
+ if (str_startswith(argv[i], "-gdwarf")) {
+ // Selection of DWARF format (-gdwarf or -gdwarf-<version>) enables
+ // debug info on level 2.
+ generating_debuginfo = true;
+ continue;
+ }
+
+ char last_char = argv[i][strlen(argv[i]) - 1];
+ if (last_char == '0') {
+ // "-g0", "-ggdb0" or similar: All debug information disabled.
+ generating_debuginfo = false;
+ generating_debuginfo_level_3 = false;
+ } else {
+ generating_debuginfo = true;
+ if (last_char == '3') {
+ generating_debuginfo_level_3 = true;
+ }
+ if (str_eq(argv[i], "-gsplit-dwarf")) {
+ seen_split_dwarf = true;
+ }
+ }
+ continue;
+ }
+
+ // These options require special handling, because they behave differently
+ // with gcc -E, when the output file is not specified.
+ if (str_eq(argv[i], "-MD") || str_eq(argv[i], "-MMD")) {
+ generating_dependencies = true;
+ args_add(dep_args, argv[i]);
+ continue;
+ }
+ if (str_startswith(argv[i], "-MF")) {
+ dependency_filename_specified = true;
+ free(output_dep);
+
+ char* arg;
+ bool separate_argument = (strlen(argv[i]) == 3);
+ if (separate_argument) {
+ // -MF arg
+ if (i == argc - 1) {
+ cc_log("Missing argument to %s", argv[i]);
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+ arg = argv[i + 1];
+ i++;
+ } else {
+ // -MFarg
+ arg = &argv[i][3];
+ }
+ output_dep = make_relative_path(x_strdup(arg));
+ // Keep the format of the args the same.
+ if (separate_argument) {
+ args_add(dep_args, "-MF");
+ args_add(dep_args, output_dep);
+ } else {
+ char* option = format("-MF%s", output_dep);
+ args_add(dep_args, option);
+ free(option);
+ }
+ continue;
+ }
+ if (str_startswith(argv[i], "-MQ") || str_startswith(argv[i], "-MT")) {
+ dependency_target_specified = true;
+
+ char* relpath;
+ if (strlen(argv[i]) == 3) {
+ // -MQ arg or -MT arg
+ if (i == argc - 1) {
+ cc_log("Missing argument to %s", argv[i]);
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+ args_add(dep_args, argv[i]);
+ relpath = make_relative_path(x_strdup(argv[i + 1]));
+ args_add(dep_args, relpath);
+ free(relpath);
+ i++;
+ } else {
+ char* arg_opt = x_strndup(argv[i], 3);
+ relpath = make_relative_path(x_strdup(argv[i] + 3));
+ char* option = format("%s%s", arg_opt, relpath);
+ args_add(dep_args, option);
+ free(arg_opt);
+ free(relpath);
+ free(option);
+ }
+ continue;
+ }
+ if (str_eq(argv[i], "-fprofile-arcs")) {
+ profile_arcs = true;
+ args_add(common_args, argv[i]);
+ continue;
+ }
+ if (str_eq(argv[i], "-ftest-coverage")) {
+ generating_coverage = true;
+ args_add(common_args, argv[i]);
+ continue;
+ }
+ if (str_eq(argv[i], "-fstack-usage")) {
+ generating_stackusage = true;
+ args_add(common_args, argv[i]);
+ continue;
+ }
+ if (str_eq(argv[i], "--coverage") // = -fprofile-arcs -ftest-coverage
+ || str_eq(argv[i], "-coverage")) { // Undocumented but still works.
+ profile_arcs = true;
+ generating_coverage = true;
+ args_add(common_args, argv[i]);
+ continue;
+ }
+ if (str_startswith(argv[i], "-fprofile-dir=")) {
+ profile_dir = x_strdup(argv[i] + 14);
+ args_add(common_args, argv[i]);
+ continue;
+ }
+ if (str_startswith(argv[i], "-fsanitize-blacklist=")) {
+ sanitize_blacklists = static_cast<char**>(x_realloc(
+ sanitize_blacklists, (sanitize_blacklists_len + 1) * sizeof(char*)));
+ sanitize_blacklists[sanitize_blacklists_len++] = x_strdup(argv[i] + 21);
+ args_add(common_args, argv[i]);
+ continue;
+ }
+ if (str_startswith(argv[i], "--sysroot=")) {
+ char* relpath = make_relative_path(x_strdup(argv[i] + 10));
+ char* option = format("--sysroot=%s", relpath);
+ args_add(common_args, option);
+ free(relpath);
+ free(option);
+ continue;
+ }
+ // Alternate form of specifying sysroot without =
+ if (str_eq(argv[i], "--sysroot")) {
+ if (i == argc - 1) {
+ cc_log("Missing argument to %s", argv[i]);
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+ args_add(common_args, argv[i]);
+ char* relpath = make_relative_path(x_strdup(argv[i + 1]));
+ args_add(common_args, relpath);
+ i++;
+ free(relpath);
+ continue;
+ }
+ // Alternate form of specifying target without =
+ if (str_eq(argv[i], "-target")) {
+ if (i == argc - 1) {
+ cc_log("Missing argument to %s", argv[i]);
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+ args_add(common_args, argv[i]);
+ args_add(common_args, argv[i + 1]);
+ i++;
+ continue;
+ }
+ if (str_startswith(argv[i], "-Wp,")) {
+ if (str_eq(argv[i], "-Wp,-P") || strstr(argv[i], ",-P,")
+ || str_endswith(argv[i], ",-P")) {
+ // -P removes preprocessor information in such a way that the object
+ // file from compiling the preprocessed file will not be equal to the
+ // object file produced when compiling without ccache.
+ cc_log("Too hard option -Wp,-P detected");
+ stats_update(STATS_UNSUPPORTED_OPTION);
+ failed();
+ } else if (str_startswith(argv[i], "-Wp,-MD,")
+ && !strchr(argv[i] + 8, ',')) {
+ generating_dependencies = true;
+ dependency_filename_specified = true;
+ free(output_dep);
+ output_dep = make_relative_path(x_strdup(argv[i] + 8));
+ args_add(dep_args, argv[i]);
+ continue;
+ } else if (str_startswith(argv[i], "-Wp,-MMD,")
+ && !strchr(argv[i] + 9, ',')) {
+ generating_dependencies = true;
+ dependency_filename_specified = true;
+ free(output_dep);
+ output_dep = make_relative_path(x_strdup(argv[i] + 9));
+ args_add(dep_args, argv[i]);
+ continue;
+ } else if (str_startswith(argv[i], "-Wp,-D")
+ && !strchr(argv[i] + 6, ',')) {
+ // Treat it like -D.
+ args_add(cpp_args, argv[i] + 4);
+ continue;
+ } else if (str_eq(argv[i], "-Wp,-MP")
+ || (strlen(argv[i]) > 8 && str_startswith(argv[i], "-Wp,-M")
+ && argv[i][7] == ','
+ && (argv[i][6] == 'F' || argv[i][6] == 'Q'
+ || argv[i][6] == 'T')
+ && !strchr(argv[i] + 8, ','))) {
+ // TODO: Make argument to MF/MQ/MT relative.
+ args_add(dep_args, argv[i]);
+ continue;
+ } else if (conf->direct_mode) {
+ // -Wp, can be used to pass too hard options to the preprocessor.
+ // Hence, disable direct mode.
+ cc_log("Unsupported compiler option for direct mode: %s", argv[i]);
+ conf->direct_mode = false;
+ }
+
+ // Any other -Wp,* arguments are only relevant for the preprocessor.
+ args_add(cpp_args, argv[i]);
+ continue;
+ }
+ if (str_eq(argv[i], "-MP")) {
+ args_add(dep_args, argv[i]);
+ continue;
+ }
+
+ // Input charset needs to be handled specially.
+ if (str_startswith(argv[i], "-finput-charset=")) {
+ input_charset = argv[i];
+ continue;
+ }
+
+ if (str_eq(argv[i], "--serialize-diagnostics")) {
+ if (i == argc - 1) {
+ cc_log("Missing argument to %s", argv[i]);
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+ generating_diagnostics = true;
+ output_dia = make_relative_path(x_strdup(argv[i + 1]));
+ i++;
+ continue;
+ }
+
+ if (str_startswith(argv[i], "-fprofile-")) {
+ char* arg = x_strdup(argv[i]);
+ const char* arg_profile_dir = strchr(argv[i], '=');
+ if (arg_profile_dir) {
+ // Convert to absolute path.
+ char* dir = x_realpath(arg_profile_dir + 1);
+ if (!dir) {
+ // Directory doesn't exist.
+ dir = x_strdup(arg_profile_dir + 1);
+ }
+
+ // We can get a better hit rate by using the real path here.
+ free(arg);
+ char* option = x_strndup(argv[i], arg_profile_dir - argv[i]);
+ arg = format("%s=%s", option, dir);
+ cc_log("Rewriting %s to %s", argv[i], arg);
+ free(option);
+ free(dir);
+ }
+
+ bool supported_profile_option = false;
+ if (str_startswith(argv[i], "-fprofile-generate")
+ || str_eq(argv[i], "-fprofile-arcs")) {
+ profile_generate = true;
+ supported_profile_option = true;
+ } else if (str_startswith(argv[i], "-fprofile-use")
+ || str_eq(argv[i], "-fbranch-probabilities")) {
+ profile_use = true;
+ supported_profile_option = true;
+ } else if (str_eq(argv[i], "-fprofile-dir")) {
+ supported_profile_option = true;
+ }
+
+ if (supported_profile_option) {
+ args_add(common_args, arg);
+ free(arg);
+
+ // If the profile directory has already been set, give up... Hard to
+ // know what the user means, and what the compiler will do.
+ if (arg_profile_dir && profile_dir) {
+ cc_log("Profile directory already set; giving up");
+ result = false;
+ goto out;
+ } else if (arg_profile_dir) {
+ cc_log("Setting profile directory to %s", arg_profile_dir);
+ profile_dir = x_strdup(arg_profile_dir);
+ }
+ continue;
+ }
+ cc_log("Unknown profile option: %s", argv[i]);
+ free(arg);
+ }
+
+ if (str_eq(argv[i], "-fcolor-diagnostics")
+ || str_eq(argv[i], "-fno-color-diagnostics")
+ || str_eq(argv[i], "-fdiagnostics-color")
+ || str_eq(argv[i], "-fdiagnostics-color=always")
+ || str_eq(argv[i], "-fno-diagnostics-color")
+ || str_eq(argv[i], "-fdiagnostics-color=never")) {
+ args_add(common_args, argv[i]);
+ found_color_diagnostics = true;
+ continue;
+ }
+ if (str_eq(argv[i], "-fdiagnostics-color=auto")) {
+ if (color_output_possible()) {
+ // Output is redirected, so color output must be forced.
+ args_add(common_args, "-fdiagnostics-color=always");
+ cc_log("Automatically forcing colors");
+ } else {
+ args_add(common_args, argv[i]);
+ }
+ found_color_diagnostics = true;
+ continue;
+ }
+
+ // GCC
+ if (str_eq(argv[i], "-fdirectives-only")) {
+ found_directives_only = true;
+ continue;
+ }
+ // Clang
+ if (str_eq(argv[i], "-frewrite-includes")) {
+ found_rewrite_includes = true;
+ continue;
+ }
+
+ if (conf->sloppiness & SLOPPY_CLANG_INDEX_STORE
+ && str_eq(argv[i], "-index-store-path")) {
+ // Xcode 9 or later calls Clang with this option. The given path includes
+ // a UUID that might lead to cache misses, especially when cache is
+ // shared among multiple users.
+ i++;
+ if (i <= argc - 1) {
+ cc_log("Skipping argument -index-store-path %s", argv[i]);
+ }
+ continue;
+ }
+
+ // Options taking an argument that we may want to rewrite to relative paths
+ // to get better hit rate. A secondary effect is that paths in the standard
+ // error output produced by the compiler will be normalized.
+ if (compopt_takes_path(argv[i])) {
+ if (i == argc - 1) {
+ cc_log("Missing argument to %s", argv[i]);
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+
+ if (!detect_pch(argv[i], argv[i + 1], &found_pch)) {
+ result = false;
+ goto out;
+ }
+
+ char* relpath = make_relative_path(x_strdup(argv[i + 1]));
+ if (compopt_affects_cpp(argv[i])) {
+ args_add(cpp_args, argv[i]);
+ args_add(cpp_args, relpath);
+ } else {
+ args_add(common_args, argv[i]);
+ args_add(common_args, relpath);
+ }
+ free(relpath);
+
+ i++;
+ continue;
+ }
+
+ // Same as above but options with concatenated argument beginning with a
+ // slash.
+ if (argv[i][0] == '-') {
+ char* slash_pos = strchr(argv[i], '/');
+ if (slash_pos) {
+ char* option = x_strndup(argv[i], slash_pos - argv[i]);
+ if (compopt_takes_concat_arg(option) && compopt_takes_path(option)) {
+ char* relpath = make_relative_path(x_strdup(slash_pos));
+ char* new_option = format("%s%s", option, relpath);
+ if (compopt_affects_cpp(option)) {
+ args_add(cpp_args, new_option);
+ } else {
+ args_add(common_args, new_option);
+ }
+ free(new_option);
+ free(relpath);
+ free(option);
+ continue;
+ } else {
+ free(option);
+ }
+ }
+ }
+
+ // Options that take an argument.
+ if (compopt_takes_arg(argv[i])) {
+ if (i == argc - 1) {
+ cc_log("Missing argument to %s", argv[i]);
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+
+ if (compopt_affects_cpp(argv[i])) {
+ args_add(cpp_args, argv[i]);
+ args_add(cpp_args, argv[i + 1]);
+ } else {
+ args_add(common_args, argv[i]);
+ args_add(common_args, argv[i + 1]);
+ }
+
+ i++;
+ continue;
+ }
+
+ // Other options.
+ if (argv[i][0] == '-') {
+ if (compopt_affects_cpp(argv[i]) || compopt_prefix_affects_cpp(argv[i])) {
+ args_add(cpp_args, argv[i]);
+ } else {
+ args_add(common_args, argv[i]);
+ }
+ continue;
+ }
+
+ // If an argument isn't a plain file then assume its an option, not an
+ // input file. This allows us to cope better with unusual compiler options.
+ //
+ // Note that "/dev/null" is an exception that is sometimes used as an input
+ // file when code is testing compiler flags.
+ struct stat st;
+ if (!str_eq(argv[i], "/dev/null")
+ && (stat(argv[i], &st) != 0 || !S_ISREG(st.st_mode))) {
+ cc_log("%s is not a regular file, not considering as input file",
+ argv[i]);
+ args_add(common_args, argv[i]);
+ continue;
+ }
+
+ if (input_file) {
+ if (language_for_file(argv[i])) {
+ cc_log("Multiple input files: %s and %s", input_file, argv[i]);
+ stats_update(STATS_MULTIPLE);
+ } else if (!found_c_opt && !found_dc_opt) {
+ cc_log("Called for link with %s", argv[i]);
+ if (strstr(argv[i], "conftest.")) {
+ stats_update(STATS_CONFTEST);
+ } else {
+ stats_update(STATS_LINK);
+ }
+ } else {
+ cc_log("Unsupported source extension: %s", argv[i]);
+ stats_update(STATS_SOURCELANG);
+ }
+ result = false;
+ goto out;
+ }
+
+ // The source code file path gets put into the notes.
+ if (generating_coverage) {
+ input_file = x_strdup(argv[i]);
+ continue;
+ }
+
+ if (is_symlink(argv[i])) {
+ // Don't rewrite source file path if it's a symlink since
+ // make_relative_path resolves symlinks using realpath(3) and this leads
+ // to potentially choosing incorrect relative header files. See the
+ // "symlink to source file" test.
+ input_file = x_strdup(argv[i]);
+ } else {
+ // Rewrite to relative to increase hit rate.
+ input_file = make_relative_path(x_strdup(argv[i]));
+ }
+ } // for
+
+ if (generating_debuginfo && conf->unify) {
+ cc_log("Generating debug info; disabling unify mode");
+ conf->unify = false;
+ }
+
+ if (generating_debuginfo_level_3 && !conf->run_second_cpp) {
+ cc_log("Generating debug info level 3; not compiling preprocessed code");
+ conf->run_second_cpp = true;
+ }
+
+ // See <http://gcc.gnu.org/onlinedocs/cpp/Environment-Variables.html>.
+ // Contrary to what the documentation seems to imply the compiler still
+ // creates object files with these defined (confirmed with GCC 8.2.1), i.e.
+ // they work as -MMD/-MD, not -MM/-M. These environment variables do nothing
+ // on Clang.
+ {
+ char* dependencies_env = getenv("DEPENDENCIES_OUTPUT");
+ bool using_sunpro_dependencies = false;
+ if (!dependencies_env) {
+ dependencies_env = getenv("SUNPRO_DEPENDENCIES");
+ using_sunpro_dependencies = true;
+ }
+ if (dependencies_env) {
+ generating_dependencies = true;
+ dependency_filename_specified = true;
+ char* saveptr = nullptr;
+ char* abspath_file = strtok_r(dependencies_env, " ", &saveptr);
+
+ free(output_dep);
+ output_dep = make_relative_path(x_strdup(abspath_file));
+
+ // specifying target object is optional.
+ char* abspath_obj = strtok_r(nullptr, " ", &saveptr);
+ if (abspath_obj) {
+ // it's the "file target" form.
+
+ dependency_target_specified = true;
+ char* relpath_obj = make_relative_path(x_strdup(abspath_obj));
+ // ensure compiler gets relative path.
+ char* relpath_both = format("%s %s", output_dep, relpath_obj);
+ if (using_sunpro_dependencies) {
+ x_setenv("SUNPRO_DEPENDENCIES", relpath_both);
+ } else {
+ x_setenv("DEPENDENCIES_OUTPUT", relpath_both);
+ }
+ free(relpath_obj);
+ free(relpath_both);
+ } else {
+ // it's the "file" form.
+
+ dependency_implicit_target_specified = true;
+ // ensure compiler gets relative path.
+ if (using_sunpro_dependencies) {
+ x_setenv("SUNPRO_DEPENDENCIES", output_dep);
+ } else {
+ x_setenv("DEPENDENCIES_OUTPUT", output_dep);
+ }
+ }
+ }
+ }
+
+ if (!input_file) {
+ cc_log("No input file found");
+ stats_update(STATS_NOINPUT);
+ result = false;
+ goto out;
+ }
+
+ if (found_pch || found_fpch_preprocess) {
+ using_precompiled_header = true;
+ if (!(conf->sloppiness & SLOPPY_TIME_MACROS)) {
+ cc_log(
+ "You have to specify \"time_macros\" sloppiness when using"
+ " precompiled headers to get direct hits");
+ cc_log("Disabling direct mode");
+ stats_update(STATS_CANTUSEPCH);
+ result = false;
+ goto out;
+ }
+ }
+
+ if (explicit_language && str_eq(explicit_language, "none")) {
+ explicit_language = NULL;
+ }
+ file_language = language_for_file(input_file);
+ if (explicit_language) {
+ if (!language_is_supported(explicit_language)) {
+ cc_log("Unsupported language: %s", explicit_language);
+ stats_update(STATS_SOURCELANG);
+ result = false;
+ goto out;
+ }
+ actual_language = x_strdup(explicit_language);
+ } else {
+ actual_language = file_language;
+ }
+
+ output_is_precompiled_header =
+ actual_language && strstr(actual_language, "-header");
+
+ if (output_is_precompiled_header
+ && !(conf->sloppiness & SLOPPY_PCH_DEFINES)) {
+ cc_log(
+ "You have to specify \"pch_defines,time_macros\" sloppiness when"
+ " creating precompiled headers");
+ stats_update(STATS_CANTUSEPCH);
+ result = false;
+ goto out;
+ }
+
+ if (!found_c_opt && !found_dc_opt && !found_S_opt) {
+ if (output_is_precompiled_header) {
+ args_add(common_args, "-c");
+ } else {
+ cc_log("No -c option found");
+ // I find that having a separate statistic for autoconf tests is useful,
+ // as they are the dominant form of "called for link" in many cases.
+ if (strstr(input_file, "conftest.")) {
+ stats_update(STATS_CONFTEST);
+ } else {
+ stats_update(STATS_LINK);
+ }
+ result = false;
+ goto out;
+ }
+ }
+
+ if (!actual_language) {
+ cc_log("Unsupported source extension: %s", input_file);
+ stats_update(STATS_SOURCELANG);
+ result = false;
+ goto out;
+ }
+
+ if (!conf->run_second_cpp && str_eq(actual_language, "cu")) {
+ cc_log("Using CUDA compiler; not compiling preprocessed code");
+ conf->run_second_cpp = true;
+ }
+
+ direct_i_file = language_is_preprocessed(actual_language);
+
+ if (output_is_precompiled_header && !conf->run_second_cpp) {
+ // It doesn't work to create the .gch from preprocessed source.
+ cc_log("Creating precompiled header; not compiling preprocessed code");
+ conf->run_second_cpp = true;
+ }
+
+ if (str_eq(conf->cpp_extension, "")) {
+ const char* p_language = p_language_for_language(actual_language);
+ free(conf->cpp_extension);
+ conf->cpp_extension = x_strdup(extension_for_language(p_language) + 1);
+ }
+
+ // Don't try to second guess the compilers heuristics for stdout handling.
+ if (output_obj && str_eq(output_obj, "-")) {
+ stats_update(STATS_OUTSTDOUT);
+ cc_log("Output file is -");
+ result = false;
+ goto out;
+ }
+
+ if (!output_obj) {
+ if (output_is_precompiled_header) {
+ output_obj = format("%s.gch", input_file);
+ } else {
+ char extension = found_S_opt ? 's' : 'o';
+ output_obj = x_basename(input_file);
+ char* p = strrchr(output_obj, '.');
+ if (!p) {
+ reformat(&output_obj, "%s.%c", output_obj, extension);
+ } else if (!p[1]) {
+ reformat(&output_obj, "%s%c", output_obj, extension);
+ } else {
+ p[1] = extension;
+ p[2] = 0;
+ }
+ }
+ }
+
+ if (seen_split_dwarf) {
+ char* p = strrchr(output_obj, '.');
+ if (!p || !p[1]) {
+ cc_log("Badly formed object filename");
+ stats_update(STATS_ARGS);
+ result = false;
+ goto out;
+ }
+
+ char* base_name = remove_extension(output_obj);
+ output_dwo = format("%s.dwo", base_name);
+ free(base_name);
+ }
+
+ // Cope with -o /dev/null.
+ struct stat st;
+ if (!str_eq(output_obj, "/dev/null") && stat(output_obj, &st) == 0
+ && !S_ISREG(st.st_mode)) {
+ cc_log("Not a regular file: %s", output_obj);
+ stats_update(STATS_BADOUTPUTFILE);
+ result = false;
+ goto out;
+ }
+
+ {
+ char* output_dir = x_dirname(output_obj);
+ if (stat(output_dir, &st) != 0 || !S_ISDIR(st.st_mode)) {
+ cc_log("Directory does not exist: %s", output_dir);
+ stats_update(STATS_BADOUTPUTFILE);
+ result = false;
+ free(output_dir);
+ goto out;
+ }
+ free(output_dir);
+ }
+
+ // Some options shouldn't be passed to the real compiler when it compiles
+ // preprocessed code:
+ //
+ // -finput-charset=XXX (otherwise conversion happens twice)
+ // -x XXX (otherwise the wrong language is selected)
+ if (input_charset) {
+ args_add(cpp_args, input_charset);
+ }
+ if (found_pch) {
+ args_add(cpp_args, "-fpch-preprocess");
+ }
+ if (explicit_language) {
+ args_add(cpp_args, "-x");
+ args_add(cpp_args, explicit_language);
+ }
+
+ // Since output is redirected, compilers will not color their output by
+ // default, so force it explicitly if it would be otherwise done.
+ if (!found_color_diagnostics && color_output_possible()) {
+ if (guessed_compiler == GUESSED_CLANG) {
+ if (!str_eq(actual_language, "assembler")) {
+ args_add(common_args, "-fcolor-diagnostics");
+ cc_log("Automatically enabling colors");
+ }
+ } else if (guessed_compiler == GUESSED_GCC) {
+ // GCC has it since 4.9, but that'd require detecting what GCC version is
+ // used for the actual compile. However it requires also GCC_COLORS to be
+ // set (and not empty), so use that for detecting if GCC would use
+ // colors.
+ if (getenv("GCC_COLORS") && getenv("GCC_COLORS")[0] != '\0') {
+ args_add(common_args, "-fdiagnostics-color");
+ cc_log("Automatically enabling colors");
+ }
+ }
+ }
+
+ // Add flags for dependency generation only to the preprocessor command line.
+ if (generating_dependencies) {
+ if (!dependency_filename_specified) {
+ char* base_name = remove_extension(output_obj);
+ char* default_depfile_name = format("%s.d", base_name);
+ free(base_name);
+ args_add(dep_args, "-MF");
+ args_add(dep_args, default_depfile_name);
+ output_dep = make_relative_path(x_strdup(default_depfile_name));
+ }
+
+ if (!dependency_target_specified && !dependency_implicit_target_specified
+ && !str_eq(get_extension(output_dep), ".o")) {
+ args_add(dep_args, "-MQ");
+ args_add(dep_args, output_obj);
+ }
+ }
+ if (generating_coverage) {
+ char* base_name = remove_extension(output_obj);
+ char* default_covfile_name = format("%s.gcno", base_name);
+ free(base_name);
+ output_cov = make_relative_path(default_covfile_name);
+ }
+ if (generating_stackusage) {
+ char* base_name = remove_extension(output_obj);
+ char* default_sufile_name = format("%s.su", base_name);
+ free(base_name);
+ output_su = make_relative_path(default_sufile_name);
+ }
+
+ *compiler_args = args_copy(common_args);
+ args_extend(*compiler_args, compiler_only_args);
+
+ if (conf->run_second_cpp) {
+ args_extend(*compiler_args, cpp_args);
+ } else if (found_directives_only || found_rewrite_includes) {
+ // Need to pass the macros and any other preprocessor directives again.
+ args_extend(*compiler_args, cpp_args);
+ if (found_directives_only) {
+ args_add(cpp_args, "-fdirectives-only");
+ // The preprocessed source code still needs some more preprocessing.
+ args_add(*compiler_args, "-fpreprocessed");
+ args_add(*compiler_args, "-fdirectives-only");
+ }
+ if (found_rewrite_includes) {
+ args_add(cpp_args, "-frewrite-includes");
+ // The preprocessed source code still needs some more preprocessing.
+ args_add(*compiler_args, "-x");
+ args_add(*compiler_args, actual_language);
+ }
+ } else if (explicit_language) {
+ // Workaround for a bug in Apple's patched distcc -- it doesn't properly
+ // reset the language specified with -x, so if -x is given, we have to
+ // specify the preprocessed language explicitly.
+ args_add(*compiler_args, "-x");
+ args_add(*compiler_args, p_language_for_language(explicit_language));
+ }
+
+ if (found_c_opt) {
+ args_add(*compiler_args, "-c");
+ }
+
+ if (found_dc_opt) {
+ args_add(*compiler_args, "-dc");
+ }
+
+ for (size_t i = 0; i < arch_args_size; ++i) {
+ args_add(*compiler_args, "-arch");
+ args_add(*compiler_args, arch_args[i]);
+ }
+
+ // Only pass dependency arguments to the preprocessor since Intel's C++
+ // compiler doesn't produce a correct .d file when compiling preprocessed
+ // source.
+ args_extend(cpp_args, dep_args);
+
+ *preprocessor_args = args_copy(common_args);
+ args_extend(*preprocessor_args, cpp_args);
out:
- args_free(expanded_args);
- args_free(common_args);
- args_free(dep_args);
- args_free(cpp_args);
- return result;
+ args_free(expanded_args);
+ args_free(common_args);
+ args_free(dep_args);
+ args_free(cpp_args);
+ return result;
}
static void
-create_initial_config_file(const char *path)
+create_initial_config_file(const char* path)
{
- if (create_parent_dirs(path) != 0) {
- return;
- }
-
- unsigned max_files;
- uint64_t max_size;
- char *stats_dir = format("%s/0", conf->cache_dir);
- struct stat st;
- if (stat(stats_dir, &st) == 0) {
- stats_get_obsolete_limits(stats_dir, &max_files, &max_size);
- // STATS_MAXFILES and STATS_MAXSIZE was stored for each top directory.
- max_files *= 16;
- max_size *= 16;
- } else {
- max_files = 0;
- max_size = conf->max_size;
- }
- free(stats_dir);
-
- FILE *f = fopen(path, "w");
- if (!f) {
- return;
- }
- if (max_files != 0) {
- fprintf(f, "max_files = %u\n", max_files);
- conf->max_files = max_files;
- }
- if (max_size != 0) {
- char *size = format_parsable_size_with_suffix(max_size);
- fprintf(f, "max_size = %s\n", size);
- free(size);
- conf->max_size = max_size;
- }
- fclose(f);
+ if (create_parent_dirs(path) != 0) {
+ return;
+ }
+
+ unsigned max_files;
+ uint64_t max_size;
+ char* stats_dir = format("%s/0", conf->cache_dir);
+ struct stat st;
+ if (stat(stats_dir, &st) == 0) {
+ stats_get_obsolete_limits(stats_dir, &max_files, &max_size);
+ // STATS_MAXFILES and STATS_MAXSIZE was stored for each top directory.
+ max_files *= 16;
+ max_size *= 16;
+ } else {
+ max_files = 0;
+ max_size = conf->max_size;
+ }
+ free(stats_dir);
+
+ FILE* f = fopen(path, "w");
+ if (!f) {
+ return;
+ }
+ if (max_files != 0) {
+ fprintf(f, "max_files = %u\n", max_files);
+ conf->max_files = max_files;
+ }
+ if (max_size != 0) {
+ char* size = format_parsable_size_with_suffix(max_size);
+ fprintf(f, "max_size = %s\n", size);
+ free(size);
+ conf->max_size = max_size;
+ }
+ fclose(f);
}
#ifdef MTR_ENABLED
-static void *trace_id;
-static char *tmp_trace_file;
+static void* trace_id;
+static char* tmp_trace_file;
static void
-trace_init(char *path)
+trace_init(char* path)
{
- tmp_trace_file = path;
- mtr_init(tmp_trace_file);
- char *s = format("%f", time_seconds());
- MTR_INSTANT_C("", "", "time", s);
+ tmp_trace_file = path;
+ mtr_init(tmp_trace_file);
+ char* s = format("%f", time_seconds());
+ MTR_INSTANT_C("", "", "time", s);
}
static void
trace_start(void)
{
- MTR_META_PROCESS_NAME(MYNAME);
- trace_id = (void *) ((long) getpid());
- MTR_START("program", "ccache", trace_id);
+ MTR_META_PROCESS_NAME(MYNAME);
+ trace_id = (void*)((long)getpid());
+ MTR_START("program", "ccache", trace_id);
}
static void
trace_stop(void)
{
- char *trace_file = format("%s.ccache-trace", output_obj);
- MTR_FINISH("program", "ccache", trace_id);
- mtr_flush();
- mtr_shutdown();
- move_file(tmp_trace_file, trace_file);
- free(trace_file);
- free(tmp_trace_file);
+ char* trace_file = format("%s.ccache-trace", output_obj);
+ MTR_FINISH("program", "ccache", trace_id);
+ mtr_flush();
+ mtr_shutdown();
+ move_file(tmp_trace_file, trace_file);
+ free(trace_file);
+ free(tmp_trace_file);
}
-static const char *
+static const char*
tmpdir()
{
-#ifndef _WIN32
- const char *tmpdir = getenv("TMPDIR");
- if (tmpdir != NULL) {
- return tmpdir;
- }
-#else
- static char dirbuf[PATH_MAX];
- DWORD retval = GetTempPath(PATH_MAX, dirbuf);
- if (retval > 0 && retval < PATH_MAX) {
- return dirbuf;
- }
-#endif
- return "/tmp";
+# ifndef _WIN32
+ const char* tmpdir = getenv("TMPDIR");
+ if (tmpdir != NULL) {
+ return tmpdir;
+ }
+# else
+ static char dirbuf[PATH_MAX];
+ DWORD retval = GetTempPath(PATH_MAX, dirbuf);
+ if (retval > 0 && retval < PATH_MAX) {
+ return dirbuf;
+ }
+# endif
+ return "/tmp";
}
#endif // MTR_ENABLED
@@ -3498,153 +3502,177 @@ tmpdir()
static void
initialize(void)
{
- bool enable_internal_trace = getenv("CCACHE_INTERNAL_TRACE");
- if (enable_internal_trace) {
+ bool enable_internal_trace = getenv("CCACHE_INTERNAL_TRACE");
+ if (enable_internal_trace) {
#ifdef MTR_ENABLED
- // We don't have any conf yet, so we can't use temp_dir() here.
- trace_init(format("%s/tmp.ccache-trace.%d", tmpdir(), (int)getpid()));
+ // We don't have any conf yet, so we can't use temp_dir() here.
+ trace_init(format("%s/tmp.ccache-trace.%d", tmpdir(), (int)getpid()));
#endif
- }
-
- conf_free(conf);
- MTR_BEGIN("config", "conf_create");
- conf = conf_create();
- MTR_END("config", "conf_create");
-
- char *errmsg;
- char *p = getenv("CCACHE_CONFIGPATH");
- if (p) {
- primary_config_path = x_strdup(p);
- } else {
- secondary_config_path = format("%s/ccache.conf", TO_STRING(SYSCONFDIR));
- MTR_BEGIN("config", "conf_read_secondary");
- if (!conf_read(conf, secondary_config_path, &errmsg)) {
- if (errno == 0) {
- // We could read the file but it contained errors.
- fatal("%s", errmsg);
- }
- // A missing config file in SYSCONFDIR is OK.
- free(errmsg);
- }
- MTR_END("config", "conf_read_secondary");
-
- if (str_eq(conf->cache_dir, "")) {
- fatal("configuration setting \"cache_dir\" must not be the empty string");
- }
- if ((p = getenv("CCACHE_DIR"))) {
- free(conf->cache_dir);
- conf->cache_dir = strdup(p);
- }
- if (str_eq(conf->cache_dir, "")) {
- fatal("CCACHE_DIR must not be the empty string");
- }
-
- primary_config_path = format("%s/ccache.conf", conf->cache_dir);
- }
-
- bool should_create_initial_config = false;
- MTR_BEGIN("config", "conf_read_primary");
- if (!conf_read(conf, primary_config_path, &errmsg)) {
- if (errno == 0) {
- // We could read the file but it contained errors.
- fatal("%s", errmsg);
- }
- if (!conf->disable) {
- should_create_initial_config = true;
- }
- }
- MTR_END("config", "conf_read_primary");
-
- MTR_BEGIN("config", "conf_update_from_environment");
- if (!conf_update_from_environment(conf, &errmsg)) {
- fatal("%s", errmsg);
- }
- MTR_END("config", "conf_update_from_environment");
-
- if (should_create_initial_config) {
- create_initial_config_file(primary_config_path);
- }
-
- exitfn_init();
- exitfn_add_nullary(stats_flush);
- exitfn_add_nullary(clean_up_pending_tmp_files);
-
- cc_log("=== CCACHE %s STARTED =========================================",
- CCACHE_VERSION);
-
- if (conf->umask != UINT_MAX) {
- umask(conf->umask);
- }
-
- if (enable_internal_trace) {
+ }
+
+ conf_free(conf);
+ MTR_BEGIN("config", "conf_create");
+ conf = conf_create();
+ MTR_END("config", "conf_create");
+
+ char* errmsg;
+ char* p = getenv("CCACHE_CONFIGPATH");
+ if (p) {
+ primary_config_path = x_strdup(p);
+ } else {
+ secondary_config_path = format("%s/ccache.conf", TO_STRING(SYSCONFDIR));
+ MTR_BEGIN("config", "conf_read_secondary");
+ if (!conf_read(conf, secondary_config_path, &errmsg)) {
+ if (errno == 0) {
+ // We could read the file but it contained errors.
+ fatal("%s", errmsg);
+ }
+ // A missing config file in SYSCONFDIR is OK.
+ free(errmsg);
+ }
+ MTR_END("config", "conf_read_secondary");
+
+ if (str_eq(conf->cache_dir, "")) {
+ fatal("configuration setting \"cache_dir\" must not be the empty string");
+ }
+ if ((p = getenv("CCACHE_DIR"))) {
+ free(conf->cache_dir);
+ conf->cache_dir = strdup(p);
+ }
+ if (str_eq(conf->cache_dir, "")) {
+ fatal("CCACHE_DIR must not be the empty string");
+ }
+
+ primary_config_path = format("%s/ccache.conf", conf->cache_dir);
+ }
+
+ bool should_create_initial_config = false;
+ MTR_BEGIN("config", "conf_read_primary");
+ if (!conf_read(conf, primary_config_path, &errmsg)) {
+ if (errno == 0) {
+ // We could read the file but it contained errors.
+ fatal("%s", errmsg);
+ }
+ if (!conf->disable) {
+ should_create_initial_config = true;
+ }
+ }
+ MTR_END("config", "conf_read_primary");
+
+ MTR_BEGIN("config", "conf_update_from_environment");
+ if (!conf_update_from_environment(conf, &errmsg)) {
+ fatal("%s", errmsg);
+ }
+ MTR_END("config", "conf_update_from_environment");
+
+ if (should_create_initial_config) {
+ create_initial_config_file(primary_config_path);
+ }
+
+ exitfn_init();
+ exitfn_add_nullary(stats_flush);
+ exitfn_add_nullary(clean_up_pending_tmp_files);
+
+ cc_log("=== CCACHE %s STARTED =========================================",
+ CCACHE_VERSION);
+
+ if (conf->umask != UINT_MAX) {
+ umask(conf->umask);
+ }
+
+ if (enable_internal_trace) {
#ifdef MTR_ENABLED
- trace_start();
- exitfn_add_nullary(trace_stop);
+ trace_start();
+ exitfn_add_nullary(trace_stop);
#else
- cc_log("Error: tracing is not enabled!");
+ cc_log("Error: tracing is not enabled!");
#endif
- }
+ }
}
// Reset the global state. Used by the test suite.
void
cc_reset(void)
{
- conf_free(conf); conf = NULL;
- free(primary_config_path); primary_config_path = NULL;
- free(secondary_config_path); secondary_config_path = NULL;
- free(current_working_dir); current_working_dir = NULL;
- for (size_t i = 0; i < debug_prefix_maps_len; i++) {
- free(debug_prefix_maps[i]);
- debug_prefix_maps[i] = NULL;
- }
- free(debug_prefix_maps); debug_prefix_maps = NULL;
- debug_prefix_maps_len = 0;
- free(profile_dir); profile_dir = NULL;
- for (size_t i = 0; i < sanitize_blacklists_len; i++) {
- free(sanitize_blacklists[i]);
- sanitize_blacklists[i] = NULL;
- }
- free(sanitize_blacklists); sanitize_blacklists = NULL;
- sanitize_blacklists_len = 0;
- free(included_pch_file); included_pch_file = NULL;
- args_free(orig_args); orig_args = NULL;
- free(input_file); input_file = NULL;
- free(output_obj); output_obj = NULL;
- free(output_dep); output_dep = NULL;
- free(output_cov); output_cov = NULL;
- free(output_su); output_su = NULL;
- free(output_dia); output_dia = NULL;
- free(output_dwo); output_dwo = NULL;
- free(cached_result_name); cached_result_name = NULL;
- free(cached_result_path); cached_result_path = NULL;
- free(manifest_path); manifest_path = NULL;
- time_of_compilation = 0;
- for (size_t i = 0; i < ignore_headers_len; i++) {
- free(ignore_headers[i]);
- ignore_headers[i] = NULL;
- }
- free(ignore_headers); ignore_headers = NULL;
- ignore_headers_len = 0;
- if (included_files) {
- hashtable_destroy(included_files, 1); included_files = NULL;
- }
- has_absolute_include_headers = false;
- generating_debuginfo = false;
- generating_debuginfo_level_3 = false;
- generating_dependencies = false;
- generating_coverage = false;
- generating_stackusage = false;
- profile_arcs = false;
- free(profile_dir); profile_dir = NULL;
- i_tmpfile = NULL;
- direct_i_file = false;
- free(cpp_stderr); cpp_stderr = NULL;
- free(stats_file); stats_file = NULL;
- output_is_precompiled_header = false;
-
- conf = conf_create();
- seen_split_dwarf = false;
+ conf_free(conf);
+ conf = NULL;
+ free(primary_config_path);
+ primary_config_path = NULL;
+ free(secondary_config_path);
+ secondary_config_path = NULL;
+ free(current_working_dir);
+ current_working_dir = NULL;
+ for (size_t i = 0; i < debug_prefix_maps_len; i++) {
+ free(debug_prefix_maps[i]);
+ debug_prefix_maps[i] = NULL;
+ }
+ free(debug_prefix_maps);
+ debug_prefix_maps = NULL;
+ debug_prefix_maps_len = 0;
+ free(profile_dir);
+ profile_dir = NULL;
+ for (size_t i = 0; i < sanitize_blacklists_len; i++) {
+ free(sanitize_blacklists[i]);
+ sanitize_blacklists[i] = NULL;
+ }
+ free(sanitize_blacklists);
+ sanitize_blacklists = NULL;
+ sanitize_blacklists_len = 0;
+ free(included_pch_file);
+ included_pch_file = NULL;
+ args_free(orig_args);
+ orig_args = NULL;
+ free(input_file);
+ input_file = NULL;
+ free(output_obj);
+ output_obj = NULL;
+ free(output_dep);
+ output_dep = NULL;
+ free(output_cov);
+ output_cov = NULL;
+ free(output_su);
+ output_su = NULL;
+ free(output_dia);
+ output_dia = NULL;
+ free(output_dwo);
+ output_dwo = NULL;
+ free(cached_result_name);
+ cached_result_name = NULL;
+ free(cached_result_path);
+ cached_result_path = NULL;
+ free(manifest_path);
+ manifest_path = NULL;
+ time_of_compilation = 0;
+ for (size_t i = 0; i < ignore_headers_len; i++) {
+ free(ignore_headers[i]);
+ ignore_headers[i] = NULL;
+ }
+ free(ignore_headers);
+ ignore_headers = NULL;
+ ignore_headers_len = 0;
+ if (included_files) {
+ hashtable_destroy(included_files, 1);
+ included_files = NULL;
+ }
+ has_absolute_include_headers = false;
+ generating_debuginfo = false;
+ generating_debuginfo_level_3 = false;
+ generating_dependencies = false;
+ generating_coverage = false;
+ generating_stackusage = false;
+ profile_arcs = false;
+ free(profile_dir);
+ profile_dir = NULL;
+ i_tmpfile = NULL;
+ direct_i_file = false;
+ free(cpp_stderr);
+ cpp_stderr = NULL;
+ free(stats_file);
+ stats_file = NULL;
+ output_is_precompiled_header = false;
+
+ conf = conf_create();
+ seen_split_dwarf = false;
}
// Make a copy of stderr that will not be cached, so things like distcc can
@@ -3652,441 +3680,434 @@ cc_reset(void)
static void
set_up_uncached_err(void)
{
- int uncached_fd = dup(2); // The file descriptor is intentionally leaked.
- if (uncached_fd == -1) {
- cc_log("dup(2) failed: %s", strerror(errno));
- failed();
- }
-
- // Leak a pointer to the environment.
- char *buf = format("UNCACHED_ERR_FD=%d", uncached_fd);
- if (putenv(buf) == -1) {
- cc_log("putenv failed: %s", strerror(errno));
- failed();
- }
+ int uncached_fd = dup(2); // The file descriptor is intentionally leaked.
+ if (uncached_fd == -1) {
+ cc_log("dup(2) failed: %s", strerror(errno));
+ failed();
+ }
+
+ // Leak a pointer to the environment.
+ char* buf = format("UNCACHED_ERR_FD=%d", uncached_fd);
+ if (putenv(buf) == -1) {
+ cc_log("putenv failed: %s", strerror(errno));
+ failed();
+ }
}
static void
-configuration_logger(const char *descr, const char *origin, void *context)
+configuration_logger(const char* descr, const char* origin, void* context)
{
- (void)context;
- cc_bulklog("Config: (%s) %s", origin, descr);
+ (void)context;
+ cc_bulklog("Config: (%s) %s", origin, descr);
}
-static void ccache(int argc, char *argv[]) ATTR_NORETURN;
+static void ccache(int argc, char* argv[]) ATTR_NORETURN;
// The main ccache driver function.
static void
-ccache(int argc, char *argv[])
+ccache(int argc, char* argv[])
{
#ifndef _WIN32
- set_up_signal_handlers();
+ set_up_signal_handlers();
#endif
- // Needed for portability when using localtime_r.
- tzset();
-
- orig_args = args_init(argc, argv);
-
- initialize();
- MTR_BEGIN("main", "find_compiler");
- find_compiler(argv);
- MTR_END("main", "find_compiler");
-
- MTR_BEGIN("main", "clean_up_internal_tempdir");
- if (str_eq(conf->temporary_dir, "")) {
- clean_up_internal_tempdir();
- }
- MTR_END("main", "clean_up_internal_tempdir");
-
- if (!str_eq(conf->log_file, "") || conf->debug) {
- conf_print_items(conf, configuration_logger, NULL);
- }
-
- if (conf->disable) {
- cc_log("ccache is disabled");
- failed();
- }
-
- MTR_BEGIN("main", "set_up_uncached_err");
- set_up_uncached_err();
- MTR_END("main", "set_up_uncached_err");
-
- cc_log_argv("Command line: ", argv);
- cc_log("Hostname: %s", get_hostname());
- cc_log("Working directory: %s", get_current_working_dir());
-
- conf->limit_multiple = MIN(MAX(conf->limit_multiple, 0.0), 1.0);
-
- MTR_BEGIN("main", "guess_compiler");
- guessed_compiler = guess_compiler(orig_args->argv[0]);
- MTR_END("main", "guess_compiler");
-
- // Arguments (except -E) to send to the preprocessor.
- struct args *preprocessor_args;
- // Arguments to send to the real compiler.
- struct args *compiler_args;
- MTR_BEGIN("main", "process_args");
- if (!cc_process_args(orig_args, &preprocessor_args, &compiler_args)) {
- failed();
- }
- MTR_END("main", "process_args");
-
- if (conf->depend_mode
- && (!generating_dependencies || str_eq(output_dep, "/dev/null")
- || !conf->run_second_cpp || conf->unify)) {
- cc_log("Disabling depend mode");
- conf->depend_mode = false;
- }
-
- cc_log("Source file: %s", input_file);
- if (generating_dependencies) {
- cc_log("Dependency file: %s", output_dep);
- }
- if (generating_coverage) {
- cc_log("Coverage file: %s", output_cov);
- }
- if (generating_stackusage) {
- cc_log("Stack usage file: %s", output_su);
- }
- if (generating_diagnostics) {
- cc_log("Diagnostics file: %s", output_dia);
- }
- if (output_dwo) {
- cc_log("Split dwarf file: %s", output_dwo);
- }
-
- cc_log("Object file: %s", output_obj);
- MTR_META_THREAD_NAME(output_obj);
-
- // Need to dump log buffer as the last exit function to not lose any logs.
- exitfn_add_last(dump_debug_log_buffer_exitfn, output_obj);
-
- FILE *debug_text_file = NULL;
- if (conf->debug) {
- char *path = format("%s.ccache-input-text", output_obj);
- debug_text_file = fopen(path, "w");
- if (debug_text_file) {
- exitfn_add(fclose_exitfn, debug_text_file);
- } else {
- cc_log("Failed to open %s: %s", path, strerror(errno));
- }
- free(path);
- }
-
- struct hash *common_hash = hash_init();
- init_hash_debug(common_hash, output_obj, 'c', "COMMON", debug_text_file);
-
- MTR_BEGIN("hash", "common_hash");
- hash_common_info(preprocessor_args, common_hash);
- MTR_END("hash", "common_hash");
-
- // Try to find the hash using the manifest.
- struct hash *direct_hash = hash_copy(common_hash);
- init_hash_debug(
- direct_hash, output_obj, 'd', "DIRECT MODE", debug_text_file);
-
- bool put_result_in_manifest = false;
- struct digest *result_name = NULL;
- struct digest *result_name_from_manifest = NULL;
- if (conf->direct_mode) {
- cc_log("Trying direct lookup");
- MTR_BEGIN("hash", "direct_hash");
- result_name = calculate_result_name(preprocessor_args, direct_hash, 1);
- MTR_END("hash", "direct_hash");
- if (result_name) {
- update_cached_result_globals(result_name);
-
- // If we can return from cache at this point then do so.
- from_cache(FROMCACHE_DIRECT_MODE, 0);
-
- // Wasn't able to return from cache at this point. However, the result
- // was already found in manifest, so don't re-add it later.
- put_result_in_manifest = false;
-
- result_name_from_manifest = result_name;
- } else {
- // Add result to manifest later.
- put_result_in_manifest = true;
- }
- }
-
- if (conf->read_only_direct) {
- cc_log("Read-only direct mode; running real compiler");
- failed();
- }
-
- if (!conf->depend_mode) {
- // Find the hash using the preprocessed output. Also updates
- // included_files.
- struct hash *cpp_hash = hash_copy(common_hash);
- init_hash_debug(
- cpp_hash, output_obj, 'p', "PREPROCESSOR MODE", debug_text_file);
-
- MTR_BEGIN("hash", "cpp_hash");
- result_name = calculate_result_name(preprocessor_args, cpp_hash, 0);
- MTR_END("hash", "cpp_hash");
- if (!result_name) {
- fatal("internal error: calculate_result_name returned NULL for cpp");
- }
- update_cached_result_globals(result_name);
-
- if (result_name_from_manifest
- && !digests_equal(result_name_from_manifest, result_name)) {
- // The hash from manifest differs from the hash of the preprocessor
- // output. This could be because:
- //
- // - The preprocessor produces different output for the same input (not
- // likely).
- // - There's a bug in ccache (maybe incorrect handling of compiler
- // arguments).
- // - The user has used a different CCACHE_BASEDIR (most likely).
- //
- // The best thing here would probably be to remove the hash entry from
- // the manifest. For now, we use a simpler method: just remove the
- // manifest file.
- cc_log("Hash from manifest doesn't match preprocessor output");
- cc_log("Likely reason: different CCACHE_BASEDIRs used");
- cc_log("Removing manifest as a safety measure");
- x_unlink(manifest_path);
-
- put_result_in_manifest = true;
- }
-
- // If we can return from cache at this point then do.
- from_cache(FROMCACHE_CPP_MODE, put_result_in_manifest);
- }
-
- if (conf->read_only) {
- cc_log("Read-only mode; running real compiler");
- failed();
- }
-
- add_prefix(compiler_args, conf->prefix_command);
-
- // In depend_mode, extend the direct hash.
- struct hash *depend_mode_hash = conf->depend_mode ? direct_hash : NULL;
-
- // Run real compiler, sending output to cache.
- MTR_BEGIN("cache", "to_cache");
- to_cache(compiler_args, depend_mode_hash);
- MTR_END("cache", "to_cache");
-
- x_exit(0);
+ // Needed for portability when using localtime_r.
+ tzset();
+
+ orig_args = args_init(argc, argv);
+
+ initialize();
+ MTR_BEGIN("main", "find_compiler");
+ find_compiler(argv);
+ MTR_END("main", "find_compiler");
+
+ MTR_BEGIN("main", "clean_up_internal_tempdir");
+ if (str_eq(conf->temporary_dir, "")) {
+ clean_up_internal_tempdir();
+ }
+ MTR_END("main", "clean_up_internal_tempdir");
+
+ if (!str_eq(conf->log_file, "") || conf->debug) {
+ conf_print_items(conf, configuration_logger, NULL);
+ }
+
+ if (conf->disable) {
+ cc_log("ccache is disabled");
+ failed();
+ }
+
+ MTR_BEGIN("main", "set_up_uncached_err");
+ set_up_uncached_err();
+ MTR_END("main", "set_up_uncached_err");
+
+ cc_log_argv("Command line: ", argv);
+ cc_log("Hostname: %s", get_hostname());
+ cc_log("Working directory: %s", get_current_working_dir());
+
+ conf->limit_multiple = MIN(MAX(conf->limit_multiple, 0.0), 1.0);
+
+ MTR_BEGIN("main", "guess_compiler");
+ guessed_compiler = guess_compiler(orig_args->argv[0]);
+ MTR_END("main", "guess_compiler");
+
+ // Arguments (except -E) to send to the preprocessor.
+ struct args* preprocessor_args;
+ // Arguments to send to the real compiler.
+ struct args* compiler_args;
+ MTR_BEGIN("main", "process_args");
+ if (!cc_process_args(orig_args, &preprocessor_args, &compiler_args)) {
+ failed();
+ }
+ MTR_END("main", "process_args");
+
+ if (conf->depend_mode
+ && (!generating_dependencies || str_eq(output_dep, "/dev/null")
+ || !conf->run_second_cpp || conf->unify)) {
+ cc_log("Disabling depend mode");
+ conf->depend_mode = false;
+ }
+
+ cc_log("Source file: %s", input_file);
+ if (generating_dependencies) {
+ cc_log("Dependency file: %s", output_dep);
+ }
+ if (generating_coverage) {
+ cc_log("Coverage file: %s", output_cov);
+ }
+ if (generating_stackusage) {
+ cc_log("Stack usage file: %s", output_su);
+ }
+ if (generating_diagnostics) {
+ cc_log("Diagnostics file: %s", output_dia);
+ }
+ if (output_dwo) {
+ cc_log("Split dwarf file: %s", output_dwo);
+ }
+
+ cc_log("Object file: %s", output_obj);
+ MTR_META_THREAD_NAME(output_obj);
+
+ // Need to dump log buffer as the last exit function to not lose any logs.
+ exitfn_add_last(dump_debug_log_buffer_exitfn, output_obj);
+
+ FILE* debug_text_file = NULL;
+ if (conf->debug) {
+ char* path = format("%s.ccache-input-text", output_obj);
+ debug_text_file = fopen(path, "w");
+ if (debug_text_file) {
+ exitfn_add(fclose_exitfn, debug_text_file);
+ } else {
+ cc_log("Failed to open %s: %s", path, strerror(errno));
+ }
+ free(path);
+ }
+
+ struct hash* common_hash = hash_init();
+ init_hash_debug(common_hash, output_obj, 'c', "COMMON", debug_text_file);
+
+ MTR_BEGIN("hash", "common_hash");
+ hash_common_info(preprocessor_args, common_hash);
+ MTR_END("hash", "common_hash");
+
+ // Try to find the hash using the manifest.
+ struct hash* direct_hash = hash_copy(common_hash);
+ init_hash_debug(direct_hash, output_obj, 'd', "DIRECT MODE", debug_text_file);
+
+ bool put_result_in_manifest = false;
+ struct digest* result_name = NULL;
+ struct digest* result_name_from_manifest = NULL;
+ if (conf->direct_mode) {
+ cc_log("Trying direct lookup");
+ MTR_BEGIN("hash", "direct_hash");
+ result_name = calculate_result_name(preprocessor_args, direct_hash, 1);
+ MTR_END("hash", "direct_hash");
+ if (result_name) {
+ update_cached_result_globals(result_name);
+
+ // If we can return from cache at this point then do so.
+ from_cache(FROMCACHE_DIRECT_MODE, 0);
+
+ // Wasn't able to return from cache at this point. However, the result
+ // was already found in manifest, so don't re-add it later.
+ put_result_in_manifest = false;
+
+ result_name_from_manifest = result_name;
+ } else {
+ // Add result to manifest later.
+ put_result_in_manifest = true;
+ }
+ }
+
+ if (conf->read_only_direct) {
+ cc_log("Read-only direct mode; running real compiler");
+ failed();
+ }
+
+ if (!conf->depend_mode) {
+ // Find the hash using the preprocessed output. Also updates
+ // included_files.
+ struct hash* cpp_hash = hash_copy(common_hash);
+ init_hash_debug(
+ cpp_hash, output_obj, 'p', "PREPROCESSOR MODE", debug_text_file);
+
+ MTR_BEGIN("hash", "cpp_hash");
+ result_name = calculate_result_name(preprocessor_args, cpp_hash, 0);
+ MTR_END("hash", "cpp_hash");
+ if (!result_name) {
+ fatal("internal error: calculate_result_name returned NULL for cpp");
+ }
+ update_cached_result_globals(result_name);
+
+ if (result_name_from_manifest
+ && !digests_equal(result_name_from_manifest, result_name)) {
+ // The hash from manifest differs from the hash of the preprocessor
+ // output. This could be because:
+ //
+ // - The preprocessor produces different output for the same input (not
+ // likely).
+ // - There's a bug in ccache (maybe incorrect handling of compiler
+ // arguments).
+ // - The user has used a different CCACHE_BASEDIR (most likely).
+ //
+ // The best thing here would probably be to remove the hash entry from
+ // the manifest. For now, we use a simpler method: just remove the
+ // manifest file.
+ cc_log("Hash from manifest doesn't match preprocessor output");
+ cc_log("Likely reason: different CCACHE_BASEDIRs used");
+ cc_log("Removing manifest as a safety measure");
+ x_unlink(manifest_path);
+
+ put_result_in_manifest = true;
+ }
+
+ // If we can return from cache at this point then do.
+ from_cache(FROMCACHE_CPP_MODE, put_result_in_manifest);
+ }
+
+ if (conf->read_only) {
+ cc_log("Read-only mode; running real compiler");
+ failed();
+ }
+
+ add_prefix(compiler_args, conf->prefix_command);
+
+ // In depend_mode, extend the direct hash.
+ struct hash* depend_mode_hash = conf->depend_mode ? direct_hash : NULL;
+
+ // Run real compiler, sending output to cache.
+ MTR_BEGIN("cache", "to_cache");
+ to_cache(compiler_args, depend_mode_hash);
+ MTR_END("cache", "to_cache");
+
+ x_exit(0);
}
static void
-configuration_printer(const char *descr, const char *origin, void *context)
+configuration_printer(const char* descr, const char* origin, void* context)
{
- assert(context);
- auto f = static_cast<FILE*>(context);
- fprintf(f, "(%s) %s\n", origin, descr);
+ assert(context);
+ auto f = static_cast<FILE*>(context);
+ fprintf(f, "(%s) %s\n", origin, descr);
}
// The main program when not doing a compile.
static int
-ccache_main_options(int argc, char *argv[])
+ccache_main_options(int argc, char* argv[])
{
- enum longopts {
- DUMP_MANIFEST,
- DUMP_RESULT,
- HASH_FILE,
- PRINT_STATS,
- };
- static const struct option options[] = {
- {"cleanup", no_argument, 0, 'c'},
- {"clear", no_argument, 0, 'C'},
- {"dump-manifest", required_argument, 0, DUMP_MANIFEST},
- {"dump-result", required_argument, 0, DUMP_RESULT},
- {"get-config", required_argument, 0, 'k'},
- {"hash-file", required_argument, 0, HASH_FILE},
- {"help", no_argument, 0, 'h'},
- {"max-files", required_argument, 0, 'F'},
- {"max-size", required_argument, 0, 'M'},
- {"print-stats", no_argument, 0, PRINT_STATS},
- {"set-config", required_argument, 0, 'o'},
- {"show-compression", no_argument, 0, 'x'},
- {"show-config", no_argument, 0, 'p'},
- {"show-stats", no_argument, 0, 's'},
- {"version", no_argument, 0, 'V'},
- {"zero-stats", no_argument, 0, 'z'},
- {0, 0, 0, 0}
- };
-
- int c;
- while ((c = getopt_long(argc, argv, "cCk:hF:M:po:sVxz", options, NULL))
- != -1) {
- switch (c) {
- case DUMP_MANIFEST:
- initialize();
- manifest_dump(optarg, stdout);
- break;
-
- case DUMP_RESULT:
- initialize();
- if (!result_dump(optarg, stdout)) {
- return 1;
- }
- break;
-
- case HASH_FILE:
- {
- initialize();
- struct hash *hash = hash_init();
- if (str_eq(optarg, "-")) {
- hash_fd(hash, STDIN_FILENO);
- } else {
- hash_file(hash, optarg);
- }
- char digest[DIGEST_STRING_BUFFER_SIZE];
- hash_result_as_string(hash, digest);
- puts(digest);
- hash_free(hash);
- break;
- }
-
- case PRINT_STATS:
- initialize();
- stats_print();
- break;
-
- case 'c': // --cleanup
- initialize();
- clean_up_all(conf);
- printf("Cleaned cache\n");
- break;
-
- case 'C': // --clear
- initialize();
- wipe_all(conf);
- printf("Cleared cache\n");
- break;
-
- case 'h': // --help
- fputs(USAGE_TEXT, stdout);
- x_exit(0);
-
- case 'k': // --get-config
- {
- initialize();
- char *errmsg;
- if (!conf_print_value(conf, optarg, stdout, &errmsg)) {
- fatal("%s", errmsg);
- }
- }
- break;
-
- case 'F': // --max-files
- {
- initialize();
- char *errmsg;
- if (conf_set_value_in_file(primary_config_path, "max_files", optarg,
- &errmsg)) {
- unsigned files = atoi(optarg);
- if (files == 0) {
- printf("Unset cache file limit\n");
- } else {
- printf("Set cache file limit to %u\n", files);
- }
- } else {
- fatal("could not set cache file limit: %s", errmsg);
- }
- }
- break;
-
- case 'M': // --max-size
- {
- initialize();
- uint64_t size;
- if (!parse_size_with_suffix(optarg, &size)) {
- fatal("invalid size: %s", optarg);
- }
- char *errmsg;
- if (conf_set_value_in_file(primary_config_path, "max_size", optarg,
- &errmsg)) {
- if (size == 0) {
- printf("Unset cache size limit\n");
- } else {
- char *s = format_human_readable_size(size);
- printf("Set cache size limit to %s\n", s);
- free(s);
- }
- } else {
- fatal("could not set cache size limit: %s", errmsg);
- }
- }
- break;
-
- case 'o': // --set-config
- {
- initialize();
- char *p = strchr(optarg, '=');
- if (!p) {
- fatal("missing equal sign in \"%s\"", optarg);
- }
- char *key = x_strndup(optarg, p - optarg);
- char *value = p + 1;
- char *errmsg;
- if (!conf_set_value_in_file(primary_config_path, key, value, &errmsg)) {
- fatal("%s", errmsg);
- }
- free(key);
- }
- break;
-
- case 'p': // --show-config
- initialize();
- conf_print_items(conf, configuration_printer, stdout);
- break;
-
- case 's': // --show-stats
- initialize();
- stats_summary();
- break;
-
- case 'V': // --version
- fprintf(stdout, VERSION_TEXT, CCACHE_VERSION);
- x_exit(0);
-
- case 'x': // --show-compression
- initialize();
- compress_stats(conf);
- break;
-
- case 'z': // --zero-stats
- initialize();
- stats_zero();
- printf("Statistics zeroed\n");
- break;
-
- default:
- fputs(USAGE_TEXT, stderr);
- x_exit(1);
- }
- }
-
- return 0;
+ enum longopts {
+ DUMP_MANIFEST,
+ DUMP_RESULT,
+ HASH_FILE,
+ PRINT_STATS,
+ };
+ static const struct option options[] = {
+ {"cleanup", no_argument, 0, 'c'},
+ {"clear", no_argument, 0, 'C'},
+ {"dump-manifest", required_argument, 0, DUMP_MANIFEST},
+ {"dump-result", required_argument, 0, DUMP_RESULT},
+ {"get-config", required_argument, 0, 'k'},
+ {"hash-file", required_argument, 0, HASH_FILE},
+ {"help", no_argument, 0, 'h'},
+ {"max-files", required_argument, 0, 'F'},
+ {"max-size", required_argument, 0, 'M'},
+ {"print-stats", no_argument, 0, PRINT_STATS},
+ {"set-config", required_argument, 0, 'o'},
+ {"show-compression", no_argument, 0, 'x'},
+ {"show-config", no_argument, 0, 'p'},
+ {"show-stats", no_argument, 0, 's'},
+ {"version", no_argument, 0, 'V'},
+ {"zero-stats", no_argument, 0, 'z'},
+ {0, 0, 0, 0}};
+
+ int c;
+ while ((c = getopt_long(argc, argv, "cCk:hF:M:po:sVxz", options, NULL))
+ != -1) {
+ switch (c) {
+ case DUMP_MANIFEST:
+ initialize();
+ manifest_dump(optarg, stdout);
+ break;
+
+ case DUMP_RESULT:
+ initialize();
+ if (!result_dump(optarg, stdout)) {
+ return 1;
+ }
+ break;
+
+ case HASH_FILE: {
+ initialize();
+ struct hash* hash = hash_init();
+ if (str_eq(optarg, "-")) {
+ hash_fd(hash, STDIN_FILENO);
+ } else {
+ hash_file(hash, optarg);
+ }
+ char digest[DIGEST_STRING_BUFFER_SIZE];
+ hash_result_as_string(hash, digest);
+ puts(digest);
+ hash_free(hash);
+ break;
+ }
+
+ case PRINT_STATS:
+ initialize();
+ stats_print();
+ break;
+
+ case 'c': // --cleanup
+ initialize();
+ clean_up_all(conf);
+ printf("Cleaned cache\n");
+ break;
+
+ case 'C': // --clear
+ initialize();
+ wipe_all(conf);
+ printf("Cleared cache\n");
+ break;
+
+ case 'h': // --help
+ fputs(USAGE_TEXT, stdout);
+ x_exit(0);
+
+ case 'k': // --get-config
+ {
+ initialize();
+ char* errmsg;
+ if (!conf_print_value(conf, optarg, stdout, &errmsg)) {
+ fatal("%s", errmsg);
+ }
+ } break;
+
+ case 'F': // --max-files
+ {
+ initialize();
+ char* errmsg;
+ if (conf_set_value_in_file(
+ primary_config_path, "max_files", optarg, &errmsg)) {
+ unsigned files = atoi(optarg);
+ if (files == 0) {
+ printf("Unset cache file limit\n");
+ } else {
+ printf("Set cache file limit to %u\n", files);
+ }
+ } else {
+ fatal("could not set cache file limit: %s", errmsg);
+ }
+ } break;
+
+ case 'M': // --max-size
+ {
+ initialize();
+ uint64_t size;
+ if (!parse_size_with_suffix(optarg, &size)) {
+ fatal("invalid size: %s", optarg);
+ }
+ char* errmsg;
+ if (conf_set_value_in_file(
+ primary_config_path, "max_size", optarg, &errmsg)) {
+ if (size == 0) {
+ printf("Unset cache size limit\n");
+ } else {
+ char* s = format_human_readable_size(size);
+ printf("Set cache size limit to %s\n", s);
+ free(s);
+ }
+ } else {
+ fatal("could not set cache size limit: %s", errmsg);
+ }
+ } break;
+
+ case 'o': // --set-config
+ {
+ initialize();
+ char* p = strchr(optarg, '=');
+ if (!p) {
+ fatal("missing equal sign in \"%s\"", optarg);
+ }
+ char* key = x_strndup(optarg, p - optarg);
+ char* value = p + 1;
+ char* errmsg;
+ if (!conf_set_value_in_file(primary_config_path, key, value, &errmsg)) {
+ fatal("%s", errmsg);
+ }
+ free(key);
+ } break;
+
+ case 'p': // --show-config
+ initialize();
+ conf_print_items(conf, configuration_printer, stdout);
+ break;
+
+ case 's': // --show-stats
+ initialize();
+ stats_summary();
+ break;
+
+ case 'V': // --version
+ fprintf(stdout, VERSION_TEXT, CCACHE_VERSION);
+ x_exit(0);
+
+ case 'x': // --show-compression
+ initialize();
+ compress_stats(conf);
+ break;
+
+ case 'z': // --zero-stats
+ initialize();
+ stats_zero();
+ printf("Statistics zeroed\n");
+ break;
+
+ default:
+ fputs(USAGE_TEXT, stderr);
+ x_exit(1);
+ }
+ }
+
+ return 0;
}
-int ccache_main(int argc, char *argv[]);
+int ccache_main(int argc, char* argv[]);
int
-ccache_main(int argc, char *argv[])
+ccache_main(int argc, char* argv[])
{
- // Check if we are being invoked as "ccache".
- char *program_name = x_basename(argv[0]);
- if (same_executable_name(program_name, MYNAME)) {
- if (argc < 2) {
- fputs(USAGE_TEXT, stderr);
- x_exit(1);
- }
- // If the first argument isn't an option, then assume we are being passed a
- // compiler name and options.
- if (argv[1][0] == '-') {
- return ccache_main_options(argc, argv);
- }
- }
- free(program_name);
-
- ccache(argc, argv);
+ // Check if we are being invoked as "ccache".
+ char* program_name = x_basename(argv[0]);
+ if (same_executable_name(program_name, MYNAME)) {
+ if (argc < 2) {
+ fputs(USAGE_TEXT, stderr);
+ x_exit(1);
+ }
+ // If the first argument isn't an option, then assume we are being passed a
+ // compiler name and options.
+ if (argv[1][0] == '-') {
+ return ccache_main_options(argc, argv);
+ }
+ }
+ free(program_name);
+
+ ccache(argc, argv);
}
diff --git a/src/ccache.hpp b/src/ccache.hpp
index 089f6b75..e8be9244 100644
--- a/src/ccache.hpp
+++ b/src/ccache.hpp
@@ -20,68 +20,71 @@
#pragma once
#include "system.hpp"
+
#include "conf.hpp"
#include "counters.hpp"
+
#include "third_party/minitrace.h"
#ifdef __GNUC__
-#define ATTR_FORMAT(x, y, z) __attribute__((format (ATTRIBUTE_FORMAT_PRINTF, y, z)))
-#define ATTR_NORETURN __attribute__((noreturn))
+# define ATTR_FORMAT(x, y, z) \
+ __attribute__((format(ATTRIBUTE_FORMAT_PRINTF, y, z)))
+# define ATTR_NORETURN __attribute__((noreturn))
#else
-#define ATTR_FORMAT(x, y, z)
-#define ATTR_NORETURN
+# define ATTR_FORMAT(x, y, z)
+# define ATTR_NORETURN
#endif
#ifndef MYNAME
-#define MYNAME "ccache"
+# define MYNAME "ccache"
#endif
extern const char CCACHE_VERSION[];
// Statistics fields in storage order.
enum stats {
- STATS_NONE = 0,
- STATS_STDOUT = 1,
- STATS_STATUS = 2,
- STATS_ERROR = 3,
- STATS_TOCACHE = 4,
- STATS_PREPROCESSOR = 5,
- STATS_COMPILER = 6,
- STATS_MISSING = 7,
- STATS_CACHEHIT_CPP = 8,
- STATS_ARGS = 9,
- STATS_LINK = 10,
- STATS_NUMFILES = 11,
- STATS_TOTALSIZE = 12,
- STATS_OBSOLETE_MAXFILES = 13,
- STATS_OBSOLETE_MAXSIZE = 14,
- STATS_SOURCELANG = 15,
- STATS_BADOUTPUTFILE = 16,
- STATS_NOINPUT = 17,
- STATS_MULTIPLE = 18,
- STATS_CONFTEST = 19,
- STATS_UNSUPPORTED_OPTION = 20,
- STATS_OUTSTDOUT = 21,
- STATS_CACHEHIT_DIR = 22,
- STATS_NOOUTPUT = 23,
- STATS_EMPTYOUTPUT = 24,
- STATS_BADEXTRAFILE = 25,
- STATS_COMPCHECK = 26,
- STATS_CANTUSEPCH = 27,
- STATS_PREPROCESSING = 28,
- STATS_NUMCLEANUPS = 29,
- STATS_UNSUPPORTED_DIRECTIVE = 30,
- STATS_ZEROTIMESTAMP = 31,
-
- STATS_END
+ STATS_NONE = 0,
+ STATS_STDOUT = 1,
+ STATS_STATUS = 2,
+ STATS_ERROR = 3,
+ STATS_TOCACHE = 4,
+ STATS_PREPROCESSOR = 5,
+ STATS_COMPILER = 6,
+ STATS_MISSING = 7,
+ STATS_CACHEHIT_CPP = 8,
+ STATS_ARGS = 9,
+ STATS_LINK = 10,
+ STATS_NUMFILES = 11,
+ STATS_TOTALSIZE = 12,
+ STATS_OBSOLETE_MAXFILES = 13,
+ STATS_OBSOLETE_MAXSIZE = 14,
+ STATS_SOURCELANG = 15,
+ STATS_BADOUTPUTFILE = 16,
+ STATS_NOINPUT = 17,
+ STATS_MULTIPLE = 18,
+ STATS_CONFTEST = 19,
+ STATS_UNSUPPORTED_OPTION = 20,
+ STATS_OUTSTDOUT = 21,
+ STATS_CACHEHIT_DIR = 22,
+ STATS_NOOUTPUT = 23,
+ STATS_EMPTYOUTPUT = 24,
+ STATS_BADEXTRAFILE = 25,
+ STATS_COMPCHECK = 26,
+ STATS_CANTUSEPCH = 27,
+ STATS_PREPROCESSING = 28,
+ STATS_NUMCLEANUPS = 29,
+ STATS_UNSUPPORTED_DIRECTIVE = 30,
+ STATS_ZEROTIMESTAMP = 31,
+
+ STATS_END
};
enum guessed_compiler {
- GUESSED_CLANG,
- GUESSED_GCC,
- GUESSED_NVCC,
- GUESSED_PUMP,
- GUESSED_UNKNOWN
+ GUESSED_CLANG,
+ GUESSED_GCC,
+ GUESSED_NVCC,
+ GUESSED_PUMP,
+ GUESSED_UNKNOWN
};
extern enum guessed_compiler guessed_compiler;
@@ -106,11 +109,11 @@ extern enum guessed_compiler guessed_compiler;
#define SLOPPY_LOCALE (1U << 9)
#define str_eq(s1, s2) (strcmp((s1), (s2)) == 0)
-#define str_startswith(s, prefix) \
- (strncmp((s), (prefix), strlen((prefix))) == 0)
-#define str_endswith(s, suffix) \
- (strlen(s) >= strlen(suffix) \
- && str_eq((s) + strlen(s) - strlen(suffix), (suffix)))
+#define str_startswith(s, prefix) \
+ (strncmp((s), (prefix), strlen((prefix))) == 0)
+#define str_endswith(s, suffix) \
+ (strlen(s) >= strlen(suffix) \
+ && str_eq((s) + strlen(s) - strlen(suffix), (suffix)))
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
// Buffer size for I/O operations. Should be a multiple of 4 KiB.
@@ -119,99 +122,100 @@ extern enum guessed_compiler guessed_compiler;
// ----------------------------------------------------------------------------
// args.c
-struct args {
- char **argv;
- int argc;
+struct args
+{
+ char** argv;
+ int argc;
};
-struct args *args_init(int, const char * const*);
-struct args *args_init_from_string(const char *);
-struct args *args_init_from_gcc_atfile(const char *filename);
-struct args *args_copy(struct args *args);
-void args_free(struct args *args);
-void args_add(struct args *args, const char *s);
-void args_add_prefix(struct args *args, const char *s);
-void args_extend(struct args *args, struct args *to_append);
-void args_insert(struct args *dest, int index, struct args *src, bool replace);
-void args_pop(struct args *args, int n);
-void args_set(struct args *args, int index, const char *value);
-void args_strip(struct args *args, const char *prefix);
-void args_remove_first(struct args *args);
-char *args_to_string(const struct args *args);
-bool args_equal(const struct args *args1, const struct args *args2);
+struct args* args_init(int, const char* const*);
+struct args* args_init_from_string(const char*);
+struct args* args_init_from_gcc_atfile(const char* filename);
+struct args* args_copy(struct args* args);
+void args_free(struct args* args);
+void args_add(struct args* args, const char* s);
+void args_add_prefix(struct args* args, const char* s);
+void args_extend(struct args* args, struct args* to_append);
+void args_insert(struct args* dest, int index, struct args* src, bool replace);
+void args_pop(struct args* args, int n);
+void args_set(struct args* args, int index, const char* value);
+void args_strip(struct args* args, const char* prefix);
+void args_remove_first(struct args* args);
+char* args_to_string(const struct args* args);
+bool args_equal(const struct args* args1, const struct args* args2);
// ----------------------------------------------------------------------------
// util.c
-void cc_log(const char *format, ...) ATTR_FORMAT(printf, 1, 2);
-void cc_bulklog(const char *format, ...) ATTR_FORMAT(printf, 1, 2);
-void cc_log_argv(const char *prefix, char **argv);
-void cc_dump_debug_log_buffer(const char *path);
-void fatal(const char *format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN;
-void warn(const char *format, ...) ATTR_FORMAT(printf, 1, 2);
+void cc_log(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
+void cc_bulklog(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
+void cc_log_argv(const char* prefix, char** argv);
+void cc_dump_debug_log_buffer(const char* path);
+void fatal(const char* format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN;
+void warn(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
-char *get_path_in_cache(const char *name, const char *suffix);
+char* get_path_in_cache(const char* name, const char* suffix);
bool copy_fd(int fd_in, int fd_out);
-bool clone_file(const char *src, const char *dest, bool via_tmp_file);
-bool copy_file(const char *src, const char *dest, bool via_tmp_file);
-bool move_file(const char *src, const char *dest);
-int create_dir(const char *dir);
-int create_parent_dirs(const char *path);
-const char *get_hostname(void);
-const char *tmp_string(void);
-int create_cachedirtag(const char *dir);
-char *format(const char *format, ...) ATTR_FORMAT(printf, 1, 2);
-void format_hex(const uint8_t *data, size_t size, char *buffer);
-void reformat(char **ptr, const char *format, ...) ATTR_FORMAT(printf, 2, 3);
-char *x_strdup(const char *s);
-char *x_strndup(const char *s, size_t n);
-void *x_malloc(size_t size);
-void *x_calloc(size_t nmemb, size_t size);
-void *x_realloc(void *ptr, size_t size);
-void x_setenv(const char *name, const char *value);
-void x_unsetenv(const char *name);
-int x_fstat(int fd, struct stat *buf);
-int x_lstat(const char *pathname, struct stat *buf);
-int x_stat(const char *pathname, struct stat *buf);
-void traverse(const char *dir, void (*fn)(const char *, struct stat *));
-char *x_basename(const char *path);
-char *x_dirname(const char *path);
-const char *get_extension(const char *path);
-char *remove_extension(const char *path);
-size_t file_size(struct stat *st);
-char *format_human_readable_size(uint64_t size);
-char *format_parsable_size_with_suffix(uint64_t size);
-bool parse_size_with_suffix(const char *str, uint64_t *size);
-char *x_realpath(const char *path);
-char *gnu_getcwd(void);
+bool clone_file(const char* src, const char* dest, bool via_tmp_file);
+bool copy_file(const char* src, const char* dest, bool via_tmp_file);
+bool move_file(const char* src, const char* dest);
+int create_dir(const char* dir);
+int create_parent_dirs(const char* path);
+const char* get_hostname(void);
+const char* tmp_string(void);
+int create_cachedirtag(const char* dir);
+char* format(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
+void format_hex(const uint8_t* data, size_t size, char* buffer);
+void reformat(char** ptr, const char* format, ...) ATTR_FORMAT(printf, 2, 3);
+char* x_strdup(const char* s);
+char* x_strndup(const char* s, size_t n);
+void* x_malloc(size_t size);
+void* x_calloc(size_t nmemb, size_t size);
+void* x_realloc(void* ptr, size_t size);
+void x_setenv(const char* name, const char* value);
+void x_unsetenv(const char* name);
+int x_fstat(int fd, struct stat* buf);
+int x_lstat(const char* pathname, struct stat* buf);
+int x_stat(const char* pathname, struct stat* buf);
+void traverse(const char* dir, void (*fn)(const char*, struct stat*));
+char* x_basename(const char* path);
+char* x_dirname(const char* path);
+const char* get_extension(const char* path);
+char* remove_extension(const char* path);
+size_t file_size(struct stat* st);
+char* format_human_readable_size(uint64_t size);
+char* format_parsable_size_with_suffix(uint64_t size);
+bool parse_size_with_suffix(const char* str, uint64_t* size);
+char* x_realpath(const char* path);
+char* gnu_getcwd(void);
#ifndef HAVE_LOCALTIME_R
-struct tm *localtime_r(const time_t *timep, struct tm *result);
+struct tm* localtime_r(const time_t* timep, struct tm* result);
#endif
#ifndef HAVE_STRTOK_R
-char *strtok_r(char *str, const char *delim, char **saveptr);
+char* strtok_r(char* str, const char* delim, char** saveptr);
#endif
-int create_tmp_fd(char **fname);
-FILE *create_tmp_file(char **fname, const char *mode);
-const char *get_home_directory(void);
-char *get_cwd(void);
-bool same_executable_name(const char *s1, const char *s2);
-size_t common_dir_prefix_length(const char *s1, const char *s2);
-char *get_relative_path(const char *from, const char *to);
-bool is_absolute_path(const char *path);
-bool is_full_path(const char *path);
-bool is_symlink(const char *path);
-void update_mtime(const char *path);
+int create_tmp_fd(char** fname);
+FILE* create_tmp_file(char** fname, const char* mode);
+const char* get_home_directory(void);
+char* get_cwd(void);
+bool same_executable_name(const char* s1, const char* s2);
+size_t common_dir_prefix_length(const char* s1, const char* s2);
+char* get_relative_path(const char* from, const char* to);
+bool is_absolute_path(const char* path);
+bool is_full_path(const char* path);
+bool is_symlink(const char* path);
+void update_mtime(const char* path);
void x_exit(int status) ATTR_NORETURN;
-int x_rename(const char *oldpath, const char *newpath);
-int tmp_unlink(const char *path);
-int x_unlink(const char *path);
-int x_try_unlink(const char *path);
+int x_rename(const char* oldpath, const char* newpath);
+int tmp_unlink(const char* path);
+int x_unlink(const char* path);
+int x_try_unlink(const char* path);
#ifndef _WIN32
-char *x_readlink(const char *path);
+char* x_readlink(const char* path);
#endif
-bool read_file(const char *path, size_t size_hint, char **data, size_t *size);
-char *read_text_file(const char *path, size_t size_hint);
-char *subst_env_in_string(const char *str, char **errmsg);
+bool read_file(const char* path, size_t size_hint, char** data, size_t* size);
+char* read_text_file(const char* path, size_t size_hint);
+char* subst_env_in_string(const char* str, char** errmsg);
void set_cloexec_flag(int fd);
double time_seconds(void);
@@ -224,49 +228,50 @@ unsigned stats_get_pending(enum stats stat);
void stats_zero(void);
void stats_summary(void);
void stats_print(void);
-void stats_update_size(const char *sfile, int64_t size, int files);
-void stats_get_obsolete_limits(const char *dir, unsigned *maxfiles,
- uint64_t *maxsize);
-void stats_set_sizes(const char *dir, unsigned num_files, uint64_t total_size);
-void stats_add_cleanup(const char *dir, unsigned count);
-void stats_timestamp(time_t time, struct counters *counters);
-void stats_read(const char *path, struct counters *counters);
-void stats_write(const char *path, struct counters *counters);
+void stats_update_size(const char* sfile, int64_t size, int files);
+void stats_get_obsolete_limits(const char* dir,
+ unsigned* maxfiles,
+ uint64_t* maxsize);
+void stats_set_sizes(const char* dir, unsigned num_files, uint64_t total_size);
+void stats_add_cleanup(const char* dir, unsigned count);
+void stats_timestamp(time_t time, struct counters* counters);
+void stats_read(const char* path, struct counters* counters);
+void stats_write(const char* path, struct counters* counters);
// ----------------------------------------------------------------------------
// exitfn.c
void exitfn_init(void);
void exitfn_add_nullary(void (*function)(void));
-void exitfn_add(void (*function)(void *), void *context);
-void exitfn_add_last(void (*function)(void *), void *context);
+void exitfn_add(void (*function)(void*), void* context);
+void exitfn_add_last(void (*function)(void*), void* context);
void exitfn_call(void);
// ----------------------------------------------------------------------------
// cleanup.c
-void clean_up_dir(struct conf *conf, const char *dir, double limit_multiple);
-void clean_up_all(struct conf *conf);
-void wipe_all(struct conf *conf);
+void clean_up_dir(struct conf* conf, const char* dir, double limit_multiple);
+void clean_up_all(struct conf* conf);
+void wipe_all(struct conf* conf);
// ----------------------------------------------------------------------------
// compress.c
-void compress_stats(struct conf *conf);
+void compress_stats(struct conf* conf);
// ----------------------------------------------------------------------------
// execute.c
-int execute(char **argv, int fd_out, int fd_err, pid_t *pid);
-char *find_executable(const char *name, const char *exclude_name);
-void print_command(FILE *fp, char **argv);
-char *format_command(const char* const* argv);
+int execute(char** argv, int fd_out, int fd_err, pid_t* pid);
+char* find_executable(const char* name, const char* exclude_name);
+void print_command(FILE* fp, char** argv);
+char* format_command(const char* const* argv);
// ----------------------------------------------------------------------------
// lockfile.c
-bool lockfile_acquire(const char *path, unsigned staleness_limit);
-void lockfile_release(const char *path);
+bool lockfile_acquire(const char* path, unsigned staleness_limit);
+void lockfile_release(const char* path);
// ----------------------------------------------------------------------------
// ccache.c
@@ -275,52 +280,55 @@ extern time_t time_of_compilation;
extern bool output_is_precompiled_header;
void block_signals(void);
void unblock_signals(void);
-bool cc_process_args(struct args *args, struct args **preprocessor_args,
- struct args **compiler_args);
+bool cc_process_args(struct args* args,
+ struct args** preprocessor_args,
+ struct args** compiler_args);
void cc_reset(void);
-bool is_precompiled_header(const char *path);
+bool is_precompiled_header(const char* path);
// ----------------------------------------------------------------------------
#ifdef HAVE_COMPAR_FN_T
-#define COMPAR_FN_T __compar_fn_t
+# define COMPAR_FN_T __compar_fn_t
#else
-typedef int (*COMPAR_FN_T)(const void *, const void *);
+typedef int (*COMPAR_FN_T)(const void*, const void*);
#endif
// Work with silly DOS binary open.
#ifndef O_BINARY
-#define O_BINARY 0
+# define O_BINARY 0
#endif
#ifdef _WIN32
-char *win32argvtos(char *prefix, char **argv, int *length);
-char *win32getshell(char *path);
-int win32execute(char *path, char **argv, int doreturn,
- int fd_stdout, int fd_stderr);
-void add_exe_ext_if_no_to_fullpath(char *full_path_win_ext, size_t max_size,
- const char *ext, const char *path);
-# ifndef _WIN32_WINNT
+char* win32argvtos(char* prefix, char** argv, int* length);
+char* win32getshell(char* path);
+int win32execute(
+ char* path, char** argv, int doreturn, int fd_stdout, int fd_stderr);
+void add_exe_ext_if_no_to_fullpath(char* full_path_win_ext,
+ size_t max_size,
+ const char* ext,
+ const char* path);
+# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0501
-# endif
-# include <windows.h>
-# define mkdir(a,b) mkdir(a)
-# define link(src,dst) (CreateHardLink(dst,src,NULL) ? 0 : -1)
-# define lstat(a,b) stat(a,b)
-# define execv(a,b) win32execute(a,b,0,-1,-1)
-# define execute(a,b,c,d) win32execute(*(a),a,1,b,c)
-# define DIR_DELIM_CH '\\'
-# define PATH_DELIM ";"
-# define F_RDLCK 0
-# define F_WRLCK 0
+# endif
+# include <windows.h>
+# define mkdir(a, b) mkdir(a)
+# define link(src, dst) (CreateHardLink(dst, src, NULL) ? 0 : -1)
+# define lstat(a, b) stat(a, b)
+# define execv(a, b) win32execute(a, b, 0, -1, -1)
+# define execute(a, b, c, d) win32execute(*(a), a, 1, b, c)
+# define DIR_DELIM_CH '\\'
+# define PATH_DELIM ";"
+# define F_RDLCK 0
+# define F_WRLCK 0
#else
-# define DIR_DELIM_CH '/'
-# define PATH_DELIM ":"
+# define DIR_DELIM_CH '/'
+# define PATH_DELIM ":"
#endif
#ifndef MAX
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+# define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef MIN
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+# define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
diff --git a/src/cleanup.cpp b/src/cleanup.cpp
index 8116aa60..4ef6665a 100644
--- a/src/cleanup.cpp
+++ b/src/cleanup.cpp
@@ -21,11 +21,14 @@
#include <math.h>
-static struct files {
- char *fname;
- time_t mtime;
- uint64_t size;
-} **files;
+struct files
+{
+ char* fname;
+ time_t mtime;
+ uint64_t size;
+};
+
+static struct files** files;
static unsigned allocated; // Size of the files array.
static unsigned num_files; // Number of used entries in the files array.
@@ -36,76 +39,76 @@ static size_t files_in_cache_threshold;
// File comparison function that orders files in mtime order, oldest first.
static int
-files_compare(struct files **f1, struct files **f2)
+files_compare(struct files** f1, struct files** f2)
{
- if ((*f2)->mtime == (*f1)->mtime) {
- return strcmp((*f1)->fname, (*f2)->fname);
- }
- if ((*f2)->mtime > (*f1)->mtime) {
- return -1;
- }
- return 1;
+ if ((*f2)->mtime == (*f1)->mtime) {
+ return strcmp((*f1)->fname, (*f2)->fname);
+ }
+ if ((*f2)->mtime > (*f1)->mtime) {
+ return -1;
+ }
+ return 1;
}
// This builds the list of files in the cache.
static void
-traverse_fn(const char *fname, struct stat *st)
+traverse_fn(const char* fname, struct stat* st)
{
- if (!S_ISREG(st->st_mode)) {
- return;
- }
-
- char *p = x_basename(fname);
- if (str_eq(p, "stats")) {
- goto out;
- }
-
- if (str_startswith(p, ".nfs")) {
- // Ignore temporary NFS files that may be left for open but deleted files.
- goto out;
- }
-
- // Delete any tmp files older than 1 hour.
- if (strstr(p, ".tmp.") && st->st_mtime + 3600 < time(NULL)) {
- x_unlink(fname);
- goto out;
- }
-
- if (strstr(p, "CACHEDIR.TAG")) {
- goto out;
- }
-
- if (num_files == allocated) {
- allocated = 10000 + num_files*2;
- files = (struct files **)x_realloc(files, sizeof(struct files *)*allocated);
- }
-
- files[num_files] = (struct files *)x_malloc(sizeof(struct files));
- files[num_files]->fname = x_strdup(fname);
- files[num_files]->mtime = st->st_mtime;
- files[num_files]->size = file_size(st);
- cache_size += files[num_files]->size;
- files_in_cache++;
- num_files++;
+ if (!S_ISREG(st->st_mode)) {
+ return;
+ }
+
+ char* p = x_basename(fname);
+ if (str_eq(p, "stats")) {
+ goto out;
+ }
+
+ if (str_startswith(p, ".nfs")) {
+ // Ignore temporary NFS files that may be left for open but deleted files.
+ goto out;
+ }
+
+ // Delete any tmp files older than 1 hour.
+ if (strstr(p, ".tmp.") && st->st_mtime + 3600 < time(NULL)) {
+ x_unlink(fname);
+ goto out;
+ }
+
+ if (strstr(p, "CACHEDIR.TAG")) {
+ goto out;
+ }
+
+ if (num_files == allocated) {
+ allocated = 10000 + num_files * 2;
+ files = (struct files**)x_realloc(files, sizeof(struct files*) * allocated);
+ }
+
+ files[num_files] = (struct files*)x_malloc(sizeof(struct files));
+ files[num_files]->fname = x_strdup(fname);
+ files[num_files]->mtime = st->st_mtime;
+ files[num_files]->size = file_size(st);
+ cache_size += files[num_files]->size;
+ files_in_cache++;
+ num_files++;
out:
- free(p);
+ free(p);
}
static void
-delete_file(const char *path, size_t size, bool update_counters)
+delete_file(const char* path, size_t size, bool update_counters)
{
- bool deleted = x_try_unlink(path) == 0;
- if (!deleted && errno != ENOENT && errno != ESTALE) {
- cc_log("Failed to unlink %s (%s)", path, strerror(errno));
- } else if (update_counters) {
- // The counters are intentionally subtracted even if there was no file to
- // delete since the final cache size calculation will be incorrect if they
- // aren't. (This can happen when there are several parallel ongoing
- // cleanups of the same directory.)
- cache_size -= size;
- files_in_cache--;
- }
+ bool deleted = x_try_unlink(path) == 0;
+ if (!deleted && errno != ENOENT && errno != ESTALE) {
+ cc_log("Failed to unlink %s (%s)", path, strerror(errno));
+ } else if (update_counters) {
+ // The counters are intentionally subtracted even if there was no file to
+ // delete since the final cache size calculation will be incorrect if they
+ // aren't. (This can happen when there are several parallel ongoing
+ // cleanups of the same directory.)
+ cache_size -= size;
+ files_in_cache--;
+ }
}
// Sort the files we've found and delete the oldest ones until we are below the
@@ -113,160 +116,162 @@ delete_file(const char *path, size_t size, bool update_counters)
static bool
sort_and_clean(void)
{
- if (num_files > 1) {
- // Sort in ascending mtime order.
- qsort(files, num_files, sizeof(struct files *), (COMPAR_FN_T)files_compare);
- }
-
- // Delete enough files to bring us below the threshold.
- bool cleaned = false;
- for (unsigned i = 0; i < num_files; i++) {
- const char *ext;
-
- if ((cache_size_threshold == 0
- || cache_size <= cache_size_threshold)
- && (files_in_cache_threshold == 0
- || files_in_cache <= files_in_cache_threshold)) {
- break;
- }
-
- ext = get_extension(files[i]->fname);
- if (str_eq(ext, ".stderr")) {
- // Make sure that the .o file is deleted before .stderr, because if the
- // ccache process gets killed after deleting the .stderr but before
- // deleting the .o, the cached result will be inconsistent. (.stderr is
- // the only file that is optional; any other file missing from the cache
- // will be detected by get_file_from_cache.)
- char *base = remove_extension(files[i]->fname);
- char *o_file = format("%s.o", base);
-
- // Don't subtract this extra deletion from the cache size; that
- // bookkeeping will be done when the loop reaches the .o file. If the
- // loop doesn't reach the .o file since the target limits have been
- // reached, the bookkeeping won't happen, but that small counter
- // discrepancy won't do much harm and it will correct itself in the next
- // cleanup.
- delete_file(o_file, 0, false);
-
- free(o_file);
- free(base);
- }
- delete_file(files[i]->fname, files[i]->size, true);
- cleaned = true;
- }
- return cleaned;
+ if (num_files > 1) {
+ // Sort in ascending mtime order.
+ qsort(files, num_files, sizeof(struct files*), (COMPAR_FN_T)files_compare);
+ }
+
+ // Delete enough files to bring us below the threshold.
+ bool cleaned = false;
+ for (unsigned i = 0; i < num_files; i++) {
+ const char* ext;
+
+ if ((cache_size_threshold == 0 || cache_size <= cache_size_threshold)
+ && (files_in_cache_threshold == 0
+ || files_in_cache <= files_in_cache_threshold)) {
+ break;
+ }
+
+ ext = get_extension(files[i]->fname);
+ if (str_eq(ext, ".stderr")) {
+ // Make sure that the .o file is deleted before .stderr, because if the
+ // ccache process gets killed after deleting the .stderr but before
+ // deleting the .o, the cached result will be inconsistent. (.stderr is
+ // the only file that is optional; any other file missing from the cache
+ // will be detected by get_file_from_cache.)
+ char* base = remove_extension(files[i]->fname);
+ char* o_file = format("%s.o", base);
+
+ // Don't subtract this extra deletion from the cache size; that
+ // bookkeeping will be done when the loop reaches the .o file. If the
+ // loop doesn't reach the .o file since the target limits have been
+ // reached, the bookkeeping won't happen, but that small counter
+ // discrepancy won't do much harm and it will correct itself in the next
+ // cleanup.
+ delete_file(o_file, 0, false);
+
+ free(o_file);
+ free(base);
+ }
+ delete_file(files[i]->fname, files[i]->size, true);
+ cleaned = true;
+ }
+ return cleaned;
}
// Clean up one cache subdirectory.
void
-clean_up_dir(struct conf *conf, const char *dir, double limit_multiple)
+clean_up_dir(struct conf* conf, const char* dir, double limit_multiple)
{
- cc_log("Cleaning up cache directory %s", dir);
-
- // When "max files" or "max cache size" is reached, one of the 16 cache
- // subdirectories is cleaned up. When doing so, files are deleted (in LRU
- // order) until the levels are below limit_multiple.
- double cache_size_float = round(conf->max_size * limit_multiple / 16);
- cache_size_threshold = (uint64_t)cache_size_float;
- double files_in_cache_float = round(conf->max_files * limit_multiple / 16);
- files_in_cache_threshold = (size_t)files_in_cache_float;
-
- num_files = 0;
- cache_size = 0;
- files_in_cache = 0;
-
- // Build a list of files.
- traverse(dir, traverse_fn);
-
- // Clean the cache.
- cc_log("Before cleanup: %.0f KiB, %.0f files",
- (double)cache_size / 1024,
- (double)files_in_cache);
- bool cleaned = sort_and_clean();
- cc_log("After cleanup: %.0f KiB, %.0f files",
- (double)cache_size / 1024,
- (double)files_in_cache);
-
- if (cleaned) {
- cc_log("Cleaned up cache directory %s", dir);
- stats_add_cleanup(dir, 1);
- }
-
- stats_set_sizes(dir, files_in_cache, cache_size);
-
- // Free it up.
- for (unsigned i = 0; i < num_files; i++) {
- free(files[i]->fname);
- free(files[i]);
- files[i] = NULL;
- }
- if (files) {
- free(files);
- }
- allocated = 0;
- files = NULL;
-
- num_files = 0;
- cache_size = 0;
- files_in_cache = 0;
+ cc_log("Cleaning up cache directory %s", dir);
+
+ // When "max files" or "max cache size" is reached, one of the 16 cache
+ // subdirectories is cleaned up. When doing so, files are deleted (in LRU
+ // order) until the levels are below limit_multiple.
+ double cache_size_float = round(conf->max_size * limit_multiple / 16);
+ cache_size_threshold = (uint64_t)cache_size_float;
+ double files_in_cache_float = round(conf->max_files * limit_multiple / 16);
+ files_in_cache_threshold = (size_t)files_in_cache_float;
+
+ num_files = 0;
+ cache_size = 0;
+ files_in_cache = 0;
+
+ // Build a list of files.
+ traverse(dir, traverse_fn);
+
+ // Clean the cache.
+ cc_log("Before cleanup: %.0f KiB, %.0f files",
+ (double)cache_size / 1024,
+ (double)files_in_cache);
+ bool cleaned = sort_and_clean();
+ cc_log("After cleanup: %.0f KiB, %.0f files",
+ (double)cache_size / 1024,
+ (double)files_in_cache);
+
+ if (cleaned) {
+ cc_log("Cleaned up cache directory %s", dir);
+ stats_add_cleanup(dir, 1);
+ }
+
+ stats_set_sizes(dir, files_in_cache, cache_size);
+
+ // Free it up.
+ for (unsigned i = 0; i < num_files; i++) {
+ free(files[i]->fname);
+ free(files[i]);
+ files[i] = NULL;
+ }
+ if (files) {
+ free(files);
+ }
+ allocated = 0;
+ files = NULL;
+
+ num_files = 0;
+ cache_size = 0;
+ files_in_cache = 0;
}
// Clean up all cache subdirectories.
-void clean_up_all(struct conf *conf)
+void
+clean_up_all(struct conf* conf)
{
- for (int i = 0; i <= 0xF; i++) {
- char *dname = format("%s/%1x", conf->cache_dir, i);
- clean_up_dir(conf, dname, 1.0);
- free(dname);
- }
+ for (int i = 0; i <= 0xF; i++) {
+ char* dname = format("%s/%1x", conf->cache_dir, i);
+ clean_up_dir(conf, dname, 1.0);
+ free(dname);
+ }
}
// Traverse function for wiping files.
-static void wipe_fn(const char *fname, struct stat *st)
+static void
+wipe_fn(const char* fname, struct stat* st)
{
- if (!S_ISREG(st->st_mode)) {
- return;
- }
+ if (!S_ISREG(st->st_mode)) {
+ return;
+ }
- char *p = x_basename(fname);
- if (str_eq(p, "stats")) {
- free(p);
- return;
- }
- free(p);
+ char* p = x_basename(fname);
+ if (str_eq(p, "stats")) {
+ free(p);
+ return;
+ }
+ free(p);
- files_in_cache++;
+ files_in_cache++;
- x_unlink(fname);
+ x_unlink(fname);
}
// Wipe one cache subdirectory.
static void
-wipe_dir(const char *dir)
+wipe_dir(const char* dir)
{
- cc_log("Clearing out cache directory %s", dir);
+ cc_log("Clearing out cache directory %s", dir);
- files_in_cache = 0;
+ files_in_cache = 0;
- traverse(dir, wipe_fn);
+ traverse(dir, wipe_fn);
- if (files_in_cache > 0) {
- cc_log("Cleared out cache directory %s", dir);
- stats_add_cleanup(dir, 1);
- }
+ if (files_in_cache > 0) {
+ cc_log("Cleared out cache directory %s", dir);
+ stats_add_cleanup(dir, 1);
+ }
- files_in_cache = 0;
+ files_in_cache = 0;
}
// Wipe all cached files in all subdirectories.
-void wipe_all(struct conf *conf)
+void
+wipe_all(struct conf* conf)
{
- for (int i = 0; i <= 0xF; i++) {
- char *dname = format("%s/%1x", conf->cache_dir, i);
- wipe_dir(dname);
- free(dname);
- }
-
- // Fix the counters.
- clean_up_all(conf);
+ for (int i = 0; i <= 0xF; i++) {
+ char* dname = format("%s/%1x", conf->cache_dir, i);
+ wipe_dir(dname);
+ free(dname);
+ }
+
+ // Fix the counters.
+ clean_up_all(conf);
}
diff --git a/src/common_header.cpp b/src/common_header.cpp
index f7f88d04..83f3f09c 100644
--- a/src/common_header.cpp
+++ b/src/common_header.cpp
@@ -16,146 +16,148 @@
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#include "common_header.hpp"
+
#include "ccache.hpp"
#include "int_bytes_conversion.hpp"
-#include "common_header.hpp"
bool
-common_header_initialize_for_writing(
- struct common_header *header,
- FILE *output,
- const char magic[4],
- uint8_t version,
- uint8_t compression_type,
- int8_t compression_level,
- uint64_t content_size,
- XXH64_state_t *checksum,
- struct compressor **compressor,
- struct compr_state **compr_state)
+common_header_initialize_for_writing(struct common_header* header,
+ FILE* output,
+ const char magic[4],
+ uint8_t version,
+ uint8_t compression_type,
+ int8_t compression_level,
+ uint64_t content_size,
+ XXH64_state_t* checksum,
+ struct compressor** compressor,
+ struct compr_state** compr_state)
{
- memcpy(header->magic, magic, 4);
- header->version = version;
- header->compression_type = compression_type;
- header->compression_level = compression_level;
- header->content_size = content_size;
-
- XXH64_reset(checksum, 0);
-
- *compressor = compressor_from_type(header->compression_type);
- assert(*compressor);
- *compr_state =
- (*compressor)->init(output, header->compression_level, checksum);
- if (!*compr_state) {
- cc_log("Failed to initialize compressor");
- return false;
- }
- header->compression_level =
- (*compressor)->get_actual_compression_level(*compr_state);
-
- uint8_t header_bytes[COMMON_HEADER_SIZE];
- memcpy(header_bytes, header->magic, 4);
- header_bytes[4] = header->version;
- header_bytes[5] = header->compression_type;
- header_bytes[6] = header->compression_level;
- BYTES_FROM_UINT64(header_bytes + 7, header->content_size);
- if (fwrite(header_bytes, sizeof(header_bytes), 1, output) != 1) {
- cc_log("Failed to write common file header");
- return false;
- }
- XXH64_update(checksum, header_bytes, sizeof(header_bytes));
- return true;
+ memcpy(header->magic, magic, 4);
+ header->version = version;
+ header->compression_type = compression_type;
+ header->compression_level = compression_level;
+ header->content_size = content_size;
+
+ XXH64_reset(checksum, 0);
+
+ *compressor = compressor_from_type(header->compression_type);
+ assert(*compressor);
+ *compr_state =
+ (*compressor)->init(output, header->compression_level, checksum);
+ if (!*compr_state) {
+ cc_log("Failed to initialize compressor");
+ return false;
+ }
+ header->compression_level =
+ (*compressor)->get_actual_compression_level(*compr_state);
+
+ uint8_t header_bytes[COMMON_HEADER_SIZE];
+ memcpy(header_bytes, header->magic, 4);
+ header_bytes[4] = header->version;
+ header_bytes[5] = header->compression_type;
+ header_bytes[6] = header->compression_level;
+ BYTES_FROM_UINT64(header_bytes + 7, header->content_size);
+ if (fwrite(header_bytes, sizeof(header_bytes), 1, output) != 1) {
+ cc_log("Failed to write common file header");
+ return false;
+ }
+ XXH64_update(checksum, header_bytes, sizeof(header_bytes));
+ return true;
}
-bool common_header_initialize_for_reading(
- struct common_header *header,
- FILE *input,
- const char expected_magic[4],
- uint8_t expected_version,
- struct decompressor **decompressor,
- struct decompr_state **decompr_state,
- XXH64_state_t *checksum,
- char **errmsg)
+bool
+common_header_initialize_for_reading(struct common_header* header,
+ FILE* input,
+ const char expected_magic[4],
+ uint8_t expected_version,
+ struct decompressor** decompressor,
+ struct decompr_state** decompr_state,
+ XXH64_state_t* checksum,
+ char** errmsg)
{
- uint8_t header_bytes[COMMON_HEADER_SIZE];
- if (fread(header_bytes, sizeof(header_bytes), 1, input) != 1) {
- *errmsg = format("Failed to read common header");
- return false;
- }
-
- memcpy(header->magic, header_bytes, 4);
- header->version = header_bytes[4];
- header->compression_type = header_bytes[5];
- header->compression_level = header_bytes[6];
- header->content_size = UINT64_FROM_BYTES(header_bytes + 7);
-
- if (memcmp(header->magic, expected_magic, sizeof(header->magic)) != 0) {
- *errmsg = format(
- "Bad magic value 0x%x%x%x%x",
- header->magic[0],
- header->magic[1],
- header->magic[2],
- header->magic[3]);
- return false;
- }
-
- if (header->version != expected_version) {
- *errmsg = format(
- "Unknown version (actual %u, expected %u)",
- header->version,
- expected_version);
- return false;
- }
-
- if (header->compression_type == COMPR_TYPE_NONE) {
- // Since we have the size available, let's use it as a super primitive
- // consistency check for the non-compressed case. (A real checksum is used
- // for compressed data.)
- struct stat st;
- if (x_fstat(fileno(input), &st) != 0) {
- return false;
- }
- if ((uint64_t)st.st_size != header->content_size) {
- *errmsg = format(
- "Bad uncompressed file size (actual %llu bytes, expected %llu bytes)",
- (unsigned long long)st.st_size,
- (unsigned long long)header->content_size);
- return false;
- }
- }
-
- if (!decompressor) {
- return true;
- }
-
- *decompressor = decompressor_from_type(header->compression_type);
- if (!*decompressor) {
- *errmsg = format(
- "Unknown compression type: %u", header->compression_type);
- return false;
- }
-
- if (checksum) {
- XXH64_reset(checksum, 0);
- XXH64_update(checksum, header_bytes, sizeof(header_bytes));
- }
-
- *decompr_state = (*decompressor)->init(input, checksum);
- if (!*decompr_state) {
- *errmsg = x_strdup("Failed to initialize decompressor");
- return false;
- }
-
- return true;
+ uint8_t header_bytes[COMMON_HEADER_SIZE];
+ if (fread(header_bytes, sizeof(header_bytes), 1, input) != 1) {
+ *errmsg = format("Failed to read common header");
+ return false;
+ }
+
+ memcpy(header->magic, header_bytes, 4);
+ header->version = header_bytes[4];
+ header->compression_type = header_bytes[5];
+ header->compression_level = header_bytes[6];
+ header->content_size = UINT64_FROM_BYTES(header_bytes + 7);
+
+ if (memcmp(header->magic, expected_magic, sizeof(header->magic)) != 0) {
+ *errmsg = format("Bad magic value 0x%x%x%x%x",
+ header->magic[0],
+ header->magic[1],
+ header->magic[2],
+ header->magic[3]);
+ return false;
+ }
+
+ if (header->version != expected_version) {
+ *errmsg = format("Unknown version (actual %u, expected %u)",
+ header->version,
+ expected_version);
+ return false;
+ }
+
+ if (header->compression_type == COMPR_TYPE_NONE) {
+ // Since we have the size available, let's use it as a super primitive
+ // consistency check for the non-compressed case. (A real checksum is used
+ // for compressed data.)
+ struct stat st;
+ if (x_fstat(fileno(input), &st) != 0) {
+ return false;
+ }
+ if ((uint64_t)st.st_size != header->content_size) {
+ *errmsg = format(
+ "Bad uncompressed file size (actual %llu bytes, expected %llu bytes)",
+ (unsigned long long)st.st_size,
+ (unsigned long long)header->content_size);
+ return false;
+ }
+ }
+
+ if (!decompressor) {
+ return true;
+ }
+
+ *decompressor = decompressor_from_type(header->compression_type);
+ if (!*decompressor) {
+ *errmsg = format("Unknown compression type: %u", header->compression_type);
+ return false;
+ }
+
+ if (checksum) {
+ XXH64_reset(checksum, 0);
+ XXH64_update(checksum, header_bytes, sizeof(header_bytes));
+ }
+
+ *decompr_state = (*decompressor)->init(input, checksum);
+ if (!*decompr_state) {
+ *errmsg = x_strdup("Failed to initialize decompressor");
+ return false;
+ }
+
+ return true;
}
-void common_header_dump(const struct common_header *header, FILE *f)
+void
+common_header_dump(const struct common_header* header, FILE* f)
{
- fprintf(
- f, "Magic: %c%c%c%c\n",
- header->magic[0], header->magic[1], header->magic[2], header->magic[3]);
- fprintf(f, "Version: %u\n", header->version);
- fprintf(f, "Compression type: %s\n",
- compression_type_to_string(header->compression_type));
- fprintf(f, "Compression level: %d\n", header->compression_level);
- fprintf(f, "Content size: %" PRIu64 "\n", header->content_size);
+ fprintf(f,
+ "Magic: %c%c%c%c\n",
+ header->magic[0],
+ header->magic[1],
+ header->magic[2],
+ header->magic[3]);
+ fprintf(f, "Version: %u\n", header->version);
+ fprintf(f,
+ "Compression type: %s\n",
+ compression_type_to_string(header->compression_type));
+ fprintf(f, "Compression level: %d\n", header->compression_level);
+ fprintf(f, "Content size: %" PRIu64 "\n", header->content_size);
}
diff --git a/src/common_header.hpp b/src/common_header.hpp
index 05bcda40..ae9af69e 100644
--- a/src/common_header.hpp
+++ b/src/common_header.hpp
@@ -19,16 +19,18 @@
#pragma once
#include "compression.hpp"
+
#include "third_party/xxhash.h"
#define COMMON_HEADER_SIZE 15
-struct common_header {
- char magic[4];
- uint8_t version;
- uint8_t compression_type;
- int8_t compression_level;
- uint64_t content_size;
+struct common_header
+{
+ char magic[4];
+ uint8_t version;
+ uint8_t compression_type;
+ int8_t compression_level;
+ uint64_t content_size;
};
// Initialize a common_header and write the header data to a file.
@@ -44,17 +46,16 @@ struct common_header {
// compressor_state: State for the compressor.
// checksum: Checksum state that will be updated with the written
// bytes.
-bool common_header_initialize_for_writing(
- struct common_header *header,
- FILE *output,
- const char magic[4],
- uint8_t version,
- uint8_t compression_type,
- int8_t compression_level,
- uint64_t content_size,
- XXH64_state_t *checksum,
- struct compressor **compressor,
- struct compr_state **compr_state);
+bool common_header_initialize_for_writing(struct common_header* header,
+ FILE* output,
+ const char magic[4],
+ uint8_t version,
+ uint8_t compression_type,
+ int8_t compression_level,
+ uint64_t content_size,
+ XXH64_state_t* checksum,
+ struct compressor** compressor,
+ struct compr_state** compr_state);
// Initialize a common_header by reading header data from a file.
//
@@ -68,14 +69,13 @@ bool common_header_initialize_for_writing(
// decompressor is NULL.
// checksum: Checksum state that will be updated with the read bytes.
// May be NULL for no checksumming.
-bool common_header_initialize_for_reading(
- struct common_header *header,
- FILE *input,
- const char expected_magic[4],
- uint8_t expected_version,
- struct decompressor **decompressor,
- struct decompr_state **decompr_state,
- XXH64_state_t *checksum,
- char **errmsg);
+bool common_header_initialize_for_reading(struct common_header* header,
+ FILE* input,
+ const char expected_magic[4],
+ uint8_t expected_version,
+ struct decompressor** decompressor,
+ struct decompr_state** decompr_state,
+ XXH64_state_t* checksum,
+ char** errmsg);
-void common_header_dump(const struct common_header *header, FILE *f);
+void common_header_dump(const struct common_header* header, FILE* f);
diff --git a/src/compopt.cpp b/src/compopt.cpp
index afc46753..0bb03645 100644
--- a/src/compopt.cpp
+++ b/src/compopt.cpp
@@ -16,165 +16,170 @@
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#include "ccache.hpp"
#include "compopt.hpp"
+#include "ccache.hpp"
+
// The option it too hard to handle at all.
-#define TOO_HARD (1 << 0)
+#define TOO_HARD (1 << 0)
// The option it too hard for the direct mode.
-#define TOO_HARD_DIRECT (1 << 1)
+#define TOO_HARD_DIRECT (1 << 1)
// The option takes a separate argument, e.g. "-D FOO=1".
-#define TAKES_ARG (1 << 2)
+#define TAKES_ARG (1 << 2)
// The option takes a concatenated argument, e.g. "-DFOO=1".
#define TAKES_CONCAT_ARG (1 << 3)
// The argument to the option is a path that may be rewritten if base_dir is
// used.
-#define TAKES_PATH (1 << 4)
+#define TAKES_PATH (1 << 4)
// The option only affects preprocessing; not passed to the compiler if
// run_second_cpp is false.
-#define AFFECTS_CPP (1 << 5)
+#define AFFECTS_CPP (1 << 5)
// The option only affects compilation; not passed to the preprocesor.
#define AFFECTS_COMP (1 << 6)
-struct compopt {
- const char *name;
- int type;
+struct compopt
+{
+ const char* name;
+ int type;
};
static const struct compopt compopts[] = {
- {"--analyze", TOO_HARD}, // clang
- {"--compiler-bindir", AFFECTS_CPP | TAKES_ARG}, // nvcc
- {"--libdevice-directory", AFFECTS_CPP | TAKES_ARG}, // nvcc
- {"--output-directory", AFFECTS_CPP | TAKES_ARG}, // nvcc
- {"--param", TAKES_ARG},
- {"--save-temps", TOO_HARD},
- {"--save-temps=cwd", TOO_HARD},
- {"--save-temps=obj", TOO_HARD},
- {"--serialize-diagnostics", TAKES_ARG | TAKES_PATH},
- {"-A", TAKES_ARG},
- {"-B", TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-D", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
- {"-E", TOO_HARD},
- {"-F", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-G", TAKES_ARG},
- {"-I", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-L", TAKES_ARG},
- {"-M", TOO_HARD},
- {"-MF", TAKES_ARG},
- {"-MJ", TAKES_ARG | TOO_HARD},
- {"-MM", TOO_HARD},
- {"-MQ", TAKES_ARG},
- {"-MT", TAKES_ARG},
- {"-P", TOO_HARD},
- {"-U", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
- {"-V", TAKES_ARG},
- {"-Wa,", TAKES_CONCAT_ARG | AFFECTS_COMP},
- {"-Werror", AFFECTS_COMP}, // don't exit with error when preprocessing
- {"-Wl,", TAKES_CONCAT_ARG | AFFECTS_COMP},
- {"-Xassembler", TAKES_ARG | TAKES_CONCAT_ARG | AFFECTS_COMP},
- {"-Xclang", TAKES_ARG},
- {"-Xlinker", TAKES_ARG | TAKES_CONCAT_ARG | AFFECTS_COMP},
- {"-Xpreprocessor", AFFECTS_CPP | TOO_HARD_DIRECT | TAKES_ARG},
- {"-all_load", AFFECTS_COMP},
- {"-analyze", TOO_HARD}, // clang
- {"-arch", TAKES_ARG},
- {"-aux-info", TAKES_ARG},
- {"-b", TAKES_ARG},
- {"-bind_at_load", AFFECTS_COMP},
- {"-bundle", AFFECTS_COMP},
- {"-ccbin", AFFECTS_CPP | TAKES_ARG}, // nvcc
- {"-fmodules", TOO_HARD},
- {"-fno-working-directory", AFFECTS_CPP},
- {"-fplugin=libcc1plugin", TOO_HARD}, // interaction with GDB
- {"-frepo", TOO_HARD},
- {"-ftime-trace", TOO_HARD}, // clang
- {"-fworking-directory", AFFECTS_CPP},
- {"-gtoggle", TOO_HARD},
- {"-idirafter", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-iframework", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-imacros", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-imultilib", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-include", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-include-pch", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-install_name", TAKES_ARG}, // Darwin linker option
- {"-iprefix", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-iquote", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-isysroot", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-isystem", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-iwithprefix", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-iwithprefixbefore",
- AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
- {"-ldir", AFFECTS_CPP | TAKES_ARG}, // nvcc
- {"-nolibc", AFFECTS_COMP},
- {"-nostdinc", AFFECTS_CPP},
- {"-nostdinc++", AFFECTS_CPP},
- {"-odir", AFFECTS_CPP | TAKES_ARG}, // nvcc
- {"-pie", AFFECTS_COMP},
- {"-prebind", AFFECTS_COMP},
- {"-preload", AFFECTS_COMP},
- {"-rdynamic", AFFECTS_COMP},
- {"-remap", AFFECTS_CPP},
- {"-save-temps", TOO_HARD},
- {"-save-temps=cwd", TOO_HARD},
- {"-save-temps=obj", TOO_HARD},
- {"-stdlib=", AFFECTS_CPP | TAKES_CONCAT_ARG},
- {"-trigraphs", AFFECTS_CPP},
- {"-u", TAKES_ARG | TAKES_CONCAT_ARG},
+ {"--analyze", TOO_HARD}, // clang
+ {"--compiler-bindir", AFFECTS_CPP | TAKES_ARG}, // nvcc
+ {"--libdevice-directory", AFFECTS_CPP | TAKES_ARG}, // nvcc
+ {"--output-directory", AFFECTS_CPP | TAKES_ARG}, // nvcc
+ {"--param", TAKES_ARG},
+ {"--save-temps", TOO_HARD},
+ {"--save-temps=cwd", TOO_HARD},
+ {"--save-temps=obj", TOO_HARD},
+ {"--serialize-diagnostics", TAKES_ARG | TAKES_PATH},
+ {"-A", TAKES_ARG},
+ {"-B", TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-D", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
+ {"-E", TOO_HARD},
+ {"-F", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-G", TAKES_ARG},
+ {"-I", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-L", TAKES_ARG},
+ {"-M", TOO_HARD},
+ {"-MF", TAKES_ARG},
+ {"-MJ", TAKES_ARG | TOO_HARD},
+ {"-MM", TOO_HARD},
+ {"-MQ", TAKES_ARG},
+ {"-MT", TAKES_ARG},
+ {"-P", TOO_HARD},
+ {"-U", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
+ {"-V", TAKES_ARG},
+ {"-Wa,", TAKES_CONCAT_ARG | AFFECTS_COMP},
+ {"-Werror", AFFECTS_COMP}, // don't exit with error when preprocessing
+ {"-Wl,", TAKES_CONCAT_ARG | AFFECTS_COMP},
+ {"-Xassembler", TAKES_ARG | TAKES_CONCAT_ARG | AFFECTS_COMP},
+ {"-Xclang", TAKES_ARG},
+ {"-Xlinker", TAKES_ARG | TAKES_CONCAT_ARG | AFFECTS_COMP},
+ {"-Xpreprocessor", AFFECTS_CPP | TOO_HARD_DIRECT | TAKES_ARG},
+ {"-all_load", AFFECTS_COMP},
+ {"-analyze", TOO_HARD}, // clang
+ {"-arch", TAKES_ARG},
+ {"-aux-info", TAKES_ARG},
+ {"-b", TAKES_ARG},
+ {"-bind_at_load", AFFECTS_COMP},
+ {"-bundle", AFFECTS_COMP},
+ {"-ccbin", AFFECTS_CPP | TAKES_ARG}, // nvcc
+ {"-fmodules", TOO_HARD},
+ {"-fno-working-directory", AFFECTS_CPP},
+ {"-fplugin=libcc1plugin", TOO_HARD}, // interaction with GDB
+ {"-frepo", TOO_HARD},
+ {"-ftime-trace", TOO_HARD}, // clang
+ {"-fworking-directory", AFFECTS_CPP},
+ {"-gtoggle", TOO_HARD},
+ {"-idirafter", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-iframework", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-imacros", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-imultilib", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-include", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-include-pch", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-install_name", TAKES_ARG}, // Darwin linker option
+ {"-iprefix", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-iquote", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-isysroot", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-isystem", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-iwithprefix", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-iwithprefixbefore",
+ AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
+ {"-ldir", AFFECTS_CPP | TAKES_ARG}, // nvcc
+ {"-nolibc", AFFECTS_COMP},
+ {"-nostdinc", AFFECTS_CPP},
+ {"-nostdinc++", AFFECTS_CPP},
+ {"-odir", AFFECTS_CPP | TAKES_ARG}, // nvcc
+ {"-pie", AFFECTS_COMP},
+ {"-prebind", AFFECTS_COMP},
+ {"-preload", AFFECTS_COMP},
+ {"-rdynamic", AFFECTS_COMP},
+ {"-remap", AFFECTS_CPP},
+ {"-save-temps", TOO_HARD},
+ {"-save-temps=cwd", TOO_HARD},
+ {"-save-temps=obj", TOO_HARD},
+ {"-stdlib=", AFFECTS_CPP | TAKES_CONCAT_ARG},
+ {"-trigraphs", AFFECTS_CPP},
+ {"-u", TAKES_ARG | TAKES_CONCAT_ARG},
};
-
static int
-compare_compopts(const void *key1, const void *key2)
+compare_compopts(const void* key1, const void* key2)
{
- const struct compopt *opt1 = (const struct compopt *)key1;
- const struct compopt *opt2 = (const struct compopt *)key2;
- return strcmp(opt1->name, opt2->name);
+ const struct compopt* opt1 = (const struct compopt*)key1;
+ const struct compopt* opt2 = (const struct compopt*)key2;
+ return strcmp(opt1->name, opt2->name);
}
static int
-compare_prefix_compopts(const void *key1, const void *key2)
+compare_prefix_compopts(const void* key1, const void* key2)
{
- const struct compopt *opt1 = (const struct compopt *)key1;
- const struct compopt *opt2 = (const struct compopt *)key2;
- return strncmp(opt1->name, opt2->name, strlen(opt2->name));
+ const struct compopt* opt1 = (const struct compopt*)key1;
+ const struct compopt* opt2 = (const struct compopt*)key2;
+ return strncmp(opt1->name, opt2->name, strlen(opt2->name));
}
-static const struct compopt *
-find(const char *option)
+static const struct compopt*
+find(const char* option)
{
- struct compopt key;
- key.name = option;
- void* result = bsearch(
- &key, compopts, ARRAY_SIZE(compopts), sizeof(compopts[0]),
- compare_compopts);
- return static_cast<compopt*>(result);
+ struct compopt key;
+ key.name = option;
+ void* result = bsearch(&key,
+ compopts,
+ ARRAY_SIZE(compopts),
+ sizeof(compopts[0]),
+ compare_compopts);
+ return static_cast<compopt*>(result);
}
-static const struct compopt *
-find_prefix(const char *option)
+static const struct compopt*
+find_prefix(const char* option)
{
- struct compopt key;
- key.name = option;
- void* result = bsearch(
- &key, compopts, ARRAY_SIZE(compopts), sizeof(compopts[0]),
- compare_prefix_compopts);
- return static_cast<compopt*>(result);
+ struct compopt key;
+ key.name = option;
+ void* result = bsearch(&key,
+ compopts,
+ ARRAY_SIZE(compopts),
+ sizeof(compopts[0]),
+ compare_prefix_compopts);
+ return static_cast<compopt*>(result);
}
// Runs fn on the first two characters of option.
bool
-compopt_short(bool (*fn)(const char *), const char *option)
+compopt_short(bool (*fn)(const char*), const char* option)
{
- char *short_opt = x_strndup(option, 2);
- bool retval = fn(short_opt);
- free(short_opt);
- return retval;
+ char* short_opt = x_strndup(option, 2);
+ bool retval = fn(short_opt);
+ free(short_opt);
+ return retval;
}
// Used by unittest/test_compopt.c.
@@ -184,83 +189,83 @@ bool compopt_verify_sortedness(void);
bool
compopt_verify_sortedness(void)
{
- for (size_t i = 1; i < ARRAY_SIZE(compopts); i++) {
- if (strcmp(compopts[i-1].name, compopts[i].name) >= 0) {
- fprintf(stderr,
- "compopt_verify_sortedness: %s >= %s\n",
- compopts[i-1].name,
- compopts[i].name);
- return false;
- }
- }
- return true;
+ for (size_t i = 1; i < ARRAY_SIZE(compopts); i++) {
+ if (strcmp(compopts[i - 1].name, compopts[i].name) >= 0) {
+ fprintf(stderr,
+ "compopt_verify_sortedness: %s >= %s\n",
+ compopts[i - 1].name,
+ compopts[i].name);
+ return false;
+ }
+ }
+ return true;
}
bool
-compopt_affects_cpp(const char *option)
+compopt_affects_cpp(const char* option)
{
- const struct compopt *co = find(option);
- return co && (co->type & AFFECTS_CPP);
+ const struct compopt* co = find(option);
+ return co && (co->type & AFFECTS_CPP);
}
bool
-compopt_affects_comp(const char *option)
+compopt_affects_comp(const char* option)
{
- const struct compopt *co = find(option);
- return co && (co->type & AFFECTS_COMP);
+ const struct compopt* co = find(option);
+ return co && (co->type & AFFECTS_COMP);
}
bool
-compopt_too_hard(const char *option)
+compopt_too_hard(const char* option)
{
- const struct compopt *co = find(option);
- return co && (co->type & TOO_HARD);
+ const struct compopt* co = find(option);
+ return co && (co->type & TOO_HARD);
}
bool
-compopt_too_hard_for_direct_mode(const char *option)
+compopt_too_hard_for_direct_mode(const char* option)
{
- const struct compopt *co = find(option);
- return co && (co->type & TOO_HARD_DIRECT);
+ const struct compopt* co = find(option);
+ return co && (co->type & TOO_HARD_DIRECT);
}
bool
-compopt_takes_path(const char *option)
+compopt_takes_path(const char* option)
{
- const struct compopt *co = find(option);
- return co && (co->type & TAKES_PATH);
+ const struct compopt* co = find(option);
+ return co && (co->type & TAKES_PATH);
}
bool
-compopt_takes_arg(const char *option)
+compopt_takes_arg(const char* option)
{
- const struct compopt *co = find(option);
- return co && (co->type & TAKES_ARG);
+ const struct compopt* co = find(option);
+ return co && (co->type & TAKES_ARG);
}
bool
-compopt_takes_concat_arg(const char *option)
+compopt_takes_concat_arg(const char* option)
{
- const struct compopt *co = find(option);
- return co && (co->type & TAKES_CONCAT_ARG);
+ const struct compopt* co = find(option);
+ return co && (co->type & TAKES_CONCAT_ARG);
}
// Determines if the prefix of the option matches any option and affects the
// preprocessor.
bool
-compopt_prefix_affects_cpp(const char *option)
+compopt_prefix_affects_cpp(const char* option)
{
- // Prefix options have to take concatenated args.
- const struct compopt *co = find_prefix(option);
- return co && (co->type & TAKES_CONCAT_ARG) && (co->type & AFFECTS_CPP);
+ // Prefix options have to take concatenated args.
+ const struct compopt* co = find_prefix(option);
+ return co && (co->type & TAKES_CONCAT_ARG) && (co->type & AFFECTS_CPP);
}
// Determines if the prefix of the option matches any option and affects the
// preprocessor.
bool
-compopt_prefix_affects_comp(const char *option)
+compopt_prefix_affects_comp(const char* option)
{
- // Prefix options have to take concatenated args.
- const struct compopt *co = find_prefix(option);
- return co && (co->type & TAKES_CONCAT_ARG) && (co->type & AFFECTS_COMP);
+ // Prefix options have to take concatenated args.
+ const struct compopt* co = find_prefix(option);
+ return co && (co->type & TAKES_CONCAT_ARG) && (co->type & AFFECTS_COMP);
}
diff --git a/src/compopt.hpp b/src/compopt.hpp
index 97157c97..bb653694 100644
--- a/src/compopt.hpp
+++ b/src/compopt.hpp
@@ -20,13 +20,13 @@
#include "system.hpp"
-bool compopt_short(bool (*fn)(const char *option), const char *option);
-bool compopt_affects_cpp(const char *option);
-bool compopt_affects_comp(const char *option);
-bool compopt_too_hard(const char *option);
-bool compopt_too_hard_for_direct_mode(const char *option);
-bool compopt_takes_path(const char *option);
-bool compopt_takes_arg(const char *option);
-bool compopt_takes_concat_arg(const char *option);
-bool compopt_prefix_affects_cpp(const char *option);
-bool compopt_prefix_affects_comp(const char *option);
+bool compopt_short(bool (*fn)(const char* option), const char* option);
+bool compopt_affects_cpp(const char* option);
+bool compopt_affects_comp(const char* option);
+bool compopt_too_hard(const char* option);
+bool compopt_too_hard_for_direct_mode(const char* option);
+bool compopt_takes_path(const char* option);
+bool compopt_takes_arg(const char* option);
+bool compopt_takes_concat_arg(const char* option);
+bool compopt_prefix_affects_cpp(const char* option);
+bool compopt_prefix_affects_comp(const char* option);
diff --git a/src/compr_none.cpp b/src/compr_none.cpp
index 7d5cfa91..7093d3aa 100644
--- a/src/compr_none.cpp
+++ b/src/compr_none.cpp
@@ -18,51 +18,51 @@
#include "compression.hpp"
-struct state {
- FILE *output;
- XXH64_state_t *checksum;
+struct state
+{
+ FILE* output;
+ XXH64_state_t* checksum;
};
-static struct compr_state *
-compr_none_init(FILE *output, int8_t level, XXH64_state_t *checksum)
+static struct compr_state*
+compr_none_init(FILE* output, int8_t level, XXH64_state_t* checksum)
{
- auto state = static_cast<struct state*>(malloc(sizeof(struct state)));
- state->output = output;
- state->checksum = checksum;
- (void)level;
- return (struct compr_state *)state;
+ auto state = static_cast<struct state*>(malloc(sizeof(struct state)));
+ state->output = output;
+ state->checksum = checksum;
+ (void)level;
+ return (struct compr_state*)state;
}
static int8_t
-compr_none_get_actual_compression_level(struct compr_state *handle)
+compr_none_get_actual_compression_level(struct compr_state* handle)
{
- (void)handle;
- return 0;
+ (void)handle;
+ return 0;
}
static bool
-compr_none_write(struct compr_state *handle, const void *data, size_t size)
+compr_none_write(struct compr_state* handle, const void* data, size_t size)
{
- struct state *state = (struct state *)handle;
- size_t ret = fwrite(data, size, 1, state->output);
- if (state->checksum) {
- XXH64_update(state->checksum, data, size);
- }
- return ret == 1;
+ struct state* state = (struct state*)handle;
+ size_t ret = fwrite(data, size, 1, state->output);
+ if (state->checksum) {
+ XXH64_update(state->checksum, data, size);
+ }
+ return ret == 1;
}
static bool
-compr_none_free(struct compr_state *handle)
+compr_none_free(struct compr_state* handle)
{
- struct state *state = (struct state *)handle;
- bool result = ferror(state->output) == 0;
- free(state);
- return result;
+ struct state* state = (struct state*)handle;
+ bool result = ferror(state->output) == 0;
+ free(state);
+ return result;
}
struct compressor compressor_none_impl = {
- compr_none_init,
- compr_none_get_actual_compression_level,
- compr_none_write,
- compr_none_free
-};
+ compr_none_init,
+ compr_none_get_actual_compression_level,
+ compr_none_write,
+ compr_none_free};
diff --git a/src/compr_zstd.cpp b/src/compr_zstd.cpp
index 873b9e7f..005c3f0e 100644
--- a/src/compr_zstd.cpp
+++ b/src/compr_zstd.cpp
@@ -23,135 +23,134 @@
#define DEFAULT_ZSTD_COMPRESSION_LEVEL -1
-struct state {
- FILE *output;
- XXH64_state_t *checksum;
- ZSTD_CStream *stream;
- ZSTD_inBuffer in;
- ZSTD_outBuffer out;
- bool failed;
- int8_t compression_level;
+struct state
+{
+ FILE* output;
+ XXH64_state_t* checksum;
+ ZSTD_CStream* stream;
+ ZSTD_inBuffer in;
+ ZSTD_outBuffer out;
+ bool failed;
+ int8_t compression_level;
};
-static struct compr_state *
-compr_zstd_init(FILE *output, int8_t level, XXH64_state_t *checksum)
+static struct compr_state*
+compr_zstd_init(FILE* output, int8_t level, XXH64_state_t* checksum)
{
- auto state = static_cast<struct state*>(malloc(sizeof(struct state)));
- state->output = output;
- state->checksum = checksum;
- state->stream = ZSTD_createCStream();
- state->failed = false;
-
- if (level == 0) {
- level = DEFAULT_ZSTD_COMPRESSION_LEVEL;
- cc_log("Using default compression level %d", level);
- }
-
- // libzstd 1.3.4 and newer support negative levels. However, the query
- // function ZSTD_minCLevel did not appear until 1.3.6, so perform detection
- // based on version instead.
- if (ZSTD_versionNumber() < 10304 && level < 1) {
- cc_log(
- "Using compression level 1 (minimum level supported by libzstd) instead"
- " of %d",
- level);
- level = 1;
- }
-
- state->compression_level = MIN(level, ZSTD_maxCLevel());
- if (state->compression_level != level) {
- cc_log(
- "Using compression level %d (max libzstd level) instead of %d",
- state->compression_level,
- level);
- }
-
- size_t ret = ZSTD_initCStream(state->stream, state->compression_level);
- if (ZSTD_isError(ret)) {
- ZSTD_freeCStream(state->stream);
- free(state);
- return NULL;
- }
- return (struct compr_state *)state;
+ auto state = static_cast<struct state*>(malloc(sizeof(struct state)));
+ state->output = output;
+ state->checksum = checksum;
+ state->stream = ZSTD_createCStream();
+ state->failed = false;
+
+ if (level == 0) {
+ level = DEFAULT_ZSTD_COMPRESSION_LEVEL;
+ cc_log("Using default compression level %d", level);
+ }
+
+ // libzstd 1.3.4 and newer support negative levels. However, the query
+ // function ZSTD_minCLevel did not appear until 1.3.6, so perform detection
+ // based on version instead.
+ if (ZSTD_versionNumber() < 10304 && level < 1) {
+ cc_log(
+ "Using compression level 1 (minimum level supported by libzstd) instead"
+ " of %d",
+ level);
+ level = 1;
+ }
+
+ state->compression_level = MIN(level, ZSTD_maxCLevel());
+ if (state->compression_level != level) {
+ cc_log("Using compression level %d (max libzstd level) instead of %d",
+ state->compression_level,
+ level);
+ }
+
+ size_t ret = ZSTD_initCStream(state->stream, state->compression_level);
+ if (ZSTD_isError(ret)) {
+ ZSTD_freeCStream(state->stream);
+ free(state);
+ return NULL;
+ }
+ return (struct compr_state*)state;
}
static int8_t
-compr_zstd_get_actual_compression_level(struct compr_state *handle)
+compr_zstd_get_actual_compression_level(struct compr_state* handle)
{
- struct state *state = (struct state *)handle;
- return state->compression_level;
+ struct state* state = (struct state*)handle;
+ return state->compression_level;
}
static bool
-compr_zstd_write(struct compr_state *handle, const void *data, size_t size)
+compr_zstd_write(struct compr_state* handle, const void* data, size_t size)
{
- if (!handle) {
- return false;
- }
- struct state *state = (struct state *)handle;
-
- if (state->checksum) {
- XXH64_update(state->checksum, data, size);
- }
-
- state->in.src = data;
- state->in.size = size;
- state->in.pos = 0;
-
- int flush = data ? 0 : 1;
-
- size_t ret;
- while (state->in.pos < state->in.size) {
- unsigned char buffer[READ_BUFFER_SIZE];
- state->out.dst = buffer;
- state->out.size = sizeof(buffer);
- state->out.pos = 0;
- ret = ZSTD_compressStream(state->stream, &state->out, &state->in);
- assert(!(ZSTD_isError(ret)));
- size_t compressed_bytes = state->out.pos;
- if (fwrite(buffer, 1, compressed_bytes, state->output) != compressed_bytes
- || ferror(state->output)) {
- state->failed = true;
- return false;
- }
- }
- ret = flush;
- while (ret > 0) {
- unsigned char buffer[READ_BUFFER_SIZE];
- state->out.dst = buffer;
- state->out.size = sizeof(buffer);
- state->out.pos = 0;
- ret = ZSTD_endStream(state->stream, &state->out);
- size_t compressed_bytes = state->out.pos;
- if (fwrite(buffer, 1, compressed_bytes, state->output) != compressed_bytes
- || ferror(state->output)) {
- state->failed = true;
- return false;
- }
- }
-
- return true;
+ if (!handle) {
+ return false;
+ }
+ struct state* state = (struct state*)handle;
+
+ if (state->checksum) {
+ XXH64_update(state->checksum, data, size);
+ }
+
+ state->in.src = data;
+ state->in.size = size;
+ state->in.pos = 0;
+
+ int flush = data ? 0 : 1;
+
+ size_t ret;
+ while (state->in.pos < state->in.size) {
+ unsigned char buffer[READ_BUFFER_SIZE];
+ state->out.dst = buffer;
+ state->out.size = sizeof(buffer);
+ state->out.pos = 0;
+ ret = ZSTD_compressStream(state->stream, &state->out, &state->in);
+ assert(!(ZSTD_isError(ret)));
+ size_t compressed_bytes = state->out.pos;
+ if (fwrite(buffer, 1, compressed_bytes, state->output) != compressed_bytes
+ || ferror(state->output)) {
+ state->failed = true;
+ return false;
+ }
+ }
+ ret = flush;
+ while (ret > 0) {
+ unsigned char buffer[READ_BUFFER_SIZE];
+ state->out.dst = buffer;
+ state->out.size = sizeof(buffer);
+ state->out.pos = 0;
+ ret = ZSTD_endStream(state->stream, &state->out);
+ size_t compressed_bytes = state->out.pos;
+ if (fwrite(buffer, 1, compressed_bytes, state->output) != compressed_bytes
+ || ferror(state->output)) {
+ state->failed = true;
+ return false;
+ }
+ }
+
+ return true;
}
static bool
-compr_zstd_free(struct compr_state *handle)
+compr_zstd_free(struct compr_state* handle)
{
- if (!handle) {
- return false;
- }
+ if (!handle) {
+ return false;
+ }
- struct state *state = (struct state *)handle;
+ struct state* state = (struct state*)handle;
- compr_zstd_write(handle, NULL, 0);
- ZSTD_freeCStream(state->stream);
- bool success = !state->failed;
- free(state);
- return success;
+ compr_zstd_write(handle, NULL, 0);
+ ZSTD_freeCStream(state->stream);
+ bool success = !state->failed;
+ free(state);
+ return success;
}
struct compressor compressor_zstd_impl = {
- compr_zstd_init,
- compr_zstd_get_actual_compression_level,
- compr_zstd_write,
- compr_zstd_free
-};
+ compr_zstd_init,
+ compr_zstd_get_actual_compression_level,
+ compr_zstd_write,
+ compr_zstd_free};
diff --git a/src/compress.cpp b/src/compress.cpp
index e9299058..d7656fc9 100644
--- a/src/compress.cpp
+++ b/src/compress.cpp
@@ -17,37 +17,31 @@
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "ccache.hpp"
-
#include "common_header.hpp"
#include "manifest.hpp"
#include "result.hpp"
static bool
-get_content_size(
- const char *path, const char *magic, uint8_t version, size_t *size)
+get_content_size(const char* path,
+ const char* magic,
+ uint8_t version,
+ size_t* size)
{
- char *errmsg;
- FILE *f = fopen(path, "rb");
- if (!f) {
- cc_log("Failed to open %s for reading: %s", path, strerror(errno));
- return false;
- }
- struct common_header header;
- bool success = common_header_initialize_for_reading(
- &header,
- f,
- magic,
- version,
- NULL,
- NULL,
- NULL,
- &errmsg);
- fclose(f);
- if (success) {
- *size = header.content_size;
- }
-
- return success;
+ char* errmsg;
+ FILE* f = fopen(path, "rb");
+ if (!f) {
+ cc_log("Failed to open %s for reading: %s", path, strerror(errno));
+ return false;
+ }
+ struct common_header header;
+ bool success = common_header_initialize_for_reading(
+ &header, f, magic, version, NULL, NULL, NULL, &errmsg);
+ fclose(f);
+ if (success) {
+ *size = header.content_size;
+ }
+
+ return success;
}
static uint64_t on_disk_size;
@@ -57,93 +51,96 @@ static uint64_t incompr_size;
// This measures the size of files in the cache.
static void
-measure_fn(const char *fname, struct stat *st)
+measure_fn(const char* fname, struct stat* st)
{
- if (!S_ISREG(st->st_mode)) {
- return;
- }
-
- char *p = x_basename(fname);
- if (str_eq(p, "stats")) {
- free(p);
- return;
- }
-
- if (str_startswith(p, ".nfs")) {
- // Ignore temporary NFS files that may be left for open but deleted files.
- free(p);
- return;
- }
-
- if (strstr(p, ".tmp.")) {
- // Ignore tmp files since they are transient.
- free(p);
- return;
- }
-
- if (strstr(p, "CACHEDIR.TAG")) {
- free(p);
- return;
- }
-
- free(p);
-
- on_disk_size += file_size(st);
-
- size_t content_size = 0;
- const char *file_ext = get_extension(p);
- bool is_compressible = false;
- if (str_eq(file_ext, ".manifest")) {
- is_compressible = get_content_size(
- fname, MANIFEST_MAGIC, MANIFEST_VERSION, &content_size);
- } else if (str_eq(file_ext, ".result")) {
- is_compressible = get_content_size(
- fname, RESULT_MAGIC, RESULT_VERSION, &content_size);
- }
-
- if (is_compressible) {
- compr_size += st->st_size;
- compr_orig_size += content_size;
- } else {
- incompr_size += st->st_size;
- }
+ if (!S_ISREG(st->st_mode)) {
+ return;
+ }
+
+ char* p = x_basename(fname);
+ if (str_eq(p, "stats")) {
+ free(p);
+ return;
+ }
+
+ if (str_startswith(p, ".nfs")) {
+ // Ignore temporary NFS files that may be left for open but deleted files.
+ free(p);
+ return;
+ }
+
+ if (strstr(p, ".tmp.")) {
+ // Ignore tmp files since they are transient.
+ free(p);
+ return;
+ }
+
+ if (strstr(p, "CACHEDIR.TAG")) {
+ free(p);
+ return;
+ }
+
+ free(p);
+
+ on_disk_size += file_size(st);
+
+ size_t content_size = 0;
+ const char* file_ext = get_extension(p);
+ bool is_compressible = false;
+ if (str_eq(file_ext, ".manifest")) {
+ is_compressible =
+ get_content_size(fname, MANIFEST_MAGIC, MANIFEST_VERSION, &content_size);
+ } else if (str_eq(file_ext, ".result")) {
+ is_compressible =
+ get_content_size(fname, RESULT_MAGIC, RESULT_VERSION, &content_size);
+ }
+
+ if (is_compressible) {
+ compr_size += st->st_size;
+ compr_orig_size += content_size;
+ } else {
+ incompr_size += st->st_size;
+ }
}
// Process up all cache subdirectories.
-void compress_stats(struct conf *conf)
+void
+compress_stats(struct conf* conf)
{
- on_disk_size = 0;
- compr_size = 0;
- compr_orig_size = 0;
- incompr_size = 0;
-
- for (int i = 0; i <= 0xF; i++) {
- char *dname = format("%s/%1x", conf->cache_dir, i);
- traverse(dname, measure_fn);
- free(dname);
- }
-
- double ratio = compr_size > 0 ? ((double) compr_orig_size) / compr_size : 0.0;
- double savings = ratio > 0.0 ? 100.0 - (100.0 / ratio) : 0.0;
-
- char *on_disk_size_str = format_human_readable_size(on_disk_size);
- char *cache_size_str = format_human_readable_size(compr_size + incompr_size);
- char *compr_size_str = format_human_readable_size(compr_size);
- char *compr_orig_size_str = format_human_readable_size(compr_orig_size);
- char *incompr_size_str = format_human_readable_size(incompr_size);
-
- printf("Total data: %8s (%s disk blocks)\n",
- cache_size_str, on_disk_size_str);
- printf("Compressible data: %8s (%.1f%% of original size)\n",
- compr_size_str, 100.0 - savings);
- printf(" - Original size: %8s\n", compr_orig_size_str);
- printf(" - Compression ratio: %5.3f x (%.1f%% space savings)\n",
- ratio, savings);
- printf("Incompressible data: %8s\n", incompr_size_str);
-
- free(incompr_size_str);
- free(compr_orig_size_str);
- free(compr_size_str);
- free(cache_size_str);
- free(on_disk_size_str);
+ on_disk_size = 0;
+ compr_size = 0;
+ compr_orig_size = 0;
+ incompr_size = 0;
+
+ for (int i = 0; i <= 0xF; i++) {
+ char* dname = format("%s/%1x", conf->cache_dir, i);
+ traverse(dname, measure_fn);
+ free(dname);
+ }
+
+ double ratio = compr_size > 0 ? ((double)compr_orig_size) / compr_size : 0.0;
+ double savings = ratio > 0.0 ? 100.0 - (100.0 / ratio) : 0.0;
+
+ char* on_disk_size_str = format_human_readable_size(on_disk_size);
+ char* cache_size_str = format_human_readable_size(compr_size + incompr_size);
+ char* compr_size_str = format_human_readable_size(compr_size);
+ char* compr_orig_size_str = format_human_readable_size(compr_orig_size);
+ char* incompr_size_str = format_human_readable_size(incompr_size);
+
+ printf("Total data: %8s (%s disk blocks)\n",
+ cache_size_str,
+ on_disk_size_str);
+ printf("Compressible data: %8s (%.1f%% of original size)\n",
+ compr_size_str,
+ 100.0 - savings);
+ printf(" - Original size: %8s\n", compr_orig_size_str);
+ printf(
+ " - Compression ratio: %5.3f x (%.1f%% space savings)\n", ratio, savings);
+ printf("Incompressible data: %8s\n", incompr_size_str);
+
+ free(incompr_size_str);
+ free(compr_orig_size_str);
+ free(compr_size_str);
+ free(cache_size_str);
+ free(on_disk_size_str);
}
diff --git a/src/compression.cpp b/src/compression.cpp
index f210541f..766c45cf 100644
--- a/src/compression.cpp
+++ b/src/compression.cpp
@@ -17,55 +17,61 @@
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "compression.hpp"
+
#include "conf.hpp"
-extern struct conf *conf;
+extern struct conf* conf;
-int8_t compression_level_from_config(void)
+int8_t
+compression_level_from_config(void)
{
- return conf->compression ? conf->compression_level : 0;
+ return conf->compression ? conf->compression_level : 0;
}
-enum compression_type compression_type_from_config(void)
+enum compression_type
+compression_type_from_config(void)
{
- return conf->compression ? COMPR_TYPE_ZSTD : COMPR_TYPE_NONE;
+ return conf->compression ? COMPR_TYPE_ZSTD : COMPR_TYPE_NONE;
}
-const char *compression_type_to_string(uint8_t type)
+const char*
+compression_type_to_string(uint8_t type)
{
- switch (type) {
- case COMPR_TYPE_NONE:
- return "none";
+ switch (type) {
+ case COMPR_TYPE_NONE:
+ return "none";
- case COMPR_TYPE_ZSTD:
- return "zstd";
- }
+ case COMPR_TYPE_ZSTD:
+ return "zstd";
+ }
- return "unknown";
+ return "unknown";
}
-struct compressor *compressor_from_type(uint8_t type)
+struct compressor*
+compressor_from_type(uint8_t type)
{
- switch (type) {
- case COMPR_TYPE_NONE:
- return &compressor_none_impl;
+ switch (type) {
+ case COMPR_TYPE_NONE:
+ return &compressor_none_impl;
- case COMPR_TYPE_ZSTD:
- return &compressor_zstd_impl;
- }
+ case COMPR_TYPE_ZSTD:
+ return &compressor_zstd_impl;
+ }
- return NULL;
+ return NULL;
}
-struct decompressor *decompressor_from_type(uint8_t type)
+struct decompressor*
+decompressor_from_type(uint8_t type)
{
- switch (type) {
- case COMPR_TYPE_NONE:
- return &decompressor_none_impl;
+ switch (type) {
+ case COMPR_TYPE_NONE:
+ return &decompressor_none_impl;
- case COMPR_TYPE_ZSTD:
- return &decompressor_zstd_impl;
- }
+ case COMPR_TYPE_ZSTD:
+ return &decompressor_zstd_impl;
+ }
- return NULL;
+ return NULL;
}
diff --git a/src/compression.hpp b/src/compression.hpp
index b48be164..93514a71 100644
--- a/src/compression.hpp
+++ b/src/compression.hpp
@@ -19,68 +19,67 @@
#pragma once
#include "system.hpp"
+
#include "third_party/xxhash.h"
struct compr_state;
-struct compressor {
- // Create and initialize a compressor.
- //
- // output: The file to write compressed data to.
- // compression_level: Desired compression level.
- // checksum: Checksum state to update (NULL for no checksum).
- struct compr_state *(*init)(
- FILE *output,
- int8_t compression_level,
- XXH64_state_t *checksum);
-
- // Get the actual compression level that will be used.
- int8_t (*get_actual_compression_level)(struct compr_state *state);
-
- // Compress data.
- //
- // data: Buffer to read decompressed data from.
- // size: How many bytes to read.
- //
- // Returns false on failure, otherwise true.
- bool (*write)(struct compr_state *state, const void *data, size_t size);
-
- // Finalize compressor and free its state.
- //
- // Returns false if finalization failed or if any previous operation failed,
- // otherwise true.
- bool (*free)(struct compr_state *state);
+struct compressor
+{
+ // Create and initialize a compressor.
+ //
+ // output: The file to write compressed data to.
+ // compression_level: Desired compression level.
+ // checksum: Checksum state to update (NULL for no checksum).
+ struct compr_state* (*init)(FILE* output,
+ int8_t compression_level,
+ XXH64_state_t* checksum);
+
+ // Get the actual compression level that will be used.
+ int8_t (*get_actual_compression_level)(struct compr_state* state);
+
+ // Compress data.
+ //
+ // data: Buffer to read decompressed data from.
+ // size: How many bytes to read.
+ //
+ // Returns false on failure, otherwise true.
+ bool (*write)(struct compr_state* state, const void* data, size_t size);
+
+ // Finalize compressor and free its state.
+ //
+ // Returns false if finalization failed or if any previous operation failed,
+ // otherwise true.
+ bool (*free)(struct compr_state* state);
};
struct decompr_state;
-struct decompressor {
- // Create and initialize a decompressor.
- //
- // input: The file to read compressed data from.
- // checksum: Checksum state to update (NULL for no checksum).
- struct decompr_state *(*init)(FILE *input, XXH64_state_t *checksum);
-
- // Decompress data.
- //
- // data: Buffer to write decompressed data to.
- // size: How many bytes to write.
- //
- // Returns false on failure, otherwise true.
- bool (*read)(struct decompr_state *state, void *data, size_t size);
-
- // Finalize the decompressor and free its state.
- //
- // Returns false if finalization failed or if any previous operation failed,
- // otherwise true.
- bool (*free)(struct decompr_state *state);
-};
+struct decompressor
+{
+ // Create and initialize a decompressor.
+ //
+ // input: The file to read compressed data from.
+ // checksum: Checksum state to update (NULL for no checksum).
+ struct decompr_state* (*init)(FILE* input, XXH64_state_t* checksum);
+
+ // Decompress data.
+ //
+ // data: Buffer to write decompressed data to.
+ // size: How many bytes to write.
+ //
+ // Returns false on failure, otherwise true.
+ bool (*read)(struct decompr_state* state, void* data, size_t size);
-enum compression_type {
- COMPR_TYPE_NONE = 0,
- COMPR_TYPE_ZSTD = 1
+ // Finalize the decompressor and free its state.
+ //
+ // Returns false if finalization failed or if any previous operation failed,
+ // otherwise true.
+ bool (*free)(struct decompr_state* state);
};
+enum compression_type { COMPR_TYPE_NONE = 0, COMPR_TYPE_ZSTD = 1 };
+
extern struct compressor compressor_none_impl;
extern struct decompressor decompressor_none_impl;
@@ -89,6 +88,6 @@ extern struct decompressor decompressor_zstd_impl;
int8_t compression_level_from_config(void);
enum compression_type compression_type_from_config(void);
-const char *compression_type_to_string(uint8_t type);
-struct compressor *compressor_from_type(uint8_t type);
-struct decompressor *decompressor_from_type(uint8_t type);
+const char* compression_type_to_string(uint8_t type);
+struct compressor* compressor_from_type(uint8_t type);
+struct decompressor* decompressor_from_type(uint8_t type);
diff --git a/src/conf.cpp b/src/conf.cpp
index 379a2315..bf0a454d 100644
--- a/src/conf.cpp
+++ b/src/conf.cpp
@@ -17,183 +17,193 @@
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "conf.hpp"
+
+#include "ccache.hpp"
#include "confitems.hpp"
#include "envtoconfitems.hpp"
-#include "ccache.hpp"
enum handle_conf_result {
- HANDLE_CONF_OK,
- HANDLE_CONF_UNKNOWN,
- HANDLE_CONF_FAIL
+ HANDLE_CONF_OK,
+ HANDLE_CONF_UNKNOWN,
+ HANDLE_CONF_FAIL
};
-static const struct conf_item *
-find_conf(const char *name)
+static const struct conf_item*
+find_conf(const char* name)
{
- return confitems_get(name, strlen(name));
+ return confitems_get(name, strlen(name));
}
-static const struct env_to_conf_item *
-find_env_to_conf(const char *name)
+static const struct env_to_conf_item*
+find_env_to_conf(const char* name)
{
- return envtoconfitems_get(name, strlen(name));
+ return envtoconfitems_get(name, strlen(name));
}
static enum handle_conf_result
-handle_conf_setting(struct conf *conf, const char *key, const char *value,
- char **errmsg, bool from_env_variable, bool negate_boolean,
- const char *origin)
+handle_conf_setting(struct conf* conf,
+ const char* key,
+ const char* value,
+ char** errmsg,
+ bool from_env_variable,
+ bool negate_boolean,
+ const char* origin)
{
- const struct conf_item *item = find_conf(key);
- if (!item) {
- return HANDLE_CONF_UNKNOWN;
- }
-
- if (from_env_variable && item->parser == confitem_parse_bool) {
- // Special rule for boolean settings from the environment: "0", "false",
- // "disable" and "no" (case insensitive) are invalid, and all other values
- // mean true.
- //
- // Previously any value meant true, but this was surprising to users, who
- // might do something like CCACHE_DISABLE=0 and expect ccache to be
- // enabled.
- if (str_eq(value, "0") || strcasecmp(value, "false") == 0
- || strcasecmp(value, "disable") == 0 || strcasecmp(value, "no") == 0) {
- fatal("invalid boolean environment variable value \"%s\"", value);
- }
-
- bool *boolvalue = (bool *)((char *)conf + item->offset);
- *boolvalue = !negate_boolean;
- goto out;
- }
-
- if (!item->parser(value, (char *)conf + item->offset, errmsg)) {
- return HANDLE_CONF_FAIL;
- }
- if (item->verifier && !item->verifier((char *)conf + item->offset, errmsg)) {
- return HANDLE_CONF_FAIL;
- }
+ const struct conf_item* item = find_conf(key);
+ if (!item) {
+ return HANDLE_CONF_UNKNOWN;
+ }
+
+ if (from_env_variable && item->parser == confitem_parse_bool) {
+ // Special rule for boolean settings from the environment: "0", "false",
+ // "disable" and "no" (case insensitive) are invalid, and all other values
+ // mean true.
+ //
+ // Previously any value meant true, but this was surprising to users, who
+ // might do something like CCACHE_DISABLE=0 and expect ccache to be
+ // enabled.
+ if (str_eq(value, "0") || strcasecmp(value, "false") == 0
+ || strcasecmp(value, "disable") == 0 || strcasecmp(value, "no") == 0) {
+ fatal("invalid boolean environment variable value \"%s\"", value);
+ }
+
+ bool* boolvalue = (bool*)((char*)conf + item->offset);
+ *boolvalue = !negate_boolean;
+ goto out;
+ }
+
+ if (!item->parser(value, (char*)conf + item->offset, errmsg)) {
+ return HANDLE_CONF_FAIL;
+ }
+ if (item->verifier && !item->verifier((char*)conf + item->offset, errmsg)) {
+ return HANDLE_CONF_FAIL;
+ }
out:
- conf->item_origins[item->number] = origin;
- return HANDLE_CONF_OK;
+ conf->item_origins[item->number] = origin;
+ return HANDLE_CONF_OK;
}
static bool
-parse_line(const char *line, char **key, char **value, char **errmsg)
+parse_line(const char* line, char** key, char** value, char** errmsg)
{
-#define SKIP_WS(x) do { while (isspace(*x)) { ++x; } } while (false)
-
- *key = NULL;
- *value = NULL;
-
- const char *p = line;
- SKIP_WS(p);
- if (*p == '\0' || *p == '#') {
- return true;
- }
- const char *q = p;
- while (isalpha(*q) || *q == '_') {
- ++q;
- }
- *key = x_strndup(p, q - p);
- p = q;
- SKIP_WS(p);
- if (*p != '=') {
- *errmsg = x_strdup("missing equal sign");
- free(*key);
- *key = NULL;
- return false;
- }
- ++p;
-
- // Skip leading whitespace.
- SKIP_WS(p);
- q = p;
- while (*q) {
- ++q;
- }
- // Skip trailing whitespace.
- while (isspace(q[-1])) {
- --q;
- }
- *value = x_strndup(p, q - p);
-
- return true;
+#define SKIP_WS(x) \
+ do { \
+ while (isspace(*x)) { \
+ ++x; \
+ } \
+ } while (false)
+
+ *key = NULL;
+ *value = NULL;
+
+ const char* p = line;
+ SKIP_WS(p);
+ if (*p == '\0' || *p == '#') {
+ return true;
+ }
+ const char* q = p;
+ while (isalpha(*q) || *q == '_') {
+ ++q;
+ }
+ *key = x_strndup(p, q - p);
+ p = q;
+ SKIP_WS(p);
+ if (*p != '=') {
+ *errmsg = x_strdup("missing equal sign");
+ free(*key);
+ *key = NULL;
+ return false;
+ }
+ ++p;
+
+ // Skip leading whitespace.
+ SKIP_WS(p);
+ q = p;
+ while (*q) {
+ ++q;
+ }
+ // Skip trailing whitespace.
+ while (isspace(q[-1])) {
+ --q;
+ }
+ *value = x_strndup(p, q - p);
+
+ return true;
#undef SKIP_WS
}
// Create a conf struct with default values.
-struct conf *
+struct conf*
conf_create(void)
{
- auto conf = static_cast<struct conf*>(x_malloc(sizeof(struct conf)));
-
- conf->base_dir = x_strdup("");
- conf->cache_dir = format("%s/.ccache", get_home_directory());
- conf->cache_dir_levels = 2;
- conf->compiler = x_strdup("");
- conf->compiler_check = x_strdup("mtime");
- conf->compression = true;
- conf->compression_level = 0;
- conf->cpp_extension = x_strdup("");
- conf->debug = false;
- conf->depend_mode = false;
- conf->direct_mode = true;
- conf->disable = false;
- conf->extra_files_to_hash = x_strdup("");
- conf->file_clone = false;
- conf->hard_link = false;
- conf->hash_dir = true;
- conf->ignore_headers_in_manifest = x_strdup("");
- conf->keep_comments_cpp = false;
- conf->limit_multiple = 0.8;
- conf->log_file = x_strdup("");
- conf->max_files = 0;
- conf->max_size = (uint64_t)5 * 1000 * 1000 * 1000;
- conf->path = x_strdup("");
- conf->pch_external_checksum = false;
- conf->prefix_command = x_strdup("");
- conf->prefix_command_cpp = x_strdup("");
- conf->read_only = false;
- conf->read_only_direct = false;
- conf->recache = false;
- conf->run_second_cpp = true;
- conf->sloppiness = 0;
- conf->stats = true;
- conf->temporary_dir = x_strdup("");
- conf->umask = UINT_MAX; // Default: don't set umask.
- conf->unify = false;
-
- conf->item_origins = static_cast<const char**>(
- x_malloc(confitems_count() * sizeof(char *)));
- for (size_t i = 0; i < confitems_count(); ++i) {
- conf->item_origins[i] = "default";
- }
- return conf;
+ auto conf = static_cast<struct conf*>(x_malloc(sizeof(struct conf)));
+
+ conf->base_dir = x_strdup("");
+ conf->cache_dir = format("%s/.ccache", get_home_directory());
+ conf->cache_dir_levels = 2;
+ conf->compiler = x_strdup("");
+ conf->compiler_check = x_strdup("mtime");
+ conf->compression = true;
+ conf->compression_level = 0;
+ conf->cpp_extension = x_strdup("");
+ conf->debug = false;
+ conf->depend_mode = false;
+ conf->direct_mode = true;
+ conf->disable = false;
+ conf->extra_files_to_hash = x_strdup("");
+ conf->file_clone = false;
+ conf->hard_link = false;
+ conf->hash_dir = true;
+ conf->ignore_headers_in_manifest = x_strdup("");
+ conf->keep_comments_cpp = false;
+ conf->limit_multiple = 0.8;
+ conf->log_file = x_strdup("");
+ conf->max_files = 0;
+ conf->max_size = (uint64_t)5 * 1000 * 1000 * 1000;
+ conf->path = x_strdup("");
+ conf->pch_external_checksum = false;
+ conf->prefix_command = x_strdup("");
+ conf->prefix_command_cpp = x_strdup("");
+ conf->read_only = false;
+ conf->read_only_direct = false;
+ conf->recache = false;
+ conf->run_second_cpp = true;
+ conf->sloppiness = 0;
+ conf->stats = true;
+ conf->temporary_dir = x_strdup("");
+ conf->umask = UINT_MAX; // Default: don't set umask.
+ conf->unify = false;
+
+ conf->item_origins =
+ static_cast<const char**>(x_malloc(confitems_count() * sizeof(char*)));
+ for (size_t i = 0; i < confitems_count(); ++i) {
+ conf->item_origins[i] = "default";
+ }
+ return conf;
}
void
-conf_free(struct conf *conf)
+conf_free(struct conf* conf)
{
- if (!conf) {
- return;
- }
- free(conf->base_dir);
- free(conf->cache_dir);
- free(conf->compiler);
- free(conf->compiler_check);
- free(conf->cpp_extension);
- free(conf->extra_files_to_hash);
- free(conf->ignore_headers_in_manifest);
- free(conf->log_file);
- free(conf->path);
- free(conf->prefix_command);
- free(conf->prefix_command_cpp);
- free(conf->temporary_dir);
- free((void *)conf->item_origins); // Workaround for MSVC warning
- free(conf);
+ if (!conf) {
+ return;
+ }
+ free(conf->base_dir);
+ free(conf->cache_dir);
+ free(conf->compiler);
+ free(conf->compiler_check);
+ free(conf->cpp_extension);
+ free(conf->extra_files_to_hash);
+ free(conf->ignore_headers_in_manifest);
+ free(conf->log_file);
+ free(conf->path);
+ free(conf->prefix_command);
+ free(conf->prefix_command_cpp);
+ free(conf->temporary_dir);
+ free((void*)conf->item_origins); // Workaround for MSVC warning
+ free(conf);
}
// Note: The path pointer is stored in conf, so path must outlive conf.
@@ -201,241 +211,249 @@ conf_free(struct conf *conf)
// On failure, if an I/O error occurred errno is set appropriately, otherwise
// errno is set to zero indicating that config itself was invalid.
bool
-conf_read(struct conf *conf, const char *path, char **errmsg)
+conf_read(struct conf* conf, const char* path, char** errmsg)
{
- assert(errmsg);
- *errmsg = NULL;
-
- FILE *f = fopen(path, "r");
- if (!f) {
- *errmsg = format("%s: %s", path, strerror(errno));
- return false;
- }
-
- unsigned line_number = 0;
- bool result = true;
- char buf[10000];
- while (fgets(buf, sizeof(buf), f)) {
- ++line_number;
-
- char *key;
- char *value;
- char *errmsg2;
- enum handle_conf_result hcr = HANDLE_CONF_OK;
- bool ok = parse_line(buf, &key, &value, &errmsg2);
- if (ok && key) { // key == NULL if comment or blank line.
- hcr =
- handle_conf_setting(conf, key, value, &errmsg2, false, false, path);
- ok = hcr != HANDLE_CONF_FAIL; // unknown is OK
- }
- free(key);
- free(value);
- if (!ok) {
- *errmsg = format("%s:%u: %s", path, line_number, errmsg2);
- free(errmsg2);
- errno = 0;
- result = false;
- goto out;
- }
- }
- if (ferror(f)) {
- *errmsg = x_strdup(strerror(errno));
- result = false;
- }
+ assert(errmsg);
+ *errmsg = NULL;
+
+ FILE* f = fopen(path, "r");
+ if (!f) {
+ *errmsg = format("%s: %s", path, strerror(errno));
+ return false;
+ }
+
+ unsigned line_number = 0;
+ bool result = true;
+ char buf[10000];
+ while (fgets(buf, sizeof(buf), f)) {
+ ++line_number;
+
+ char* key;
+ char* value;
+ char* errmsg2;
+ enum handle_conf_result hcr = HANDLE_CONF_OK;
+ bool ok = parse_line(buf, &key, &value, &errmsg2);
+ if (ok && key) { // key == NULL if comment or blank line.
+ hcr = handle_conf_setting(conf, key, value, &errmsg2, false, false, path);
+ ok = hcr != HANDLE_CONF_FAIL; // unknown is OK
+ }
+ free(key);
+ free(value);
+ if (!ok) {
+ *errmsg = format("%s:%u: %s", path, line_number, errmsg2);
+ free(errmsg2);
+ errno = 0;
+ result = false;
+ goto out;
+ }
+ }
+ if (ferror(f)) {
+ *errmsg = x_strdup(strerror(errno));
+ result = false;
+ }
out:
- fclose(f);
- return result;
+ fclose(f);
+ return result;
}
bool
-conf_update_from_environment(struct conf *conf, char **errmsg)
+conf_update_from_environment(struct conf* conf, char** errmsg)
{
- for (char **p = environ; *p; ++p) {
- if (!str_startswith(*p, "CCACHE_")) {
- continue;
- }
- char *q = strchr(*p, '=');
- if (!q) {
- continue;
- }
-
- bool negate;
- size_t key_start;
- if (str_startswith(*p + 7, "NO")) {
- negate = true;
- key_start = 9;
- } else {
- negate = false;
- key_start = 7;
- }
- char *key = x_strndup(*p + key_start, q - *p - key_start);
-
- ++q; // Now points to the value.
-
- const struct env_to_conf_item *env_to_conf_item = find_env_to_conf(key);
- if (!env_to_conf_item) {
- free(key);
- continue;
- }
-
- char *errmsg2 = NULL;
- enum handle_conf_result hcr = handle_conf_setting(
- conf, env_to_conf_item->conf_name, q, &errmsg2, true, negate,
- "environment");
- if (hcr != HANDLE_CONF_OK) {
- *errmsg = format("%s: %s", key, errmsg2);
- free(errmsg2);
- free(key);
- return false;
- }
-
- free(key);
- }
-
- return true;
+ for (char** p = environ; *p; ++p) {
+ if (!str_startswith(*p, "CCACHE_")) {
+ continue;
+ }
+ char* q = strchr(*p, '=');
+ if (!q) {
+ continue;
+ }
+
+ bool negate;
+ size_t key_start;
+ if (str_startswith(*p + 7, "NO")) {
+ negate = true;
+ key_start = 9;
+ } else {
+ negate = false;
+ key_start = 7;
+ }
+ char* key = x_strndup(*p + key_start, q - *p - key_start);
+
+ ++q; // Now points to the value.
+
+ const struct env_to_conf_item* env_to_conf_item = find_env_to_conf(key);
+ if (!env_to_conf_item) {
+ free(key);
+ continue;
+ }
+
+ char* errmsg2 = NULL;
+ enum handle_conf_result hcr =
+ handle_conf_setting(conf,
+ env_to_conf_item->conf_name,
+ q,
+ &errmsg2,
+ true,
+ negate,
+ "environment");
+ if (hcr != HANDLE_CONF_OK) {
+ *errmsg = format("%s: %s", key, errmsg2);
+ free(errmsg2);
+ free(key);
+ return false;
+ }
+
+ free(key);
+ }
+
+ return true;
}
bool
-conf_set_value_in_file(const char *path, const char *key, const char *value,
- char **errmsg)
+conf_set_value_in_file(const char* path,
+ const char* key,
+ const char* value,
+ char** errmsg)
{
- const struct conf_item *item = find_conf(key);
- if (!item) {
- *errmsg = format("unknown configuration option \"%s\"", key);
- return false;
- }
-
- char dummy[8] = {0}; // The maximum entry size in struct conf.
- if (!item->parser(value, (void *)dummy, errmsg)
- || (item->verifier && !item->verifier(value, errmsg))) {
- return false;
- }
-
- FILE *infile = fopen(path, "r");
- if (!infile) {
- *errmsg = format("%s: %s", path, strerror(errno));
- return false;
- }
-
- char *outpath = format("%s.tmp", path);
- FILE *outfile = create_tmp_file(&outpath, "w");
- if (!outfile) {
- *errmsg = format("%s: %s", outpath, strerror(errno));
- free(outpath);
- fclose(infile);
- return false;
- }
-
- bool found = false;
- char buf[10000];
- while (fgets(buf, sizeof(buf), infile)) {
- char *key2;
- char *value2;
- char *errmsg2;
- bool ok = parse_line(buf, &key2, &value2, &errmsg2);
- if (ok && key2 && str_eq(key2, key)) {
- found = true;
- fprintf(outfile, "%s = %s\n", key, value);
- } else {
- fputs(buf, outfile);
- }
- free(key2);
- free(value2);
- }
-
- if (!found) {
- fprintf(outfile, "%s = %s\n", key, value);
- }
-
- fclose(infile);
- fclose(outfile);
- if (x_rename(outpath, path) != 0) {
- *errmsg = format("rename %s to %s: %s", outpath, path, strerror(errno));
- return false;
- }
- free(outpath);
-
- return true;
+ const struct conf_item* item = find_conf(key);
+ if (!item) {
+ *errmsg = format("unknown configuration option \"%s\"", key);
+ return false;
+ }
+
+ char dummy[8] = {0}; // The maximum entry size in struct conf.
+ if (!item->parser(value, (void*)dummy, errmsg)
+ || (item->verifier && !item->verifier(value, errmsg))) {
+ return false;
+ }
+
+ FILE* infile = fopen(path, "r");
+ if (!infile) {
+ *errmsg = format("%s: %s", path, strerror(errno));
+ return false;
+ }
+
+ char* outpath = format("%s.tmp", path);
+ FILE* outfile = create_tmp_file(&outpath, "w");
+ if (!outfile) {
+ *errmsg = format("%s: %s", outpath, strerror(errno));
+ free(outpath);
+ fclose(infile);
+ return false;
+ }
+
+ bool found = false;
+ char buf[10000];
+ while (fgets(buf, sizeof(buf), infile)) {
+ char* key2;
+ char* value2;
+ char* errmsg2;
+ bool ok = parse_line(buf, &key2, &value2, &errmsg2);
+ if (ok && key2 && str_eq(key2, key)) {
+ found = true;
+ fprintf(outfile, "%s = %s\n", key, value);
+ } else {
+ fputs(buf, outfile);
+ }
+ free(key2);
+ free(value2);
+ }
+
+ if (!found) {
+ fprintf(outfile, "%s = %s\n", key, value);
+ }
+
+ fclose(infile);
+ fclose(outfile);
+ if (x_rename(outpath, path) != 0) {
+ *errmsg = format("rename %s to %s: %s", outpath, path, strerror(errno));
+ return false;
+ }
+ free(outpath);
+
+ return true;
}
bool
-conf_print_value(struct conf *conf, const char *key,
- FILE *file, char **errmsg)
+conf_print_value(struct conf* conf, const char* key, FILE* file, char** errmsg)
{
- const struct conf_item *item = find_conf(key);
- if (!item) {
- *errmsg = format("unknown configuration option \"%s\"", key);
- return false;
- }
- void *value = (char *)conf + item->offset;
- char *str = item->formatter(value);
- fprintf(file, "%s\n", str);
- free(str);
- return true;
+ const struct conf_item* item = find_conf(key);
+ if (!item) {
+ *errmsg = format("unknown configuration option \"%s\"", key);
+ return false;
+ }
+ void* value = (char*)conf + item->offset;
+ char* str = item->formatter(value);
+ fprintf(file, "%s\n", str);
+ free(str);
+ return true;
}
static bool
-print_item(struct conf *conf, const char *key,
- void (*printer)(const char *descr, const char *origin,
- void *context),
- void *context)
+print_item(struct conf* conf,
+ const char* key,
+ void (*printer)(const char* descr,
+ const char* origin,
+ void* context),
+ void* context)
{
- const struct conf_item *item = find_conf(key);
- if (!item) {
- return false;
- }
- void *value = (char *)conf + item->offset;
- char *str = item->formatter(value);
- char *buf = x_strdup("");
- reformat(&buf, "%s = %s", key, str);
- printer(buf, conf->item_origins[item->number], context);
- free(buf);
- free(str);
- return true;
+ const struct conf_item* item = find_conf(key);
+ if (!item) {
+ return false;
+ }
+ void* value = (char*)conf + item->offset;
+ char* str = item->formatter(value);
+ char* buf = x_strdup("");
+ reformat(&buf, "%s = %s", key, str);
+ printer(buf, conf->item_origins[item->number], context);
+ free(buf);
+ free(str);
+ return true;
}
bool
-conf_print_items(struct conf *conf,
- void (*printer)(const char *descr, const char *origin,
- void *context),
- void *context)
+conf_print_items(struct conf* conf,
+ void (*printer)(const char* descr,
+ const char* origin,
+ void* context),
+ void* context)
{
- bool ok = true;
- ok &= print_item(conf, "base_dir", printer, context);
- ok &= print_item(conf, "cache_dir", printer, context);
- ok &= print_item(conf, "cache_dir_levels", printer, context);
- ok &= print_item(conf, "compiler", printer, context);
- ok &= print_item(conf, "compiler_check", printer, context);
- ok &= print_item(conf, "compression", printer, context);
- ok &= print_item(conf, "compression_level", printer, context);
- ok &= print_item(conf, "cpp_extension", printer, context);
- ok &= print_item(conf, "debug", printer, context);
- ok &= print_item(conf, "depend_mode", printer, context);
- ok &= print_item(conf, "direct_mode", printer, context);
- ok &= print_item(conf, "disable", printer, context);
- ok &= print_item(conf, "extra_files_to_hash", printer, context);
- ok &= print_item(conf, "file_clone", printer, context);
- ok &= print_item(conf, "hard_link", printer, context);
- ok &= print_item(conf, "hash_dir", printer, context);
- ok &= print_item(conf, "ignore_headers_in_manifest", printer, context);
- ok &= print_item(conf, "keep_comments_cpp", printer, context);
- ok &= print_item(conf, "limit_multiple", printer, context);
- ok &= print_item(conf, "log_file", printer, context);
- ok &= print_item(conf, "max_files", printer, context);
- ok &= print_item(conf, "max_size", printer, context);
- ok &= print_item(conf, "path", printer, context);
- ok &= print_item(conf, "pch_external_checksum", printer, context);
- ok &= print_item(conf, "prefix_command", printer, context);
- ok &= print_item(conf, "prefix_command_cpp", printer, context);
- ok &= print_item(conf, "read_only", printer, context);
- ok &= print_item(conf, "read_only_direct", printer, context);
- ok &= print_item(conf, "recache", printer, context);
- ok &= print_item(conf, "run_second_cpp", printer, context);
- ok &= print_item(conf, "sloppiness", printer, context);
- ok &= print_item(conf, "stats", printer, context);
- ok &= print_item(conf, "temporary_dir", printer, context);
- ok &= print_item(conf, "umask", printer, context);
- ok &= print_item(conf, "unify", printer, context);
- return ok;
+ bool ok = true;
+ ok &= print_item(conf, "base_dir", printer, context);
+ ok &= print_item(conf, "cache_dir", printer, context);
+ ok &= print_item(conf, "cache_dir_levels", printer, context);
+ ok &= print_item(conf, "compiler", printer, context);
+ ok &= print_item(conf, "compiler_check", printer, context);
+ ok &= print_item(conf, "compression", printer, context);
+ ok &= print_item(conf, "compression_level", printer, context);
+ ok &= print_item(conf, "cpp_extension", printer, context);
+ ok &= print_item(conf, "debug", printer, context);
+ ok &= print_item(conf, "depend_mode", printer, context);
+ ok &= print_item(conf, "direct_mode", printer, context);
+ ok &= print_item(conf, "disable", printer, context);
+ ok &= print_item(conf, "extra_files_to_hash", printer, context);
+ ok &= print_item(conf, "file_clone", printer, context);
+ ok &= print_item(conf, "hard_link", printer, context);
+ ok &= print_item(conf, "hash_dir", printer, context);
+ ok &= print_item(conf, "ignore_headers_in_manifest", printer, context);
+ ok &= print_item(conf, "keep_comments_cpp", printer, context);
+ ok &= print_item(conf, "limit_multiple", printer, context);
+ ok &= print_item(conf, "log_file", printer, context);
+ ok &= print_item(conf, "max_files", printer, context);
+ ok &= print_item(conf, "max_size", printer, context);
+ ok &= print_item(conf, "path", printer, context);
+ ok &= print_item(conf, "pch_external_checksum", printer, context);
+ ok &= print_item(conf, "prefix_command", printer, context);
+ ok &= print_item(conf, "prefix_command_cpp", printer, context);
+ ok &= print_item(conf, "read_only", printer, context);
+ ok &= print_item(conf, "read_only_direct", printer, context);
+ ok &= print_item(conf, "recache", printer, context);
+ ok &= print_item(conf, "run_second_cpp", printer, context);
+ ok &= print_item(conf, "sloppiness", printer, context);
+ ok &= print_item(conf, "stats", printer, context);
+ ok &= print_item(conf, "temporary_dir", printer, context);
+ ok &= print_item(conf, "umask", printer, context);
+ ok &= print_item(conf, "unify", printer, context);
+ return ok;
}
diff --git a/src/conf.hpp b/src/conf.hpp
index 792d48a9..54c27f03 100644
--- a/src/conf.hpp
+++ b/src/conf.hpp
@@ -20,55 +20,59 @@
#include "system.hpp"
-struct conf {
- char *base_dir;
- char *cache_dir;
- unsigned cache_dir_levels;
- char *compiler;
- char *compiler_check;
- bool compression;
- int compression_level;
- char *cpp_extension;
- bool debug;
- bool depend_mode;
- bool direct_mode;
- bool disable;
- char *extra_files_to_hash;
- bool file_clone;
- bool hard_link;
- bool hash_dir;
- char *ignore_headers_in_manifest;
- bool keep_comments_cpp;
- double limit_multiple;
- char *log_file;
- unsigned max_files;
- uint64_t max_size;
- char *path;
- bool pch_external_checksum;
- char *prefix_command;
- char *prefix_command_cpp;
- bool read_only;
- bool read_only_direct;
- bool recache;
- bool run_second_cpp;
- unsigned sloppiness;
- bool stats;
- char *temporary_dir;
- unsigned umask;
- bool unify;
+struct conf
+{
+ char* base_dir;
+ char* cache_dir;
+ unsigned cache_dir_levels;
+ char* compiler;
+ char* compiler_check;
+ bool compression;
+ int compression_level;
+ char* cpp_extension;
+ bool debug;
+ bool depend_mode;
+ bool direct_mode;
+ bool disable;
+ char* extra_files_to_hash;
+ bool file_clone;
+ bool hard_link;
+ bool hash_dir;
+ char* ignore_headers_in_manifest;
+ bool keep_comments_cpp;
+ double limit_multiple;
+ char* log_file;
+ unsigned max_files;
+ uint64_t max_size;
+ char* path;
+ bool pch_external_checksum;
+ char* prefix_command;
+ char* prefix_command_cpp;
+ bool read_only;
+ bool read_only_direct;
+ bool recache;
+ bool run_second_cpp;
+ unsigned sloppiness;
+ bool stats;
+ char* temporary_dir;
+ unsigned umask;
+ bool unify;
- const char **item_origins;
+ const char** item_origins;
};
-struct conf *conf_create(void);
-void conf_free(struct conf *conf);
-bool conf_read(struct conf *conf, const char *path, char **errmsg);
-bool conf_update_from_environment(struct conf *conf, char **errmsg);
-bool conf_print_value(struct conf *conf, const char *key,
- FILE *file, char **errmsg);
-bool conf_set_value_in_file(const char *path, const char *key,
- const char *value, char **errmsg);
-bool conf_print_items(struct conf *conf,
- void (*printer)(const char *descr, const char *origin,
- void *context),
- void *context);
+struct conf* conf_create(void);
+void conf_free(struct conf* conf);
+bool conf_read(struct conf* conf, const char* path, char** errmsg);
+bool conf_update_from_environment(struct conf* conf, char** errmsg);
+bool
+conf_print_value(struct conf* conf, const char* key, FILE* file, char** errmsg);
+bool conf_set_value_in_file(const char* path,
+ const char* key,
+ const char* value,
+ char** errmsg);
+bool conf_print_items(struct conf* conf,
+ void (*printer)(const char* descr,
+ const char* origin,
+ void* context),
+ void* context);
diff --git a/src/confitems.cpp b/src/confitems.cpp
index 1b4023f4..386a430f 100644
--- a/src/confitems.cpp
+++ b/src/confitems.cpp
@@ -17,317 +17,318 @@
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "confitems.hpp"
+
#include "ccache.hpp"
-static char *
-format_string(const void *value)
+static char*
+format_string(const void* value)
{
- const char *const *str = (const char *const *)value;
- return x_strdup(*str);
+ const char* const* str = (const char* const*)value;
+ return x_strdup(*str);
}
bool
-confitem_parse_bool(const char *str, void *result, char **errmsg)
+confitem_parse_bool(const char* str, void* result, char** errmsg)
{
- bool *value = (bool *)result;
+ bool* value = (bool*)result;
- if (str_eq(str, "true")) {
- *value = true;
- return true;
- } else if (str_eq(str, "false")) {
- *value = false;
- return true;
- } else {
- *errmsg = format("not a boolean value: \"%s\"", str);
- return false;
- }
+ if (str_eq(str, "true")) {
+ *value = true;
+ return true;
+ } else if (str_eq(str, "false")) {
+ *value = false;
+ return true;
+ } else {
+ *errmsg = format("not a boolean value: \"%s\"", str);
+ return false;
+ }
}
-char *
-confitem_format_bool(const void *value)
+char*
+confitem_format_bool(const void* value)
{
- const bool *b = (const bool *)value;
- return x_strdup(*b ? "true" : "false");
+ const bool* b = (const bool*)value;
+ return x_strdup(*b ? "true" : "false");
}
bool
-confitem_parse_env_string(const char *str, void *result, char **errmsg)
+confitem_parse_env_string(const char* str, void* result, char** errmsg)
{
- char **value = (char **)result;
- free(*value);
- *value = subst_env_in_string(str, errmsg);
- return *value != NULL;
+ char** value = (char**)result;
+ free(*value);
+ *value = subst_env_in_string(str, errmsg);
+ return *value != NULL;
}
-char *
-confitem_format_env_string(const void *value)
+char*
+confitem_format_env_string(const void* value)
{
- return format_string(value);
+ return format_string(value);
}
bool
-confitem_parse_double(const char *str, void *result, char **errmsg)
+confitem_parse_double(const char* str, void* result, char** errmsg)
{
- double *value = (double *)result;
- errno = 0;
- char *endptr;
- double x = strtod(str, &endptr);
- if (errno == 0 && *str != '\0' && *endptr == '\0') {
- *value = x;
- return true;
- } else {
- *errmsg = format("invalid floating point: \"%s\"", str);
- return false;
- }
+ double* value = (double*)result;
+ errno = 0;
+ char* endptr;
+ double x = strtod(str, &endptr);
+ if (errno == 0 && *str != '\0' && *endptr == '\0') {
+ *value = x;
+ return true;
+ } else {
+ *errmsg = format("invalid floating point: \"%s\"", str);
+ return false;
+ }
}
-char *
-confitem_format_double(const void *value)
+char*
+confitem_format_double(const void* value)
{
- const double *x = (const double *)value;
- return format("%.1f", *x);
+ const double* x = (const double*)value;
+ return format("%.1f", *x);
}
bool
-confitem_parse_size(const char *str, void *result, char **errmsg)
+confitem_parse_size(const char* str, void* result, char** errmsg)
{
- uint64_t *value = (uint64_t *)result;
- uint64_t size;
- if (parse_size_with_suffix(str, &size)) {
- *value = size;
- return true;
- } else {
- *errmsg = format("invalid size: \"%s\"", str);
- return false;
- }
+ uint64_t* value = (uint64_t*)result;
+ uint64_t size;
+ if (parse_size_with_suffix(str, &size)) {
+ *value = size;
+ return true;
+ } else {
+ *errmsg = format("invalid size: \"%s\"", str);
+ return false;
+ }
}
-char *
-confitem_format_size(const void *value)
+char*
+confitem_format_size(const void* value)
{
- const uint64_t *size = (const uint64_t *)value;
- return format_parsable_size_with_suffix(*size);
+ const uint64_t* size = (const uint64_t*)value;
+ return format_parsable_size_with_suffix(*size);
}
bool
-confitem_parse_sloppiness(const char *str, void *result, char **errmsg)
+confitem_parse_sloppiness(const char* str, void* result, char** errmsg)
{
- unsigned *value = (unsigned *)result;
- if (!str) {
- return *value;
- }
+ unsigned* value = (unsigned*)result;
+ if (!str) {
+ return *value;
+ }
- char *p = x_strdup(str);
- char *q = p;
- char *word;
- char *saveptr = NULL;
- while ((word = strtok_r(q, ", ", &saveptr))) {
- if (str_eq(word, "file_macro")) {
- *value |= SLOPPY_FILE_MACRO;
- } else if (str_eq(word, "file_stat_matches")) {
- *value |= SLOPPY_FILE_STAT_MATCHES;
- } else if (str_eq(word, "file_stat_matches_ctime")) {
- *value |= SLOPPY_FILE_STAT_MATCHES_CTIME;
- } else if (str_eq(word, "include_file_ctime")) {
- *value |= SLOPPY_INCLUDE_FILE_CTIME;
- } else if (str_eq(word, "include_file_mtime")) {
- *value |= SLOPPY_INCLUDE_FILE_MTIME;
- } else if (str_eq(word, "system_headers")
- || str_eq(word, "no_system_headers")) {
- *value |= SLOPPY_SYSTEM_HEADERS;
- } else if (str_eq(word, "pch_defines")) {
- *value |= SLOPPY_PCH_DEFINES;
- } else if (str_eq(word, "time_macros")) {
- *value |= SLOPPY_TIME_MACROS;
- } else if (str_eq(word, "clang_index_store")) {
- *value |= SLOPPY_CLANG_INDEX_STORE;
- } else if (str_eq(word, "locale")) {
- *value |= SLOPPY_LOCALE;
- } else {
- *errmsg = format("unknown sloppiness: \"%s\"", word);
- free(p);
- return false;
- }
- q = NULL;
- }
- free(p);
- return true;
+ char* p = x_strdup(str);
+ char* q = p;
+ char* word;
+ char* saveptr = NULL;
+ while ((word = strtok_r(q, ", ", &saveptr))) {
+ if (str_eq(word, "file_macro")) {
+ *value |= SLOPPY_FILE_MACRO;
+ } else if (str_eq(word, "file_stat_matches")) {
+ *value |= SLOPPY_FILE_STAT_MATCHES;
+ } else if (str_eq(word, "file_stat_matches_ctime")) {
+ *value |= SLOPPY_FILE_STAT_MATCHES_CTIME;
+ } else if (str_eq(word, "include_file_ctime")) {
+ *value |= SLOPPY_INCLUDE_FILE_CTIME;
+ } else if (str_eq(word, "include_file_mtime")) {
+ *value |= SLOPPY_INCLUDE_FILE_MTIME;
+ } else if (str_eq(word, "system_headers")
+ || str_eq(word, "no_system_headers")) {
+ *value |= SLOPPY_SYSTEM_HEADERS;
+ } else if (str_eq(word, "pch_defines")) {
+ *value |= SLOPPY_PCH_DEFINES;
+ } else if (str_eq(word, "time_macros")) {
+ *value |= SLOPPY_TIME_MACROS;
+ } else if (str_eq(word, "clang_index_store")) {
+ *value |= SLOPPY_CLANG_INDEX_STORE;
+ } else if (str_eq(word, "locale")) {
+ *value |= SLOPPY_LOCALE;
+ } else {
+ *errmsg = format("unknown sloppiness: \"%s\"", word);
+ free(p);
+ return false;
+ }
+ q = NULL;
+ }
+ free(p);
+ return true;
}
-char *
-confitem_format_sloppiness(const void *value)
+char*
+confitem_format_sloppiness(const void* value)
{
- const unsigned *sloppiness = (const unsigned *)value;
- char *s = x_strdup("");
- if (*sloppiness & SLOPPY_FILE_MACRO) {
- reformat(&s, "%sfile_macro, ", s);
- }
- if (*sloppiness & SLOPPY_INCLUDE_FILE_MTIME) {
- reformat(&s, "%sinclude_file_mtime, ", s);
- }
- if (*sloppiness & SLOPPY_INCLUDE_FILE_CTIME) {
- reformat(&s, "%sinclude_file_ctime, ", s);
- }
- if (*sloppiness & SLOPPY_TIME_MACROS) {
- reformat(&s, "%stime_macros, ", s);
- }
- if (*sloppiness & SLOPPY_PCH_DEFINES) {
- reformat(&s, "%spch_defines, ", s);
- }
- if (*sloppiness & SLOPPY_FILE_STAT_MATCHES) {
- reformat(&s, "%sfile_stat_matches, ", s);
- }
- if (*sloppiness & SLOPPY_FILE_STAT_MATCHES_CTIME) {
- reformat(&s, "%sfile_stat_matches_ctime, ", s);
- }
- if (*sloppiness & SLOPPY_SYSTEM_HEADERS) {
- reformat(&s, "%ssystem_headers, ", s);
- }
- if (*sloppiness & SLOPPY_CLANG_INDEX_STORE) {
- reformat(&s, "%sclang_index_store, ", s);
- }
- if (*sloppiness & SLOPPY_LOCALE) {
- reformat(&s, "%slocale, ", s);
- }
- if (*sloppiness) {
- // Strip last ", ".
- s[strlen(s) - 2] = '\0';
- }
- return s;
+ const unsigned* sloppiness = (const unsigned*)value;
+ char* s = x_strdup("");
+ if (*sloppiness & SLOPPY_FILE_MACRO) {
+ reformat(&s, "%sfile_macro, ", s);
+ }
+ if (*sloppiness & SLOPPY_INCLUDE_FILE_MTIME) {
+ reformat(&s, "%sinclude_file_mtime, ", s);
+ }
+ if (*sloppiness & SLOPPY_INCLUDE_FILE_CTIME) {
+ reformat(&s, "%sinclude_file_ctime, ", s);
+ }
+ if (*sloppiness & SLOPPY_TIME_MACROS) {
+ reformat(&s, "%stime_macros, ", s);
+ }
+ if (*sloppiness & SLOPPY_PCH_DEFINES) {
+ reformat(&s, "%spch_defines, ", s);
+ }
+ if (*sloppiness & SLOPPY_FILE_STAT_MATCHES) {
+ reformat(&s, "%sfile_stat_matches, ", s);
+ }
+ if (*sloppiness & SLOPPY_FILE_STAT_MATCHES_CTIME) {
+ reformat(&s, "%sfile_stat_matches_ctime, ", s);
+ }
+ if (*sloppiness & SLOPPY_SYSTEM_HEADERS) {
+ reformat(&s, "%ssystem_headers, ", s);
+ }
+ if (*sloppiness & SLOPPY_CLANG_INDEX_STORE) {
+ reformat(&s, "%sclang_index_store, ", s);
+ }
+ if (*sloppiness & SLOPPY_LOCALE) {
+ reformat(&s, "%slocale, ", s);
+ }
+ if (*sloppiness) {
+ // Strip last ", ".
+ s[strlen(s) - 2] = '\0';
+ }
+ return s;
}
bool
-confitem_parse_string(const char *str, void *result, char **errmsg)
+confitem_parse_string(const char* str, void* result, char** errmsg)
{
- (void)errmsg;
+ (void)errmsg;
- char **value = (char **)result;
- free(*value);
- *value = x_strdup(str);
- return true;
+ char** value = (char**)result;
+ free(*value);
+ *value = x_strdup(str);
+ return true;
}
-char *
-confitem_format_string(const void *value)
+char*
+confitem_format_string(const void* value)
{
- return format_string(value);
+ return format_string(value);
}
bool
-confitem_parse_umask(const char *str, void *result, char **errmsg)
+confitem_parse_umask(const char* str, void* result, char** errmsg)
{
- unsigned *value = (unsigned *)result;
- if (str_eq(str, "")) {
- *value = UINT_MAX;
- return true;
- }
+ unsigned* value = (unsigned*)result;
+ if (str_eq(str, "")) {
+ *value = UINT_MAX;
+ return true;
+ }
- errno = 0;
- char *endptr;
- *value = strtoul(str, &endptr, 8);
- if (errno == 0 && *str != '\0' && *endptr == '\0') {
- return true;
- } else {
- *errmsg = format("not an octal integer: \"%s\"", str);
- return false;
- }
+ errno = 0;
+ char* endptr;
+ *value = strtoul(str, &endptr, 8);
+ if (errno == 0 && *str != '\0' && *endptr == '\0') {
+ return true;
+ } else {
+ *errmsg = format("not an octal integer: \"%s\"", str);
+ return false;
+ }
}
-char *
-confitem_format_umask(const void *value)
+char*
+confitem_format_umask(const void* value)
{
- const unsigned *umask = (const unsigned *)value;
- if (*umask == UINT_MAX) {
- return x_strdup("");
- } else {
- return format("%03o", *umask);
- }
+ const unsigned* umask = (const unsigned*)value;
+ if (*umask == UINT_MAX) {
+ return x_strdup("");
+ } else {
+ return format("%03o", *umask);
+ }
}
bool
-confitem_parse_int(const char *str, void *result, char **errmsg)
+confitem_parse_int(const char* str, void* result, char** errmsg)
{
- int *value = (int *)result;
- errno = 0;
- char *endptr;
- long x = strtol(str, &endptr, 10);
- if (errno == 0 && *str != '\0' && *endptr == '\0') {
- *value = x;
- return true;
- } else {
- *errmsg = format("invalid integer: \"%s\"", str);
- return false;
- }
+ int* value = (int*)result;
+ errno = 0;
+ char* endptr;
+ long x = strtol(str, &endptr, 10);
+ if (errno == 0 && *str != '\0' && *endptr == '\0') {
+ *value = x;
+ return true;
+ } else {
+ *errmsg = format("invalid integer: \"%s\"", str);
+ return false;
+ }
}
-char *
-confitem_format_int(const void *value)
+char*
+confitem_format_int(const void* value)
{
- const int *i = (const int *)value;
- return format("%d", *i);
+ const int* i = (const int*)value;
+ return format("%d", *i);
}
bool
-confitem_parse_unsigned(const char *str, void *result, char **errmsg)
+confitem_parse_unsigned(const char* str, void* result, char** errmsg)
{
- unsigned *value = (unsigned *)result;
- errno = 0;
- char *endptr;
- long x = strtol(str, &endptr, 10);
- if (errno == 0 && x >= 0 && *str != '\0' && *endptr == '\0') {
- *value = x;
- return true;
- } else {
- *errmsg = format("invalid unsigned integer: \"%s\"", str);
- return false;
- }
+ unsigned* value = (unsigned*)result;
+ errno = 0;
+ char* endptr;
+ long x = strtol(str, &endptr, 10);
+ if (errno == 0 && x >= 0 && *str != '\0' && *endptr == '\0') {
+ *value = x;
+ return true;
+ } else {
+ *errmsg = format("invalid unsigned integer: \"%s\"", str);
+ return false;
+ }
}
-char *
-confitem_format_unsigned(const void *value)
+char*
+confitem_format_unsigned(const void* value)
{
- const unsigned *i = (const unsigned *)value;
- return format("%u", *i);
+ const unsigned* i = (const unsigned*)value;
+ return format("%u", *i);
}
bool
-confitem_verify_absolute_path(const void *value, char **errmsg)
+confitem_verify_absolute_path(const void* value, char** errmsg)
{
- const char *const *path = (const char *const *)value;
- assert(*path);
- if (str_eq(*path, "")) {
- // The empty string means "disable" in this case.
- return true;
- } else if (is_absolute_path(*path)) {
- return true;
- } else {
- *errmsg = format("not an absolute path: \"%s\"", *path);
- return false;
- }
+ const char* const* path = (const char* const*)value;
+ assert(*path);
+ if (str_eq(*path, "")) {
+ // The empty string means "disable" in this case.
+ return true;
+ } else if (is_absolute_path(*path)) {
+ return true;
+ } else {
+ *errmsg = format("not an absolute path: \"%s\"", *path);
+ return false;
+ }
}
bool
-confitem_verify_compression_level(const void *value, char **errmsg)
+confitem_verify_compression_level(const void* value, char** errmsg)
{
- const int *level = (const int *)value;
- assert(level);
- if (*level >= -128 && *level <= 127) {
- return true;
- } else {
- *errmsg = format("compression level must be between -128 and 127");
- return false;
- }
+ const int* level = (const int*)value;
+ assert(level);
+ if (*level >= -128 && *level <= 127) {
+ return true;
+ } else {
+ *errmsg = format("compression level must be between -128 and 127");
+ return false;
+ }
}
bool
-confitem_verify_dir_levels(const void *value, char **errmsg)
+confitem_verify_dir_levels(const void* value, char** errmsg)
{
- const unsigned *levels = (const unsigned *)value;
- assert(levels);
- if (*levels >= 1 && *levels <= 8) {
- return true;
- } else {
- *errmsg = format("cache directory levels must be between 1 and 8");
- return false;
- }
+ const unsigned* levels = (const unsigned*)value;
+ assert(levels);
+ if (*levels >= 1 && *levels <= 8) {
+ return true;
+ } else {
+ *errmsg = format("cache directory levels must be between 1 and 8");
+ return false;
+ }
}
diff --git a/src/confitems.hpp b/src/confitems.hpp
index ae2f2534..aba12d98 100644
--- a/src/confitems.hpp
+++ b/src/confitems.hpp
@@ -20,49 +20,50 @@
#include "system.hpp"
-typedef bool (*conf_item_parser)(const char *str, void *result, char **errmsg);
-typedef bool (*conf_item_verifier)(const void *value, char **errmsg);
-typedef char *(*conf_item_formatter)(const void *value);
+typedef bool (*conf_item_parser)(const char* str, void* result, char** errmsg);
+typedef bool (*conf_item_verifier)(const void* value, char** errmsg);
+typedef char* (*conf_item_formatter)(const void* value);
-struct conf_item {
- const char *name;
- size_t number;
- size_t offset;
- conf_item_parser parser;
- conf_item_formatter formatter;
- conf_item_verifier verifier;
+struct conf_item
+{
+ const char* name;
+ size_t number;
+ size_t offset;
+ conf_item_parser parser;
+ conf_item_formatter formatter;
+ conf_item_verifier verifier;
};
-bool confitem_parse_bool(const char *str, void *result, char **errmsg);
-char *confitem_format_bool(const void *value);
+bool confitem_parse_bool(const char* str, void* result, char** errmsg);
+char* confitem_format_bool(const void* value);
-bool confitem_parse_env_string(const char *str, void *result, char **errmsg);
-char *confitem_format_env_string(const void *value);
+bool confitem_parse_env_string(const char* str, void* result, char** errmsg);
+char* confitem_format_env_string(const void* value);
-bool confitem_parse_double(const char *str, void *result, char **errmsg);
-char *confitem_format_double(const void *value);
+bool confitem_parse_double(const char* str, void* result, char** errmsg);
+char* confitem_format_double(const void* value);
-bool confitem_parse_size(const char *str, void *result, char **errmsg);
-char *confitem_format_size(const void *value);
+bool confitem_parse_size(const char* str, void* result, char** errmsg);
+char* confitem_format_size(const void* value);
-bool confitem_parse_sloppiness(const char *str, void *result, char **errmsg);
-char *confitem_format_sloppiness(const void *value);
+bool confitem_parse_sloppiness(const char* str, void* result, char** errmsg);
+char* confitem_format_sloppiness(const void* value);
-bool confitem_parse_string(const char *str, void *result, char **errmsg);
-char *confitem_format_string(const void *value);
+bool confitem_parse_string(const char* str, void* result, char** errmsg);
+char* confitem_format_string(const void* value);
-bool confitem_parse_umask(const char *str, void *result, char **errmsg);
-char *confitem_format_umask(const void *value);
+bool confitem_parse_umask(const char* str, void* result, char** errmsg);
+char* confitem_format_umask(const void* value);
-bool confitem_parse_int(const char *str, void *result, char **errmsg);
-char *confitem_format_int(const void *value);
+bool confitem_parse_int(const char* str, void* result, char** errmsg);
+char* confitem_format_int(const void* value);
-bool confitem_parse_unsigned(const char *str, void *result, char **errmsg);
-char *confitem_format_unsigned(const void *value);
+bool confitem_parse_unsigned(const char* str, void* result, char** errmsg);
+char* confitem_format_unsigned(const void* value);
-bool confitem_verify_absolute_path(const void *value, char **errmsg);
-bool confitem_verify_compression_level(const void *value, char **errmsg);
-bool confitem_verify_dir_levels(const void *value, char **errmsg);
+bool confitem_verify_absolute_path(const void* value, char** errmsg);
+bool confitem_verify_compression_level(const void* value, char** errmsg);
+bool confitem_verify_dir_levels(const void* value, char** errmsg);
-const struct conf_item *confitems_get(const char *str, size_t len);
+const struct conf_item* confitems_get(const char* str, size_t len);
size_t confitems_count(void);
diff --git a/src/counters.cpp b/src/counters.cpp
index d846f9d8..ade493c2 100644
--- a/src/counters.cpp
+++ b/src/counters.cpp
@@ -22,45 +22,45 @@
// Allocate and initialize a struct counters. Data entries up to the size are
// set to 0.
-struct counters *
+struct counters*
counters_init(size_t initial_size)
{
- auto c = static_cast<counters*>(x_malloc(sizeof(counters)));
- c->data = NULL;
- c->size = 0;
- c->allocated = 0;
- counters_resize(c, initial_size);
- return c;
+ auto c = static_cast<counters*>(x_malloc(sizeof(counters)));
+ c->data = NULL;
+ c->size = 0;
+ c->allocated = 0;
+ counters_resize(c, initial_size);
+ return c;
}
// Free a counters struct.
void
-counters_free(struct counters *c)
+counters_free(struct counters* c)
{
- if (c) {
- free(c->data);
- free(c);
- }
+ if (c) {
+ free(c->data);
+ free(c);
+ }
}
// Set a new size. New data entries are set to 0.
void
-counters_resize(struct counters *c, size_t new_size)
+counters_resize(struct counters* c, size_t new_size)
{
- if (new_size > c->size) {
- bool realloc = false;
- while (c->allocated < new_size) {
- c->allocated += 32 + c->allocated;
- realloc = true;
- }
- if (realloc) {
- c->data = static_cast<unsigned*>(
- x_realloc(c->data, c->allocated * sizeof(c->data[0])));
- }
- for (size_t i = c->size; i < new_size; i++) {
- c->data[i] = 0;
- }
- }
+ if (new_size > c->size) {
+ bool realloc = false;
+ while (c->allocated < new_size) {
+ c->allocated += 32 + c->allocated;
+ realloc = true;
+ }
+ if (realloc) {
+ c->data = static_cast<unsigned*>(
+ x_realloc(c->data, c->allocated * sizeof(c->data[0])));
+ }
+ for (size_t i = c->size; i < new_size; i++) {
+ c->data[i] = 0;
+ }
+ }
- c->size = new_size;
+ c->size = new_size;
}
diff --git a/src/counters.hpp b/src/counters.hpp
index 43d334b6..c2560b73 100644
--- a/src/counters.hpp
+++ b/src/counters.hpp
@@ -20,12 +20,13 @@
#include <stddef.h>
-struct counters {
- unsigned *data; // counter value
- size_t size; // logical array size
- size_t allocated; // allocated size
+struct counters
+{
+ unsigned* data; // counter value
+ size_t size; // logical array size
+ size_t allocated; // allocated size
};
-struct counters *counters_init(size_t initial_size);
-void counters_resize(struct counters *c, size_t new_size);
-void counters_free(struct counters *c);
+struct counters* counters_init(size_t initial_size);
+void counters_resize(struct counters* c, size_t new_size);
+void counters_free(struct counters* c);
diff --git a/src/decompr_none.cpp b/src/decompr_none.cpp
index e4c87c7e..4c40cd49 100644
--- a/src/decompr_none.cpp
+++ b/src/decompr_none.cpp
@@ -18,48 +18,46 @@
#include "compression.hpp"
-struct state {
- FILE *input;
- XXH64_state_t *checksum;
- bool failed;
+struct state
+{
+ FILE* input;
+ XXH64_state_t* checksum;
+ bool failed;
};
-static struct decompr_state *
-decompr_none_init(FILE *input, XXH64_state_t *checksum)
+static struct decompr_state*
+decompr_none_init(FILE* input, XXH64_state_t* checksum)
{
- auto state = static_cast<struct state*>(malloc(sizeof(struct state)));
- state->input = input;
- state->checksum = checksum;
- state->failed = false;
- return (struct decompr_state *)state;
+ auto state = static_cast<struct state*>(malloc(sizeof(struct state)));
+ state->input = input;
+ state->checksum = checksum;
+ state->failed = false;
+ return (struct decompr_state*)state;
}
static bool
-decompr_none_read(struct decompr_state *handle, void *data, size_t size)
+decompr_none_read(struct decompr_state* handle, void* data, size_t size)
{
- struct state *state = (struct state *)handle;
+ struct state* state = (struct state*)handle;
- bool result = fread(data, 1, size, state->input) == size;
- if (result && state->checksum) {
- XXH64_update(state->checksum, data, size);
- }
- if (!result) {
- state->failed = true;
- }
- return result;
+ bool result = fread(data, 1, size, state->input) == size;
+ if (result && state->checksum) {
+ XXH64_update(state->checksum, data, size);
+ }
+ if (!result) {
+ state->failed = true;
+ }
+ return result;
}
static bool
-decompr_none_free(struct decompr_state *handle)
+decompr_none_free(struct decompr_state* handle)
{
- struct state *state = (struct state *)handle;
- bool result = !state->failed;
- free(state);
- return result;
+ struct state* state = (struct state*)handle;
+ bool result = !state->failed;
+ free(state);
+ return result;
}
struct decompressor decompressor_none_impl = {
- decompr_none_init,
- decompr_none_read,
- decompr_none_free
-};
+ decompr_none_init, decompr_none_read, decompr_none_free};
diff --git a/src/decompr_zstd.cpp b/src/decompr_zstd.cpp
index b6691654..9fb895c3 100644
--- a/src/decompr_zstd.cpp
+++ b/src/decompr_zstd.cpp
@@ -22,105 +22,104 @@
#include <zstd.h>
enum stream_state {
- STREAM_STATE_READING,
- STREAM_STATE_FAILED,
- STREAM_STATE_END
+ STREAM_STATE_READING,
+ STREAM_STATE_FAILED,
+ STREAM_STATE_END
};
-struct state {
- FILE *input;
- XXH64_state_t *checksum;
- char input_buffer[READ_BUFFER_SIZE];
- size_t input_size;
- size_t input_consumed;
- ZSTD_DStream *stream;
- ZSTD_inBuffer in;
- ZSTD_outBuffer out;
- enum stream_state stream_state;
+struct state
+{
+ FILE* input;
+ XXH64_state_t* checksum;
+ char input_buffer[READ_BUFFER_SIZE];
+ size_t input_size;
+ size_t input_consumed;
+ ZSTD_DStream* stream;
+ ZSTD_inBuffer in;
+ ZSTD_outBuffer out;
+ enum stream_state stream_state;
};
-static struct decompr_state *
-decompr_zstd_init(FILE *input, XXH64_state_t *checksum)
+static struct decompr_state*
+decompr_zstd_init(FILE* input, XXH64_state_t* checksum)
{
- auto state = static_cast<struct state*>(malloc(sizeof(struct state)));
+ auto state = static_cast<struct state*>(malloc(sizeof(struct state)));
- state->input = input;
- state->checksum = checksum;
- state->input_size = 0;
- state->input_consumed = 0;
- state->stream = ZSTD_createDStream();
- state->stream_state = STREAM_STATE_READING;
+ state->input = input;
+ state->checksum = checksum;
+ state->input_size = 0;
+ state->input_consumed = 0;
+ state->stream = ZSTD_createDStream();
+ state->stream_state = STREAM_STATE_READING;
- size_t ret = ZSTD_initDStream(state->stream);
- if (ZSTD_isError(ret)) {
- ZSTD_freeDStream(state->stream);
- free(state);
- return NULL;
- }
- return (struct decompr_state *)state;
+ size_t ret = ZSTD_initDStream(state->stream);
+ if (ZSTD_isError(ret)) {
+ ZSTD_freeDStream(state->stream);
+ free(state);
+ return NULL;
+ }
+ return (struct decompr_state*)state;
}
static bool
-decompr_zstd_read(struct decompr_state *handle, void *data, size_t size)
+decompr_zstd_read(struct decompr_state* handle, void* data, size_t size)
{
- if (!handle) {
- return false;
- }
- struct state *state = (struct state *)handle;
+ if (!handle) {
+ return false;
+ }
+ struct state* state = (struct state*)handle;
- size_t bytes_read = 0;
- while (bytes_read < size) {
- assert(state->input_size >= state->input_consumed);
- if (state->input_size == state->input_consumed) {
- state->input_size = fread(
- state->input_buffer, 1, sizeof(state->input_buffer), state->input);
- if (state->input_size == 0) {
- state->stream_state = STREAM_STATE_FAILED;
- return false;
- }
- state->input_consumed = 0;
- }
+ size_t bytes_read = 0;
+ while (bytes_read < size) {
+ assert(state->input_size >= state->input_consumed);
+ if (state->input_size == state->input_consumed) {
+ state->input_size = fread(
+ state->input_buffer, 1, sizeof(state->input_buffer), state->input);
+ if (state->input_size == 0) {
+ state->stream_state = STREAM_STATE_FAILED;
+ return false;
+ }
+ state->input_consumed = 0;
+ }
- state->in.src = (state->input_buffer + state->input_consumed);
- state->in.size = state->input_size - state->input_consumed;
- state->in.pos = 0;
+ state->in.src = (state->input_buffer + state->input_consumed);
+ state->in.size = state->input_size - state->input_consumed;
+ state->in.pos = 0;
- state->out.dst = ((char *)data + bytes_read);
- state->out.size = size - bytes_read;
- state->out.pos = 0;
- size_t ret = ZSTD_decompressStream(state->stream, &state->out, &state->in);
- if (ZSTD_isError(ret)) {
- state->stream_state = STREAM_STATE_FAILED;
- return false;
- }
- if (state->checksum) {
- XXH64_update(state->checksum, state->out.dst, state->out.pos);
- }
- if (ret == 0) {
- state->stream_state = STREAM_STATE_END;
- break;
- }
- bytes_read += state->out.pos;
- state->input_consumed += state->in.pos;
- }
+ state->out.dst = ((char*)data + bytes_read);
+ state->out.size = size - bytes_read;
+ state->out.pos = 0;
+ size_t ret = ZSTD_decompressStream(state->stream, &state->out, &state->in);
+ if (ZSTD_isError(ret)) {
+ state->stream_state = STREAM_STATE_FAILED;
+ return false;
+ }
+ if (state->checksum) {
+ XXH64_update(state->checksum, state->out.dst, state->out.pos);
+ }
+ if (ret == 0) {
+ state->stream_state = STREAM_STATE_END;
+ break;
+ }
+ bytes_read += state->out.pos;
+ state->input_consumed += state->in.pos;
+ }
- return true;
+ return true;
}
-static bool decompr_zstd_free(struct decompr_state *handle)
+static bool
+decompr_zstd_free(struct decompr_state* handle)
{
- if (!handle) {
- return false;
- }
- struct state *state = (struct state *)handle;
- ZSTD_freeDStream(state->stream);
- bool success = state->stream_state == STREAM_STATE_END;
- free(handle);
- return success;
+ if (!handle) {
+ return false;
+ }
+ struct state* state = (struct state*)handle;
+ ZSTD_freeDStream(state->stream);
+ bool success = state->stream_state == STREAM_STATE_END;
+ free(handle);
+ return success;
}
struct decompressor decompressor_zstd_impl = {
- decompr_zstd_init,
- decompr_zstd_read,
- decompr_zstd_free
-};
+ decompr_zstd_init, decompr_zstd_read, decompr_zstd_free};
diff --git a/src/envtoconfitems.hpp b/src/envtoconfitems.hpp
index 425e38f8..7885b483 100644
--- a/src/envtoconfitems.hpp
+++ b/src/envtoconfitems.hpp
@@ -20,11 +20,12 @@
#include "system.hpp"
-struct env_to_conf_item {
- const char *env_name;
- const char *conf_name;
+struct env_to_conf_item
+{
+ const char* env_name;
+ const char* conf_name;
};
-const struct env_to_conf_item *envtoconfitems_get(const char *str, size_t len);
+const struct env_to_conf_item* envtoconfitems_get(const char* str, size_t len);
size_t envtoconfitems_count(void);
diff --git a/src/execute.cpp b/src/execute.cpp
index 2a31bfae..fb5c638f 100644
--- a/src/execute.cpp
+++ b/src/execute.cpp
@@ -19,223 +19,228 @@
#include "ccache.hpp"
-extern struct conf *conf;
+extern struct conf* conf;
-static char *
-find_executable_in_path(const char *name, const char *exclude_name, char *path);
+static char*
+find_executable_in_path(const char* name, const char* exclude_name, char* path);
#ifdef _WIN32
// Re-create a win32 command line string based on **argv.
// http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
-char *
-win32argvtos(char *prefix, char **argv, int *length)
+char*
+win32argvtos(char* prefix, char** argv, int* length)
{
- int i = 0;
- int k = 0;
- char *arg = prefix ? prefix : argv[i++];
- do {
- int bs = 0;
- for (int j = 0; arg[j]; j++) {
- switch (arg[j]) {
- case '\\':
- bs++;
- break;
- case '"':
- bs = (bs << 1) + 1;
- // Fallthrough.
- default:
- k += bs + 1;
- bs = 0;
- }
- }
- k += (bs << 1) + 3;
- } while ((arg = argv[i++]));
-
- char *ptr = static_cast<char*>(malloc(k + 1));
- char *str = ptr;
- if (!str) {
- *length = 0;
- return NULL;
- }
-
- i = 0;
- arg = prefix ? prefix : argv[i++];
- do {
- int bs = 0;
- *ptr++ = '"';
- for (int j = 0; arg[j]; j++) {
- switch (arg[j]) {
- case '\\':
- bs++;
- break;
- // Fallthrough.
- case '"':
- bs = (bs << 1) + 1;
- // Fallthrough.
- default:
- while (bs && bs--) {
- *ptr++ = '\\';
- }
- *ptr++ = arg[j];
- }
- }
- bs <<= 1;
- while (bs && bs--) {
- *ptr++ = '\\';
- }
- *ptr++ = '"';
- *ptr++ = ' ';
- } while ((arg = argv[i++]));
- ptr[-1] = '\0';
-
- *length = ptr - str - 1;
- return str;
+ int i = 0;
+ int k = 0;
+ char* arg = prefix ? prefix : argv[i++];
+ do {
+ int bs = 0;
+ for (int j = 0; arg[j]; j++) {
+ switch (arg[j]) {
+ case '\\':
+ bs++;
+ break;
+ case '"':
+ bs = (bs << 1) + 1;
+ // Fallthrough.
+ default:
+ k += bs + 1;
+ bs = 0;
+ }
+ }
+ k += (bs << 1) + 3;
+ } while ((arg = argv[i++]));
+
+ char* ptr = static_cast<char*>(malloc(k + 1));
+ char* str = ptr;
+ if (!str) {
+ *length = 0;
+ return NULL;
+ }
+
+ i = 0;
+ arg = prefix ? prefix : argv[i++];
+ do {
+ int bs = 0;
+ *ptr++ = '"';
+ for (int j = 0; arg[j]; j++) {
+ switch (arg[j]) {
+ case '\\':
+ bs++;
+ break;
+ // Fallthrough.
+ case '"':
+ bs = (bs << 1) + 1;
+ // Fallthrough.
+ default:
+ while (bs && bs--) {
+ *ptr++ = '\\';
+ }
+ *ptr++ = arg[j];
+ }
+ }
+ bs <<= 1;
+ while (bs && bs--) {
+ *ptr++ = '\\';
+ }
+ *ptr++ = '"';
+ *ptr++ = ' ';
+ } while ((arg = argv[i++]));
+ ptr[-1] = '\0';
+
+ *length = ptr - str - 1;
+ return str;
}
-char *
-win32getshell(char *path)
+char*
+win32getshell(char* path)
{
- char *path_env;
- char *sh = NULL;
- const char *ext = get_extension(path);
- if (ext && strcasecmp(ext, ".sh") == 0 && (path_env = getenv("PATH"))) {
- sh = find_executable_in_path("sh.exe", NULL, path_env);
- }
- if (!sh && getenv("CCACHE_DETECT_SHEBANG")) {
- // Detect shebang.
- FILE *fp = fopen(path, "r");
- if (fp) {
- char buf[10];
- fgets(buf, sizeof(buf), fp);
- buf[9] = 0;
- if (str_eq(buf, "#!/bin/sh") && (path_env = getenv("PATH"))) {
- sh = find_executable_in_path("sh.exe", NULL, path_env);
- }
- fclose(fp);
- }
- }
-
- return sh;
+ char* path_env;
+ char* sh = NULL;
+ const char* ext = get_extension(path);
+ if (ext && strcasecmp(ext, ".sh") == 0 && (path_env = getenv("PATH"))) {
+ sh = find_executable_in_path("sh.exe", NULL, path_env);
+ }
+ if (!sh && getenv("CCACHE_DETECT_SHEBANG")) {
+ // Detect shebang.
+ FILE* fp = fopen(path, "r");
+ if (fp) {
+ char buf[10];
+ fgets(buf, sizeof(buf), fp);
+ buf[9] = 0;
+ if (str_eq(buf, "#!/bin/sh") && (path_env = getenv("PATH"))) {
+ sh = find_executable_in_path("sh.exe", NULL, path_env);
+ }
+ fclose(fp);
+ }
+ }
+
+ return sh;
}
-void add_exe_ext_if_no_to_fullpath(char *full_path_win_ext, size_t max_size,
- const char *ext, const char *path) {
- if (!ext || (!str_eq(".exe", ext)
- && !str_eq(".sh", ext)
- && !str_eq(".bat", ext)
- && !str_eq(".EXE", ext)
- && !str_eq(".BAT", ext))) {
- snprintf(full_path_win_ext, max_size, "%s.exe", path);
- } else {
- snprintf(full_path_win_ext, max_size, "%s", path);
- }
+void
+add_exe_ext_if_no_to_fullpath(char* full_path_win_ext,
+ size_t max_size,
+ const char* ext,
+ const char* path)
+{
+ if (!ext
+ || (!str_eq(".exe", ext) && !str_eq(".sh", ext) && !str_eq(".bat", ext)
+ && !str_eq(".EXE", ext) && !str_eq(".BAT", ext))) {
+ snprintf(full_path_win_ext, max_size, "%s.exe", path);
+ } else {
+ snprintf(full_path_win_ext, max_size, "%s", path);
+ }
}
int
-win32execute(char *path, char **argv, int doreturn,
- int fd_stdout, int fd_stderr)
+win32execute(
+ char* path, char** argv, int doreturn, int fd_stdout, int fd_stderr)
{
- PROCESS_INFORMATION pi;
- memset(&pi, 0x00, sizeof(pi));
-
- STARTUPINFO si;
- memset(&si, 0x00, sizeof(si));
-
- char *sh = win32getshell(path);
- if (sh) {
- path = sh;
- }
-
- si.cb = sizeof(STARTUPINFO);
- if (fd_stdout != -1) {
- si.hStdOutput = (HANDLE)_get_osfhandle(fd_stdout);
- si.hStdError = (HANDLE)_get_osfhandle(fd_stderr);
- si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- si.dwFlags = STARTF_USESTDHANDLES;
- if (si.hStdOutput == INVALID_HANDLE_VALUE
- || si.hStdError == INVALID_HANDLE_VALUE) {
- return -1;
- }
- } else {
- // Redirect subprocess stdout, stderr into current process.
- si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
- si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- si.dwFlags = STARTF_USESTDHANDLES;
- if (si.hStdOutput == INVALID_HANDLE_VALUE
- || si.hStdError == INVALID_HANDLE_VALUE) {
- return -1;
- }
- }
-
- int length;
- char *args = win32argvtos(sh, argv, &length);
- const char *ext = strrchr(path, '.');
- char full_path_win_ext[MAX_PATH] = {0};
- add_exe_ext_if_no_to_fullpath(full_path_win_ext, MAX_PATH, ext, path);
- BOOL ret = FALSE;
- if (length > 8192) {
- char *tmp_file = format("%s.tmp", path);
- FILE *fp = create_tmp_file(&tmp_file, "w");
- char atfile[MAX_PATH + 3];
- fwrite(args, 1, length, fp);
- if (ferror(fp)) {
- cc_log("Error writing @file; this command will probably fail: %s", args);
- }
- fclose(fp);
- snprintf(atfile, sizeof(atfile), "\"@%s\"", tmp_file);
- ret = CreateProcess(NULL, atfile, NULL, NULL, 1, 0, NULL, NULL,
- &si, &pi);
- tmp_unlink(tmp_file);
- free(tmp_file);
- }
- if (!ret) {
- ret = CreateProcess(full_path_win_ext, args, NULL, NULL, 1, 0, NULL, NULL,
- &si, &pi);
- }
- if (fd_stdout != -1) {
- close(fd_stdout);
- close(fd_stderr);
- }
- free(args);
- if (ret == 0) {
- LPVOID lpMsgBuf;
- DWORD dw = GetLastError();
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf,
- 0, NULL);
-
- LPVOID lpDisplayBuf =
- (LPVOID) LocalAlloc(LMEM_ZEROINIT,
- (lstrlen((LPCTSTR) lpMsgBuf)
- + lstrlen((LPCTSTR) __FILE__) + 200)
- * sizeof(TCHAR));
- _snprintf((LPTSTR) lpDisplayBuf,
- LocalSize(lpDisplayBuf) / sizeof(TCHAR),
- TEXT("%s failed with error %lu: %s"), __FILE__, dw,
- (const char *)lpMsgBuf);
-
- cc_log("can't execute %s; OS returned error: %s",
- full_path_win_ext, (char *)lpDisplayBuf);
-
- LocalFree(lpMsgBuf);
- LocalFree(lpDisplayBuf);
-
- return -1;
- }
- WaitForSingleObject(pi.hProcess, INFINITE);
-
- DWORD exitcode;
- GetExitCodeProcess(pi.hProcess, &exitcode);
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- if (!doreturn) {
- x_exit(exitcode);
- }
- return exitcode;
+ PROCESS_INFORMATION pi;
+ memset(&pi, 0x00, sizeof(pi));
+
+ STARTUPINFO si;
+ memset(&si, 0x00, sizeof(si));
+
+ char* sh = win32getshell(path);
+ if (sh) {
+ path = sh;
+ }
+
+ si.cb = sizeof(STARTUPINFO);
+ if (fd_stdout != -1) {
+ si.hStdOutput = (HANDLE)_get_osfhandle(fd_stdout);
+ si.hStdError = (HANDLE)_get_osfhandle(fd_stderr);
+ si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ if (si.hStdOutput == INVALID_HANDLE_VALUE
+ || si.hStdError == INVALID_HANDLE_VALUE) {
+ return -1;
+ }
+ } else {
+ // Redirect subprocess stdout, stderr into current process.
+ si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+ si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ if (si.hStdOutput == INVALID_HANDLE_VALUE
+ || si.hStdError == INVALID_HANDLE_VALUE) {
+ return -1;
+ }
+ }
+
+ int length;
+ char* args = win32argvtos(sh, argv, &length);
+ const char* ext = strrchr(path, '.');
+ char full_path_win_ext[MAX_PATH] = {0};
+ add_exe_ext_if_no_to_fullpath(full_path_win_ext, MAX_PATH, ext, path);
+ BOOL ret = FALSE;
+ if (length > 8192) {
+ char* tmp_file = format("%s.tmp", path);
+ FILE* fp = create_tmp_file(&tmp_file, "w");
+ char atfile[MAX_PATH + 3];
+ fwrite(args, 1, length, fp);
+ if (ferror(fp)) {
+ cc_log("Error writing @file; this command will probably fail: %s", args);
+ }
+ fclose(fp);
+ snprintf(atfile, sizeof(atfile), "\"@%s\"", tmp_file);
+ ret = CreateProcess(NULL, atfile, NULL, NULL, 1, 0, NULL, NULL, &si, &pi);
+ tmp_unlink(tmp_file);
+ free(tmp_file);
+ }
+ if (!ret) {
+ ret = CreateProcess(
+ full_path_win_ext, args, NULL, NULL, 1, 0, NULL, NULL, &si, &pi);
+ }
+ if (fd_stdout != -1) {
+ close(fd_stdout);
+ close(fd_stderr);
+ }
+ free(args);
+ if (ret == 0) {
+ LPVOID lpMsgBuf;
+ DWORD dw = GetLastError();
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ dw,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&lpMsgBuf,
+ 0,
+ NULL);
+
+ LPVOID lpDisplayBuf = (LPVOID)LocalAlloc(
+ LMEM_ZEROINIT,
+ (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)__FILE__) + 200)
+ * sizeof(TCHAR));
+ _snprintf((LPTSTR)lpDisplayBuf,
+ LocalSize(lpDisplayBuf) / sizeof(TCHAR),
+ TEXT("%s failed with error %lu: %s"),
+ __FILE__,
+ dw,
+ (const char*)lpMsgBuf);
+
+ cc_log("can't execute %s; OS returned error: %s",
+ full_path_win_ext,
+ (char*)lpDisplayBuf);
+
+ LocalFree(lpMsgBuf);
+ LocalFree(lpDisplayBuf);
+
+ return -1;
+ }
+ WaitForSingleObject(pi.hProcess, INFINITE);
+
+ DWORD exitcode;
+ GetExitCodeProcess(pi.hProcess, &exitcode);
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ if (!doreturn) {
+ x_exit(exitcode);
+ }
+ return exitcode;
}
#else
@@ -243,156 +248,153 @@ win32execute(char *path, char **argv, int doreturn,
// Execute a compiler backend, capturing all output to the given paths the full
// path to the compiler to run is in argv[0].
int
-execute(char **argv, int fd_out, int fd_err, pid_t *pid)
+execute(char** argv, int fd_out, int fd_err, pid_t* pid)
{
- cc_log_argv("Executing ", argv);
-
- block_signals();
- *pid = fork();
- unblock_signals();
-
- if (*pid == -1) {
- fatal("Failed to fork: %s", strerror(errno));
- }
-
- if (*pid == 0) {
- // Child.
- dup2(fd_out, 1);
- close(fd_out);
- dup2(fd_err, 2);
- close(fd_err);
- x_exit(execv(argv[0], argv));
- }
-
- close(fd_out);
- close(fd_err);
-
- int status;
- if (waitpid(*pid, &status, 0) != *pid) {
- fatal("waitpid failed: %s", strerror(errno));
- }
-
- block_signals();
- *pid = 0;
- unblock_signals();
-
- if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) {
- return -1;
- }
-
- return WEXITSTATUS(status);
+ cc_log_argv("Executing ", argv);
+
+ block_signals();
+ *pid = fork();
+ unblock_signals();
+
+ if (*pid == -1) {
+ fatal("Failed to fork: %s", strerror(errno));
+ }
+
+ if (*pid == 0) {
+ // Child.
+ dup2(fd_out, 1);
+ close(fd_out);
+ dup2(fd_err, 2);
+ close(fd_err);
+ x_exit(execv(argv[0], argv));
+ }
+
+ close(fd_out);
+ close(fd_err);
+
+ int status;
+ if (waitpid(*pid, &status, 0) != *pid) {
+ fatal("waitpid failed: %s", strerror(errno));
+ }
+
+ block_signals();
+ *pid = 0;
+ unblock_signals();
+
+ if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) {
+ return -1;
+ }
+
+ return WEXITSTATUS(status);
}
#endif
// Find an executable by name in $PATH. Exclude any that are links to
// exclude_name.
-char *
-find_executable(const char *name, const char *exclude_name)
+char*
+find_executable(const char* name, const char* exclude_name)
{
- if (is_absolute_path(name)) {
- return x_strdup(name);
- }
-
- char *path = conf->path;
- if (str_eq(path, "")) {
- path = getenv("PATH");
- }
- if (!path) {
- cc_log("No PATH variable");
- return NULL;
- }
-
- return find_executable_in_path(name, exclude_name, path);
+ if (is_absolute_path(name)) {
+ return x_strdup(name);
+ }
+
+ char* path = conf->path;
+ if (str_eq(path, "")) {
+ path = getenv("PATH");
+ }
+ if (!path) {
+ cc_log("No PATH variable");
+ return NULL;
+ }
+
+ return find_executable_in_path(name, exclude_name, path);
}
-static char *
-find_executable_in_path(const char *name, const char *exclude_name, char *path)
+static char*
+find_executable_in_path(const char* name, const char* exclude_name, char* path)
{
- path = x_strdup(path);
-
- // Search the path looking for the first compiler of the right name that
- // isn't us.
- char *saveptr = NULL;
- for (char *tok = strtok_r(path, PATH_DELIM, &saveptr);
- tok;
- tok = strtok_r(NULL, PATH_DELIM, &saveptr)) {
+ path = x_strdup(path);
+
+ // Search the path looking for the first compiler of the right name that
+ // isn't us.
+ char* saveptr = NULL;
+ for (char* tok = strtok_r(path, PATH_DELIM, &saveptr); tok;
+ tok = strtok_r(NULL, PATH_DELIM, &saveptr)) {
#ifdef _WIN32
- char namebuf[MAX_PATH];
- int ret = SearchPath(tok, name, NULL, sizeof(namebuf), namebuf, NULL);
- if (!ret) {
- char *exename = format("%s.exe", name);
- ret = SearchPath(tok, exename, NULL, sizeof(namebuf), namebuf, NULL);
- free(exename);
- }
- (void) exclude_name;
- if (ret) {
- free(path);
- return x_strdup(namebuf);
- }
+ char namebuf[MAX_PATH];
+ int ret = SearchPath(tok, name, NULL, sizeof(namebuf), namebuf, NULL);
+ if (!ret) {
+ char* exename = format("%s.exe", name);
+ ret = SearchPath(tok, exename, NULL, sizeof(namebuf), namebuf, NULL);
+ free(exename);
+ }
+ (void)exclude_name;
+ if (ret) {
+ free(path);
+ return x_strdup(namebuf);
+ }
#else
- struct stat st1, st2;
- char *fname = format("%s/%s", tok, name);
- // Look for a normal executable file.
- if (access(fname, X_OK) == 0 &&
- lstat(fname, &st1) == 0 &&
- stat(fname, &st2) == 0 &&
- S_ISREG(st2.st_mode)) {
- if (S_ISLNK(st1.st_mode)) {
- char *buf = x_realpath(fname);
- if (buf) {
- char *p = x_basename(buf);
- if (str_eq(p, exclude_name)) {
- // It's a link to "ccache"!
- free(p);
- free(buf);
- continue;
- }
- free(buf);
- free(p);
- }
- }
-
- // Found it!
- free(path);
- return fname;
- }
- free(fname);
+ struct stat st1, st2;
+ char* fname = format("%s/%s", tok, name);
+ // Look for a normal executable file.
+ if (access(fname, X_OK) == 0 && lstat(fname, &st1) == 0
+ && stat(fname, &st2) == 0 && S_ISREG(st2.st_mode)) {
+ if (S_ISLNK(st1.st_mode)) {
+ char* buf = x_realpath(fname);
+ if (buf) {
+ char* p = x_basename(buf);
+ if (str_eq(p, exclude_name)) {
+ // It's a link to "ccache"!
+ free(p);
+ free(buf);
+ continue;
+ }
+ free(buf);
+ free(p);
+ }
+ }
+
+ // Found it!
+ free(path);
+ return fname;
+ }
+ free(fname);
#endif
- }
+ }
- free(path);
- return NULL;
+ free(path);
+ return NULL;
}
void
-print_command(FILE *fp, char **argv)
+print_command(FILE* fp, char** argv)
{
- for (int i = 0; argv[i]; i++) {
- fprintf(fp, "%s%s", (i == 0) ? "" : " ", argv[i]);
- }
- fprintf(fp, "\n");
+ for (int i = 0; argv[i]; i++) {
+ fprintf(fp, "%s%s", (i == 0) ? "" : " ", argv[i]);
+ }
+ fprintf(fp, "\n");
}
-char *
+char*
format_command(const char* const* argv)
{
- size_t len = 0;
- for (int i = 0; argv[i]; i++) {
- len += (i == 0) ? 0 : 1;
- len += strlen(argv[i]);
- }
- len += 1;
- char *buf = static_cast<char*>(x_malloc(len + 1));
- char *p = buf;
- for (int i = 0; argv[i]; i++) {
- if (i != 0) {
- *p++ = ' ';
- }
- for (const char *q = argv[i]; *q != '\0'; q++) {
- *p++ = *q;
- }
- }
- *p++ = '\n';
- *p++ = '\0';
- return buf;
+ size_t len = 0;
+ for (int i = 0; argv[i]; i++) {
+ len += (i == 0) ? 0 : 1;
+ len += strlen(argv[i]);
+ }
+ len += 1;
+ char* buf = static_cast<char*>(x_malloc(len + 1));
+ char* p = buf;
+ for (int i = 0; argv[i]; i++) {
+ if (i != 0) {
+ *p++ = ' ';
+ }
+ for (const char* q = argv[i]; *q != '\0'; q++) {
+ *p++ = *q;
+ }
+ }
+ *p++ = '\n';
+ *p++ = '\0';
+ return buf;
}
diff --git a/src/exitfn.cpp b/src/exitfn.cpp
index bc0562f7..32dfbdfa 100644
--- a/src/exitfn.cpp
+++ b/src/exitfn.cpp
@@ -18,33 +18,35 @@
#include "ccache.hpp"
-struct exit_function {
- void (*function)(void *);
- void *context;
- struct exit_function *next;
+struct exit_function
+{
+ void (*function)(void*);
+ void* context;
+ struct exit_function* next;
};
-struct nullary_exit_function {
- void (*function)(void);
+struct nullary_exit_function
+{
+ void (*function)(void);
};
-static struct exit_function *exit_functions;
+static struct exit_function* exit_functions;
static void
-call_nullary_exit_function(void *context)
+call_nullary_exit_function(void* context)
{
- struct nullary_exit_function *p = (struct nullary_exit_function *)context;
- p->function();
- free(p);
+ struct nullary_exit_function* p = (struct nullary_exit_function*)context;
+ p->function();
+ free(p);
}
// Initialize exit functions. Must be called once before exitfn_add* are used.
void
exitfn_init(void)
{
- if (atexit(exitfn_call) != 0) {
- fatal("atexit failed: %s", strerror(errno));
- }
+ if (atexit(exitfn_call) != 0) {
+ fatal("atexit failed: %s", strerror(errno));
+ }
}
// Add a nullary function to be called when ccache exits. Functions are called
@@ -52,51 +54,51 @@ exitfn_init(void)
void
exitfn_add_nullary(void (*function)(void))
{
- auto p = static_cast<exit_function*>(x_malloc(sizeof(exit_function)));
- p->function = reinterpret_cast<void (*)(void*)>(function);
- exitfn_add(call_nullary_exit_function, p);
+ auto p = static_cast<exit_function*>(x_malloc(sizeof(exit_function)));
+ p->function = reinterpret_cast<void (*)(void*)>(function);
+ exitfn_add(call_nullary_exit_function, p);
}
// Add a function to be called with a context parameter when ccache exits.
// Functions are called in LIFO order except when added via exitfn_add_last.
void
-exitfn_add(void (*function)(void *), void *context)
+exitfn_add(void (*function)(void*), void* context)
{
- auto p = static_cast<exit_function*>(x_malloc(sizeof(exit_function)));
- p->function = function;
- p->context = context;
- p->next = exit_functions;
- exit_functions = p;
+ auto p = static_cast<exit_function*>(x_malloc(sizeof(exit_function)));
+ p->function = function;
+ p->context = context;
+ p->next = exit_functions;
+ exit_functions = p;
}
// Add a function to be called with a context parameter when ccache exits. In
// contrast to exitfn_add, exitfn_add_last sets up the function to be called
// last.
void
-exitfn_add_last(void (*function)(void *), void *context)
+exitfn_add_last(void (*function)(void*), void* context)
{
- auto p = static_cast<exit_function*>(x_malloc(sizeof(exit_function)));
- p->function = function;
- p->context = context;
- p->next = NULL;
+ auto p = static_cast<exit_function*>(x_malloc(sizeof(exit_function)));
+ p->function = function;
+ p->context = context;
+ p->next = NULL;
- struct exit_function **q = &exit_functions;
- while (*q) {
- q = &(*q)->next;
- }
- *q = p;
+ struct exit_function** q = &exit_functions;
+ while (*q) {
+ q = &(*q)->next;
+ }
+ *q = p;
}
// Call added functions.
void
exitfn_call(void)
{
- struct exit_function *p = exit_functions;
- exit_functions = NULL;
- while (p) {
- p->function(p->context);
- struct exit_function *q = p;
- p = p->next;
- free(q);
- }
+ struct exit_function* p = exit_functions;
+ exit_functions = NULL;
+ while (p) {
+ p->function(p->context);
+ struct exit_function* q = p;
+ p = p->next;
+ free(q);
+ }
}
diff --git a/src/hash.cpp b/src/hash.cpp
index b3d6d468..83dc4703 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -17,172 +17,178 @@
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#include "ccache.hpp"
#include "hash.hpp"
+
+#include "ccache.hpp"
+
#include <blake2.h>
#define HASH_DELIMITER "\000cCaChE"
-struct hash {
- blake2b_state state;
- FILE *debug_binary;
- FILE *debug_text;
+struct hash
+{
+ blake2b_state state;
+ FILE* debug_binary;
+ FILE* debug_text;
};
void
-digest_as_string(const struct digest *d, char *buffer)
+digest_as_string(const struct digest* d, char* buffer)
{
- format_hex(d->bytes, DIGEST_SIZE, buffer);
+ format_hex(d->bytes, DIGEST_SIZE, buffer);
}
bool
-digests_equal(const struct digest *d1, const struct digest *d2)
+digests_equal(const struct digest* d1, const struct digest* d2)
{
- return memcmp(d1->bytes, d2->bytes, DIGEST_SIZE) == 0;
+ return memcmp(d1->bytes, d2->bytes, DIGEST_SIZE) == 0;
}
static void
-do_hash_buffer(struct hash *hash, const void *s, size_t len)
+do_hash_buffer(struct hash* hash, const void* s, size_t len)
{
- assert(s);
+ assert(s);
- blake2b_update(&hash->state, (const uint8_t *)s, len);
- if (len > 0 && hash->debug_binary) {
- (void) fwrite(s, 1, len, hash->debug_binary);
- }
+ blake2b_update(&hash->state, (const uint8_t*)s, len);
+ if (len > 0 && hash->debug_binary) {
+ (void)fwrite(s, 1, len, hash->debug_binary);
+ }
}
static void
-do_debug_text(struct hash *hash, const void *s, size_t len)
+do_debug_text(struct hash* hash, const void* s, size_t len)
{
- if (len > 0 && hash->debug_text) {
- (void) fwrite(s, 1, len, hash->debug_text);
- }
+ if (len > 0 && hash->debug_text) {
+ (void)fwrite(s, 1, len, hash->debug_text);
+ }
}
-struct hash *
+struct hash*
hash_init(void)
{
- auto hash = static_cast<struct hash*>(malloc(sizeof(struct hash)));
- blake2b_init(&hash->state, DIGEST_SIZE);
- hash->debug_binary = NULL;
- hash->debug_text = NULL;
- return hash;
+ auto hash = static_cast<struct hash*>(malloc(sizeof(struct hash)));
+ blake2b_init(&hash->state, DIGEST_SIZE);
+ hash->debug_binary = NULL;
+ hash->debug_text = NULL;
+ return hash;
}
-struct hash *
-hash_copy(struct hash *hash)
+struct hash*
+hash_copy(struct hash* hash)
{
- auto result = static_cast<struct hash*>(malloc(sizeof(struct hash)));
- result->state = hash->state;
- result->debug_binary = NULL;
- result->debug_text = NULL;
- return result;
+ auto result = static_cast<struct hash*>(malloc(sizeof(struct hash)));
+ result->state = hash->state;
+ result->debug_binary = NULL;
+ result->debug_text = NULL;
+ return result;
}
-void hash_free(struct hash *hash)
+void
+hash_free(struct hash* hash)
{
- free(hash);
+ free(hash);
}
-void hash_enable_debug(
- struct hash *hash, const char *section_name,
- FILE *debug_binary, FILE *debug_text)
+void
+hash_enable_debug(struct hash* hash,
+ const char* section_name,
+ FILE* debug_binary,
+ FILE* debug_text)
{
- hash->debug_binary = debug_binary;
- hash->debug_text = debug_text;
+ hash->debug_binary = debug_binary;
+ hash->debug_text = debug_text;
- do_debug_text(hash, "=== ", 4);
- do_debug_text(hash, section_name, strlen(section_name));
- do_debug_text(hash, " ===\n", 5);
+ do_debug_text(hash, "=== ", 4);
+ do_debug_text(hash, section_name, strlen(section_name));
+ do_debug_text(hash, " ===\n", 5);
}
void
-hash_buffer(struct hash *hash, const void *s, size_t len)
+hash_buffer(struct hash* hash, const void* s, size_t len)
{
- do_hash_buffer(hash, s, len);
- do_debug_text(hash, s, len);
+ do_hash_buffer(hash, s, len);
+ do_debug_text(hash, s, len);
}
void
-hash_result_as_bytes(struct hash *hash, struct digest *digest)
+hash_result_as_bytes(struct hash* hash, struct digest* digest)
{
- // make a copy before altering state
- struct hash *copy = hash_copy(hash);
- blake2b_final(&copy->state, digest->bytes, DIGEST_SIZE);
- hash_free(copy);
+ // make a copy before altering state
+ struct hash* copy = hash_copy(hash);
+ blake2b_final(&copy->state, digest->bytes, DIGEST_SIZE);
+ hash_free(copy);
}
void
-hash_result_as_string(struct hash *hash, char *buffer)
+hash_result_as_string(struct hash* hash, char* buffer)
{
- struct digest d;
- hash_result_as_bytes(hash, &d);
- digest_as_string(&d, buffer);
+ struct digest d;
+ hash_result_as_bytes(hash, &d);
+ digest_as_string(&d, buffer);
}
void
-hash_delimiter(struct hash *hash, const char *type)
+hash_delimiter(struct hash* hash, const char* type)
{
- do_hash_buffer(hash, HASH_DELIMITER, sizeof(HASH_DELIMITER));
- do_hash_buffer(hash, type, strlen(type) + 1); // Include NUL.
- do_debug_text(hash, "### ", 4);
- do_debug_text(hash, type, strlen(type));
- do_debug_text(hash, "\n", 1);
+ do_hash_buffer(hash, HASH_DELIMITER, sizeof(HASH_DELIMITER));
+ do_hash_buffer(hash, type, strlen(type) + 1); // Include NUL.
+ do_debug_text(hash, "### ", 4);
+ do_debug_text(hash, type, strlen(type));
+ do_debug_text(hash, "\n", 1);
}
void
-hash_string(struct hash *hash, const char *s)
+hash_string(struct hash* hash, const char* s)
{
- hash_string_buffer(hash, s, strlen(s));
+ hash_string_buffer(hash, s, strlen(s));
}
void
-hash_string_buffer(struct hash *hash, const char *s, int length)
+hash_string_buffer(struct hash* hash, const char* s, int length)
{
- hash_buffer(hash, s, length);
- do_debug_text(hash, "\n", 1);
+ hash_buffer(hash, s, length);
+ do_debug_text(hash, "\n", 1);
}
void
-hash_int(struct hash *hash, int x)
+hash_int(struct hash* hash, int x)
{
- do_hash_buffer(hash, (char *)&x, sizeof(x));
+ do_hash_buffer(hash, (char*)&x, sizeof(x));
- char buf[16];
- snprintf(buf, sizeof(buf), "%d", x);
- do_debug_text(hash, buf, strlen(buf));
- do_debug_text(hash, "\n", 1);
+ char buf[16];
+ snprintf(buf, sizeof(buf), "%d", x);
+ do_debug_text(hash, buf, strlen(buf));
+ do_debug_text(hash, "\n", 1);
}
bool
-hash_fd(struct hash *hash, int fd)
+hash_fd(struct hash* hash, int fd)
{
- char buf[READ_BUFFER_SIZE];
- ssize_t n;
+ char buf[READ_BUFFER_SIZE];
+ ssize_t n;
- while ((n = read(fd, buf, sizeof(buf))) != 0) {
- if (n == -1 && errno != EINTR) {
- break;
- }
- if (n > 0) {
- do_hash_buffer(hash, buf, n);
- do_debug_text(hash, buf, n);
- }
- }
- return n == 0;
+ while ((n = read(fd, buf, sizeof(buf))) != 0) {
+ if (n == -1 && errno != EINTR) {
+ break;
+ }
+ if (n > 0) {
+ do_hash_buffer(hash, buf, n);
+ do_debug_text(hash, buf, n);
+ }
+ }
+ return n == 0;
}
bool
-hash_file(struct hash *hash, const char *fname)
+hash_file(struct hash* hash, const char* fname)
{
- int fd = open(fname, O_RDONLY|O_BINARY);
- if (fd == -1) {
- cc_log("Failed to open %s: %s", fname, strerror(errno));
- return false;
- }
+ int fd = open(fname, O_RDONLY | O_BINARY);
+ if (fd == -1) {
+ cc_log("Failed to open %s: %s", fname, strerror(errno));
+ return false;
+ }
- bool ret = hash_fd(hash, fd);
- close(fd);
- return ret;
+ bool ret = hash_fd(hash, fd);
+ close(fd);
+ return ret;
}
diff --git a/src/hash.hpp b/src/hash.hpp
index eb341b2f..43b3a29a 100644
--- a/src/hash.hpp
+++ b/src/hash.hpp
@@ -27,39 +27,40 @@
// checksum) produced by the hash algorithm.
struct digest
{
- uint8_t bytes[DIGEST_SIZE];
+ uint8_t bytes[DIGEST_SIZE];
};
// Format the digest as a NUL-terminated hex string. The string buffer must
// contain at least DIGEST_STRING_BUFFER_SIZE bytes.
-void digest_as_string(const struct digest *d, char *buffer);
+void digest_as_string(const struct digest* d, char* buffer);
// Return true if d1 and d2 are equal, else false.
-bool digests_equal(const struct digest *d1, const struct digest *d2);
+bool digests_equal(const struct digest* d1, const struct digest* d2);
// struct hash represents the hash algorithm's inner state.
struct hash;
// Create a new hash state.
-struct hash *hash_init(void);
+struct hash* hash_init(void);
// Create a new hash state from an existing hash state.
-struct hash *hash_copy(struct hash *hash);
+struct hash* hash_copy(struct hash* hash);
// Free a hash state created by hash_init or hash_copy.
-void hash_free(struct hash *hash);
+void hash_free(struct hash* hash);
// Enable debug logging of hashed input to a binary and a text file.
-void hash_enable_debug(
- struct hash *hash, const char *section_name, FILE *debug_binary,
- FILE *debug_text);
+void hash_enable_debug(struct hash* hash,
+ const char* section_name,
+ FILE* debug_binary,
+ FILE* debug_text);
// Retrieve the digest as bytes.
-void hash_result_as_bytes(struct hash *hash, struct digest *digest);
+void hash_result_as_bytes(struct hash* hash, struct digest* digest);
// Retrieve the digest as a NUL-terminated hex string. The string buffer must
// contain at least DIGEST_STRING_BUFFER_SIZE bytes.
-void hash_result_as_string(struct hash *hash, char *buffer);
+void hash_result_as_string(struct hash* hash, char* buffer);
// Hash some data that is unlikely to occur in the input. The idea is twofold:
//
@@ -69,31 +70,31 @@ void hash_result_as_string(struct hash *hash, char *buffer);
// conditional hashing of information in a safe way (e.g., if we want to hash
// information X if CCACHE_A is set and information Y if CCACHE_B is set,
// there should never be a hash collision risk).
-void hash_delimiter(struct hash *hash, const char *type);
+void hash_delimiter(struct hash* hash, const char* type);
// Hash bytes in a buffer.
//
// If hash debugging is enabled, the bytes are written verbatim to the text
// input file.
-void hash_buffer(struct hash *hash, const void *s, size_t len);
+void hash_buffer(struct hash* hash, const void* s, size_t len);
// Hash a string.
//
// If hash debugging is enabled, the string is written to the text input file
// followed by a newline.
-void hash_string(struct hash *hash, const char *s);
+void hash_string(struct hash* hash, const char* s);
// Hash a string with a known size.
//
// If hash debugging is enabled, the string is written to the text input file
// followed by a newline.
-void hash_string_buffer(struct hash *hash, const char *s, int length);
+void hash_string_buffer(struct hash* hash, const char* s, int length);
// Hash an integer.
//
// If hash debugging is enabled, the integer is written in text form to the
// text input file followed by a newline.
-void hash_int(struct hash *hash, int x);
+void hash_int(struct hash* hash, int x);
// Add contents of an open file to the hash.
//
@@ -101,7 +102,7 @@ void hash_int(struct hash *hash, int x);
// file.
//
// Returns true on success, otherwise false.
-bool hash_fd(struct hash *hash, int fd);
+bool hash_fd(struct hash* hash, int fd);
// Add contents of a file to the hash.
//
@@ -109,4 +110,4 @@ bool hash_fd(struct hash *hash, int fd);
// file.
//
// Returns true on success, otherwise false.
-bool hash_file(struct hash *hash, const char *fname);
+bool hash_file(struct hash* hash, const char* fname);
diff --git a/src/hashutil.cpp b/src/hashutil.cpp
index c9848a57..99888296 100644
--- a/src/hashutil.cpp
+++ b/src/hashutil.cpp
@@ -16,27 +16,29 @@
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#include "ccache.hpp"
#include "hashutil.hpp"
+
+#include "ccache.hpp"
#include "macroskip.hpp"
+
#include "third_party/xxhash.h"
unsigned
-hash_from_string(void *str)
+hash_from_string(void* str)
{
- return XXH64(str, strlen((const char *)str), 0);
+ return XXH64(str, strlen((const char*)str), 0);
}
unsigned
hash_from_int(int i)
{
- return XXH64(&i, sizeof(int), 0);
+ return XXH64(&i, sizeof(int), 0);
}
int
-strings_equal(void *str1, void *str2)
+strings_equal(void* str1, void* str2)
{
- return str_eq((const char *)str1, (const char *)str2);
+ return str_eq((const char*)str1, (const char*)str2);
}
// Search for the strings "__DATE__" and "__TIME__" in str.
@@ -44,265 +46,266 @@ strings_equal(void *str1, void *str2)
// Returns a bitmask with HASH_SOURCE_CODE_FOUND_DATE and
// HASH_SOURCE_CODE_FOUND_TIME set appropriately.
int
-check_for_temporal_macros(const char *str, size_t len)
+check_for_temporal_macros(const char* str, size_t len)
{
- int result = 0;
+ int result = 0;
- // We're using the Boyer-Moore-Horspool algorithm, which searches starting
- // from the *end* of the needle. Our needles are 8 characters long, so i
- // starts at 7.
- size_t i = 7;
+ // We're using the Boyer-Moore-Horspool algorithm, which searches starting
+ // from the *end* of the needle. Our needles are 8 characters long, so i
+ // starts at 7.
+ size_t i = 7;
- while (i < len) {
- // Check whether the substring ending at str[i] has the form "__...E__". On
- // the assumption that 'E' is less common in source than '_', we check
- // str[i-2] first.
- if (str[i - 2] == 'E'
- && str[i - 0] == '_'
- && str[i - 7] == '_'
- && str[i - 1] == '_'
- && str[i - 6] == '_'
- && (i < 8 || (str[i - 8] != '_' && !isalnum(str[i - 8])))
- && (i + 1 >= len || (str[i + 1] != '_' && !isalnum(str[i + 1])))) {
- // Check the remaining characters to see if the substring is "__DATE__"
- // or "__TIME__".
- if (str[i - 5] == 'D' && str[i - 4] == 'A' && str[i - 3] == 'T') {
- result |= HASH_SOURCE_CODE_FOUND_DATE;
- } else if (str[i - 5] == 'T' && str[i - 4] == 'I' && str[i - 3] == 'M') {
- result |= HASH_SOURCE_CODE_FOUND_TIME;
- }
- }
+ while (i < len) {
+ // Check whether the substring ending at str[i] has the form "__...E__". On
+ // the assumption that 'E' is less common in source than '_', we check
+ // str[i-2] first.
+ if (str[i - 2] == 'E' && str[i - 0] == '_' && str[i - 7] == '_'
+ && str[i - 1] == '_' && str[i - 6] == '_'
+ && (i < 8 || (str[i - 8] != '_' && !isalnum(str[i - 8])))
+ && (i + 1 >= len || (str[i + 1] != '_' && !isalnum(str[i + 1])))) {
+ // Check the remaining characters to see if the substring is "__DATE__"
+ // or "__TIME__".
+ if (str[i - 5] == 'D' && str[i - 4] == 'A' && str[i - 3] == 'T') {
+ result |= HASH_SOURCE_CODE_FOUND_DATE;
+ } else if (str[i - 5] == 'T' && str[i - 4] == 'I' && str[i - 3] == 'M') {
+ result |= HASH_SOURCE_CODE_FOUND_TIME;
+ }
+ }
- // macro_skip tells us how far we can skip forward upon seeing str[i] at
- // the end of a substring.
- i += macro_skip[(uint8_t)str[i]];
- }
+ // macro_skip tells us how far we can skip forward upon seeing str[i] at
+ // the end of a substring.
+ i += macro_skip[(uint8_t)str[i]];
+ }
- return result;
+ return result;
}
// Hash a string. Returns a bitmask of HASH_SOURCE_CODE_* results.
int
-hash_source_code_string(
- struct conf *conf, struct hash *hash, const char *str, size_t len,
- const char *path)
+hash_source_code_string(struct conf* conf,
+ struct hash* hash,
+ const char* str,
+ size_t len,
+ const char* path)
{
- int result = HASH_SOURCE_CODE_OK;
+ int result = HASH_SOURCE_CODE_OK;
- // Check for __DATE__ and __TIME__ if the sloppiness configuration tells us
- // we should.
- if (!(conf->sloppiness & SLOPPY_TIME_MACROS)) {
- result |= check_for_temporal_macros(str, len);
- }
+ // Check for __DATE__ and __TIME__ if the sloppiness configuration tells us
+ // we should.
+ if (!(conf->sloppiness & SLOPPY_TIME_MACROS)) {
+ result |= check_for_temporal_macros(str, len);
+ }
- // Hash the source string.
- hash_string_buffer(hash, str, len);
+ // Hash the source string.
+ hash_string_buffer(hash, str, len);
- if (result & HASH_SOURCE_CODE_FOUND_DATE) {
- // Make sure that the hash sum changes if the (potential) expansion of
- // __DATE__ changes.
- time_t t = time(NULL);
- struct tm now;
- localtime_r(&t, &now);
- cc_log("Found __DATE__ in %s", path);
- hash_delimiter(hash, "date");
- hash_int(hash, now.tm_year);
- hash_int(hash, now.tm_mon);
- hash_int(hash, now.tm_mday);
- }
- if (result & HASH_SOURCE_CODE_FOUND_TIME) {
- // We don't know for sure that the program actually uses the __TIME__
- // macro, but we have to assume it anyway and hash the time stamp. However,
- // that's not very useful since the chance that we get a cache hit later
- // the same second should be quite slim... So, just signal back to the
- // caller that __TIME__ has been found so that the direct mode can be
- // disabled.
- cc_log("Found __TIME__ in %s", path);
- }
+ if (result & HASH_SOURCE_CODE_FOUND_DATE) {
+ // Make sure that the hash sum changes if the (potential) expansion of
+ // __DATE__ changes.
+ time_t t = time(NULL);
+ struct tm now;
+ localtime_r(&t, &now);
+ cc_log("Found __DATE__ in %s", path);
+ hash_delimiter(hash, "date");
+ hash_int(hash, now.tm_year);
+ hash_int(hash, now.tm_mon);
+ hash_int(hash, now.tm_mday);
+ }
+ if (result & HASH_SOURCE_CODE_FOUND_TIME) {
+ // We don't know for sure that the program actually uses the __TIME__
+ // macro, but we have to assume it anyway and hash the time stamp. However,
+ // that's not very useful since the chance that we get a cache hit later
+ // the same second should be quite slim... So, just signal back to the
+ // caller that __TIME__ has been found so that the direct mode can be
+ // disabled.
+ cc_log("Found __TIME__ in %s", path);
+ }
- return result;
+ return result;
}
// Hash a file ignoring comments. Returns a bitmask of HASH_SOURCE_CODE_*
// results.
int
-hash_source_code_file(struct conf *conf, struct hash *hash, const char *path)
+hash_source_code_file(struct conf* conf, struct hash* hash, const char* path)
{
- if (is_precompiled_header(path)) {
- if (hash_file(hash, path)) {
- return HASH_SOURCE_CODE_OK;
- } else {
- return HASH_SOURCE_CODE_ERROR;
- }
- } else {
- char *data;
- size_t size;
- if (!read_file(path, 0, &data, &size)) {
- return HASH_SOURCE_CODE_ERROR;
- }
- int result = hash_source_code_string(conf, hash, data, size, path);
- free(data);
- return result;
- }
+ if (is_precompiled_header(path)) {
+ if (hash_file(hash, path)) {
+ return HASH_SOURCE_CODE_OK;
+ } else {
+ return HASH_SOURCE_CODE_ERROR;
+ }
+ } else {
+ char* data;
+ size_t size;
+ if (!read_file(path, 0, &data, &size)) {
+ return HASH_SOURCE_CODE_ERROR;
+ }
+ int result = hash_source_code_string(conf, hash, data, size, path);
+ free(data);
+ return result;
+ }
}
bool
-hash_command_output(struct hash *hash, const char *command,
- const char *compiler)
+hash_command_output(struct hash* hash,
+ const char* command,
+ const char* compiler)
{
#ifdef _WIN32
- // Trim leading space.
- while (isspace(*command)) {
- command++;
- }
+ // Trim leading space.
+ while (isspace(*command)) {
+ command++;
+ }
- // Add "echo" command.
- bool cmd;
- if (str_startswith(command, "echo")) {
- command = format("cmd.exe /c \"%s\"", command);
- cmd = true;
- } else if (str_startswith(command,
- "%compiler%") && str_eq(compiler, "echo")) {
- command = format("cmd.exe /c \"%s%s\"", compiler, command + 10);
- cmd = true;
- } else {
- command = x_strdup(command);
- cmd = false;
- }
+ // Add "echo" command.
+ bool cmd;
+ if (str_startswith(command, "echo")) {
+ command = format("cmd.exe /c \"%s\"", command);
+ cmd = true;
+ } else if (str_startswith(command, "%compiler%")
+ && str_eq(compiler, "echo")) {
+ command = format("cmd.exe /c \"%s%s\"", compiler, command + 10);
+ cmd = true;
+ } else {
+ command = x_strdup(command);
+ cmd = false;
+ }
#endif
- struct args *args = args_init_from_string(command);
- for (int i = 0; i < args->argc; i++) {
- if (str_eq(args->argv[i], "%compiler%")) {
- args_set(args, i, compiler);
- }
- }
- cc_log_argv("Executing compiler check command ", args->argv);
+ struct args* args = args_init_from_string(command);
+ for (int i = 0; i < args->argc; i++) {
+ if (str_eq(args->argv[i], "%compiler%")) {
+ args_set(args, i, compiler);
+ }
+ }
+ cc_log_argv("Executing compiler check command ", args->argv);
#ifdef _WIN32
- PROCESS_INFORMATION pi;
- memset(&pi, 0x00, sizeof(pi));
- STARTUPINFO si;
- memset(&si, 0x00, sizeof(si));
+ PROCESS_INFORMATION pi;
+ memset(&pi, 0x00, sizeof(pi));
+ STARTUPINFO si;
+ memset(&si, 0x00, sizeof(si));
- char *path = find_executable(args->argv[0], NULL);
- if (!path) {
- path = args->argv[0];
- }
- char *sh = win32getshell(path);
- if (sh) {
- path = sh;
- }
+ char* path = find_executable(args->argv[0], NULL);
+ if (!path) {
+ path = args->argv[0];
+ }
+ char* sh = win32getshell(path);
+ if (sh) {
+ path = sh;
+ }
- si.cb = sizeof(STARTUPINFO);
+ si.cb = sizeof(STARTUPINFO);
- HANDLE pipe_out[2];
- SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
- CreatePipe(&pipe_out[0], &pipe_out[1], &sa, 0);
- SetHandleInformation(pipe_out[0], HANDLE_FLAG_INHERIT, 0);
- si.hStdOutput = pipe_out[1];
- si.hStdError = pipe_out[1];
- si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- si.dwFlags = STARTF_USESTDHANDLES;
+ HANDLE pipe_out[2];
+ SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
+ CreatePipe(&pipe_out[0], &pipe_out[1], &sa, 0);
+ SetHandleInformation(pipe_out[0], HANDLE_FLAG_INHERIT, 0);
+ si.hStdOutput = pipe_out[1];
+ si.hStdError = pipe_out[1];
+ si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ si.dwFlags = STARTF_USESTDHANDLES;
- char *win32args;
- if (!cmd) {
- int length;
- win32args = win32argvtos(sh, args->argv, &length);
- } else {
- win32args = (char *)command; // quoted
- }
- BOOL ret =
- CreateProcess(path, win32args, NULL, NULL, 1, 0, NULL, NULL, &si, &pi);
- CloseHandle(pipe_out[1]);
- args_free(args);
- free(win32args);
- if (!cmd) {
- free((char *)command); // Original argument was replaced above.
- }
- if (ret == 0) {
- stats_update(STATS_COMPCHECK);
- return false;
- }
- int fd = _open_osfhandle((intptr_t) pipe_out[0], O_BINARY);
- bool ok = hash_fd(hash, fd);
- if (!ok) {
- cc_log("Error hashing compiler check command output: %s", strerror(errno));
- stats_update(STATS_COMPCHECK);
- }
- WaitForSingleObject(pi.hProcess, INFINITE);
- DWORD exitcode;
- GetExitCodeProcess(pi.hProcess, &exitcode);
- CloseHandle(pipe_out[0]);
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- if (exitcode != 0) {
- cc_log("Compiler check command returned %d", (int) exitcode);
- stats_update(STATS_COMPCHECK);
- return false;
- }
- return ok;
+ char* win32args;
+ if (!cmd) {
+ int length;
+ win32args = win32argvtos(sh, args->argv, &length);
+ } else {
+ win32args = (char*)command; // quoted
+ }
+ BOOL ret =
+ CreateProcess(path, win32args, NULL, NULL, 1, 0, NULL, NULL, &si, &pi);
+ CloseHandle(pipe_out[1]);
+ args_free(args);
+ free(win32args);
+ if (!cmd) {
+ free((char*)command); // Original argument was replaced above.
+ }
+ if (ret == 0) {
+ stats_update(STATS_COMPCHECK);
+ return false;
+ }
+ int fd = _open_osfhandle((intptr_t)pipe_out[0], O_BINARY);
+ bool ok = hash_fd(hash, fd);
+ if (!ok) {
+ cc_log("Error hashing compiler check command output: %s", strerror(errno));
+ stats_update(STATS_COMPCHECK);
+ }
+ WaitForSingleObject(pi.hProcess, INFINITE);
+ DWORD exitcode;
+ GetExitCodeProcess(pi.hProcess, &exitcode);
+ CloseHandle(pipe_out[0]);
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ if (exitcode != 0) {
+ cc_log("Compiler check command returned %d", (int)exitcode);
+ stats_update(STATS_COMPCHECK);
+ return false;
+ }
+ return ok;
#else
- int pipefd[2];
- if (pipe(pipefd) == -1) {
- fatal("pipe failed");
- }
+ int pipefd[2];
+ if (pipe(pipefd) == -1) {
+ fatal("pipe failed");
+ }
- pid_t pid = fork();
- if (pid == -1) {
- fatal("fork failed");
- }
+ pid_t pid = fork();
+ if (pid == -1) {
+ fatal("fork failed");
+ }
- if (pid == 0) {
- // Child.
- close(pipefd[0]);
- close(0);
- dup2(pipefd[1], 1);
- dup2(pipefd[1], 2);
- _exit(execvp(args->argv[0], args->argv));
- // Never reached.
- } else {
- // Parent.
- args_free(args);
- close(pipefd[1]);
- bool ok = hash_fd(hash, pipefd[0]);
- if (!ok) {
- cc_log("Error hashing compiler check command output: %s",
- strerror(errno));
- stats_update(STATS_COMPCHECK);
- }
- close(pipefd[0]);
+ if (pid == 0) {
+ // Child.
+ close(pipefd[0]);
+ close(0);
+ dup2(pipefd[1], 1);
+ dup2(pipefd[1], 2);
+ _exit(execvp(args->argv[0], args->argv));
+ // Never reached.
+ } else {
+ // Parent.
+ args_free(args);
+ close(pipefd[1]);
+ bool ok = hash_fd(hash, pipefd[0]);
+ if (!ok) {
+ cc_log("Error hashing compiler check command output: %s",
+ strerror(errno));
+ stats_update(STATS_COMPCHECK);
+ }
+ close(pipefd[0]);
- int status;
- if (waitpid(pid, &status, 0) != pid) {
- cc_log("waitpid failed");
- return false;
- }
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- cc_log("Compiler check command returned %d", WEXITSTATUS(status));
- stats_update(STATS_COMPCHECK);
- return false;
- }
- return ok;
- }
+ int status;
+ if (waitpid(pid, &status, 0) != pid) {
+ cc_log("waitpid failed");
+ return false;
+ }
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ cc_log("Compiler check command returned %d", WEXITSTATUS(status));
+ stats_update(STATS_COMPCHECK);
+ return false;
+ }
+ return ok;
+ }
#endif
}
bool
-hash_multicommand_output(struct hash *hash, const char *commands,
- const char *compiler)
+hash_multicommand_output(struct hash* hash,
+ const char* commands,
+ const char* compiler)
{
- char *command_string = x_strdup(commands);
- char *p = command_string;
- char *command;
- char *saveptr = NULL;
- bool ok = true;
- while ((command = strtok_r(p, ";", &saveptr))) {
- if (!hash_command_output(hash, command, compiler)) {
- ok = false;
- }
- p = NULL;
- }
- free(command_string);
- return ok;
+ char* command_string = x_strdup(commands);
+ char* p = command_string;
+ char* command;
+ char* saveptr = NULL;
+ bool ok = true;
+ while ((command = strtok_r(p, ";", &saveptr))) {
+ if (!hash_command_output(hash, command, compiler)) {
+ ok = false;
+ }
+ p = NULL;
+ }
+ free(command_string);
+ return ok;
}
diff --git a/src/hashutil.hpp b/src/hashutil.hpp
index 3a270ac4..09112d10 100644
--- a/src/hashutil.hpp
+++ b/src/hashutil.hpp
@@ -20,24 +20,29 @@
#include "conf.hpp"
#include "hash.hpp"
+
#include <inttypes.h>
-unsigned hash_from_string(void *str);
+unsigned hash_from_string(void* str);
unsigned hash_from_int(int i);
-int strings_equal(void *str1, void *str2);
+int strings_equal(void* str1, void* str2);
#define HASH_SOURCE_CODE_OK 0
#define HASH_SOURCE_CODE_ERROR 1
-#define HASH_SOURCE_CODE_FOUND_DATE 2
-#define HASH_SOURCE_CODE_FOUND_TIME 4
+#define HASH_SOURCE_CODE_FOUND_DATE 2
+#define HASH_SOURCE_CODE_FOUND_TIME 4
-int check_for_temporal_macros(const char *str, size_t len);
-int hash_source_code_string(
- struct conf *conf, struct hash *hash, const char *str, size_t len,
- const char *path);
-int hash_source_code_file(
- struct conf *conf, struct hash *hash, const char *path);
-bool hash_command_output(struct hash *hash, const char *command,
- const char *compiler);
-bool hash_multicommand_output(struct hash *hash, const char *command,
- const char *compiler);
+int check_for_temporal_macros(const char* str, size_t len);
+int hash_source_code_string(struct conf* conf,
+ struct hash* hash,
+ const char* str,
+ size_t len,
+ const char* path);
+int
+hash_source_code_file(struct conf* conf, struct hash* hash, const char* path);
+bool hash_command_output(struct hash* hash,
+ const char* command,
+ const char* compiler);
+bool hash_multicommand_output(struct hash* hash,
+ const char* command,
+ const char* compiler);
diff --git a/src/int_bytes_conversion.hpp b/src/int_bytes_conversion.hpp
index 24996fde..47540dae 100644
--- a/src/int_bytes_conversion.hpp
+++ b/src/int_bytes_conversion.hpp
@@ -16,70 +16,59 @@
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#define BYTES_FROM_UINT16(bytes, uint16) \
- do { \
- (bytes)[0] = (uint16) >> 8 & 0xFF; \
- (bytes)[1] = (uint16) >> 0 & 0xFF; \
- } while (false)
+#define BYTES_FROM_UINT16(bytes, uint16) \
+ do { \
+ (bytes)[0] = (uint16) >> 8 & 0xFF; \
+ (bytes)[1] = (uint16) >> 0 & 0xFF; \
+ } while (false)
-#define UINT16_FROM_BYTES(bytes) \
- ((uint16_t)(uint8_t)(bytes)[0] << 8 | \
- (uint16_t)(uint8_t)(bytes)[1] << 0)
+#define UINT16_FROM_BYTES(bytes) \
+ ((uint16_t)(uint8_t)(bytes)[0] << 8 | (uint16_t)(uint8_t)(bytes)[1] << 0)
-#define BYTES_FROM_UINT32(bytes, uint32) \
- do { \
- (bytes)[0] = (uint32) >> 24 & 0xFF; \
- (bytes)[1] = (uint32) >> 16 & 0xFF; \
- (bytes)[2] = (uint32) >> 8 & 0xFF; \
- (bytes)[3] = (uint32) >> 0 & 0xFF; \
- } while (false)
+#define BYTES_FROM_UINT32(bytes, uint32) \
+ do { \
+ (bytes)[0] = (uint32) >> 24 & 0xFF; \
+ (bytes)[1] = (uint32) >> 16 & 0xFF; \
+ (bytes)[2] = (uint32) >> 8 & 0xFF; \
+ (bytes)[3] = (uint32) >> 0 & 0xFF; \
+ } while (false)
-#define UINT32_FROM_BYTES(bytes) \
- ((uint32_t)(uint8_t)(bytes)[0] << 24 | \
- (uint32_t)(uint8_t)(bytes)[1] << 16 | \
- (uint32_t)(uint8_t)(bytes)[2] << 8 | \
- (uint32_t)(uint8_t)(bytes)[3] << 0)
+#define UINT32_FROM_BYTES(bytes) \
+ ((uint32_t)(uint8_t)(bytes)[0] << 24 | (uint32_t)(uint8_t)(bytes)[1] << 16 \
+ | (uint32_t)(uint8_t)(bytes)[2] << 8 | (uint32_t)(uint8_t)(bytes)[3] << 0)
-#define BYTES_FROM_INT64(bytes, int64) \
- do { \
- (bytes)[0] = (int64) >> 56 & 0xFF; \
- (bytes)[1] = (int64) >> 48 & 0xFF; \
- (bytes)[2] = (int64) >> 40 & 0xFF; \
- (bytes)[3] = (int64) >> 32 & 0xFF; \
- (bytes)[4] = (int64) >> 24 & 0xFF; \
- (bytes)[5] = (int64) >> 16 & 0xFF; \
- (bytes)[6] = (int64) >> 8 & 0xFF; \
- (bytes)[7] = (int64) >> 0 & 0xFF; \
- } while (false)
+#define BYTES_FROM_INT64(bytes, int64) \
+ do { \
+ (bytes)[0] = (int64) >> 56 & 0xFF; \
+ (bytes)[1] = (int64) >> 48 & 0xFF; \
+ (bytes)[2] = (int64) >> 40 & 0xFF; \
+ (bytes)[3] = (int64) >> 32 & 0xFF; \
+ (bytes)[4] = (int64) >> 24 & 0xFF; \
+ (bytes)[5] = (int64) >> 16 & 0xFF; \
+ (bytes)[6] = (int64) >> 8 & 0xFF; \
+ (bytes)[7] = (int64) >> 0 & 0xFF; \
+ } while (false)
-#define INT64_FROM_BYTES(bytes) \
- ((int64_t)(uint8_t)(bytes)[0] << 56 | \
- (int64_t)(uint8_t)(bytes)[1] << 48 | \
- (int64_t)(uint8_t)(bytes)[2] << 40 | \
- (int64_t)(uint8_t)(bytes)[3] << 32 | \
- (int64_t)(uint8_t)(bytes)[4] << 24 | \
- (int64_t)(uint8_t)(bytes)[5] << 16 | \
- (int64_t)(uint8_t)(bytes)[6] << 8 | \
- (int64_t)(uint8_t)(bytes)[7] << 0)
+#define INT64_FROM_BYTES(bytes) \
+ ((int64_t)(uint8_t)(bytes)[0] << 56 | (int64_t)(uint8_t)(bytes)[1] << 48 \
+ | (int64_t)(uint8_t)(bytes)[2] << 40 | (int64_t)(uint8_t)(bytes)[3] << 32 \
+ | (int64_t)(uint8_t)(bytes)[4] << 24 | (int64_t)(uint8_t)(bytes)[5] << 16 \
+ | (int64_t)(uint8_t)(bytes)[6] << 8 | (int64_t)(uint8_t)(bytes)[7] << 0)
-#define BYTES_FROM_UINT64(bytes, uint64) \
- do { \
- (bytes)[0] = (uint64) >> 56 & 0xFF; \
- (bytes)[1] = (uint64) >> 48 & 0xFF; \
- (bytes)[2] = (uint64) >> 40 & 0xFF; \
- (bytes)[3] = (uint64) >> 32 & 0xFF; \
- (bytes)[4] = (uint64) >> 24 & 0xFF; \
- (bytes)[5] = (uint64) >> 16 & 0xFF; \
- (bytes)[6] = (uint64) >> 8 & 0xFF; \
- (bytes)[7] = (uint64) >> 0 & 0xFF; \
- } while (false)
+#define BYTES_FROM_UINT64(bytes, uint64) \
+ do { \
+ (bytes)[0] = (uint64) >> 56 & 0xFF; \
+ (bytes)[1] = (uint64) >> 48 & 0xFF; \
+ (bytes)[2] = (uint64) >> 40 & 0xFF; \
+ (bytes)[3] = (uint64) >> 32 & 0xFF; \
+ (bytes)[4] = (uint64) >> 24 & 0xFF; \
+ (bytes)[5] = (uint64) >> 16 & 0xFF; \
+ (bytes)[6] = (uint64) >> 8 & 0xFF; \
+ (bytes)[7] = (uint64) >> 0 & 0xFF; \
+ } while (false)
-#define UINT64_FROM_BYTES(bytes) \
- ((uint64_t)(uint8_t)(bytes)[0] << 56 | \
- (uint64_t)(uint8_t)(bytes)[1] << 48 | \
- (uint64_t)(uint8_t)(bytes)[2] << 40 | \
- (uint64_t)(uint8_t)(bytes)[3] << 32 | \
- (uint64_t)(uint8_t)(bytes)[4] << 24 | \
- (uint64_t)(uint8_t)(bytes)[5] << 16 | \
- (uint64_t)(uint8_t)(bytes)[6] << 8 | \
- (uint64_t)(uint8_t)(bytes)[7] << 0)
+#define UINT64_FROM_BYTES(bytes) \
+ ((uint64_t)(uint8_t)(bytes)[0] << 56 | (uint64_t)(uint8_t)(bytes)[1] << 48 \
+ | (uint64_t)(uint8_t)(bytes)[2] << 40 | (uint64_t)(uint8_t)(bytes)[3] << 32 \
+ | (uint64_t)(uint8_t)(bytes)[4] << 24 | (uint64_t)(uint8_t)(bytes)[5] << 16 \
+ | (uint64_t)(uint8_t)(bytes)[6] << 8 | (uint64_t)(uint8_t)(bytes)[7] << 0)
diff --git a/src/language.cpp b/src/language.cpp
index 24b99ff0..4b32f95f 100644
--- a/src/language.cpp
+++ b/src/language.cpp
@@ -16,138 +16,144 @@
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#include "ccache.hpp"
-
#include "language.hpp"
+#include "ccache.hpp"
+
// Supported file extensions and corresponding languages (as in parameter to
// the -x option).
-static const struct {
- const char *extension;
- const char *language;
+//
+// clang-format off
+static const struct
+{
+ const char* extension;
+ const char* language;
} extensions[] = {
- {".c", "c"},
- {".C", "c++"},
- {".cc", "c++"},
- {".CC", "c++"},
- {".cp", "c++"},
- {".CP", "c++"},
- {".cpp", "c++"},
- {".CPP", "c++"},
- {".cxx", "c++"},
- {".CXX", "c++"},
- {".c++", "c++"},
- {".C++", "c++"},
- {".m", "objective-c"},
- {".M", "objective-c++"},
- {".mm", "objective-c++"},
- {".sx", "assembler-with-cpp"},
- {".S", "assembler-with-cpp"},
- // Preprocessed:
- {".i", "cpp-output"},
- {".ii", "c++-cpp-output"},
- {".mi", "objective-c-cpp-output"},
- {".mii", "objective-c++-cpp-output"},
- {".s", "assembler"},
- // Header file (for precompilation):
- {".h", "c-header"},
- {".H", "c++-header"},
- {".h++", "c++-header"},
- {".H++", "c++-header"},
- {".hh", "c++-header"},
- {".HH", "c++-header"},
- {".hp", "c++-header"},
- {".HP", "c++-header"},
- {".hpp", "c++-header"},
- {".HPP", "c++-header"},
- {".hxx", "c++-header"},
- {".HXX", "c++-header"},
- {".tcc", "c++-header"},
- {".TCC", "c++-header"},
- {".cu", "cu"},
- {NULL, NULL}
-};
+ {".c", "c"},
+ {".C", "c++"},
+ {".cc", "c++"},
+ {".CC", "c++"},
+ {".cp", "c++"},
+ {".CP", "c++"},
+ {".cpp", "c++"},
+ {".CPP", "c++"},
+ {".cxx", "c++"},
+ {".CXX", "c++"},
+ {".c++", "c++"},
+ {".C++", "c++"},
+ {".m", "objective-c"},
+ {".M", "objective-c++"},
+ {".mm", "objective-c++"},
+ {".sx", "assembler-with-cpp"},
+ {".S", "assembler-with-cpp"},
+ // Preprocessed:
+ {".i", "cpp-output"},
+ {".ii", "c++-cpp-output"},
+ {".mi", "objective-c-cpp-output"},
+ {".mii", "objective-c++-cpp-output"},
+ {".s", "assembler"},
+ // Header file (for precompilation):
+ {".h", "c-header"},
+ {".H", "c++-header"},
+ {".h++", "c++-header"},
+ {".H++", "c++-header"},
+ {".hh", "c++-header"},
+ {".HH", "c++-header"},
+ {".hp", "c++-header"},
+ {".HP", "c++-header"},
+ {".hpp", "c++-header"},
+ {".HPP", "c++-header"},
+ {".hxx", "c++-header"},
+ {".HXX", "c++-header"},
+ {".tcc", "c++-header"},
+ {".TCC", "c++-header"},
+ {".cu", "cu"},
+ {NULL, NULL}};
+// clang-format on
// Supported languages and corresponding preprocessed languages.
-static const struct {
- const char *language;
- const char *p_language;
+//
+// clang-format off
+static const struct
+{
+ const char* language;
+ const char* p_language;
} languages[] = {
- {"c", "cpp-output"},
- {"cpp-output", "cpp-output"},
- {"c-header", "cpp-output"},
- {"c++", "c++-cpp-output"},
- {"c++-cpp-output", "c++-cpp-output"},
- {"c++-header", "c++-cpp-output"},
- {"cu", "cpp-output"},
- {"objective-c", "objective-c-cpp-output"},
- {"objective-c-header", "objective-c-cpp-output"},
- {"objc-cpp-output", "objective-c-cpp-output"},
- {"objective-c-cpp-output", "objective-c-cpp-output"},
- {"objective-c++", "objective-c++-cpp-output"},
- {"objc++-cpp-output", "objective-c++-cpp-output"},
- {"objective-c++-header", "objective-c++-cpp-output"},
- {"objective-c++-cpp-output", "objective-c++-cpp-output"},
- {"assembler-with-cpp", "assembler"},
- {"assembler", "assembler"},
- {NULL, NULL}
-};
+ {"c", "cpp-output"},
+ {"cpp-output", "cpp-output"},
+ {"c-header", "cpp-output"},
+ {"c++", "c++-cpp-output"},
+ {"c++-cpp-output", "c++-cpp-output"},
+ {"c++-header", "c++-cpp-output"},
+ {"cu", "cpp-output"},
+ {"objective-c", "objective-c-cpp-output"},
+ {"objective-c-header", "objective-c-cpp-output"},
+ {"objc-cpp-output", "objective-c-cpp-output"},
+ {"objective-c-cpp-output", "objective-c-cpp-output"},
+ {"objective-c++", "objective-c++-cpp-output"},
+ {"objc++-cpp-output", "objective-c++-cpp-output"},
+ {"objective-c++-header", "objective-c++-cpp-output"},
+ {"objective-c++-cpp-output", "objective-c++-cpp-output"},
+ {"assembler-with-cpp", "assembler"},
+ {"assembler", "assembler"},
+ {NULL, NULL}};
+// clang-format on
// Guess the language of a file based on its extension. Returns NULL if the
// extension is unknown.
-const char *
-language_for_file(const char *fname)
+const char*
+language_for_file(const char* fname)
{
- const char *p = get_extension(fname);
- for (int i = 0; extensions[i].extension; i++) {
- if (str_eq(p, extensions[i].extension)) {
- return extensions[i].language;
- }
- }
- return NULL;
+ const char* p = get_extension(fname);
+ for (int i = 0; extensions[i].extension; i++) {
+ if (str_eq(p, extensions[i].extension)) {
+ return extensions[i].language;
+ }
+ }
+ return NULL;
}
// Return the preprocessed language for a given language, or NULL if unknown.
-const char *
-p_language_for_language(const char *language)
+const char*
+p_language_for_language(const char* language)
{
- if (!language) {
- return NULL;
- }
- for (int i = 0; languages[i].language; ++i) {
- if (str_eq(language, languages[i].language)) {
- return languages[i].p_language;
- }
- }
- return NULL;
+ if (!language) {
+ return NULL;
+ }
+ for (int i = 0; languages[i].language; ++i) {
+ if (str_eq(language, languages[i].language)) {
+ return languages[i].p_language;
+ }
+ }
+ return NULL;
}
// Return the default file extension (including dot) for a language, or NULL if
// unknown.
-const char *
-extension_for_language(const char *language)
+const char*
+extension_for_language(const char* language)
{
- if (!language) {
- return NULL;
- }
- for (int i = 0; extensions[i].extension; i++) {
- if (str_eq(language, extensions[i].language)) {
- return extensions[i].extension;
- }
- }
- return NULL;
+ if (!language) {
+ return NULL;
+ }
+ for (int i = 0; extensions[i].extension; i++) {
+ if (str_eq(language, extensions[i].language)) {
+ return extensions[i].extension;
+ }
+ }
+ return NULL;
}
bool
-language_is_supported(const char *language)
+language_is_supported(const char* language)
{
- return p_language_for_language(language) != NULL;
+ return p_language_for_language(language) != NULL;
}
bool
-language_is_preprocessed(const char *language)
+language_is_preprocessed(const char* language)
{
- const char *p_language = p_language_for_language(language);
- assert(p_language);
- return str_eq(language, p_language);
+ const char* p_language = p_language_for_language(language);
+ assert(p_language);
+ return str_eq(language, p_language);
}
diff --git a/src/language.hpp b/src/language.hpp
index f119ece8..481d608d 100644
--- a/src/language.hpp
+++ b/src/language.hpp
@@ -20,8 +20,8 @@
#include <stdbool.h>
-const char *language_for_file(const char *fname);
-const char *p_language_for_language(const char *language);
-const char *extension_for_language(const char *language);
-bool language_is_supported(const char *language);
-bool language_is_preprocessed(const char *language);
+const char* language_for_file(const char* fname);
+const char* p_language_for_language(const char* language);
+const char* extension_for_language(const char* language);
+bool language_is_supported(const char* language);
+bool language_is_preprocessed(const char* language);
diff --git a/src/lockfile.cpp b/src/lockfile.cpp
index d904b190..c717d091 100644
--- a/src/lockfile.cpp
+++ b/src/lockfile.cpp
@@ -27,189 +27,190 @@
// probably be made with an atomic rename(2) to avoid corruption in the rare
// case that the lock is broken by another process.
bool
-lockfile_acquire(const char *path, unsigned staleness_limit)
+lockfile_acquire(const char* path, unsigned staleness_limit)
{
- char *lockfile = format("%s.lock", path);
- char *my_content = NULL;
- char *content = NULL;
- char *initial_content = NULL;
- const char *hostname = get_hostname();
- bool acquired = false;
- unsigned to_sleep = 1000; // Microseconds.
- unsigned slept = 0; // Microseconds.
+ char* lockfile = format("%s.lock", path);
+ char* my_content = NULL;
+ char* content = NULL;
+ char* initial_content = NULL;
+ const char* hostname = get_hostname();
+ bool acquired = false;
+ unsigned to_sleep = 1000; // Microseconds.
+ unsigned slept = 0; // Microseconds.
- while (true) {
- free(my_content);
- my_content = format("%s:%d:%d", hostname, (int)getpid(), (int)time(NULL));
+ while (true) {
+ free(my_content);
+ my_content = format("%s:%d:%d", hostname, (int)getpid(), (int)time(NULL));
#if defined(_WIN32) || defined(__CYGWIN__)
- int fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0666);
- if (fd == -1) {
- int saved_errno = errno;
- cc_log("lockfile_acquire: open WRONLY %s: %s", lockfile, strerror(errno));
- if (saved_errno == ENOENT) {
- // Directory doesn't exist?
- if (create_parent_dirs(lockfile) == 0) {
- // OK. Retry.
- continue;
- }
- }
- if (saved_errno != EEXIST) {
- // Directory doesn't exist or isn't writable?
- goto out;
- }
- // Someone else has the lock.
- fd = open(lockfile, O_RDONLY|O_BINARY);
- if (fd == -1) {
- if (errno == ENOENT) {
- // The file was removed after the open() call above, so retry
- // acquiring it.
- continue;
- } else {
- cc_log("lockfile_acquire: open RDONLY %s: %s",
- lockfile, strerror(errno));
- goto out;
- }
- }
- free(content);
- const size_t bufsize = 1024;
- content = static_cast<char*>(x_malloc(bufsize));
- int len = read(fd, content, bufsize - 1);
- if (len == -1) {
- cc_log("lockfile_acquire: read %s: %s", lockfile, strerror(errno));
- close(fd);
- goto out;
- }
- close(fd);
- content[len] = '\0';
- } else {
- // We got the lock.
- if (write(fd, my_content, strlen(my_content)) == -1) {
- cc_log("lockfile_acquire: write %s: %s", lockfile, strerror(errno));
- close(fd);
- x_unlink(lockfile);
- goto out;
- }
- close(fd);
- acquired = true;
- goto out;
- }
+ int fd = open(lockfile, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0666);
+ if (fd == -1) {
+ int saved_errno = errno;
+ cc_log("lockfile_acquire: open WRONLY %s: %s", lockfile, strerror(errno));
+ if (saved_errno == ENOENT) {
+ // Directory doesn't exist?
+ if (create_parent_dirs(lockfile) == 0) {
+ // OK. Retry.
+ continue;
+ }
+ }
+ if (saved_errno != EEXIST) {
+ // Directory doesn't exist or isn't writable?
+ goto out;
+ }
+ // Someone else has the lock.
+ fd = open(lockfile, O_RDONLY | O_BINARY);
+ if (fd == -1) {
+ if (errno == ENOENT) {
+ // The file was removed after the open() call above, so retry
+ // acquiring it.
+ continue;
+ } else {
+ cc_log(
+ "lockfile_acquire: open RDONLY %s: %s", lockfile, strerror(errno));
+ goto out;
+ }
+ }
+ free(content);
+ const size_t bufsize = 1024;
+ content = static_cast<char*>(x_malloc(bufsize));
+ int len = read(fd, content, bufsize - 1);
+ if (len == -1) {
+ cc_log("lockfile_acquire: read %s: %s", lockfile, strerror(errno));
+ close(fd);
+ goto out;
+ }
+ close(fd);
+ content[len] = '\0';
+ } else {
+ // We got the lock.
+ if (write(fd, my_content, strlen(my_content)) == -1) {
+ cc_log("lockfile_acquire: write %s: %s", lockfile, strerror(errno));
+ close(fd);
+ x_unlink(lockfile);
+ goto out;
+ }
+ close(fd);
+ acquired = true;
+ goto out;
+ }
#else
- if (symlink(my_content, lockfile) == 0) {
- // We got the lock.
- acquired = true;
- goto out;
- }
- int saved_errno = errno;
- cc_log("lockfile_acquire: symlink %s: %s", lockfile, strerror(saved_errno));
- if (saved_errno == ENOENT) {
- // Directory doesn't exist?
- if (create_parent_dirs(lockfile) == 0) {
- // OK. Retry.
- continue;
- }
- }
- if (saved_errno == EPERM) {
- // The file system does not support symbolic links. We have no choice but
- // to grant the lock anyway.
- acquired = true;
- goto out;
- }
- if (saved_errno != EEXIST) {
- // Directory doesn't exist or isn't writable?
- goto out;
- }
- free(content);
- content = x_readlink(lockfile);
- if (!content) {
- if (errno == ENOENT) {
- // The symlink was removed after the symlink() call above, so retry
- // acquiring it.
- continue;
- } else {
- cc_log("lockfile_acquire: readlink %s: %s", lockfile, strerror(errno));
- goto out;
- }
- }
+ if (symlink(my_content, lockfile) == 0) {
+ // We got the lock.
+ acquired = true;
+ goto out;
+ }
+ int saved_errno = errno;
+ cc_log("lockfile_acquire: symlink %s: %s", lockfile, strerror(saved_errno));
+ if (saved_errno == ENOENT) {
+ // Directory doesn't exist?
+ if (create_parent_dirs(lockfile) == 0) {
+ // OK. Retry.
+ continue;
+ }
+ }
+ if (saved_errno == EPERM) {
+ // The file system does not support symbolic links. We have no choice but
+ // to grant the lock anyway.
+ acquired = true;
+ goto out;
+ }
+ if (saved_errno != EEXIST) {
+ // Directory doesn't exist or isn't writable?
+ goto out;
+ }
+ free(content);
+ content = x_readlink(lockfile);
+ if (!content) {
+ if (errno == ENOENT) {
+ // The symlink was removed after the symlink() call above, so retry
+ // acquiring it.
+ continue;
+ } else {
+ cc_log("lockfile_acquire: readlink %s: %s", lockfile, strerror(errno));
+ goto out;
+ }
+ }
#endif
- if (str_eq(content, my_content)) {
- // Lost NFS reply?
- cc_log("lockfile_acquire: symlink %s failed but we got the lock anyway",
- lockfile);
- acquired = true;
- goto out;
- }
- // A possible improvement here would be to check if the process holding the
- // lock is still alive and break the lock early if it isn't.
- cc_log("lockfile_acquire: lock info for %s: %s", lockfile, content);
- if (!initial_content) {
- initial_content = x_strdup(content);
- }
- if (slept > staleness_limit) {
- if (str_eq(content, initial_content)) {
- // The lock seems to be stale -- break it.
- cc_log("lockfile_acquire: breaking %s", lockfile);
- // Try to acquire path.lock.lock:
- if (lockfile_acquire(lockfile, staleness_limit)) {
- lockfile_release(path); // Remove path.lock
- lockfile_release(lockfile); // Remove path.lock.lock
- to_sleep = 1000;
- slept = 0;
- continue;
- }
- }
- cc_log("lockfile_acquire: gave up acquiring %s", lockfile);
- goto out;
- }
- cc_log("lockfile_acquire: failed to acquire %s; sleeping %u microseconds",
- lockfile, to_sleep);
- usleep(to_sleep);
- slept += to_sleep;
- to_sleep *= 2;
- }
+ if (str_eq(content, my_content)) {
+ // Lost NFS reply?
+ cc_log("lockfile_acquire: symlink %s failed but we got the lock anyway",
+ lockfile);
+ acquired = true;
+ goto out;
+ }
+ // A possible improvement here would be to check if the process holding the
+ // lock is still alive and break the lock early if it isn't.
+ cc_log("lockfile_acquire: lock info for %s: %s", lockfile, content);
+ if (!initial_content) {
+ initial_content = x_strdup(content);
+ }
+ if (slept > staleness_limit) {
+ if (str_eq(content, initial_content)) {
+ // The lock seems to be stale -- break it.
+ cc_log("lockfile_acquire: breaking %s", lockfile);
+ // Try to acquire path.lock.lock:
+ if (lockfile_acquire(lockfile, staleness_limit)) {
+ lockfile_release(path); // Remove path.lock
+ lockfile_release(lockfile); // Remove path.lock.lock
+ to_sleep = 1000;
+ slept = 0;
+ continue;
+ }
+ }
+ cc_log("lockfile_acquire: gave up acquiring %s", lockfile);
+ goto out;
+ }
+ cc_log("lockfile_acquire: failed to acquire %s; sleeping %u microseconds",
+ lockfile,
+ to_sleep);
+ usleep(to_sleep);
+ slept += to_sleep;
+ to_sleep *= 2;
+ }
out:
- if (acquired) {
- cc_log("Acquired lock %s", lockfile);
- } else {
- cc_log("Failed to acquire lock %s", lockfile);
- }
- free(lockfile);
- free(my_content);
- free(initial_content);
- free(content);
- return acquired;
+ if (acquired) {
+ cc_log("Acquired lock %s", lockfile);
+ } else {
+ cc_log("Failed to acquire lock %s", lockfile);
+ }
+ free(lockfile);
+ free(my_content);
+ free(initial_content);
+ free(content);
+ return acquired;
}
// Release the lockfile for the given path. Assumes that we are the legitimate
// owner.
void
-lockfile_release(const char *path)
+lockfile_release(const char* path)
{
- char *lockfile = format("%s.lock", path);
- cc_log("Releasing lock %s", lockfile);
- tmp_unlink(lockfile);
- free(lockfile);
+ char* lockfile = format("%s.lock", path);
+ cc_log("Releasing lock %s", lockfile);
+ tmp_unlink(lockfile);
+ free(lockfile);
}
#ifdef TEST_LOCKFILE
int
-main(int argc, char **argv)
+main(int argc, char** argv)
{
- extern char *cache_logfile;
- cache_logfile = "/dev/stdout";
- if (argc == 4) {
- unsigned staleness_limit = atoi(argv[1]);
- if (str_eq(argv[2], "acquire")) {
- return lockfile_acquire(argv[3], staleness_limit) == 0;
- } else if (str_eq(argv[2], "release")) {
- lockfile_release(argv[3]);
- return 0;
- }
- }
- fprintf(stderr,
- "Usage: testlockfile <staleness_limit> <acquire|release> <path>\n");
- return 1;
+ extern char* cache_logfile;
+ cache_logfile = "/dev/stdout";
+ if (argc == 4) {
+ unsigned staleness_limit = atoi(argv[1]);
+ if (str_eq(argv[2], "acquire")) {
+ return lockfile_acquire(argv[3], staleness_limit) == 0;
+ } else if (str_eq(argv[2], "release")) {
+ lockfile_release(argv[3]);
+ return 0;
+ }
+ }
+ fprintf(stderr,
+ "Usage: testlockfile <staleness_limit> <acquire|release> <path>\n");
+ return 1;
}
#endif
diff --git a/src/macroskip.hpp b/src/macroskip.hpp
index 52a06b14..d8dfc528 100644
--- a/src/macroskip.hpp
+++ b/src/macroskip.hpp
@@ -57,20 +57,14 @@
// print ""
static const uint32_t macro_skip[] = {
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 4, 8, 8, 5, 2, 8, 8, 8, 4, 8, 8, 8, 3, 8, 8,
- 8, 8, 8, 8, 3, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 8, 8, 5, 2, 8, 8, 8, 4, 8, 8, 8, 3,
+ 8, 8, 8, 8, 8, 8, 3, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
};
diff --git a/src/manifest.cpp b/src/manifest.cpp
index 788f313f..623ade18 100644
--- a/src/manifest.cpp
+++ b/src/manifest.cpp
@@ -16,13 +16,15 @@
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#include "manifest.hpp"
+
#include "ccache.hpp"
-#include "third_party/hashtable_itr.h"
-#include "hashutil.hpp"
#include "common_header.hpp"
#include "compression.hpp"
+#include "hashutil.hpp"
#include "int_bytes_conversion.hpp"
-#include "manifest.hpp"
+
+#include "third_party/hashtable_itr.h"
#include "third_party/xxhash.h"
// Manifest data format
@@ -104,731 +106,737 @@ const char MANIFEST_MAGIC[4] = {'c', 'C', 'm', 'F'};
static const uint32_t MAX_MANIFEST_ENTRIES = 100;
static const uint32_t MAX_MANIFEST_FILE_INFO_ENTRIES = 10000;
-#define ccache_static_assert(e) \
- do { enum { ccache_static_assert__ = 1/(e) }; } while (false)
+#define ccache_static_assert(e) \
+ do { \
+ enum { ccache_static_assert__ = 1 / (e) }; \
+ } while (false)
-struct file {
- uint16_t path_len; // strlen(path)
- char *path; // NUL-terminated
+struct file
+{
+ uint16_t path_len; // strlen(path)
+ char* path; // NUL-terminated
};
-struct file_info {
- // Index to n_files.
- uint32_t index;
- // Digest of referenced file.
- struct digest digest;
- // Size of referenced file.
- uint64_t fsize;
- // mtime of referenced file.
- int64_t mtime;
- // ctime of referenced file.
- int64_t ctime;
+struct file_info
+{
+ // Index to n_files.
+ uint32_t index;
+ // Digest of referenced file.
+ struct digest digest;
+ // Size of referenced file.
+ uint64_t fsize;
+ // mtime of referenced file.
+ int64_t mtime;
+ // ctime of referenced file.
+ int64_t ctime;
};
-struct result {
- // Number of entries in file_info_indexes.
- uint32_t n_file_info_indexes;
- // Indexes to file_infos.
- uint32_t *file_info_indexes;
- // Name of the result.
- struct digest name;
+struct result
+{
+ // Number of entries in file_info_indexes.
+ uint32_t n_file_info_indexes;
+ // Indexes to file_infos.
+ uint32_t* file_info_indexes;
+ // Name of the result.
+ struct digest name;
};
-struct manifest {
- struct common_header header;
+struct manifest
+{
+ struct common_header header;
- // Referenced include files.
- uint32_t n_files;
- struct file *files;
+ // Referenced include files.
+ uint32_t n_files;
+ struct file* files;
- // Information about referenced include files.
- uint32_t n_file_infos;
- struct file_info *file_infos;
+ // Information about referenced include files.
+ uint32_t n_file_infos;
+ struct file_info* file_infos;
- // Result names plus references to include file infos.
- uint32_t n_results;
- struct result *results;
+ // Result names plus references to include file infos.
+ uint32_t n_results;
+ struct result* results;
};
-struct file_stats {
- uint64_t size;
- int64_t mtime;
- int64_t ctime;
+struct file_stats
+{
+ uint64_t size;
+ int64_t mtime;
+ int64_t ctime;
};
static unsigned int
-hash_from_file_info(void *key)
+hash_from_file_info(void* key)
{
- ccache_static_assert(sizeof(struct file_info) == 48); // No padding.
- return XXH64(key, sizeof(struct file_info), 0);
+ ccache_static_assert(sizeof(struct file_info) == 48); // No padding.
+ return XXH64(key, sizeof(struct file_info), 0);
}
static int
-file_infos_equal(void *key1, void *key2)
+file_infos_equal(void* key1, void* key2)
{
- struct file_info *fi1 = (struct file_info *)key1;
- struct file_info *fi2 = (struct file_info *)key2;
- return fi1->index == fi2->index
- && digests_equal(&fi1->digest, &fi2->digest)
- && fi1->fsize == fi2->fsize
- && fi1->mtime == fi2->mtime
- && fi1->ctime == fi2->ctime;
+ struct file_info* fi1 = (struct file_info*)key1;
+ struct file_info* fi2 = (struct file_info*)key2;
+ return fi1->index == fi2->index && digests_equal(&fi1->digest, &fi2->digest)
+ && fi1->fsize == fi2->fsize && fi1->mtime == fi2->mtime
+ && fi1->ctime == fi2->ctime;
}
static void
-free_manifest(struct manifest *mf)
+free_manifest(struct manifest* mf)
{
- for (uint32_t i = 0; i < mf->n_files; i++) {
- free(mf->files[i].path);
- }
- free(mf->files);
- free(mf->file_infos);
- for (uint32_t i = 0; i < mf->n_results; i++) {
- free(mf->results[i].file_info_indexes);
- }
- free(mf->results);
- free(mf);
+ for (uint32_t i = 0; i < mf->n_files; i++) {
+ free(mf->files[i].path);
+ }
+ free(mf->files);
+ free(mf->file_infos);
+ for (uint32_t i = 0; i < mf->n_results; i++) {
+ free(mf->results[i].file_info_indexes);
+ }
+ free(mf->results);
+ free(mf);
}
-#define READ_BYTES(buf, length) \
- do { \
- if (!decompressor->read(decompr_state, buf, length)) { \
- goto out; \
- } \
- } while (false)
-
-#define READ_UINT16(var) \
- do { \
- char buf_[2]; \
- READ_BYTES(buf_, sizeof(buf_)); \
- (var) = UINT16_FROM_BYTES(buf_); \
- } while (false)
-
-#define READ_UINT32(var) \
- do { \
- char buf_[4]; \
- READ_BYTES(buf_, sizeof(buf_)); \
- (var) = UINT32_FROM_BYTES(buf_); \
- } while (false)
-
-#define READ_INT64(var) \
- do { \
- char buf_[8]; \
- READ_BYTES(buf_, sizeof(buf_)); \
- (var) = INT64_FROM_BYTES(buf_); \
- } while (false)
-
-#define READ_UINT64(var) \
- do { \
- char buf_[8]; \
- READ_BYTES(buf_, sizeof(buf_)); \
- (var) = UINT64_FROM_BYTES(buf_); \
- } while (false)
-
-#define READ_STR(str_var, len_var) \
- do { \
- READ_UINT16(len_var); \
- (str_var) = static_cast<char*>(x_malloc(len_var + 1)); \
- READ_BYTES(str_var, len_var); \
- str_var[len_var] = '\0'; \
- } while (false)
-
-static struct manifest *
+#define READ_BYTES(buf, length) \
+ do { \
+ if (!decompressor->read(decompr_state, buf, length)) { \
+ goto out; \
+ } \
+ } while (false)
+
+#define READ_UINT16(var) \
+ do { \
+ char buf_[2]; \
+ READ_BYTES(buf_, sizeof(buf_)); \
+ (var) = UINT16_FROM_BYTES(buf_); \
+ } while (false)
+
+#define READ_UINT32(var) \
+ do { \
+ char buf_[4]; \
+ READ_BYTES(buf_, sizeof(buf_)); \
+ (var) = UINT32_FROM_BYTES(buf_); \
+ } while (false)
+
+#define READ_INT64(var) \
+ do { \
+ char buf_[8]; \
+ READ_BYTES(buf_, sizeof(buf_)); \
+ (var) = INT64_FROM_BYTES(buf_); \
+ } while (false)
+
+#define READ_UINT64(var) \
+ do { \
+ char buf_[8]; \
+ READ_BYTES(buf_, sizeof(buf_)); \
+ (var) = UINT64_FROM_BYTES(buf_); \
+ } while (false)
+
+#define READ_STR(str_var, len_var) \
+ do { \
+ READ_UINT16(len_var); \
+ (str_var) = static_cast<char*>(x_malloc(len_var + 1)); \
+ READ_BYTES(str_var, len_var); \
+ str_var[len_var] = '\0'; \
+ } while (false)
+
+static struct manifest*
create_empty_manifest(void)
{
- auto mf = static_cast<manifest*>(x_malloc(sizeof(manifest)));
- mf->n_files = 0;
- mf->files = NULL;
- mf->n_file_infos = 0;
- mf->file_infos = NULL;
- mf->n_results = 0;
- mf->results = NULL;
-
- return mf;
+ auto mf = static_cast<manifest*>(x_malloc(sizeof(manifest)));
+ mf->n_files = 0;
+ mf->files = NULL;
+ mf->n_file_infos = 0;
+ mf->file_infos = NULL;
+ mf->n_results = 0;
+ mf->results = NULL;
+
+ return mf;
}
-static struct manifest *
-read_manifest(const char *path, char **errmsg)
+static struct manifest*
+read_manifest(const char* path, char** errmsg)
{
- bool success = false;
- struct manifest *mf = create_empty_manifest();
- struct decompressor *decompressor = NULL;
- struct decompr_state *decompr_state = NULL;
- *errmsg = NULL;
- XXH64_state_t *checksum = XXH64_createState();
- uint64_t actual_checksum;
- uint64_t expected_checksum;
-
- FILE *f = fopen(path, "rb");
- if (!f) {
- *errmsg = x_strdup("No such manifest file");
- goto out;
- }
-
- if (!common_header_initialize_for_reading(
- &mf->header,
- f,
- MANIFEST_MAGIC,
- MANIFEST_VERSION,
- &decompressor,
- &decompr_state,
- checksum,
- errmsg)) {
- goto out;
- }
-
- READ_UINT32(mf->n_files);
- mf->files = static_cast<file*>(x_calloc(mf->n_files, sizeof(file)));
- for (uint32_t i = 0; i < mf->n_files; i++) {
- READ_STR(mf->files[i].path, mf->files[i].path_len);
- }
-
- READ_UINT32(mf->n_file_infos);
- mf->file_infos =
- static_cast<file_info*>(x_calloc(mf->n_file_infos, sizeof(file_info)));
- for (uint32_t i = 0; i < mf->n_file_infos; i++) {
- READ_UINT32(mf->file_infos[i].index);
- READ_BYTES(mf->file_infos[i].digest.bytes, DIGEST_SIZE);
- READ_UINT64(mf->file_infos[i].fsize);
- READ_INT64(mf->file_infos[i].mtime);
- READ_INT64(mf->file_infos[i].ctime);
- }
-
- READ_UINT32(mf->n_results);
- mf->results = static_cast<result*>(x_calloc(mf->n_results, sizeof(result)));
- for (uint32_t i = 0; i < mf->n_results; i++) {
- READ_UINT32(mf->results[i].n_file_info_indexes);
- mf->results[i].file_info_indexes = static_cast<uint32_t*>(
- x_calloc(mf->results[i].n_file_info_indexes, sizeof(uint32_t)));
- for (uint32_t j = 0; j < mf->results[i].n_file_info_indexes; j++) {
- READ_UINT32(mf->results[i].file_info_indexes[j]);
- }
- READ_BYTES(mf->results[i].name.bytes, DIGEST_SIZE);
- }
-
- actual_checksum = XXH64_digest(checksum);
- READ_UINT64(expected_checksum);
- if (actual_checksum == expected_checksum) {
- success = true;
- } else {
- *errmsg = format(
- "Incorrect checksum (actual %016llx, expected %016llx)",
- (unsigned long long)actual_checksum,
- (unsigned long long)expected_checksum);
- }
+ bool success = false;
+ struct manifest* mf = create_empty_manifest();
+ struct decompressor* decompressor = NULL;
+ struct decompr_state* decompr_state = NULL;
+ *errmsg = NULL;
+ XXH64_state_t* checksum = XXH64_createState();
+ uint64_t actual_checksum;
+ uint64_t expected_checksum;
+
+ FILE* f = fopen(path, "rb");
+ if (!f) {
+ *errmsg = x_strdup("No such manifest file");
+ goto out;
+ }
+
+ if (!common_header_initialize_for_reading(&mf->header,
+ f,
+ MANIFEST_MAGIC,
+ MANIFEST_VERSION,
+ &decompressor,
+ &decompr_state,
+ checksum,
+ errmsg)) {
+ goto out;
+ }
+
+ READ_UINT32(mf->n_files);
+ mf->files = static_cast<file*>(x_calloc(mf->n_files, sizeof(file)));
+ for (uint32_t i = 0; i < mf->n_files; i++) {
+ READ_STR(mf->files[i].path, mf->files[i].path_len);
+ }
+
+ READ_UINT32(mf->n_file_infos);
+ mf->file_infos =
+ static_cast<file_info*>(x_calloc(mf->n_file_infos, sizeof(file_info)));
+ for (uint32_t i = 0; i < mf->n_file_infos; i++) {
+ READ_UINT32(mf->file_infos[i].index);
+ READ_BYTES(mf->file_infos[i].digest.bytes, DIGEST_SIZE);
+ READ_UINT64(mf->file_infos[i].fsize);
+ READ_INT64(mf->file_infos[i].mtime);
+ READ_INT64(mf->file_infos[i].ctime);
+ }
+
+ READ_UINT32(mf->n_results);
+ mf->results = static_cast<result*>(x_calloc(mf->n_results, sizeof(result)));
+ for (uint32_t i = 0; i < mf->n_results; i++) {
+ READ_UINT32(mf->results[i].n_file_info_indexes);
+ mf->results[i].file_info_indexes = static_cast<uint32_t*>(
+ x_calloc(mf->results[i].n_file_info_indexes, sizeof(uint32_t)));
+ for (uint32_t j = 0; j < mf->results[i].n_file_info_indexes; j++) {
+ READ_UINT32(mf->results[i].file_info_indexes[j]);
+ }
+ READ_BYTES(mf->results[i].name.bytes, DIGEST_SIZE);
+ }
+
+ actual_checksum = XXH64_digest(checksum);
+ READ_UINT64(expected_checksum);
+ if (actual_checksum == expected_checksum) {
+ success = true;
+ } else {
+ *errmsg = format("Incorrect checksum (actual %016llx, expected %016llx)",
+ (unsigned long long)actual_checksum,
+ (unsigned long long)expected_checksum);
+ }
out:
- if (decompressor && !decompressor->free(decompr_state)) {
- success = false;
- }
- if (f) {
- fclose(f);
- }
- if (checksum) {
- XXH64_freeState(checksum);
- }
- if (!success) {
- if (!*errmsg) {
- *errmsg = x_strdup("Corrupt manifest file");
- }
- free_manifest(mf);
- mf = NULL;
- }
- return mf;
+ if (decompressor && !decompressor->free(decompr_state)) {
+ success = false;
+ }
+ if (f) {
+ fclose(f);
+ }
+ if (checksum) {
+ XXH64_freeState(checksum);
+ }
+ if (!success) {
+ if (!*errmsg) {
+ *errmsg = x_strdup("Corrupt manifest file");
+ }
+ free_manifest(mf);
+ mf = NULL;
+ }
+ return mf;
}
-#define WRITE_BYTES(buf, length) \
- do { \
- if (!compressor->write(compr_state, buf, length)) { \
- goto out; \
- } \
- } while (false)
-
-#define WRITE_UINT16(var) \
- do { \
- char buf_[2]; \
- BYTES_FROM_UINT16(buf_, (var)); \
- WRITE_BYTES(buf_, sizeof(buf_)); \
- } while (false)
-
-#define WRITE_UINT32(var) \
- do { \
- char buf_[4]; \
- BYTES_FROM_UINT32(buf_, (var)); \
- WRITE_BYTES(buf_, sizeof(buf_)); \
- } while (false)
-
-#define WRITE_INT64(var) \
- do { \
- char buf_[8]; \
- BYTES_FROM_INT64(buf_, (var)); \
- WRITE_BYTES(buf_, sizeof(buf_)); \
- } while (false)
-
-#define WRITE_UINT64(var) \
- do { \
- char buf_[8]; \
- BYTES_FROM_UINT64(buf_, (var)); \
- WRITE_BYTES(buf_, sizeof(buf_)); \
- } while (false)
+#define WRITE_BYTES(buf, length) \
+ do { \
+ if (!compressor->write(compr_state, buf, length)) { \
+ goto out; \
+ } \
+ } while (false)
+
+#define WRITE_UINT16(var) \
+ do { \
+ char buf_[2]; \
+ BYTES_FROM_UINT16(buf_, (var)); \
+ WRITE_BYTES(buf_, sizeof(buf_)); \
+ } while (false)
+
+#define WRITE_UINT32(var) \
+ do { \
+ char buf_[4]; \
+ BYTES_FROM_UINT32(buf_, (var)); \
+ WRITE_BYTES(buf_, sizeof(buf_)); \
+ } while (false)
+
+#define WRITE_INT64(var) \
+ do { \
+ char buf_[8]; \
+ BYTES_FROM_INT64(buf_, (var)); \
+ WRITE_BYTES(buf_, sizeof(buf_)); \
+ } while (false)
+
+#define WRITE_UINT64(var) \
+ do { \
+ char buf_[8]; \
+ BYTES_FROM_UINT64(buf_, (var)); \
+ WRITE_BYTES(buf_, sizeof(buf_)); \
+ } while (false)
static bool
-write_manifest(FILE *f, const struct manifest *mf)
+write_manifest(FILE* f, const struct manifest* mf)
{
- int ret = false;
- XXH64_state_t *checksum = XXH64_createState();
-
- uint64_t content_size = COMMON_HEADER_SIZE;
- content_size += 4; // n_files
- for (size_t i = 0; i < mf->n_files; i++) {
- content_size += 2 + mf->files[i].path_len;
- }
- content_size += 4; // n_file_infos
- content_size += mf->n_file_infos * (4 + DIGEST_SIZE + 8 + 8 + 8);
- content_size += 4; // n_results
- for (size_t i = 0; i < mf->n_results; i++) {
- content_size += 4; // n_file_info_indexes
- content_size += mf->results[i].n_file_info_indexes * 4;
- content_size += DIGEST_SIZE;
- }
- content_size += 8; // checksum
-
- struct common_header header;
- struct compressor *compressor;
- struct compr_state *compr_state;
- if (!common_header_initialize_for_writing(
- &header,
- f,
- MANIFEST_MAGIC,
- MANIFEST_VERSION,
- compression_type_from_config(),
- compression_level_from_config(),
- content_size,
- checksum,
- &compressor,
- &compr_state)) {
- goto out;
- }
-
- WRITE_UINT32(mf->n_files);
- for (uint32_t i = 0; i < mf->n_files; i++) {
- WRITE_UINT16(mf->files[i].path_len);
- WRITE_BYTES(mf->files[i].path, mf->files[i].path_len);
- }
-
- WRITE_UINT32(mf->n_file_infos);
- for (uint32_t i = 0; i < mf->n_file_infos; i++) {
- WRITE_UINT32(mf->file_infos[i].index);
- WRITE_BYTES(mf->file_infos[i].digest.bytes, DIGEST_SIZE);
- WRITE_UINT64(mf->file_infos[i].fsize);
- WRITE_INT64(mf->file_infos[i].mtime);
- WRITE_INT64(mf->file_infos[i].ctime);
- }
-
- WRITE_UINT32(mf->n_results);
- for (uint32_t i = 0; i < mf->n_results; i++) {
- WRITE_UINT32(mf->results[i].n_file_info_indexes);
- for (uint32_t j = 0; j < mf->results[i].n_file_info_indexes; j++) {
- WRITE_UINT32(mf->results[i].file_info_indexes[j]);
- }
- WRITE_BYTES(mf->results[i].name.bytes, DIGEST_SIZE);
- }
-
- WRITE_UINT64(XXH64_digest(checksum));
-
- ret = compressor->free(compr_state);
+ int ret = false;
+ XXH64_state_t* checksum = XXH64_createState();
+
+ uint64_t content_size = COMMON_HEADER_SIZE;
+ content_size += 4; // n_files
+ for (size_t i = 0; i < mf->n_files; i++) {
+ content_size += 2 + mf->files[i].path_len;
+ }
+ content_size += 4; // n_file_infos
+ content_size += mf->n_file_infos * (4 + DIGEST_SIZE + 8 + 8 + 8);
+ content_size += 4; // n_results
+ for (size_t i = 0; i < mf->n_results; i++) {
+ content_size += 4; // n_file_info_indexes
+ content_size += mf->results[i].n_file_info_indexes * 4;
+ content_size += DIGEST_SIZE;
+ }
+ content_size += 8; // checksum
+
+ struct common_header header;
+ struct compressor* compressor;
+ struct compr_state* compr_state;
+ if (!common_header_initialize_for_writing(&header,
+ f,
+ MANIFEST_MAGIC,
+ MANIFEST_VERSION,
+ compression_type_from_config(),
+ compression_level_from_config(),
+ content_size,
+ checksum,
+ &compressor,
+ &compr_state)) {
+ goto out;
+ }
+
+ WRITE_UINT32(mf->n_files);
+ for (uint32_t i = 0; i < mf->n_files; i++) {
+ WRITE_UINT16(mf->files[i].path_len);
+ WRITE_BYTES(mf->files[i].path, mf->files[i].path_len);
+ }
+
+ WRITE_UINT32(mf->n_file_infos);
+ for (uint32_t i = 0; i < mf->n_file_infos; i++) {
+ WRITE_UINT32(mf->file_infos[i].index);
+ WRITE_BYTES(mf->file_infos[i].digest.bytes, DIGEST_SIZE);
+ WRITE_UINT64(mf->file_infos[i].fsize);
+ WRITE_INT64(mf->file_infos[i].mtime);
+ WRITE_INT64(mf->file_infos[i].ctime);
+ }
+
+ WRITE_UINT32(mf->n_results);
+ for (uint32_t i = 0; i < mf->n_results; i++) {
+ WRITE_UINT32(mf->results[i].n_file_info_indexes);
+ for (uint32_t j = 0; j < mf->results[i].n_file_info_indexes; j++) {
+ WRITE_UINT32(mf->results[i].file_info_indexes[j]);
+ }
+ WRITE_BYTES(mf->results[i].name.bytes, DIGEST_SIZE);
+ }
+
+ WRITE_UINT64(XXH64_digest(checksum));
+
+ ret = compressor->free(compr_state);
out:
- XXH64_freeState(checksum);
- if (!ret) {
- cc_log("Error writing to manifest file");
- }
- return ret;
+ XXH64_freeState(checksum);
+ if (!ret) {
+ cc_log("Error writing to manifest file");
+ }
+ return ret;
}
static bool
-verify_result(struct conf *conf, struct manifest *mf, struct result *result,
- struct hashtable *stated_files, struct hashtable *hashed_files)
+verify_result(struct conf* conf,
+ struct manifest* mf,
+ struct result* result,
+ struct hashtable* stated_files,
+ struct hashtable* hashed_files)
{
- for (uint32_t i = 0; i < result->n_file_info_indexes; i++) {
- struct file_info *fi = &mf->file_infos[result->file_info_indexes[i]];
- char *path = mf->files[fi->index].path;
- auto st = static_cast<file_stats*>(hashtable_search(stated_files, path));
- if (!st) {
- struct stat file_stat;
- if (x_stat(path, &file_stat) != 0) {
- return false;
- }
- st = static_cast<file_stats*>(x_malloc(sizeof(file_stats)));
- st->size = file_stat.st_size;
- st->mtime = file_stat.st_mtime;
- st->ctime = file_stat.st_ctime;
- hashtable_insert(stated_files, x_strdup(path), st);
- }
-
- if (fi->fsize != st->size) {
- return false;
- }
-
- // Clang stores the mtime of the included files in the precompiled header,
- // and will error out if that header is later used without rebuilding.
- if ((guessed_compiler == GUESSED_CLANG
- || guessed_compiler == GUESSED_UNKNOWN)
- && output_is_precompiled_header
- && fi->mtime != st->mtime) {
- cc_log("Precompiled header includes %s, which has a new mtime", path);
- return false;
- }
-
- if (conf->sloppiness & SLOPPY_FILE_STAT_MATCHES) {
- if (!(conf->sloppiness & SLOPPY_FILE_STAT_MATCHES_CTIME)) {
- if (fi->mtime == st->mtime && fi->ctime == st->ctime) {
- cc_log("mtime/ctime hit for %s", path);
- continue;
- } else {
- cc_log("mtime/ctime miss for %s", path);
- }
- } else {
- if (fi->mtime == st->mtime) {
- cc_log("mtime hit for %s", path);
- continue;
- } else {
- cc_log("mtime miss for %s", path);
- }
- }
- }
-
- auto actual = static_cast<digest*>(hashtable_search(hashed_files, path));
- if (!actual) {
- struct hash *hash = hash_init();
- int ret = hash_source_code_file(conf, hash, path);
- if (ret & HASH_SOURCE_CODE_ERROR) {
- cc_log("Failed hashing %s", path);
- hash_free(hash);
- return false;
- }
- if (ret & HASH_SOURCE_CODE_FOUND_TIME) {
- hash_free(hash);
- return false;
- }
-
- actual = static_cast<digest*>(malloc(sizeof(digest)));
- hash_result_as_bytes(hash, actual);
- hashtable_insert(hashed_files, x_strdup(path), actual);
- hash_free(hash);
- }
- if (!digests_equal(&fi->digest, actual)) {
- return false;
- }
- }
-
- return true;
+ for (uint32_t i = 0; i < result->n_file_info_indexes; i++) {
+ struct file_info* fi = &mf->file_infos[result->file_info_indexes[i]];
+ char* path = mf->files[fi->index].path;
+ auto st = static_cast<file_stats*>(hashtable_search(stated_files, path));
+ if (!st) {
+ struct stat file_stat;
+ if (x_stat(path, &file_stat) != 0) {
+ return false;
+ }
+ st = static_cast<file_stats*>(x_malloc(sizeof(file_stats)));
+ st->size = file_stat.st_size;
+ st->mtime = file_stat.st_mtime;
+ st->ctime = file_stat.st_ctime;
+ hashtable_insert(stated_files, x_strdup(path), st);
+ }
+
+ if (fi->fsize != st->size) {
+ return false;
+ }
+
+ // Clang stores the mtime of the included files in the precompiled header,
+ // and will error out if that header is later used without rebuilding.
+ if ((guessed_compiler == GUESSED_CLANG
+ || guessed_compiler == GUESSED_UNKNOWN)
+ && output_is_precompiled_header && fi->mtime != st->mtime) {
+ cc_log("Precompiled header includes %s, which has a new mtime", path);
+ return false;
+ }
+
+ if (conf->sloppiness & SLOPPY_FILE_STAT_MATCHES) {
+ if (!(conf->sloppiness & SLOPPY_FILE_STAT_MATCHES_CTIME)) {
+ if (fi->mtime == st->mtime && fi->ctime == st->ctime) {
+ cc_log("mtime/ctime hit for %s", path);
+ continue;
+ } else {
+ cc_log("mtime/ctime miss for %s", path);
+ }
+ } else {
+ if (fi->mtime == st->mtime) {
+ cc_log("mtime hit for %s", path);
+ continue;
+ } else {
+ cc_log("mtime miss for %s", path);
+ }
+ }
+ }
+
+ auto actual = static_cast<digest*>(hashtable_search(hashed_files, path));
+ if (!actual) {
+ struct hash* hash = hash_init();
+ int ret = hash_source_code_file(conf, hash, path);
+ if (ret & HASH_SOURCE_CODE_ERROR) {
+ cc_log("Failed hashing %s", path);
+ hash_free(hash);
+ return false;
+ }
+ if (ret & HASH_SOURCE_CODE_FOUND_TIME) {
+ hash_free(hash);
+ return false;
+ }
+
+ actual = static_cast<digest*>(malloc(sizeof(digest)));
+ hash_result_as_bytes(hash, actual);
+ hashtable_insert(hashed_files, x_strdup(path), actual);
+ hash_free(hash);
+ }
+ if (!digests_equal(&fi->digest, actual)) {
+ return false;
+ }
+ }
+
+ return true;
}
-static struct hashtable *
-create_file_index_map(struct file *files, uint32_t len)
+static struct hashtable*
+create_file_index_map(struct file* files, uint32_t len)
{
- struct hashtable *h =
- create_hashtable(1000, hash_from_string, strings_equal);
- for (uint32_t i = 0; i < len; i++) {
- auto index = static_cast<uint32_t*>(x_malloc(sizeof(uint32_t)));
- *index = i;
- hashtable_insert(h, x_strdup(files[i].path), index);
- }
- return h;
+ struct hashtable* h = create_hashtable(1000, hash_from_string, strings_equal);
+ for (uint32_t i = 0; i < len; i++) {
+ auto index = static_cast<uint32_t*>(x_malloc(sizeof(uint32_t)));
+ *index = i;
+ hashtable_insert(h, x_strdup(files[i].path), index);
+ }
+ return h;
}
-static struct hashtable *
-create_file_info_index_map(struct file_info *infos, uint32_t len)
+static struct hashtable*
+create_file_info_index_map(struct file_info* infos, uint32_t len)
{
- struct hashtable *h =
- create_hashtable(1000, hash_from_file_info, file_infos_equal);
- for (uint32_t i = 0; i < len; i++) {
- auto fi = static_cast<file_info*>(x_malloc(sizeof(file_info)));
- *fi = infos[i];
- uint32_t *index = static_cast<uint32_t*>(x_malloc(sizeof(uint32_t)));
- *index = i;
- hashtable_insert(h, fi, index);
- }
- return h;
+ struct hashtable* h =
+ create_hashtable(1000, hash_from_file_info, file_infos_equal);
+ for (uint32_t i = 0; i < len; i++) {
+ auto fi = static_cast<file_info*>(x_malloc(sizeof(file_info)));
+ *fi = infos[i];
+ uint32_t* index = static_cast<uint32_t*>(x_malloc(sizeof(uint32_t)));
+ *index = i;
+ hashtable_insert(h, fi, index);
+ }
+ return h;
}
static uint32_t
-get_include_file_index(struct manifest *mf, char *path,
- struct hashtable *mf_files)
+get_include_file_index(struct manifest* mf,
+ char* path,
+ struct hashtable* mf_files)
{
- uint32_t *index = static_cast<uint32_t*>(hashtable_search(mf_files, path));
- if (index) {
- return *index;
- }
-
- uint32_t n = mf->n_files;
- mf->files = static_cast<file*>(x_realloc(mf->files, (n + 1) * sizeof(file)));
- mf->n_files++;
- mf->files[n].path_len = strlen(path);
- mf->files[n].path = x_strdup(path);
- return n;
+ uint32_t* index = static_cast<uint32_t*>(hashtable_search(mf_files, path));
+ if (index) {
+ return *index;
+ }
+
+ uint32_t n = mf->n_files;
+ mf->files = static_cast<file*>(x_realloc(mf->files, (n + 1) * sizeof(file)));
+ mf->n_files++;
+ mf->files[n].path_len = strlen(path);
+ mf->files[n].path = x_strdup(path);
+ return n;
}
static uint32_t
-get_file_info_index(struct manifest *mf,
- char *path,
- struct digest *digest,
- struct hashtable *mf_files,
- struct hashtable *mf_file_infos)
+get_file_info_index(struct manifest* mf,
+ char* path,
+ struct digest* digest,
+ struct hashtable* mf_files,
+ struct hashtable* mf_file_infos)
{
- struct file_info fi;
- fi.index = get_include_file_index(mf, path, mf_files);
- fi.digest = *digest;
-
- // file_stat.st_{m,c}time has a resolution of 1 second, so we can cache the
- // file's mtime and ctime only if they're at least one second older than
- // time_of_compilation.
- //
- // st->ctime may be 0, so we have to check time_of_compilation against
- // MAX(mtime, ctime).
-
- struct stat file_stat;
- if (stat(path, &file_stat) != -1) {
- if (time_of_compilation > MAX(file_stat.st_mtime, file_stat.st_ctime)) {
- fi.mtime = file_stat.st_mtime;
- fi.ctime = file_stat.st_ctime;
- } else {
- fi.mtime = -1;
- fi.ctime = -1;
- }
- fi.fsize = file_stat.st_size;
- } else {
- fi.mtime = -1;
- fi.ctime = -1;
- fi.fsize = 0;
- }
-
- auto fi_index = static_cast<uint32_t*>(hashtable_search(mf_file_infos, &fi));
- if (fi_index) {
- return *fi_index;
- }
-
- uint32_t n = mf->n_file_infos;
- mf->file_infos = static_cast<file_info*>(
- x_realloc(mf->file_infos, (n + 1) * sizeof(file_info)));
- mf->n_file_infos++;
- mf->file_infos[n] = fi;
- return n;
+ struct file_info fi;
+ fi.index = get_include_file_index(mf, path, mf_files);
+ fi.digest = *digest;
+
+ // file_stat.st_{m,c}time has a resolution of 1 second, so we can cache the
+ // file's mtime and ctime only if they're at least one second older than
+ // time_of_compilation.
+ //
+ // st->ctime may be 0, so we have to check time_of_compilation against
+ // MAX(mtime, ctime).
+
+ struct stat file_stat;
+ if (stat(path, &file_stat) != -1) {
+ if (time_of_compilation > MAX(file_stat.st_mtime, file_stat.st_ctime)) {
+ fi.mtime = file_stat.st_mtime;
+ fi.ctime = file_stat.st_ctime;
+ } else {
+ fi.mtime = -1;
+ fi.ctime = -1;
+ }
+ fi.fsize = file_stat.st_size;
+ } else {
+ fi.mtime = -1;
+ fi.ctime = -1;
+ fi.fsize = 0;
+ }
+
+ auto fi_index = static_cast<uint32_t*>(hashtable_search(mf_file_infos, &fi));
+ if (fi_index) {
+ return *fi_index;
+ }
+
+ uint32_t n = mf->n_file_infos;
+ mf->file_infos = static_cast<file_info*>(
+ x_realloc(mf->file_infos, (n + 1) * sizeof(file_info)));
+ mf->n_file_infos++;
+ mf->file_infos[n] = fi;
+ return n;
}
static void
-add_file_info_indexes(uint32_t *indexes, uint32_t size,
- struct manifest *mf, struct hashtable *included_files)
+add_file_info_indexes(uint32_t* indexes,
+ uint32_t size,
+ struct manifest* mf,
+ struct hashtable* included_files)
{
- if (size == 0) {
- return;
- }
-
- // path --> index
- struct hashtable *mf_files = create_file_index_map(mf->files, mf->n_files);
- // struct file_info --> index
- struct hashtable *mf_file_infos =
- create_file_info_index_map(mf->file_infos, mf->n_file_infos);
- struct hashtable_itr *iter = hashtable_iterator(included_files);
- uint32_t i = 0;
- do {
- auto path = static_cast<char*>(hashtable_iterator_key(iter));
- auto digest = static_cast<struct digest*>(hashtable_iterator_value(iter));
- indexes[i] = get_file_info_index(mf, path, digest, mf_files,
- mf_file_infos);
- i++;
- } while (hashtable_iterator_advance(iter));
- assert(i == size);
-
- hashtable_destroy(mf_file_infos, 1);
- hashtable_destroy(mf_files, 1);
+ if (size == 0) {
+ return;
+ }
+
+ // path --> index
+ struct hashtable* mf_files = create_file_index_map(mf->files, mf->n_files);
+ // struct file_info --> index
+ struct hashtable* mf_file_infos =
+ create_file_info_index_map(mf->file_infos, mf->n_file_infos);
+ struct hashtable_itr* iter = hashtable_iterator(included_files);
+ uint32_t i = 0;
+ do {
+ auto path = static_cast<char*>(hashtable_iterator_key(iter));
+ auto digest = static_cast<struct digest*>(hashtable_iterator_value(iter));
+ indexes[i] = get_file_info_index(mf, path, digest, mf_files, mf_file_infos);
+ i++;
+ } while (hashtable_iterator_advance(iter));
+ assert(i == size);
+
+ hashtable_destroy(mf_file_infos, 1);
+ hashtable_destroy(mf_files, 1);
}
static void
-add_result_entry(struct manifest *mf,
- struct digest *result_digest,
- struct hashtable *included_files)
+add_result_entry(struct manifest* mf,
+ struct digest* result_digest,
+ struct hashtable* included_files)
{
- uint32_t n_results = mf->n_results;
- mf->results = static_cast<result*>(
- x_realloc(mf->results, (n_results + 1) * sizeof(result)));
- mf->n_results++;
- struct result *result = &mf->results[n_results];
-
- uint32_t n_fii = hashtable_count(included_files);
- result->n_file_info_indexes = n_fii;
- result->file_info_indexes = static_cast<uint32_t*>(
- x_malloc(n_fii * sizeof(uint32_t)));
- add_file_info_indexes(result->file_info_indexes, n_fii, mf, included_files);
- result->name = *result_digest;
+ uint32_t n_results = mf->n_results;
+ mf->results = static_cast<result*>(
+ x_realloc(mf->results, (n_results + 1) * sizeof(result)));
+ mf->n_results++;
+ struct result* result = &mf->results[n_results];
+
+ uint32_t n_fii = hashtable_count(included_files);
+ result->n_file_info_indexes = n_fii;
+ result->file_info_indexes =
+ static_cast<uint32_t*>(x_malloc(n_fii * sizeof(uint32_t)));
+ add_file_info_indexes(result->file_info_indexes, n_fii, mf, included_files);
+ result->name = *result_digest;
}
// Try to get the result name from a manifest file. Caller frees. Returns NULL
// on failure.
-struct digest *
-manifest_get(struct conf *conf, const char *manifest_path)
+struct digest*
+manifest_get(struct conf* conf, const char* manifest_path)
{
- char *errmsg;
- struct manifest *mf = read_manifest(manifest_path, &errmsg);
- if (!mf) {
- cc_log("%s", errmsg);
- return NULL;
- }
-
- // path --> struct digest
- struct hashtable *hashed_files =
- create_hashtable(1000, hash_from_string, strings_equal);
- // path --> struct file_stats
- struct hashtable *stated_files =
- create_hashtable(1000, hash_from_string, strings_equal);
-
- // Check newest result first since it's a bit more likely to match.
- struct digest *name = NULL;
- for (uint32_t i = mf->n_results; i > 0; i--) {
- if (verify_result(conf, mf, &mf->results[i - 1],
- stated_files, hashed_files)) {
- name = static_cast<digest*>(x_malloc(sizeof(digest)));
- *name = mf->results[i - 1].name;
- goto out;
- }
- }
+ char* errmsg;
+ struct manifest* mf = read_manifest(manifest_path, &errmsg);
+ if (!mf) {
+ cc_log("%s", errmsg);
+ return NULL;
+ }
+
+ // path --> struct digest
+ struct hashtable* hashed_files =
+ create_hashtable(1000, hash_from_string, strings_equal);
+ // path --> struct file_stats
+ struct hashtable* stated_files =
+ create_hashtable(1000, hash_from_string, strings_equal);
+
+ // Check newest result first since it's a bit more likely to match.
+ struct digest* name = NULL;
+ for (uint32_t i = mf->n_results; i > 0; i--) {
+ if (verify_result(
+ conf, mf, &mf->results[i - 1], stated_files, hashed_files)) {
+ name = static_cast<digest*>(x_malloc(sizeof(digest)));
+ *name = mf->results[i - 1].name;
+ goto out;
+ }
+ }
out:
- if (hashed_files) {
- hashtable_destroy(hashed_files, 1);
- }
- if (stated_files) {
- hashtable_destroy(stated_files, 1);
- }
- free_manifest(mf);
- if (name) {
- // Update modification timestamp to save files from LRU cleanup.
- update_mtime(manifest_path);
- }
- return name;
+ if (hashed_files) {
+ hashtable_destroy(hashed_files, 1);
+ }
+ if (stated_files) {
+ hashtable_destroy(stated_files, 1);
+ }
+ free_manifest(mf);
+ if (name) {
+ // Update modification timestamp to save files from LRU cleanup.
+ update_mtime(manifest_path);
+ }
+ return name;
}
// Put the result name into a manifest file given a set of included files.
// Returns true on success, otherwise false.
bool
-manifest_put(const char *manifest_path, struct digest *result_name,
- struct hashtable *included_files)
+manifest_put(const char* manifest_path,
+ struct digest* result_name,
+ struct hashtable* included_files)
{
- // We don't bother to acquire a lock when writing the manifest to disk. A
- // race between two processes will only result in one lost entry, which is
- // not a big deal, and it's also very unlikely.
-
- char *errmsg;
- struct manifest *mf = read_manifest(manifest_path, &errmsg);
- if (!mf) {
- // New or corrupt file.
- mf = create_empty_manifest();
- free(errmsg); // Ignore.
- }
-
- if (mf->n_results > MAX_MANIFEST_ENTRIES) {
- // Normally, there shouldn't be many result entries in the manifest since
- // new entries are added only if an include file has changed but not the
- // source file, and you typically change source files more often than
- // header files. However, it's certainly possible to imagine cases where
- // the manifest will grow large (for instance, a generated header file that
- // changes for every build), and this must be taken care of since
- // processing an ever growing manifest eventually will take too much time.
- // A good way of solving this would be to maintain the result entries in
- // LRU order and discarding the old ones. An easy way is to throw away all
- // entries when there are too many. Let's do that for now.
- cc_log("More than %u entries in manifest file; discarding",
- MAX_MANIFEST_ENTRIES);
- free_manifest(mf);
- mf = create_empty_manifest();
- } else if (mf->n_file_infos > MAX_MANIFEST_FILE_INFO_ENTRIES) {
- // Rarely, file_info entries can grow large in pathological cases where
- // many included files change, but the main file does not. This also puts
- // an upper bound on the number of file_info entries.
- cc_log("More than %u file_info entries in manifest file; discarding",
- MAX_MANIFEST_FILE_INFO_ENTRIES);
- free_manifest(mf);
- mf = create_empty_manifest();
- }
-
- add_result_entry(mf, result_name, included_files);
-
- int ret = false;
- char *tmp_file = format("%s.tmp", manifest_path);
- int fd = create_tmp_fd(&tmp_file);
- FILE *f = fdopen(fd, "wb");
- if (!f) {
- cc_log("Failed to fdopen %s", tmp_file);
- goto out;
- }
- if (write_manifest(f, mf)) {
- fclose(f);
- f = NULL;
- if (x_rename(tmp_file, manifest_path) == 0) {
- ret = true;
- } else {
- cc_log("Failed to rename %s to %s", tmp_file, manifest_path);
- }
- } else {
- cc_log("Failed to write manifest file %s", tmp_file);
- }
+ // We don't bother to acquire a lock when writing the manifest to disk. A
+ // race between two processes will only result in one lost entry, which is
+ // not a big deal, and it's also very unlikely.
+
+ char* errmsg;
+ struct manifest* mf = read_manifest(manifest_path, &errmsg);
+ if (!mf) {
+ // New or corrupt file.
+ mf = create_empty_manifest();
+ free(errmsg); // Ignore.
+ }
+
+ if (mf->n_results > MAX_MANIFEST_ENTRIES) {
+ // Normally, there shouldn't be many result entries in the manifest since
+ // new entries are added only if an include file has changed but not the
+ // source file, and you typically change source files more often than
+ // header files. However, it's certainly possible to imagine cases where
+ // the manifest will grow large (for instance, a generated header file that
+ // changes for every build), and this must be taken care of since
+ // processing an ever growing manifest eventually will take too much time.
+ // A good way of solving this would be to maintain the result entries in
+ // LRU order and discarding the old ones. An easy way is to throw away all
+ // entries when there are too many. Let's do that for now.
+ cc_log("More than %u entries in manifest file; discarding",
+ MAX_MANIFEST_ENTRIES);
+ free_manifest(mf);
+ mf = create_empty_manifest();
+ } else if (mf->n_file_infos > MAX_MANIFEST_FILE_INFO_ENTRIES) {
+ // Rarely, file_info entries can grow large in pathological cases where
+ // many included files change, but the main file does not. This also puts
+ // an upper bound on the number of file_info entries.
+ cc_log("More than %u file_info entries in manifest file; discarding",
+ MAX_MANIFEST_FILE_INFO_ENTRIES);
+ free_manifest(mf);
+ mf = create_empty_manifest();
+ }
+
+ add_result_entry(mf, result_name, included_files);
+
+ int ret = false;
+ char* tmp_file = format("%s.tmp", manifest_path);
+ int fd = create_tmp_fd(&tmp_file);
+ FILE* f = fdopen(fd, "wb");
+ if (!f) {
+ cc_log("Failed to fdopen %s", tmp_file);
+ goto out;
+ }
+ if (write_manifest(f, mf)) {
+ fclose(f);
+ f = NULL;
+ if (x_rename(tmp_file, manifest_path) == 0) {
+ ret = true;
+ } else {
+ cc_log("Failed to rename %s to %s", tmp_file, manifest_path);
+ }
+ } else {
+ cc_log("Failed to write manifest file %s", tmp_file);
+ }
out:
- if (f) {
- fclose(f);
- }
- if (mf) {
- free_manifest(mf);
- }
- if (tmp_file) {
- free(tmp_file);
- }
- return ret;
+ if (f) {
+ fclose(f);
+ }
+ if (mf) {
+ free_manifest(mf);
+ }
+ if (tmp_file) {
+ free(tmp_file);
+ }
+ return ret;
}
bool
-manifest_dump(const char *manifest_path, FILE *stream)
+manifest_dump(const char* manifest_path, FILE* stream)
{
- char *errmsg;
- struct manifest *mf = read_manifest(manifest_path, &errmsg);
- if (!mf) {
- assert(errmsg);
- fprintf(stream, "Error: %s\n", errmsg);
- free(errmsg);
- return false;
- }
-
- common_header_dump(&mf->header, stream);
-
- fprintf(stream, "File paths (%u):\n", (unsigned)mf->n_files);
- for (unsigned i = 0; i < mf->n_files; ++i) {
- fprintf(stream, " %u: %s\n", i, mf->files[i].path);
- }
- fprintf(stream, "File infos (%u):\n", (unsigned)mf->n_file_infos);
- for (unsigned i = 0; i < mf->n_file_infos; ++i) {
- char digest[DIGEST_STRING_BUFFER_SIZE];
- fprintf(stream, " %u:\n", i);
- fprintf(stream, " Path index: %u\n", mf->file_infos[i].index);
- digest_as_string(&mf->file_infos[i].digest, digest);
- fprintf(stream, " Hash: %s\n", digest);
- fprintf(stream, " File size: %" PRIu64 "\n", mf->file_infos[i].fsize);
- fprintf(stream, " Mtime: %lld\n", (long long)mf->file_infos[i].mtime);
- fprintf(stream, " Ctime: %lld\n", (long long)mf->file_infos[i].ctime);
- }
- fprintf(stream, "Results (%u):\n", (unsigned)mf->n_results);
- for (unsigned i = 0; i < mf->n_results; ++i) {
- char name[DIGEST_STRING_BUFFER_SIZE];
- fprintf(stream, " %u:\n", i);
- fprintf(stream, " File info indexes:");
- for (unsigned j = 0; j < mf->results[i].n_file_info_indexes; ++j) {
- fprintf(stream, " %u", mf->results[i].file_info_indexes[j]);
- }
- fprintf(stream, "\n");
- digest_as_string(&mf->results[i].name, name);
- fprintf(stream, " Name: %s\n", name);
- }
-
- free_manifest(mf);
- return true;
+ char* errmsg;
+ struct manifest* mf = read_manifest(manifest_path, &errmsg);
+ if (!mf) {
+ assert(errmsg);
+ fprintf(stream, "Error: %s\n", errmsg);
+ free(errmsg);
+ return false;
+ }
+
+ common_header_dump(&mf->header, stream);
+
+ fprintf(stream, "File paths (%u):\n", (unsigned)mf->n_files);
+ for (unsigned i = 0; i < mf->n_files; ++i) {
+ fprintf(stream, " %u: %s\n", i, mf->files[i].path);
+ }
+ fprintf(stream, "File infos (%u):\n", (unsigned)mf->n_file_infos);
+ for (unsigned i = 0; i < mf->n_file_infos; ++i) {
+ char digest[DIGEST_STRING_BUFFER_SIZE];
+ fprintf(stream, " %u:\n", i);
+ fprintf(stream, " Path index: %u\n", mf->file_infos[i].index);
+ digest_as_string(&mf->file_infos[i].digest, digest);
+ fprintf(stream, " Hash: %s\n", digest);
+ fprintf(stream, " File size: %" PRIu64 "\n", mf->file_infos[i].fsize);
+ fprintf(stream, " Mtime: %lld\n", (long long)mf->file_infos[i].mtime);
+ fprintf(stream, " Ctime: %lld\n", (long long)mf->file_infos[i].ctime);
+ }
+ fprintf(stream, "Results (%u):\n", (unsigned)mf->n_results);
+ for (unsigned i = 0; i < mf->n_results; ++i) {
+ char name[DIGEST_STRING_BUFFER_SIZE];
+ fprintf(stream, " %u:\n", i);
+ fprintf(stream, " File info indexes:");
+ for (unsigned j = 0; j < mf->results[i].n_file_info_indexes; ++j) {
+ fprintf(stream, " %u", mf->results[i].file_info_indexes[j]);
+ }
+ fprintf(stream, "\n");
+ digest_as_string(&mf->results[i].name, name);
+ fprintf(stream, " Name: %s\n", name);
+ }
+
+ free_manifest(mf);
+ return true;
}
diff --git a/src/manifest.hpp b/src/manifest.hpp
index 4fe9e0c7..05dae1e8 100644
--- a/src/manifest.hpp
+++ b/src/manifest.hpp
@@ -20,12 +20,14 @@
#include "conf.hpp"
#include "hashutil.hpp"
+
#include "third_party/hashtable.h"
extern const char MANIFEST_MAGIC[4];
#define MANIFEST_VERSION 2
-struct digest *manifest_get(struct conf *conf, const char *manifest_path);
-bool manifest_put(const char *manifest_path, struct digest *result_digest,
- struct hashtable *included_files);
-bool manifest_dump(const char *manifest_path, FILE *stream);
+struct digest* manifest_get(struct conf* conf, const char* manifest_path);
+bool manifest_put(const char* manifest_path,
+ struct digest* result_digest,
+ struct hashtable* included_files);
+bool manifest_dump(const char* manifest_path, FILE* stream);
diff --git a/src/result.cpp b/src/result.cpp
index 45eac639..c1374e31 100644
--- a/src/result.cpp
+++ b/src/result.cpp
@@ -16,12 +16,13 @@
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#include "result.hpp"
+
#include "ccache.hpp"
#include "common_header.hpp"
-#include "int_bytes_conversion.hpp"
#include "compression.hpp"
#include "hash.hpp"
-#include "result.hpp"
+#include "int_bytes_conversion.hpp"
// Result data format
// ==================
@@ -81,672 +82,655 @@
//
// 1: Introduced in ccache 3.8.
-extern const struct conf *conf;
-extern char *stats_file;
+extern const struct conf* conf;
+extern char* stats_file;
const char RESULT_MAGIC[4] = {'c', 'C', 'r', 'S'};
enum {
- // File data stored inside the result file.
- EMBEDDED_FILE_MARKER = 0,
+ // File data stored inside the result file.
+ EMBEDDED_FILE_MARKER = 0,
- // File stored as-is in the file system.
- RAW_FILE_MARKER = 1
+ // File stored as-is in the file system.
+ RAW_FILE_MARKER = 1
};
-struct result_file {
- char *suffix;
- char *path;
- uint64_t size;
+struct result_file
+{
+ char* suffix;
+ char* path;
+ uint64_t size;
};
-struct result_files {
- uint32_t n_files;
- struct result_file *files;
- uint64_t *sizes;
+struct result_files
+{
+ uint32_t n_files;
+ struct result_file* files;
+ uint64_t* sizes;
};
-typedef bool (*read_entry_fn)(
- struct decompressor *decompressor,
- struct decompr_state *decompr_state,
- const char *result_path_in_cache,
- uint32_t entry_number,
- const struct result_files *list,
- FILE *dump_stream);
-
-typedef bool (*write_entry_fn)(
- struct compressor *compressor,
- struct compr_state *compr_state,
- const char *result_path_in_cache,
- uint32_t entry_number,
- const struct result_file *file);
-
-struct result_files *
+typedef bool (*read_entry_fn)(struct decompressor* decompressor,
+ struct decompr_state* decompr_state,
+ const char* result_path_in_cache,
+ uint32_t entry_number,
+ const struct result_files* list,
+ FILE* dump_stream);
+
+typedef bool (*write_entry_fn)(struct compressor* compressor,
+ struct compr_state* compr_state,
+ const char* result_path_in_cache,
+ uint32_t entry_number,
+ const struct result_file* file);
+
+struct result_files*
result_files_init(void)
{
- auto list = static_cast<result_files*>(x_malloc(sizeof(result_files)));
- list->n_files = 0;
- list->files = NULL;
- list->sizes = NULL;
+ auto list = static_cast<result_files*>(x_malloc(sizeof(result_files)));
+ list->n_files = 0;
+ list->files = NULL;
+ list->sizes = NULL;
- return list;
+ return list;
}
void
-result_files_add(struct result_files *list, const char *path,
- const char *suffix)
+result_files_add(struct result_files* list,
+ const char* path,
+ const char* suffix)
{
- uint32_t n = list->n_files;
- list->files = static_cast<result_file*>(
- x_realloc(list->files, (n + 1) * sizeof(result_file)));
- list->sizes = static_cast<uint64_t*>(
- x_realloc(list->sizes, (n + 1) * sizeof(uint64_t)));
- struct result_file *f = &list->files[list->n_files];
- list->n_files++;
-
- struct stat st;
- x_stat(path, &st);
-
- f->suffix = x_strdup(suffix);
- f->path = x_strdup(path);
- f->size = st.st_size;
+ uint32_t n = list->n_files;
+ list->files = static_cast<result_file*>(
+ x_realloc(list->files, (n + 1) * sizeof(result_file)));
+ list->sizes =
+ static_cast<uint64_t*>(x_realloc(list->sizes, (n + 1) * sizeof(uint64_t)));
+ struct result_file* f = &list->files[list->n_files];
+ list->n_files++;
+
+ struct stat st;
+ x_stat(path, &st);
+
+ f->suffix = x_strdup(suffix);
+ f->path = x_strdup(path);
+ f->size = st.st_size;
}
void
-result_files_free(struct result_files *list)
+result_files_free(struct result_files* list)
{
- for (uint32_t i = 0; i < list->n_files; i++) {
- free(list->files[i].suffix);
- free(list->files[i].path);
- }
- free(list->files);
- list->files = NULL;
- free(list->sizes);
- list->sizes = NULL;
-
- free(list);
+ for (uint32_t i = 0; i < list->n_files; i++) {
+ free(list->files[i].suffix);
+ free(list->files[i].path);
+ }
+ free(list->files);
+ list->files = NULL;
+ free(list->sizes);
+ list->sizes = NULL;
+
+ free(list);
}
-#define READ_BYTES(buf, length) \
- do { \
- if (!decompressor->read(decompr_state, buf, length)) { \
- goto out; \
- } \
- } while (false)
+#define READ_BYTES(buf, length) \
+ do { \
+ if (!decompressor->read(decompr_state, buf, length)) { \
+ goto out; \
+ } \
+ } while (false)
-#define READ_BYTE(var) \
- READ_BYTES(&var, 1)
+#define READ_BYTE(var) READ_BYTES(&var, 1)
-#define READ_UINT64(var) \
- do { \
- char buf_[8]; \
- READ_BYTES(buf_, sizeof(buf_)); \
- (var) = UINT64_FROM_BYTES(buf_); \
- } while (false)
+#define READ_UINT64(var) \
+ do { \
+ char buf_[8]; \
+ READ_BYTES(buf_, sizeof(buf_)); \
+ (var) = UINT64_FROM_BYTES(buf_); \
+ } while (false)
static bool
-read_embedded_file_entry(
- struct decompressor *decompressor,
- struct decompr_state *decompr_state,
- const char *result_path_in_cache,
- uint32_t entry_number,
- const struct result_files *list,
- FILE *dump_stream)
+read_embedded_file_entry(struct decompressor* decompressor,
+ struct decompr_state* decompr_state,
+ const char* result_path_in_cache,
+ uint32_t entry_number,
+ const struct result_files* list,
+ FILE* dump_stream)
{
- (void)result_path_in_cache;
- bool found = false;
- bool success = false;
- FILE *subfile = NULL;
-
- uint8_t suffix_len;
- READ_BYTE(suffix_len);
-
- char suffix[256 + 1];
- READ_BYTES(suffix, suffix_len);
- suffix[suffix_len] = '\0';
-
- uint64_t file_len;
- READ_UINT64(file_len);
-
- if (dump_stream) {
- fprintf(
- dump_stream,
- "Embedded file #%u: %s (%" PRIu64 " bytes)\n",
- entry_number,
- suffix,
- file_len);
- } else {
- cc_log(
- "Retrieving embedded file #%u %s (%llu bytes)",
- entry_number,
- suffix,
- (unsigned long long)file_len);
-
- for (uint32_t i = 0; i < list->n_files; i++) {
- if (str_eq(suffix, list->files[i].suffix)) {
- found = true;
-
- cc_log("Copying to %s", list->files[i].path);
-
- subfile = fopen(list->files[i].path, "wb");
- if (!subfile) {
- cc_log("Failed to open %s for writing", list->files[i].path);
- goto out;
- }
- char buf[READ_BUFFER_SIZE];
- size_t remain = file_len;
- while (remain > 0) {
- size_t n = MIN(remain, sizeof(buf));
- READ_BYTES(buf, n);
- if (fwrite(buf, 1, n, subfile) != n) {
- goto out;
- }
- remain -= n;
- }
- fclose(subfile);
- subfile = NULL;
-
- break;
- }
- }
- }
-
- if (!found) {
- // Discard the file data.
- char buf[READ_BUFFER_SIZE];
- size_t remain = file_len;
- while (remain > 0) {
- size_t n = MIN(remain, sizeof(buf));
- READ_BYTES(buf, n);
- remain -= n;
- }
- }
-
- success = true;
+ (void)result_path_in_cache;
+ bool found = false;
+ bool success = false;
+ FILE* subfile = NULL;
+
+ uint8_t suffix_len;
+ READ_BYTE(suffix_len);
+
+ char suffix[256 + 1];
+ READ_BYTES(suffix, suffix_len);
+ suffix[suffix_len] = '\0';
+
+ uint64_t file_len;
+ READ_UINT64(file_len);
+
+ if (dump_stream) {
+ fprintf(dump_stream,
+ "Embedded file #%u: %s (%" PRIu64 " bytes)\n",
+ entry_number,
+ suffix,
+ file_len);
+ } else {
+ cc_log("Retrieving embedded file #%u %s (%llu bytes)",
+ entry_number,
+ suffix,
+ (unsigned long long)file_len);
+
+ for (uint32_t i = 0; i < list->n_files; i++) {
+ if (str_eq(suffix, list->files[i].suffix)) {
+ found = true;
+
+ cc_log("Copying to %s", list->files[i].path);
+
+ subfile = fopen(list->files[i].path, "wb");
+ if (!subfile) {
+ cc_log("Failed to open %s for writing", list->files[i].path);
+ goto out;
+ }
+ char buf[READ_BUFFER_SIZE];
+ size_t remain = file_len;
+ while (remain > 0) {
+ size_t n = MIN(remain, sizeof(buf));
+ READ_BYTES(buf, n);
+ if (fwrite(buf, 1, n, subfile) != n) {
+ goto out;
+ }
+ remain -= n;
+ }
+ fclose(subfile);
+ subfile = NULL;
+
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ // Discard the file data.
+ char buf[READ_BUFFER_SIZE];
+ size_t remain = file_len;
+ while (remain > 0) {
+ size_t n = MIN(remain, sizeof(buf));
+ READ_BYTES(buf, n);
+ remain -= n;
+ }
+ }
+
+ success = true;
out:
- if (subfile) {
- fclose(subfile);
- }
+ if (subfile) {
+ fclose(subfile);
+ }
- return success;
+ return success;
}
-static char *
-get_raw_file_path(const char *result_path_in_cache, uint32_t entry_number)
+static char*
+get_raw_file_path(const char* result_path_in_cache, uint32_t entry_number)
{
- return format(
- "%.*s_%u.raw",
- (int)strlen(result_path_in_cache) - 7, // .result
- result_path_in_cache,
- entry_number);
+ return format("%.*s_%u.raw",
+ (int)strlen(result_path_in_cache) - 7, // .result
+ result_path_in_cache,
+ entry_number);
}
static bool
-copy_raw_file(const char *source, const char *dest, bool to_cache)
+copy_raw_file(const char* source, const char* dest, bool to_cache)
{
- if (conf->file_clone) {
- cc_log("Cloning %s to %s", source, dest);
- if (clone_file(source, dest, to_cache)) {
- return true;
- }
- cc_log("Failed to clone: %s", strerror(errno));
- }
- if (conf->hard_link) {
- x_try_unlink(dest);
- cc_log("Hard linking %s to %s", source, dest);
- int ret = link(source, dest);
- if (ret == 0) {
- return true;
- }
- cc_log("Failed to hard link: %s", strerror(errno));
- }
-
- cc_log("Copying %s to %s", source, dest);
- return copy_file(source, dest, to_cache);
+ if (conf->file_clone) {
+ cc_log("Cloning %s to %s", source, dest);
+ if (clone_file(source, dest, to_cache)) {
+ return true;
+ }
+ cc_log("Failed to clone: %s", strerror(errno));
+ }
+ if (conf->hard_link) {
+ x_try_unlink(dest);
+ cc_log("Hard linking %s to %s", source, dest);
+ int ret = link(source, dest);
+ if (ret == 0) {
+ return true;
+ }
+ cc_log("Failed to hard link: %s", strerror(errno));
+ }
+
+ cc_log("Copying %s to %s", source, dest);
+ return copy_file(source, dest, to_cache);
}
static bool
-read_raw_file_entry(
- struct decompressor *decompressor,
- struct decompr_state *decompr_state,
- const char *result_path_in_cache,
- uint32_t entry_number,
- const struct result_files *list,
- FILE *dump_stream)
+read_raw_file_entry(struct decompressor* decompressor,
+ struct decompr_state* decompr_state,
+ const char* result_path_in_cache,
+ uint32_t entry_number,
+ const struct result_files* list,
+ FILE* dump_stream)
{
- bool success = false;
- char *raw_path = get_raw_file_path(result_path_in_cache, entry_number);
-
- uint8_t suffix_len;
- READ_BYTE(suffix_len);
-
- char suffix[256 + 1];
- READ_BYTES(suffix, suffix_len);
- suffix[suffix_len] = '\0';
-
- uint64_t file_len;
- READ_UINT64(file_len);
-
- if (dump_stream) {
- fprintf(
- dump_stream,
- "Raw file #%u: %s (%" PRIu64 " bytes)\n",
- entry_number,
- suffix,
- file_len);
- } else {
- cc_log(
- "Retrieving raw file #%u %s (%llu bytes)",
- entry_number,
- suffix,
- (unsigned long long)file_len);
-
- struct stat st;
- if (x_stat(raw_path, &st) != 0) {
- goto out;
- }
- if ((uint64_t)st.st_size != file_len) {
- cc_log(
- "Bad file size of %s (actual %llu bytes, expected %llu bytes)",
- raw_path,
- (unsigned long long)st.st_size,
- (unsigned long long)file_len);
- goto out;
- }
-
- for (uint32_t i = 0; i < list->n_files; i++) {
- if (str_eq(suffix, list->files[i].suffix)) {
- if (!copy_raw_file(raw_path, list->files[i].path, false)) {
- goto out;
- }
- // Update modification timestamp to save the file from LRU cleanup
- // (and, if hard-linked, to make the object file newer than the source
- // file).
- update_mtime(raw_path);
- break;
- }
- }
- }
-
- success = true;
+ bool success = false;
+ char* raw_path = get_raw_file_path(result_path_in_cache, entry_number);
+
+ uint8_t suffix_len;
+ READ_BYTE(suffix_len);
+
+ char suffix[256 + 1];
+ READ_BYTES(suffix, suffix_len);
+ suffix[suffix_len] = '\0';
+
+ uint64_t file_len;
+ READ_UINT64(file_len);
+
+ if (dump_stream) {
+ fprintf(dump_stream,
+ "Raw file #%u: %s (%" PRIu64 " bytes)\n",
+ entry_number,
+ suffix,
+ file_len);
+ } else {
+ cc_log("Retrieving raw file #%u %s (%llu bytes)",
+ entry_number,
+ suffix,
+ (unsigned long long)file_len);
+
+ struct stat st;
+ if (x_stat(raw_path, &st) != 0) {
+ goto out;
+ }
+ if ((uint64_t)st.st_size != file_len) {
+ cc_log("Bad file size of %s (actual %llu bytes, expected %llu bytes)",
+ raw_path,
+ (unsigned long long)st.st_size,
+ (unsigned long long)file_len);
+ goto out;
+ }
+
+ for (uint32_t i = 0; i < list->n_files; i++) {
+ if (str_eq(suffix, list->files[i].suffix)) {
+ if (!copy_raw_file(raw_path, list->files[i].path, false)) {
+ goto out;
+ }
+ // Update modification timestamp to save the file from LRU cleanup
+ // (and, if hard-linked, to make the object file newer than the source
+ // file).
+ update_mtime(raw_path);
+ break;
+ }
+ }
+ }
+
+ success = true;
out:
- free(raw_path);
- return success;
+ free(raw_path);
+ return success;
}
static bool
-read_result(
- const char *path,
- struct result_files *list,
- FILE *dump_stream,
- char **errmsg)
+read_result(const char* path,
+ struct result_files* list,
+ FILE* dump_stream,
+ char** errmsg)
{
- *errmsg = NULL;
- bool cache_miss = false;
- bool success = false;
- struct decompressor *decompressor = NULL;
- struct decompr_state *decompr_state = NULL;
- XXH64_state_t *checksum = XXH64_createState();
-
- FILE *f = fopen(path, "rb");
- if (!f) {
- cache_miss = true;
- goto out;
- }
-
- struct common_header header;
- if (!common_header_initialize_for_reading(
- &header,
- f,
- RESULT_MAGIC,
- RESULT_VERSION,
- &decompressor,
- &decompr_state,
- checksum,
- errmsg)) {
- goto out;
- }
-
- if (dump_stream) {
- common_header_dump(&header, dump_stream);
- }
-
- uint8_t n_entries;
- READ_BYTE(n_entries);
-
- uint32_t i;
- for (i = 0; i < n_entries; i++) {
- uint8_t marker;
- READ_BYTE(marker);
-
- read_entry_fn read_entry;
-
- switch (marker) {
- case EMBEDDED_FILE_MARKER:
- read_entry = read_embedded_file_entry;
- break;
-
- case RAW_FILE_MARKER:
- read_entry = read_raw_file_entry;
- break;
-
- default:
- *errmsg = format("Unknown entry type: %u", marker);
- goto out;
- }
-
- if (!read_entry(decompressor, decompr_state, path, i, list, dump_stream)) {
- goto out;
- }
- }
-
- if (i != n_entries) {
- *errmsg = format("Too few entries (read %u, expected %u)", i, n_entries);
- goto out;
- }
-
- {
- uint64_t actual_checksum = XXH64_digest(checksum);
- uint64_t expected_checksum;
- READ_UINT64(expected_checksum);
-
- if (actual_checksum == expected_checksum) {
- success = true;
- } else {
- *errmsg = format(
- "Incorrect checksum (actual %016llx, expected %016llx)",
- (unsigned long long)actual_checksum,
- (unsigned long long)expected_checksum);
- }
- }
+ *errmsg = NULL;
+ bool cache_miss = false;
+ bool success = false;
+ struct decompressor* decompressor = NULL;
+ struct decompr_state* decompr_state = NULL;
+ XXH64_state_t* checksum = XXH64_createState();
+
+ FILE* f = fopen(path, "rb");
+ if (!f) {
+ cache_miss = true;
+ goto out;
+ }
+
+ struct common_header header;
+ if (!common_header_initialize_for_reading(&header,
+ f,
+ RESULT_MAGIC,
+ RESULT_VERSION,
+ &decompressor,
+ &decompr_state,
+ checksum,
+ errmsg)) {
+ goto out;
+ }
+
+ if (dump_stream) {
+ common_header_dump(&header, dump_stream);
+ }
+
+ uint8_t n_entries;
+ READ_BYTE(n_entries);
+
+ uint32_t i;
+ for (i = 0; i < n_entries; i++) {
+ uint8_t marker;
+ READ_BYTE(marker);
+
+ read_entry_fn read_entry;
+
+ switch (marker) {
+ case EMBEDDED_FILE_MARKER:
+ read_entry = read_embedded_file_entry;
+ break;
+
+ case RAW_FILE_MARKER:
+ read_entry = read_raw_file_entry;
+ break;
+
+ default:
+ *errmsg = format("Unknown entry type: %u", marker);
+ goto out;
+ }
+
+ if (!read_entry(decompressor, decompr_state, path, i, list, dump_stream)) {
+ goto out;
+ }
+ }
+
+ if (i != n_entries) {
+ *errmsg = format("Too few entries (read %u, expected %u)", i, n_entries);
+ goto out;
+ }
+
+ {
+ uint64_t actual_checksum = XXH64_digest(checksum);
+ uint64_t expected_checksum;
+ READ_UINT64(expected_checksum);
+
+ if (actual_checksum == expected_checksum) {
+ success = true;
+ } else {
+ *errmsg = format("Incorrect checksum (actual %016llx, expected %016llx)",
+ (unsigned long long)actual_checksum,
+ (unsigned long long)expected_checksum);
+ }
+ }
out:
- if (decompressor && !decompressor->free(decompr_state)) {
- success = false;
- }
- if (f) {
- fclose(f);
- }
- if (checksum) {
- XXH64_freeState(checksum);
- }
- if (!success && !cache_miss && !*errmsg) {
- *errmsg = x_strdup("Corrupt result");
- }
- return success;
+ if (decompressor && !decompressor->free(decompr_state)) {
+ success = false;
+ }
+ if (f) {
+ fclose(f);
+ }
+ if (checksum) {
+ XXH64_freeState(checksum);
+ }
+ if (!success && !cache_miss && !*errmsg) {
+ *errmsg = x_strdup("Corrupt result");
+ }
+ return success;
}
-#define WRITE_BYTES(buf, length) \
- do { \
- if (!compressor->write(compr_state, buf, length)) { \
- goto error; \
- } \
- } while (false)
-
-#define WRITE_BYTE(var) \
- do { \
- char ch_ = var; \
- WRITE_BYTES(&ch_, 1); \
- } while (false)
-
-#define WRITE_UINT64(var) \
- do { \
- char buf_[8]; \
- BYTES_FROM_UINT64(buf_, (var)); \
- WRITE_BYTES(buf_, sizeof(buf_)); \
- } while (false)
+#define WRITE_BYTES(buf, length) \
+ do { \
+ if (!compressor->write(compr_state, buf, length)) { \
+ goto error; \
+ } \
+ } while (false)
+
+#define WRITE_BYTE(var) \
+ do { \
+ char ch_ = var; \
+ WRITE_BYTES(&ch_, 1); \
+ } while (false)
+
+#define WRITE_UINT64(var) \
+ do { \
+ char buf_[8]; \
+ BYTES_FROM_UINT64(buf_, (var)); \
+ WRITE_BYTES(buf_, sizeof(buf_)); \
+ } while (false)
static bool
-write_embedded_file_entry(
- struct compressor *compressor,
- struct compr_state *compr_state,
- const char *result_path_in_cache,
- uint32_t entry_number,
- const struct result_file *file)
+write_embedded_file_entry(struct compressor* compressor,
+ struct compr_state* compr_state,
+ const char* result_path_in_cache,
+ uint32_t entry_number,
+ const struct result_file* file)
{
- (void)result_path_in_cache;
- bool success = false;
- size_t suffix_len;
- FILE* f;
- char buf[READ_BUFFER_SIZE];
- size_t remain;
-
- cc_log(
- "Storing embedded file #%u %s (%llu bytes) from %s",
- entry_number,
- file->suffix,
- (unsigned long long)file->size,
- file->path);
-
- WRITE_BYTE(EMBEDDED_FILE_MARKER);
- suffix_len = strlen(file->suffix);
- WRITE_BYTE(suffix_len);
- WRITE_BYTES(file->suffix, suffix_len);
- WRITE_UINT64(file->size);
-
- f = fopen(file->path, "rb");
- if (!f) {
- cc_log("Failed to open %s for reading", file->path);
- goto error;
- }
- remain = file->size;
- while (remain > 0) {
- size_t n = MIN(remain, sizeof(buf));
- if (fread(buf, 1, n, f) != n) {
- goto error;
- }
- WRITE_BYTES(buf, n);
- remain -= n;
- }
- fclose(f);
-
- success = true;
+ (void)result_path_in_cache;
+ bool success = false;
+ size_t suffix_len;
+ FILE* f;
+ char buf[READ_BUFFER_SIZE];
+ size_t remain;
+
+ cc_log("Storing embedded file #%u %s (%llu bytes) from %s",
+ entry_number,
+ file->suffix,
+ (unsigned long long)file->size,
+ file->path);
+
+ WRITE_BYTE(EMBEDDED_FILE_MARKER);
+ suffix_len = strlen(file->suffix);
+ WRITE_BYTE(suffix_len);
+ WRITE_BYTES(file->suffix, suffix_len);
+ WRITE_UINT64(file->size);
+
+ f = fopen(file->path, "rb");
+ if (!f) {
+ cc_log("Failed to open %s for reading", file->path);
+ goto error;
+ }
+ remain = file->size;
+ while (remain > 0) {
+ size_t n = MIN(remain, sizeof(buf));
+ if (fread(buf, 1, n, f) != n) {
+ goto error;
+ }
+ WRITE_BYTES(buf, n);
+ remain -= n;
+ }
+ fclose(f);
+
+ success = true;
error:
- return success;
+ return success;
}
static bool
-write_raw_file_entry(
- struct compressor *compressor,
- struct compr_state *compr_state,
- const char *result_path_in_cache,
- uint32_t entry_number,
- const struct result_file *file)
+write_raw_file_entry(struct compressor* compressor,
+ struct compr_state* compr_state,
+ const char* result_path_in_cache,
+ uint32_t entry_number,
+ const struct result_file* file)
{
- bool success = false;
- size_t suffix_len;
- char* raw_file;
- struct stat old_stat;
- bool old_existed;
- struct stat new_stat;
- bool new_exists;
- size_t old_size;
- size_t new_size;
-
- cc_log(
- "Storing raw file #%u %s (%llu bytes) from %s",
- entry_number,
- file->suffix,
- (unsigned long long)file->size,
- file->path);
-
- WRITE_BYTE(RAW_FILE_MARKER);
- suffix_len = strlen(file->suffix);
- WRITE_BYTE(suffix_len);
- WRITE_BYTES(file->suffix, suffix_len);
- WRITE_UINT64(file->size);
-
- raw_file = get_raw_file_path(result_path_in_cache, entry_number);
- old_existed = stat(raw_file, &old_stat) == 0;
- success = copy_raw_file(file->path, raw_file, true);
- new_exists = stat(raw_file, &new_stat) == 0;
- free(raw_file);
-
- old_size = old_existed ? file_size(&old_stat) : 0;
- new_size = new_exists ? file_size(&new_stat) : 0;
- stats_update_size(
- stats_file,
- new_size - old_size,
- (new_exists ? 1 : 0) - (old_existed ? 1 : 0));
+ bool success = false;
+ size_t suffix_len;
+ char* raw_file;
+ struct stat old_stat;
+ bool old_existed;
+ struct stat new_stat;
+ bool new_exists;
+ size_t old_size;
+ size_t new_size;
+
+ cc_log("Storing raw file #%u %s (%llu bytes) from %s",
+ entry_number,
+ file->suffix,
+ (unsigned long long)file->size,
+ file->path);
+
+ WRITE_BYTE(RAW_FILE_MARKER);
+ suffix_len = strlen(file->suffix);
+ WRITE_BYTE(suffix_len);
+ WRITE_BYTES(file->suffix, suffix_len);
+ WRITE_UINT64(file->size);
+
+ raw_file = get_raw_file_path(result_path_in_cache, entry_number);
+ old_existed = stat(raw_file, &old_stat) == 0;
+ success = copy_raw_file(file->path, raw_file, true);
+ new_exists = stat(raw_file, &new_stat) == 0;
+ free(raw_file);
+
+ old_size = old_existed ? file_size(&old_stat) : 0;
+ new_size = new_exists ? file_size(&new_stat) : 0;
+ stats_update_size(stats_file,
+ new_size - old_size,
+ (new_exists ? 1 : 0) - (old_existed ? 1 : 0));
error:
- return success;
+ return success;
}
static bool
-should_store_raw_file(const char *suffix)
+should_store_raw_file(const char* suffix)
{
- if (!conf->file_clone && !conf->hard_link) {
- return false;
- }
-
- // - Don't store stderr outputs as raw files since they:
- // 1. Never are large.
- // 2. Will end up in a temporary file anyway.
- //
- // - Don't store .d files since they:
- // 1. Never are large.
- // 2. Compress well.
- // 3. Cause trouble for automake if hard-linked (see ccache issue 378).
- //
- // Note that .d files can't be stored as raw files for the file_clone case
- // since the hard link mode happily will try to use them if they exist. This
- // could be fixed by letting read_raw_file_entry refuse to hard link .d
- // files, but it's easier to simply always store them embedded. This will
- // also save i-nodes in the cache.
- return !str_eq(suffix, RESULT_STDERR_NAME) && !str_eq(suffix, ".d");
+ if (!conf->file_clone && !conf->hard_link) {
+ return false;
+ }
+
+ // - Don't store stderr outputs as raw files since they:
+ // 1. Never are large.
+ // 2. Will end up in a temporary file anyway.
+ //
+ // - Don't store .d files since they:
+ // 1. Never are large.
+ // 2. Compress well.
+ // 3. Cause trouble for automake if hard-linked (see ccache issue 378).
+ //
+ // Note that .d files can't be stored as raw files for the file_clone case
+ // since the hard link mode happily will try to use them if they exist. This
+ // could be fixed by letting read_raw_file_entry refuse to hard link .d
+ // files, but it's easier to simply always store them embedded. This will
+ // also save i-nodes in the cache.
+ return !str_eq(suffix, RESULT_STDERR_NAME) && !str_eq(suffix, ".d");
}
static bool
-write_result(
- const struct result_files *list,
- struct compressor *compressor,
- struct compr_state *compr_state,
- XXH64_state_t *checksum,
- const char *result_path_in_cache)
+write_result(const struct result_files* list,
+ struct compressor* compressor,
+ struct compr_state* compr_state,
+ XXH64_state_t* checksum,
+ const char* result_path_in_cache)
{
- WRITE_BYTE(list->n_files);
+ WRITE_BYTE(list->n_files);
- for (uint32_t i = 0; i < list->n_files; i++) {
- write_entry_fn write_entry =
- should_store_raw_file(list->files[i].suffix)
- ? write_raw_file_entry
- : write_embedded_file_entry;
- if (!write_entry(
- compressor, compr_state, result_path_in_cache, i, &list->files[i])) {
- goto error;
- }
- }
+ for (uint32_t i = 0; i < list->n_files; i++) {
+ write_entry_fn write_entry = should_store_raw_file(list->files[i].suffix)
+ ? write_raw_file_entry
+ : write_embedded_file_entry;
+ if (!write_entry(
+ compressor, compr_state, result_path_in_cache, i, &list->files[i])) {
+ goto error;
+ }
+ }
- WRITE_UINT64(XXH64_digest(checksum));
+ WRITE_UINT64(XXH64_digest(checksum));
- return true;
+ return true;
error:
- cc_log("Error writing to result file");
- return false;
+ cc_log("Error writing to result file");
+ return false;
}
-bool result_get(const char *path, struct result_files *list)
+bool
+result_get(const char* path, struct result_files* list)
{
- cc_log("Getting result %s", path);
-
- char *errmsg;
- bool success = read_result(path, list, NULL, &errmsg);
- if (success) {
- // Update modification timestamp to save files from LRU cleanup.
- update_mtime(path);
- } else if (errmsg) {
- cc_log("Error: %s", errmsg);
- free(errmsg);
- } else {
- cc_log("No such result file");
- }
- return success;
+ cc_log("Getting result %s", path);
+
+ char* errmsg;
+ bool success = read_result(path, list, NULL, &errmsg);
+ if (success) {
+ // Update modification timestamp to save files from LRU cleanup.
+ update_mtime(path);
+ } else if (errmsg) {
+ cc_log("Error: %s", errmsg);
+ free(errmsg);
+ } else {
+ cc_log("No such result file");
+ }
+ return success;
}
-bool result_put(const char *path, struct result_files *list)
+bool
+result_put(const char* path, struct result_files* list)
{
- bool ret = false;
- XXH64_state_t *checksum = XXH64_createState();
- bool ok;
- uint64_t content_size;
-
- char *tmp_file = format("%s.tmp", path);
- int fd = create_tmp_fd(&tmp_file);
- FILE *f = fdopen(fd, "wb");
- if (!f) {
- cc_log("Failed to fdopen %s", tmp_file);
- goto out;
- }
-
- content_size = COMMON_HEADER_SIZE;
- content_size += 1; // n_entries
- for (uint32_t i = 0; i < list->n_files; i++) {
- content_size += 1; // embedded_file_marker
- content_size += 1; // suffix_len
- content_size += strlen(list->files[i].suffix); // suffix
- content_size += 8; // data_len
- content_size += list->files[i].size; // data
- }
- content_size += 8; // checksum
-
- struct common_header header;
- struct compressor *compressor;
- struct compr_state *compr_state;
- if (!common_header_initialize_for_writing(
- &header,
- f,
- RESULT_MAGIC,
- RESULT_VERSION,
- compression_type_from_config(),
- compression_level_from_config(),
- content_size,
- checksum,
- &compressor,
- &compr_state)) {
- goto out;
- }
-
- ok = write_result(list, compressor, compr_state, checksum, path)
- && compressor->free(compr_state);
- if (!ok) {
- cc_log("Failed to write result file");
- goto out;
- }
-
- fclose(f);
- f = NULL;
- if (x_rename(tmp_file, path) == 0) {
- ret = true;
- } else {
- cc_log("Failed to rename %s to %s", tmp_file, path);
- }
+ bool ret = false;
+ XXH64_state_t* checksum = XXH64_createState();
+ bool ok;
+ uint64_t content_size;
+
+ char* tmp_file = format("%s.tmp", path);
+ int fd = create_tmp_fd(&tmp_file);
+ FILE* f = fdopen(fd, "wb");
+ if (!f) {
+ cc_log("Failed to fdopen %s", tmp_file);
+ goto out;
+ }
+
+ content_size = COMMON_HEADER_SIZE;
+ content_size += 1; // n_entries
+ for (uint32_t i = 0; i < list->n_files; i++) {
+ content_size += 1; // embedded_file_marker
+ content_size += 1; // suffix_len
+ content_size += strlen(list->files[i].suffix); // suffix
+ content_size += 8; // data_len
+ content_size += list->files[i].size; // data
+ }
+ content_size += 8; // checksum
+
+ struct common_header header;
+ struct compressor* compressor;
+ struct compr_state* compr_state;
+ if (!common_header_initialize_for_writing(&header,
+ f,
+ RESULT_MAGIC,
+ RESULT_VERSION,
+ compression_type_from_config(),
+ compression_level_from_config(),
+ content_size,
+ checksum,
+ &compressor,
+ &compr_state)) {
+ goto out;
+ }
+
+ ok = write_result(list, compressor, compr_state, checksum, path)
+ && compressor->free(compr_state);
+ if (!ok) {
+ cc_log("Failed to write result file");
+ goto out;
+ }
+
+ fclose(f);
+ f = NULL;
+ if (x_rename(tmp_file, path) == 0) {
+ ret = true;
+ } else {
+ cc_log("Failed to rename %s to %s", tmp_file, path);
+ }
out:
- free(tmp_file);
- if (f) {
- fclose(f);
- }
- if (checksum) {
- XXH64_freeState(checksum);
- }
- return ret;
+ free(tmp_file);
+ if (f) {
+ fclose(f);
+ }
+ if (checksum) {
+ XXH64_freeState(checksum);
+ }
+ return ret;
}
bool
-result_dump(const char *path, FILE *stream)
+result_dump(const char* path, FILE* stream)
{
- assert(stream);
-
- char *errmsg;
- bool success = read_result(path, NULL, stream, &errmsg);
- if (errmsg) {
- fprintf(stream, "Error: %s\n", errmsg);
- free(errmsg);
- }
- return success;
+ assert(stream);
+
+ char* errmsg;
+ bool success = read_result(path, NULL, stream, &errmsg);
+ if (errmsg) {
+ fprintf(stream, "Error: %s\n", errmsg);
+ free(errmsg);
+ }
+ return success;
}
diff --git a/src/result.hpp b/src/result.hpp
index 20212b60..e9b0700d 100644
--- a/src/result.hpp
+++ b/src/result.hpp
@@ -26,11 +26,11 @@ extern const char RESULT_MAGIC[4];
struct result_files;
-struct result_files *result_files_init(void);
-void result_files_add(
- struct result_files *c, const char *path, const char *suffix);
-void result_files_free(struct result_files *c);
+struct result_files* result_files_init(void);
+void
+result_files_add(struct result_files* c, const char* path, const char* suffix);
+void result_files_free(struct result_files* c);
-bool result_get(const char *path, struct result_files *list);
-bool result_put(const char *path, struct result_files *list);
-bool result_dump(const char *path, FILE *stream);
+bool result_get(const char* path, struct result_files* list);
+bool result_put(const char* path, struct result_files* list);
+bool result_dump(const char* path, FILE* stream);
diff --git a/src/stats.cpp b/src/stats.cpp
index 033b458e..0a6b9c60 100644
--- a/src/stats.cpp
+++ b/src/stats.cpp
@@ -23,687 +23,572 @@
#include "ccache.hpp"
#include "hashutil.hpp"
-#include <sys/types.h>
-#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
-extern char *stats_file;
-extern struct conf *conf;
+extern char* stats_file;
+extern struct conf* conf;
extern unsigned lock_staleness_limit;
-extern char *primary_config_path;
-extern char *secondary_config_path;
+extern char* primary_config_path;
+extern char* secondary_config_path;
-static struct counters *counter_updates;
+static struct counters* counter_updates;
#define FLAG_NOZERO 1 // don't zero with the -z option
#define FLAG_ALWAYS 2 // always show, even if zero
-#define FLAG_NEVER 4 // never show
+#define FLAG_NEVER 4 // never show
// Returns a formatted version of a statistics value, or NULL if the statistics
// line shouldn't be printed. Caller frees.
-typedef char *(*format_fn)(uint64_t value);
+typedef char* (*format_fn)(uint64_t value);
-static char *format_size_times_1024(uint64_t size);
-static char *format_timestamp(uint64_t timestamp);
-static void stats_flush_to_file(const char *sfile, struct counters *updates);
+static char* format_size_times_1024(uint64_t size);
+static char* format_timestamp(uint64_t timestamp);
+static void stats_flush_to_file(const char* sfile, struct counters* updates);
// Statistics fields in display order.
-static struct {
- enum stats stat;
- const char *id; // for --print-stats
- const char *message; // for --show-stats
- format_fn format; // NULL -> use plain integer format
- unsigned flags;
+static struct
+{
+ enum stats stat;
+ const char* id; // for --print-stats
+ const char* message; // for --show-stats
+ format_fn format; // NULL -> use plain integer format
+ unsigned flags;
} stats_info[] = {
- {
- STATS_ZEROTIMESTAMP,
- "stats_zeroed_timestamp",
- "stats zeroed",
- format_timestamp,
- FLAG_ALWAYS
- },
- {
- STATS_CACHEHIT_DIR,
- "direct_cache_hit",
- "cache hit (direct)",
- NULL,
- FLAG_ALWAYS
- },
- {
- STATS_CACHEHIT_CPP,
- "preprocessed_cache_hit",
- "cache hit (preprocessed)",
- NULL,
- FLAG_ALWAYS
- },
- {
- STATS_TOCACHE,
- "cache_miss",
- "cache miss",
- NULL,
- FLAG_ALWAYS
- },
- {
- STATS_LINK,
- "called_for_link",
- "called for link",
- NULL,
- 0
- },
- {
- STATS_PREPROCESSING,
- "called_for_preprocessing",
- "called for preprocessing",
- NULL,
- 0
- },
- {
- STATS_MULTIPLE,
- "multiple_source_files",
- "multiple source files",
- NULL,
- 0
- },
- {
- STATS_STDOUT,
- "compiler_produced_stdout",
- "compiler produced stdout",
- NULL,
- 0
- },
- {
- STATS_NOOUTPUT,
- "compiler_produced_no_output",
- "compiler produced no output",
- NULL,
- 0
- },
- {
- STATS_EMPTYOUTPUT,
- "compiler_produced_empty_output",
- "compiler produced empty output",
- NULL,
- 0
- },
- {
- STATS_STATUS,
- "compile_failed",
- "compile failed",
- NULL,
- 0
- },
- {
- STATS_ERROR,
- "internal_error",
- "ccache internal error",
- NULL,
- 0
- },
- {
- STATS_PREPROCESSOR,
- "preprocessor_error",
- "preprocessor error",
- NULL,
- 0
- },
- {
- STATS_CANTUSEPCH,
- "could_not_use_precompiled_header",
- "can't use precompiled header",
- NULL,
- 0
- },
- {
- STATS_COMPILER,
- "could_not_find_compiler",
- "couldn't find the compiler",
- NULL,
- 0
- },
- {
- STATS_MISSING,
- "missing_cache_file",
- "cache file missing",
- NULL,
- 0
- },
- {
- STATS_ARGS,
- "bad_compiler_arguments",
- "bad compiler arguments",
- NULL,
- 0
- },
- {
- STATS_SOURCELANG,
- "unsupported_source_language",
- "unsupported source language",
- NULL,
- 0
- },
- {
- STATS_COMPCHECK,
- "compiler_check_failed",
- "compiler check failed",
- NULL,
- 0
- },
- {
- STATS_CONFTEST,
- "autoconf_test",
- "autoconf compile/link",
- NULL,
- 0
- },
- {
- STATS_UNSUPPORTED_OPTION,
- "unsupported_compiler_option",
- "unsupported compiler option",
- NULL,
- 0
- },
- {
- STATS_UNSUPPORTED_DIRECTIVE,
- "unsupported_code_directive",
- "unsupported code directive",
- NULL,
- 0
- },
- {
- STATS_OUTSTDOUT,
- "output_to_stdout",
- "output to stdout",
- NULL,
- 0
- },
- {
- STATS_BADOUTPUTFILE,
- "bad_output_file",
- "could not write to output file",
- NULL,
- 0
- },
- {
- STATS_NOINPUT,
- "no_input_file",
- "no input file",
- NULL,
- 0
- },
- {
- STATS_BADEXTRAFILE,
- "error_hashing_extra_file",
- "error hashing extra file",
- NULL,
- 0
- },
- {
- STATS_NUMCLEANUPS,
- "cleanups_performed",
- "cleanups performed",
- NULL,
- FLAG_ALWAYS
- },
- {
- STATS_NUMFILES,
- "files_in_cache",
- "files in cache",
- NULL,
- FLAG_NOZERO|FLAG_ALWAYS
- },
- {
- STATS_TOTALSIZE,
- "cache_size_kibibyte",
- "cache size",
- format_size_times_1024,
- FLAG_NOZERO|FLAG_ALWAYS
- },
- {
- STATS_OBSOLETE_MAXFILES,
- "OBSOLETE",
- "OBSOLETE",
- NULL,
- FLAG_NOZERO|FLAG_NEVER
- },
- {
- STATS_OBSOLETE_MAXSIZE,
- "OBSOLETE",
- "OBSOLETE",
- NULL,
- FLAG_NOZERO|FLAG_NEVER
- },
- {
- STATS_NONE,
- NULL,
- NULL,
- NULL,
- 0
- }
-};
-
-static char *
+ {STATS_ZEROTIMESTAMP,
+ "stats_zeroed_timestamp",
+ "stats zeroed",
+ format_timestamp,
+ FLAG_ALWAYS},
+ {STATS_CACHEHIT_DIR,
+ "direct_cache_hit",
+ "cache hit (direct)",
+ NULL,
+ FLAG_ALWAYS},
+ {STATS_CACHEHIT_CPP,
+ "preprocessed_cache_hit",
+ "cache hit (preprocessed)",
+ NULL,
+ FLAG_ALWAYS},
+ {STATS_TOCACHE, "cache_miss", "cache miss", NULL, FLAG_ALWAYS},
+ {STATS_LINK, "called_for_link", "called for link", NULL, 0},
+ {STATS_PREPROCESSING,
+ "called_for_preprocessing",
+ "called for preprocessing",
+ NULL,
+ 0},
+ {STATS_MULTIPLE, "multiple_source_files", "multiple source files", NULL, 0},
+ {STATS_STDOUT,
+ "compiler_produced_stdout",
+ "compiler produced stdout",
+ NULL,
+ 0},
+ {STATS_NOOUTPUT,
+ "compiler_produced_no_output",
+ "compiler produced no output",
+ NULL,
+ 0},
+ {STATS_EMPTYOUTPUT,
+ "compiler_produced_empty_output",
+ "compiler produced empty output",
+ NULL,
+ 0},
+ {STATS_STATUS, "compile_failed", "compile failed", NULL, 0},
+ {STATS_ERROR, "internal_error", "ccache internal error", NULL, 0},
+ {STATS_PREPROCESSOR, "preprocessor_error", "preprocessor error", NULL, 0},
+ {STATS_CANTUSEPCH,
+ "could_not_use_precompiled_header",
+ "can't use precompiled header",
+ NULL,
+ 0},
+ {STATS_COMPILER,
+ "could_not_find_compiler",
+ "couldn't find the compiler",
+ NULL,
+ 0},
+ {STATS_MISSING, "missing_cache_file", "cache file missing", NULL, 0},
+ {STATS_ARGS, "bad_compiler_arguments", "bad compiler arguments", NULL, 0},
+ {STATS_SOURCELANG,
+ "unsupported_source_language",
+ "unsupported source language",
+ NULL,
+ 0},
+ {STATS_COMPCHECK, "compiler_check_failed", "compiler check failed", NULL, 0},
+ {STATS_CONFTEST, "autoconf_test", "autoconf compile/link", NULL, 0},
+ {STATS_UNSUPPORTED_OPTION,
+ "unsupported_compiler_option",
+ "unsupported compiler option",
+ NULL,
+ 0},
+ {STATS_UNSUPPORTED_DIRECTIVE,
+ "unsupported_code_directive",
+ "unsupported code directive",
+ NULL,
+ 0},
+ {STATS_OUTSTDOUT, "output_to_stdout", "output to stdout", NULL, 0},
+ {STATS_BADOUTPUTFILE,
+ "bad_output_file",
+ "could not write to output file",
+ NULL,
+ 0},
+ {STATS_NOINPUT, "no_input_file", "no input file", NULL, 0},
+ {STATS_BADEXTRAFILE,
+ "error_hashing_extra_file",
+ "error hashing extra file",
+ NULL,
+ 0},
+ {STATS_NUMCLEANUPS,
+ "cleanups_performed",
+ "cleanups performed",
+ NULL,
+ FLAG_ALWAYS},
+ {STATS_NUMFILES,
+ "files_in_cache",
+ "files in cache",
+ NULL,
+ FLAG_NOZERO | FLAG_ALWAYS},
+ {STATS_TOTALSIZE,
+ "cache_size_kibibyte",
+ "cache size",
+ format_size_times_1024,
+ FLAG_NOZERO | FLAG_ALWAYS},
+ {STATS_OBSOLETE_MAXFILES,
+ "OBSOLETE",
+ "OBSOLETE",
+ NULL,
+ FLAG_NOZERO | FLAG_NEVER},
+ {STATS_OBSOLETE_MAXSIZE,
+ "OBSOLETE",
+ "OBSOLETE",
+ NULL,
+ FLAG_NOZERO | FLAG_NEVER},
+ {STATS_NONE, NULL, NULL, NULL, 0}};
+
+static char*
format_size(uint64_t size)
{
- char *s = format_human_readable_size(size);
- reformat(&s, "%11s", s);
- return s;
+ char* s = format_human_readable_size(size);
+ reformat(&s, "%11s", s);
+ return s;
}
-static char *
+static char*
format_size_times_1024(uint64_t size)
{
- return format_size(size * 1024);
+ return format_size(size * 1024);
}
-static char *
+static char*
format_timestamp(uint64_t timestamp)
{
- if (timestamp > 0) {
- struct tm tm;
- localtime_r((time_t *)&timestamp, &tm);
- char buffer[100];
- strftime(buffer, sizeof(buffer), "%c", &tm);
- return format(" %s", buffer);
- } else {
- return NULL;
- }
+ if (timestamp > 0) {
+ struct tm tm;
+ localtime_r((time_t*)&timestamp, &tm);
+ char buffer[100];
+ strftime(buffer, sizeof(buffer), "%c", &tm);
+ return format(" %s", buffer);
+ } else {
+ return NULL;
+ }
}
// Parse a stats file from a buffer, adding to the counters.
static void
-parse_stats(struct counters *counters, const char *buf)
+parse_stats(struct counters* counters, const char* buf)
{
- size_t i = 0;
- const char *p = buf;
- while (true) {
- char *p2;
- long val = strtol(p, &p2, 10);
- if (p2 == p) {
- break;
- }
- if (counters->size < i + 1) {
- counters_resize(counters, i + 1);
- }
- counters->data[i] += val;
- i++;
- p = p2;
- }
+ size_t i = 0;
+ const char* p = buf;
+ while (true) {
+ char* p2;
+ long val = strtol(p, &p2, 10);
+ if (p2 == p) {
+ break;
+ }
+ if (counters->size < i + 1) {
+ counters_resize(counters, i + 1);
+ }
+ counters->data[i] += val;
+ i++;
+ p = p2;
+ }
}
// Write out a stats file.
void
-stats_write(const char *path, struct counters *counters)
+stats_write(const char* path, struct counters* counters)
{
- char *tmp_file = format("%s.tmp", path);
- FILE *f = create_tmp_file(&tmp_file, "wb");
- for (size_t i = 0; i < counters->size; i++) {
- if (fprintf(f, "%u\n", counters->data[i]) < 0) {
- fatal("Failed to write to %s", tmp_file);
- }
- }
- fclose(f);
- x_rename(tmp_file, path);
- free(tmp_file);
+ char* tmp_file = format("%s.tmp", path);
+ FILE* f = create_tmp_file(&tmp_file, "wb");
+ for (size_t i = 0; i < counters->size; i++) {
+ if (fprintf(f, "%u\n", counters->data[i]) < 0) {
+ fatal("Failed to write to %s", tmp_file);
+ }
+ }
+ fclose(f);
+ x_rename(tmp_file, path);
+ free(tmp_file);
}
static void
init_counter_updates(void)
{
- if (!counter_updates) {
- counter_updates = counters_init(STATS_END);
- }
+ if (!counter_updates) {
+ counter_updates = counters_init(STATS_END);
+ }
}
static double
-stats_hit_rate(struct counters *counters)
+stats_hit_rate(struct counters* counters)
{
- unsigned direct = counters->data[STATS_CACHEHIT_DIR];
- unsigned preprocessed = counters->data[STATS_CACHEHIT_CPP];
- unsigned hit = direct + preprocessed;
- unsigned miss = counters->data[STATS_TOCACHE];
- unsigned total = hit + miss;
- return total > 0 ? (100.0 * hit) / total : 0.0;
+ unsigned direct = counters->data[STATS_CACHEHIT_DIR];
+ unsigned preprocessed = counters->data[STATS_CACHEHIT_CPP];
+ unsigned hit = direct + preprocessed;
+ unsigned miss = counters->data[STATS_TOCACHE];
+ unsigned total = hit + miss;
+ return total > 0 ? (100.0 * hit) / total : 0.0;
}
static void
-stats_collect(struct counters *counters, time_t *last_updated)
+stats_collect(struct counters* counters, time_t* last_updated)
{
- struct stat st;
- unsigned zero_timestamp = 0;
-
- *last_updated = 0;
-
- // Add up the stats in each directory.
- for (int dir = -1; dir <= 0xF; dir++) {
- char *fname;
-
- if (dir == -1) {
- fname = format("%s/stats", conf->cache_dir);
- } else {
- fname = format("%s/%1x/stats", conf->cache_dir, dir);
- }
-
- counters->data[STATS_ZEROTIMESTAMP] = 0; // Don't add
- stats_read(fname, counters);
- zero_timestamp = MAX(counters->data[STATS_ZEROTIMESTAMP], zero_timestamp);
- if (stat(fname, &st) == 0 && st.st_mtime > *last_updated) {
- *last_updated = st.st_mtime;
- }
- free(fname);
- }
-
- counters->data[STATS_ZEROTIMESTAMP] = zero_timestamp;
+ struct stat st;
+ unsigned zero_timestamp = 0;
+
+ *last_updated = 0;
+
+ // Add up the stats in each directory.
+ for (int dir = -1; dir <= 0xF; dir++) {
+ char* fname;
+
+ if (dir == -1) {
+ fname = format("%s/stats", conf->cache_dir);
+ } else {
+ fname = format("%s/%1x/stats", conf->cache_dir, dir);
+ }
+
+ counters->data[STATS_ZEROTIMESTAMP] = 0; // Don't add
+ stats_read(fname, counters);
+ zero_timestamp = MAX(counters->data[STATS_ZEROTIMESTAMP], zero_timestamp);
+ if (stat(fname, &st) == 0 && st.st_mtime > *last_updated) {
+ *last_updated = st.st_mtime;
+ }
+ free(fname);
+ }
+
+ counters->data[STATS_ZEROTIMESTAMP] = zero_timestamp;
}
// Record that a number of bytes and files have been added to the cache. Size
// is in bytes.
void
-stats_update_size(const char *sfile, int64_t size, int files)
+stats_update_size(const char* sfile, int64_t size, int files)
{
- struct counters *updates;
- if (sfile == stats_file) {
- init_counter_updates();
- updates = counter_updates;
- } else {
- updates = counters_init(STATS_END);
- }
- updates->data[STATS_NUMFILES] += files;
- updates->data[STATS_TOTALSIZE] += size / 1024;
- if (sfile != stats_file) {
- stats_flush_to_file(sfile, updates);
- counters_free(updates);
- }
+ struct counters* updates;
+ if (sfile == stats_file) {
+ init_counter_updates();
+ updates = counter_updates;
+ } else {
+ updates = counters_init(STATS_END);
+ }
+ updates->data[STATS_NUMFILES] += files;
+ updates->data[STATS_TOTALSIZE] += size / 1024;
+ if (sfile != stats_file) {
+ stats_flush_to_file(sfile, updates);
+ counters_free(updates);
+ }
}
// Read in the stats from one directory and add to the counters.
void
-stats_read(const char *sfile, struct counters *counters)
+stats_read(const char* sfile, struct counters* counters)
{
- char *data = read_text_file(sfile, 1024);
- if (data) {
- parse_stats(counters, data);
- }
- free(data);
+ char* data = read_text_file(sfile, 1024);
+ if (data) {
+ parse_stats(counters, data);
+ }
+ free(data);
}
// Write counter updates in updates to sfile.
static void
-stats_flush_to_file(const char *sfile, struct counters *updates)
+stats_flush_to_file(const char* sfile, struct counters* updates)
{
- assert(conf);
-
- if (!conf->stats) {
- return;
- }
-
- if (!updates) {
- return;
- }
-
- bool should_flush = false;
- for (int i = 0; i < STATS_END; ++i) {
- if (updates->data[i] > 0) {
- should_flush = true;
- break;
- }
- }
- if (!should_flush) {
- return;
- }
-
- if (!sfile) {
- char *stats_dir;
-
- // A NULL sfile means that we didn't get past calculate_object_hash(), so
- // we just choose one of stats files in the 16 subdirectories.
- stats_dir = format("%s/%x", conf->cache_dir, hash_from_int(getpid()) % 16);
- sfile = format("%s/stats", stats_dir);
- free(stats_dir);
- }
-
- if (!lockfile_acquire(sfile, lock_staleness_limit)) {
- return;
- }
-
- struct counters *counters = counters_init(STATS_END);
- stats_read(sfile, counters);
- for (int i = 0; i < STATS_END; ++i) {
- counters->data[i] += updates->data[i];
- }
- stats_write(sfile, counters);
- lockfile_release(sfile);
-
- if (!str_eq(conf->log_file, "") || conf->debug) {
- for (int i = 0; i < STATS_END; ++i) {
- if (updates->data[stats_info[i].stat] != 0
- && !(stats_info[i].flags & FLAG_NOZERO)) {
- cc_log("Result: %s", stats_info[i].message);
- }
- }
- }
-
- char *subdir = x_dirname(sfile);
- bool need_cleanup = false;
-
- if (conf->max_files != 0
- && counters->data[STATS_NUMFILES] > conf->max_files / 16) {
- cc_log("Need to clean up %s since it holds %u files (limit: %u files)",
- subdir,
- counters->data[STATS_NUMFILES],
- conf->max_files / 16);
- need_cleanup = true;
- }
- if (conf->max_size != 0
- && counters->data[STATS_TOTALSIZE] > conf->max_size / 1024 / 16) {
- cc_log("Need to clean up %s since it holds %u KiB (limit: %lu KiB)",
- subdir,
- counters->data[STATS_TOTALSIZE],
- (unsigned long)conf->max_size / 1024 / 16);
- need_cleanup = true;
- }
-
- if (need_cleanup) {
- clean_up_dir(conf, subdir, conf->limit_multiple);
- }
-
- free(subdir);
- counters_free(counters);
+ assert(conf);
+
+ if (!conf->stats) {
+ return;
+ }
+
+ if (!updates) {
+ return;
+ }
+
+ bool should_flush = false;
+ for (int i = 0; i < STATS_END; ++i) {
+ if (updates->data[i] > 0) {
+ should_flush = true;
+ break;
+ }
+ }
+ if (!should_flush) {
+ return;
+ }
+
+ if (!sfile) {
+ char* stats_dir;
+
+ // A NULL sfile means that we didn't get past calculate_object_hash(), so
+ // we just choose one of stats files in the 16 subdirectories.
+ stats_dir = format("%s/%x", conf->cache_dir, hash_from_int(getpid()) % 16);
+ sfile = format("%s/stats", stats_dir);
+ free(stats_dir);
+ }
+
+ if (!lockfile_acquire(sfile, lock_staleness_limit)) {
+ return;
+ }
+
+ struct counters* counters = counters_init(STATS_END);
+ stats_read(sfile, counters);
+ for (int i = 0; i < STATS_END; ++i) {
+ counters->data[i] += updates->data[i];
+ }
+ stats_write(sfile, counters);
+ lockfile_release(sfile);
+
+ if (!str_eq(conf->log_file, "") || conf->debug) {
+ for (int i = 0; i < STATS_END; ++i) {
+ if (updates->data[stats_info[i].stat] != 0
+ && !(stats_info[i].flags & FLAG_NOZERO)) {
+ cc_log("Result: %s", stats_info[i].message);
+ }
+ }
+ }
+
+ char* subdir = x_dirname(sfile);
+ bool need_cleanup = false;
+
+ if (conf->max_files != 0
+ && counters->data[STATS_NUMFILES] > conf->max_files / 16) {
+ cc_log("Need to clean up %s since it holds %u files (limit: %u files)",
+ subdir,
+ counters->data[STATS_NUMFILES],
+ conf->max_files / 16);
+ need_cleanup = true;
+ }
+ if (conf->max_size != 0
+ && counters->data[STATS_TOTALSIZE] > conf->max_size / 1024 / 16) {
+ cc_log("Need to clean up %s since it holds %u KiB (limit: %lu KiB)",
+ subdir,
+ counters->data[STATS_TOTALSIZE],
+ (unsigned long)conf->max_size / 1024 / 16);
+ need_cleanup = true;
+ }
+
+ if (need_cleanup) {
+ clean_up_dir(conf, subdir, conf->limit_multiple);
+ }
+
+ free(subdir);
+ counters_free(counters);
}
// Write counter updates in counter_updates to disk.
void
stats_flush(void)
{
- stats_flush_to_file(stats_file, counter_updates);
- counters_free(counter_updates);
- counter_updates = NULL;
+ stats_flush_to_file(stats_file, counter_updates);
+ counters_free(counter_updates);
+ counter_updates = NULL;
}
// Update a normal stat.
void
stats_update(enum stats stat)
{
- assert(stat > STATS_NONE && stat < STATS_END);
- init_counter_updates();
- counter_updates->data[stat]++;
+ assert(stat > STATS_NONE && stat < STATS_END);
+ init_counter_updates();
+ counter_updates->data[stat]++;
}
// Get the pending update of a counter value.
unsigned
stats_get_pending(enum stats stat)
{
- init_counter_updates();
- return counter_updates->data[stat];
+ init_counter_updates();
+ return counter_updates->data[stat];
}
// Sum and display the total stats for all cache dirs.
void
stats_summary(void)
{
- assert(conf);
-
- struct counters *counters = counters_init(STATS_END);
- time_t last_updated;
- stats_collect(counters, &last_updated);
-
- printf("cache directory %s\n", conf->cache_dir);
- printf("primary config %s\n",
- primary_config_path ? primary_config_path : "");
- printf("secondary config (readonly) %s\n",
- secondary_config_path ? secondary_config_path : "");
- if (last_updated > 0) {
- struct tm tm;
- localtime_r(&last_updated, &tm);
- char timestamp[100];
- strftime(timestamp, sizeof(timestamp), "%c", &tm);
- printf("stats updated %s\n", timestamp);
- }
-
- // ...and display them.
- for (int i = 0; stats_info[i].message; i++) {
- enum stats stat = stats_info[i].stat;
-
- if (stats_info[i].flags & FLAG_NEVER) {
- continue;
- }
- if (counters->data[stat] == 0 && !(stats_info[i].flags & FLAG_ALWAYS)) {
- continue;
- }
-
- char *value;
- if (stats_info[i].format) {
- value = stats_info[i].format(counters->data[stat]);
- } else {
- value = format("%8u", counters->data[stat]);
- }
- if (value) {
- printf("%-31s %s\n", stats_info[i].message, value);
- free(value);
- }
-
- if (stat == STATS_TOCACHE) {
- double percent = stats_hit_rate(counters);
- printf("cache hit rate %6.2f %%\n", percent);
- }
- }
-
- if (conf->max_files != 0) {
- printf("max files %8u\n", conf->max_files);
- }
- if (conf->max_size != 0) {
- char *value = format_size(conf->max_size);
- printf("max cache size %s\n", value);
- free(value);
- }
-
- counters_free(counters);
+ assert(conf);
+
+ struct counters* counters = counters_init(STATS_END);
+ time_t last_updated;
+ stats_collect(counters, &last_updated);
+
+ printf("cache directory %s\n", conf->cache_dir);
+ printf("primary config %s\n",
+ primary_config_path ? primary_config_path : "");
+ printf("secondary config (readonly) %s\n",
+ secondary_config_path ? secondary_config_path : "");
+ if (last_updated > 0) {
+ struct tm tm;
+ localtime_r(&last_updated, &tm);
+ char timestamp[100];
+ strftime(timestamp, sizeof(timestamp), "%c", &tm);
+ printf("stats updated %s\n", timestamp);
+ }
+
+ // ...and display them.
+ for (int i = 0; stats_info[i].message; i++) {
+ enum stats stat = stats_info[i].stat;
+
+ if (stats_info[i].flags & FLAG_NEVER) {
+ continue;
+ }
+ if (counters->data[stat] == 0 && !(stats_info[i].flags & FLAG_ALWAYS)) {
+ continue;
+ }
+
+ char* value;
+ if (stats_info[i].format) {
+ value = stats_info[i].format(counters->data[stat]);
+ } else {
+ value = format("%8u", counters->data[stat]);
+ }
+ if (value) {
+ printf("%-31s %s\n", stats_info[i].message, value);
+ free(value);
+ }
+
+ if (stat == STATS_TOCACHE) {
+ double percent = stats_hit_rate(counters);
+ printf("cache hit rate %6.2f %%\n", percent);
+ }
+ }
+
+ if (conf->max_files != 0) {
+ printf("max files %8u\n", conf->max_files);
+ }
+ if (conf->max_size != 0) {
+ char* value = format_size(conf->max_size);
+ printf("max cache size %s\n", value);
+ free(value);
+ }
+
+ counters_free(counters);
}
// Print machine-parsable (tab-separated) statistics counters.
void
stats_print(void)
{
- assert(conf);
+ assert(conf);
- struct counters *counters = counters_init(STATS_END);
- time_t last_updated;
- stats_collect(counters, &last_updated);
+ struct counters* counters = counters_init(STATS_END);
+ time_t last_updated;
+ stats_collect(counters, &last_updated);
- printf("stats_updated_timestamp\t%llu\n", (unsigned long long)last_updated);
+ printf("stats_updated_timestamp\t%llu\n", (unsigned long long)last_updated);
- for (int i = 0; stats_info[i].message; i++) {
- if (!(stats_info[i].flags & FLAG_NEVER)) {
- printf("%s\t%u\n", stats_info[i].id, counters->data[stats_info[i].stat]);
- }
- }
+ for (int i = 0; stats_info[i].message; i++) {
+ if (!(stats_info[i].flags & FLAG_NEVER)) {
+ printf("%s\t%u\n", stats_info[i].id, counters->data[stats_info[i].stat]);
+ }
+ }
- counters_free(counters);
+ counters_free(counters);
}
// Zero all the stats structures.
void
stats_zero(void)
{
- assert(conf);
-
- char *fname = format("%s/stats", conf->cache_dir);
- x_unlink(fname);
- free(fname);
-
- time_t timestamp = time(NULL);
-
- for (int dir = 0; dir <= 0xF; dir++) {
- struct counters *counters = counters_init(STATS_END);
- struct stat st;
- fname = format("%s/%1x/stats", conf->cache_dir, dir);
- if (stat(fname, &st) != 0) {
- // No point in trying to reset the stats file if it doesn't exist.
- free(fname);
- continue;
- }
- if (lockfile_acquire(fname, lock_staleness_limit)) {
- stats_read(fname, counters);
- for (unsigned i = 0; stats_info[i].message; i++) {
- if (!(stats_info[i].flags & FLAG_NOZERO)) {
- counters->data[stats_info[i].stat] = 0;
- }
- }
- counters->data[STATS_ZEROTIMESTAMP] = timestamp;
- stats_write(fname, counters);
- lockfile_release(fname);
- }
- counters_free(counters);
- free(fname);
- }
+ assert(conf);
+
+ char* fname = format("%s/stats", conf->cache_dir);
+ x_unlink(fname);
+ free(fname);
+
+ time_t timestamp = time(NULL);
+
+ for (int dir = 0; dir <= 0xF; dir++) {
+ struct counters* counters = counters_init(STATS_END);
+ struct stat st;
+ fname = format("%s/%1x/stats", conf->cache_dir, dir);
+ if (stat(fname, &st) != 0) {
+ // No point in trying to reset the stats file if it doesn't exist.
+ free(fname);
+ continue;
+ }
+ if (lockfile_acquire(fname, lock_staleness_limit)) {
+ stats_read(fname, counters);
+ for (unsigned i = 0; stats_info[i].message; i++) {
+ if (!(stats_info[i].flags & FLAG_NOZERO)) {
+ counters->data[stats_info[i].stat] = 0;
+ }
+ }
+ counters->data[STATS_ZEROTIMESTAMP] = timestamp;
+ stats_write(fname, counters);
+ lockfile_release(fname);
+ }
+ counters_free(counters);
+ free(fname);
+ }
}
// Get the per-directory limits.
void
-stats_get_obsolete_limits(const char *dir, unsigned *maxfiles,
- uint64_t *maxsize)
+stats_get_obsolete_limits(const char* dir,
+ unsigned* maxfiles,
+ uint64_t* maxsize)
{
- struct counters *counters = counters_init(STATS_END);
- char *sname = format("%s/stats", dir);
- stats_read(sname, counters);
- *maxfiles = counters->data[STATS_OBSOLETE_MAXFILES];
- *maxsize = (uint64_t)counters->data[STATS_OBSOLETE_MAXSIZE] * 1024;
- free(sname);
- counters_free(counters);
+ struct counters* counters = counters_init(STATS_END);
+ char* sname = format("%s/stats", dir);
+ stats_read(sname, counters);
+ *maxfiles = counters->data[STATS_OBSOLETE_MAXFILES];
+ *maxsize = (uint64_t)counters->data[STATS_OBSOLETE_MAXSIZE] * 1024;
+ free(sname);
+ counters_free(counters);
}
// Set the per-directory sizes.
void
-stats_set_sizes(const char *dir, unsigned num_files, uint64_t total_size)
+stats_set_sizes(const char* dir, unsigned num_files, uint64_t total_size)
{
- struct counters *counters = counters_init(STATS_END);
- char *statsfile = format("%s/stats", dir);
- if (lockfile_acquire(statsfile, lock_staleness_limit)) {
- stats_read(statsfile, counters);
- counters->data[STATS_NUMFILES] = num_files;
- counters->data[STATS_TOTALSIZE] = total_size / 1024;
- stats_write(statsfile, counters);
- lockfile_release(statsfile);
- }
- free(statsfile);
- counters_free(counters);
+ struct counters* counters = counters_init(STATS_END);
+ char* statsfile = format("%s/stats", dir);
+ if (lockfile_acquire(statsfile, lock_staleness_limit)) {
+ stats_read(statsfile, counters);
+ counters->data[STATS_NUMFILES] = num_files;
+ counters->data[STATS_TOTALSIZE] = total_size / 1024;
+ stats_write(statsfile, counters);
+ lockfile_release(statsfile);
+ }
+ free(statsfile);
+ counters_free(counters);
}
// Count directory cleanup run.
void
-stats_add_cleanup(const char *dir, unsigned count)
+stats_add_cleanup(const char* dir, unsigned count)
{
- struct counters *counters = counters_init(STATS_END);
- char *statsfile = format("%s/stats", dir);
- if (lockfile_acquire(statsfile, lock_staleness_limit)) {
- stats_read(statsfile, counters);
- counters->data[STATS_NUMCLEANUPS] += count;
- stats_write(statsfile, counters);
- lockfile_release(statsfile);
- }
- free(statsfile);
- counters_free(counters);
+ struct counters* counters = counters_init(STATS_END);
+ char* statsfile = format("%s/stats", dir);
+ if (lockfile_acquire(statsfile, lock_staleness_limit)) {
+ stats_read(statsfile, counters);
+ counters->data[STATS_NUMCLEANUPS] += count;
+ stats_write(statsfile, counters);
+ lockfile_release(statsfile);
+ }
+ free(statsfile);
+ counters_free(counters);
}
diff --git a/src/system.hpp b/src/system.hpp
index 72a98dbf..e95f3e72 100644
--- a/src/system.hpp
+++ b/src/system.hpp
@@ -30,12 +30,12 @@
#include <sys/file.h>
#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
+# include <sys/mman.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
+# include <sys/wait.h>
#endif
#include <assert.h>
@@ -64,29 +64,29 @@
extern int usleep(useconds_t);
#endif
-extern char **environ;
+extern char** environ;
#ifndef ESTALE
-#define ESTALE -1
+# define ESTALE -1
#endif
extern "C" {
#if !HAVE_VSNPRINTF
- int rpl_vsnprintf(char *, size_t, const char *, va_list);
- #define vsnprintf rpl_vsnprintf
+int rpl_vsnprintf(char*, size_t, const char*, va_list);
+# define vsnprintf rpl_vsnprintf
#endif
#if !HAVE_SNPRINTF
- int rpl_snprintf(char *, size_t, const char *, ...);
- #define snprintf rpl_snprintf
+int rpl_snprintf(char*, size_t, const char*, ...);
+# define snprintf rpl_snprintf
#endif
#if !HAVE_VASPRINTF
- int rpl_vasprintf(char **, const char *, va_list);
- #define vasprintf rpl_vasprintf
+int rpl_vasprintf(char**, const char*, va_list);
+# define vasprintf rpl_vasprintf
#endif
#if !HAVE_ASPRINTF
- int rpl_asprintf(char **, const char *, ...);
- #define asprintf rpl_asprintf
+int rpl_asprintf(char**, const char*, ...);
+# define asprintf rpl_asprintf
#endif
} // extern "C"
diff --git a/src/unify.cpp b/src/unify.cpp
index e2f700e2..7a7744ed 100644
--- a/src/unify.cpp
+++ b/src/unify.cpp
@@ -29,236 +29,235 @@
// syntactic errors is important to cope with C/C++ extensions in the local
// compiler (for example, inline assembly systems).
+#include "unify.hpp"
+
#include "ccache.hpp"
#include "hash.hpp"
-#include "unify.hpp"
static bool print_unified = true;
-static const char *const s_tokens[] = {
- "...", ">>=", "<<=", "+=", "-=", "*=", "/=", "%=", "&=", "^=",
- "|=", ">>", "<<", "++", "--", "->", "&&", "||", "<=", ">=",
- "==", "!=", ";", "{", "<%", "}", "%>", ",", ":", "=",
- "(", ")", "[", "<:", "]", ":>", ".", "&", "!", "~",
- "-", "+", "*", "/", "%", "<", ">", "^", "|", "?",
- 0
-};
+static const char* const s_tokens[] = {
+ "...", ">>=", "<<=", "+=", "-=", "*=", "/=", "%=", "&=", "^=", "|=",
+ ">>", "<<", "++", "--", "->", "&&", "||", "<=", ">=", "==", "!=",
+ ";", "{", "<%", "}", "%>", ",", ":", "=", "(", ")", "[",
+ "<:", "]", ":>", ".", "&", "!", "~", "-", "+", "*", "/",
+ "%", "<", ">", "^", "|", "?", 0};
#define C_ALPHA 1
#define C_SPACE 2
#define C_TOKEN 4
#define C_QUOTE 8
#define C_DIGIT 16
-#define C_HEX 32
+#define C_HEX 32
#define C_FLOAT 64
-#define C_SIGN 128
+#define C_SIGN 128
-static struct {
- unsigned char type;
- unsigned char num_toks;
- const char *toks[7];
+static struct
+{
+ unsigned char type;
+ unsigned char num_toks;
+ const char* toks[7];
} tokens[256];
// Build up the table used by the unifier.
static void
build_table(void)
{
- static bool done;
- if (done) {
- return;
- }
- done = true;
+ static bool done;
+ if (done) {
+ return;
+ }
+ done = true;
- memset(tokens, 0, sizeof(tokens));
- for (unsigned char c = 0; c < 128; c++) {
- if (isalpha(c) || c == '_') {
- tokens[c].type |= C_ALPHA;
- }
- if (isdigit(c)) {
- tokens[c].type |= C_DIGIT;
- }
- if (isspace(c)) {
- tokens[c].type |= C_SPACE;
- }
- if (isxdigit(c)) {
- tokens[c].type |= C_HEX;
- }
- }
- tokens[static_cast<unsigned char>('\'')].type |= C_QUOTE;
- tokens[static_cast<unsigned char>('"')].type |= C_QUOTE;
- tokens[static_cast<unsigned char>('l')].type |= C_FLOAT;
- tokens[static_cast<unsigned char>('L')].type |= C_FLOAT;
- tokens[static_cast<unsigned char>('f')].type |= C_FLOAT;
- tokens[static_cast<unsigned char>('F')].type |= C_FLOAT;
- tokens[static_cast<unsigned char>('U')].type |= C_FLOAT;
- tokens[static_cast<unsigned char>('u')].type |= C_FLOAT;
+ memset(tokens, 0, sizeof(tokens));
+ for (unsigned char c = 0; c < 128; c++) {
+ if (isalpha(c) || c == '_') {
+ tokens[c].type |= C_ALPHA;
+ }
+ if (isdigit(c)) {
+ tokens[c].type |= C_DIGIT;
+ }
+ if (isspace(c)) {
+ tokens[c].type |= C_SPACE;
+ }
+ if (isxdigit(c)) {
+ tokens[c].type |= C_HEX;
+ }
+ }
+ tokens[static_cast<unsigned char>('\'')].type |= C_QUOTE;
+ tokens[static_cast<unsigned char>('"')].type |= C_QUOTE;
+ tokens[static_cast<unsigned char>('l')].type |= C_FLOAT;
+ tokens[static_cast<unsigned char>('L')].type |= C_FLOAT;
+ tokens[static_cast<unsigned char>('f')].type |= C_FLOAT;
+ tokens[static_cast<unsigned char>('F')].type |= C_FLOAT;
+ tokens[static_cast<unsigned char>('U')].type |= C_FLOAT;
+ tokens[static_cast<unsigned char>('u')].type |= C_FLOAT;
- tokens[static_cast<unsigned char>('-')].type |= C_SIGN;
- tokens[static_cast<unsigned char>('+')].type |= C_SIGN;
+ tokens[static_cast<unsigned char>('-')].type |= C_SIGN;
+ tokens[static_cast<unsigned char>('+')].type |= C_SIGN;
- for (int i = 0; s_tokens[i]; i++) {
- unsigned char c = s_tokens[i][0];
- tokens[c].type |= C_TOKEN;
- tokens[c].toks[tokens[c].num_toks] = s_tokens[i];
- tokens[c].num_toks++;
- }
+ for (int i = 0; s_tokens[i]; i++) {
+ unsigned char c = s_tokens[i][0];
+ tokens[c].type |= C_TOKEN;
+ tokens[c].toks[tokens[c].num_toks] = s_tokens[i];
+ tokens[c].num_toks++;
+ }
}
// Buffer up characters before hashing them.
static void
-pushchar(struct hash *hash, unsigned char c)
+pushchar(struct hash* hash, unsigned char c)
{
- static unsigned char buf[64];
- static size_t len;
+ static unsigned char buf[64];
+ static size_t len;
- if (c == 0) {
- if (len > 0) {
- hash_buffer(hash, (char *)buf, len);
- if (print_unified) {
- printf("%.*s", (int) len, buf);
- }
- len = 0;
- }
- return;
- }
+ if (c == 0) {
+ if (len > 0) {
+ hash_buffer(hash, (char*)buf, len);
+ if (print_unified) {
+ printf("%.*s", (int)len, buf);
+ }
+ len = 0;
+ }
+ return;
+ }
- buf[len++] = c;
- if (len == 64) {
- hash_buffer(hash, (char *)buf, len);
- if (print_unified) {
- printf("%.*s", (int) len, buf);
- }
- len = 0;
- }
+ buf[len++] = c;
+ if (len == 64) {
+ hash_buffer(hash, (char*)buf, len);
+ if (print_unified) {
+ printf("%.*s", (int)len, buf);
+ }
+ len = 0;
+ }
}
// Hash some C/C++ code after unifying.
static void
-unify(struct hash *hash, unsigned char *p, size_t size)
+unify(struct hash* hash, unsigned char* p, size_t size)
{
- build_table();
+ build_table();
- for (size_t ofs = 0; ofs < size;) {
- if (p[ofs] == '#') {
- if ((size-ofs) > 2 && p[ofs+1] == ' ' && isdigit(p[ofs+2])) {
- do {
- ofs++;
- } while (ofs < size && p[ofs] != '\n');
- ofs++;
- } else {
- do {
- pushchar(hash, p[ofs]);
- ofs++;
- } while (ofs < size && p[ofs] != '\n');
- pushchar(hash, '\n');
- ofs++;
- }
- continue;
- }
+ for (size_t ofs = 0; ofs < size;) {
+ if (p[ofs] == '#') {
+ if ((size - ofs) > 2 && p[ofs + 1] == ' ' && isdigit(p[ofs + 2])) {
+ do {
+ ofs++;
+ } while (ofs < size && p[ofs] != '\n');
+ ofs++;
+ } else {
+ do {
+ pushchar(hash, p[ofs]);
+ ofs++;
+ } while (ofs < size && p[ofs] != '\n');
+ pushchar(hash, '\n');
+ ofs++;
+ }
+ continue;
+ }
- if (tokens[p[ofs]].type & C_ALPHA) {
- do {
- pushchar(hash, p[ofs]);
- ofs++;
- } while (ofs < size && (tokens[p[ofs]].type & (C_ALPHA|C_DIGIT)));
- pushchar(hash, '\n');
- continue;
- }
+ if (tokens[p[ofs]].type & C_ALPHA) {
+ do {
+ pushchar(hash, p[ofs]);
+ ofs++;
+ } while (ofs < size && (tokens[p[ofs]].type & (C_ALPHA | C_DIGIT)));
+ pushchar(hash, '\n');
+ continue;
+ }
- if (tokens[p[ofs]].type & C_DIGIT) {
- do {
- pushchar(hash, p[ofs]);
- ofs++;
- } while (ofs < size &&
- ((tokens[p[ofs]].type & C_DIGIT) || p[ofs] == '.'));
- if (ofs < size && (p[ofs] == 'x' || p[ofs] == 'X')) {
- do {
- pushchar(hash, p[ofs]);
- ofs++;
- } while (ofs < size && (tokens[p[ofs]].type & C_HEX));
- }
- if (ofs < size && (p[ofs] == 'E' || p[ofs] == 'e')) {
- pushchar(hash, p[ofs]);
- ofs++;
- while (ofs < size && (tokens[p[ofs]].type & (C_DIGIT|C_SIGN))) {
- pushchar(hash, p[ofs]);
- ofs++;
- }
- }
- while (ofs < size && (tokens[p[ofs]].type & C_FLOAT)) {
- pushchar(hash, p[ofs]);
- ofs++;
- }
- pushchar(hash, '\n');
- continue;
- }
+ if (tokens[p[ofs]].type & C_DIGIT) {
+ do {
+ pushchar(hash, p[ofs]);
+ ofs++;
+ } while (ofs < size
+ && ((tokens[p[ofs]].type & C_DIGIT) || p[ofs] == '.'));
+ if (ofs < size && (p[ofs] == 'x' || p[ofs] == 'X')) {
+ do {
+ pushchar(hash, p[ofs]);
+ ofs++;
+ } while (ofs < size && (tokens[p[ofs]].type & C_HEX));
+ }
+ if (ofs < size && (p[ofs] == 'E' || p[ofs] == 'e')) {
+ pushchar(hash, p[ofs]);
+ ofs++;
+ while (ofs < size && (tokens[p[ofs]].type & (C_DIGIT | C_SIGN))) {
+ pushchar(hash, p[ofs]);
+ ofs++;
+ }
+ }
+ while (ofs < size && (tokens[p[ofs]].type & C_FLOAT)) {
+ pushchar(hash, p[ofs]);
+ ofs++;
+ }
+ pushchar(hash, '\n');
+ continue;
+ }
- if (tokens[p[ofs]].type & C_SPACE) {
- do {
- ofs++;
- } while (ofs < size && (tokens[p[ofs]].type & C_SPACE));
- continue;
- }
+ if (tokens[p[ofs]].type & C_SPACE) {
+ do {
+ ofs++;
+ } while (ofs < size && (tokens[p[ofs]].type & C_SPACE));
+ continue;
+ }
- if (tokens[p[ofs]].type & C_QUOTE) {
- unsigned char q = p[ofs];
- pushchar(hash, p[ofs]);
- do {
- ofs++;
- while (ofs < size-1 && p[ofs] == '\\') {
- pushchar(hash, p[ofs]);
- pushchar(hash, p[ofs+1]);
- ofs += 2;
- }
- pushchar(hash, p[ofs]);
- } while (ofs < size && p[ofs] != q);
- pushchar(hash, '\n');
- ofs++;
- continue;
- }
+ if (tokens[p[ofs]].type & C_QUOTE) {
+ unsigned char q = p[ofs];
+ pushchar(hash, p[ofs]);
+ do {
+ ofs++;
+ while (ofs < size - 1 && p[ofs] == '\\') {
+ pushchar(hash, p[ofs]);
+ pushchar(hash, p[ofs + 1]);
+ ofs += 2;
+ }
+ pushchar(hash, p[ofs]);
+ } while (ofs < size && p[ofs] != q);
+ pushchar(hash, '\n');
+ ofs++;
+ continue;
+ }
- if (tokens[p[ofs]].type & C_TOKEN) {
- unsigned char q = p[ofs];
- int i;
- for (i = 0; i < tokens[q].num_toks; i++) {
- const unsigned char *s = (const unsigned char *)tokens[q].toks[i];
- int len = strlen((const char *)s);
- if (size >= ofs+len && memcmp(&p[ofs], s, len) == 0) {
- int j;
- for (j = 0; s[j]; j++) {
- pushchar(hash, s[j]);
- ofs++;
- }
- pushchar(hash, '\n');
- break;
- }
- }
- if (i < tokens[q].num_toks) {
- continue;
- }
- }
+ if (tokens[p[ofs]].type & C_TOKEN) {
+ unsigned char q = p[ofs];
+ int i;
+ for (i = 0; i < tokens[q].num_toks; i++) {
+ const unsigned char* s = (const unsigned char*)tokens[q].toks[i];
+ int len = strlen((const char*)s);
+ if (size >= ofs + len && memcmp(&p[ofs], s, len) == 0) {
+ int j;
+ for (j = 0; s[j]; j++) {
+ pushchar(hash, s[j]);
+ ofs++;
+ }
+ pushchar(hash, '\n');
+ break;
+ }
+ }
+ if (i < tokens[q].num_toks) {
+ continue;
+ }
+ }
- pushchar(hash, p[ofs]);
- pushchar(hash, '\n');
- ofs++;
- }
- pushchar(hash, 0);
+ pushchar(hash, p[ofs]);
+ pushchar(hash, '\n');
+ ofs++;
+ }
+ pushchar(hash, 0);
}
-
// Hash a file that consists of preprocessor output, but remove any line number
// information from the hash.
int
-unify_hash(struct hash *hash, const char *fname, bool debug)
+unify_hash(struct hash* hash, const char* fname, bool debug)
{
- char *data;
- size_t size;
- if (!read_file(fname, 0, &data, &size)) {
- stats_update(STATS_PREPROCESSOR);
- return -1;
- }
- print_unified = debug;
- unify(hash, (unsigned char *)data, size);
- free(data);
- return 0;
+ char* data;
+ size_t size;
+ if (!read_file(fname, 0, &data, &size)) {
+ stats_update(STATS_PREPROCESSOR);
+ return -1;
+ }
+ print_unified = debug;
+ unify(hash, (unsigned char*)data, size);
+ free(data);
+ return 0;
}
diff --git a/src/unify.hpp b/src/unify.hpp
index eb6e6c4b..3629f693 100644
--- a/src/unify.hpp
+++ b/src/unify.hpp
@@ -20,4 +20,4 @@
#include "hash.hpp"
-int unify_hash(struct hash *hash, const char *fname, bool print);
+int unify_hash(struct hash* hash, const char* fname, bool print);
diff --git a/src/util.cpp b/src/util.cpp
index ca0ec00b..26c7e499 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -20,18 +20,18 @@
#include "ccache.hpp"
#ifdef HAVE_PWD_H
-#include <pwd.h>
+# include <pwd.h>
#endif
#ifdef HAVE_SYSLOG_H
-#include <syslog.h>
+# include <syslog.h>
#endif
#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
+# include <sys/time.h>
#endif
#ifdef __linux__
# ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
+# include <sys/ioctl.h>
# endif
# ifdef HAVE_LINUX_FS_H
# include <linux/fs.h>
@@ -50,22 +50,22 @@
#endif
#ifdef _WIN32
-#include <windows.h>
-#include <sys/locking.h>
-#include <psapi.h>
-#include <tchar.h>
+# include <psapi.h>
+# include <sys/locking.h>
+# include <tchar.h>
+# include <windows.h>
#endif
-extern const struct conf *conf;
+extern const struct conf* conf;
// Destination for conf->log_file.
-static FILE *logfile;
+static FILE* logfile;
// Whether to use syslog() instead.
static bool use_syslog;
// Buffer used for logs in conf->debug mode.
-static char *debug_log_buffer;
+static char* debug_log_buffer;
// Allocated debug_log_buffer size.
static size_t debug_log_buffer_capacity;
@@ -78,96 +78,100 @@ static size_t debug_log_size;
static bool
init_log(void)
{
- if (debug_log_buffer || logfile || use_syslog) {
- return true;
- }
- assert(conf);
- if (conf->debug) {
- debug_log_buffer_capacity = DEBUG_LOG_BUFFER_MARGIN;
- debug_log_buffer = static_cast<char*>(x_malloc(debug_log_buffer_capacity));
- debug_log_size = 0;
- }
- if (str_eq(conf->log_file, "")) {
- return conf->debug;
- }
+ if (debug_log_buffer || logfile || use_syslog) {
+ return true;
+ }
+ assert(conf);
+ if (conf->debug) {
+ debug_log_buffer_capacity = DEBUG_LOG_BUFFER_MARGIN;
+ debug_log_buffer = static_cast<char*>(x_malloc(debug_log_buffer_capacity));
+ debug_log_size = 0;
+ }
+ if (str_eq(conf->log_file, "")) {
+ return conf->debug;
+ }
#ifdef HAVE_SYSLOG
- if (str_eq(conf->log_file, "syslog")) {
- use_syslog = true;
- openlog("ccache", LOG_PID, LOG_USER);
- return true;
- }
+ if (str_eq(conf->log_file, "syslog")) {
+ use_syslog = true;
+ openlog("ccache", LOG_PID, LOG_USER);
+ return true;
+ }
#endif
- logfile = fopen(conf->log_file, "a");
- if (logfile) {
+ logfile = fopen(conf->log_file, "a");
+ if (logfile) {
#ifndef _WIN32
- set_cloexec_flag(fileno(logfile));
+ set_cloexec_flag(fileno(logfile));
#endif
- return true;
- } else {
- return false;
- }
+ return true;
+ } else {
+ return false;
+ }
}
static void
-append_to_debug_log(const char *s, size_t len)
+append_to_debug_log(const char* s, size_t len)
{
- assert(debug_log_buffer);
- if (debug_log_size + len + 1 > debug_log_buffer_capacity) {
- debug_log_buffer_capacity += len + 1 + DEBUG_LOG_BUFFER_MARGIN;
- debug_log_buffer = static_cast<char*>(
- x_realloc(debug_log_buffer, debug_log_buffer_capacity));
- }
- memcpy(debug_log_buffer + debug_log_size, s, len);
- debug_log_size += len;
+ assert(debug_log_buffer);
+ if (debug_log_size + len + 1 > debug_log_buffer_capacity) {
+ debug_log_buffer_capacity += len + 1 + DEBUG_LOG_BUFFER_MARGIN;
+ debug_log_buffer = static_cast<char*>(
+ x_realloc(debug_log_buffer, debug_log_buffer_capacity));
+ }
+ memcpy(debug_log_buffer + debug_log_size, s, len);
+ debug_log_size += len;
}
static void
log_prefix(bool log_updated_time)
{
- static char prefix[200];
+ static char prefix[200];
#ifdef HAVE_GETTIMEOFDAY
- if (log_updated_time) {
- char timestamp[100];
- struct tm tm;
- struct timeval tv;
- gettimeofday(&tv, NULL);
-#ifdef __MINGW64_VERSION_MAJOR
- localtime_r((time_t *)&tv.tv_sec, &tm);
-#else
- localtime_r(&tv.tv_sec, &tm);
-#endif
- strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S", &tm);
- snprintf(prefix, sizeof(prefix),
- "[%s.%06d %-5d] ", timestamp, (int)tv.tv_usec, (int)getpid());
- }
+ if (log_updated_time) {
+ char timestamp[100];
+ struct tm tm;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+# ifdef __MINGW64_VERSION_MAJOR
+ localtime_r((time_t*)&tv.tv_sec, &tm);
+# else
+ localtime_r(&tv.tv_sec, &tm);
+# endif
+ strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S", &tm);
+ snprintf(prefix,
+ sizeof(prefix),
+ "[%s.%06d %-5d] ",
+ timestamp,
+ (int)tv.tv_usec,
+ (int)getpid());
+ }
#else
- snprintf(prefix, sizeof(prefix), "[%-5d] ", (int)getpid());
+ snprintf(prefix, sizeof(prefix), "[%-5d] ", (int)getpid());
#endif
- if (logfile) {
- fputs(prefix, logfile);
- }
+ if (logfile) {
+ fputs(prefix, logfile);
+ }
#ifdef HAVE_SYSLOG
- if (use_syslog) {
- // prefix information will be added by syslog
- }
+ if (use_syslog) {
+ // prefix information will be added by syslog
+ }
#endif
- if (debug_log_buffer) {
- append_to_debug_log(prefix, strlen(prefix));
- }
+ if (debug_log_buffer) {
+ append_to_debug_log(prefix, strlen(prefix));
+ }
}
static long
-path_max(const char *path)
+path_max(const char* path)
{
#ifdef PATH_MAX
- (void)path;
- return PATH_MAX;
+ (void)path;
+ return PATH_MAX;
#elif defined(MAXPATHLEN)
- (void)path;
- return MAXPATHLEN;
+ (void)path;
+ return MAXPATHLEN;
#elif defined(_PC_PATH_MAX)
- long maxlen = pathconf(path, _PC_PATH_MAX);
- return maxlen >= 4096 ? maxlen : 4096;
+ long maxlen = pathconf(path, _PC_PATH_MAX);
+ return maxlen >= 4096 ? maxlen : 4096;
#endif
}
@@ -177,185 +181,186 @@ static void warn_log_fail(void) ATTR_NORETURN;
static void
warn_log_fail(void)
{
- // Note: Can't call fatal() since that would lead to recursion.
- fprintf(stderr, "ccache: error: Failed to write to %s: %s\n",
- conf->log_file, strerror(errno));
- x_exit(EXIT_FAILURE);
+ // Note: Can't call fatal() since that would lead to recursion.
+ fprintf(stderr,
+ "ccache: error: Failed to write to %s: %s\n",
+ conf->log_file,
+ strerror(errno));
+ x_exit(EXIT_FAILURE);
}
static void
-vlog(const char *format, va_list ap, bool log_updated_time)
-{
- if (!init_log()) {
- return;
- }
-
- va_list aq;
- va_copy(aq, ap);
- log_prefix(log_updated_time);
- if (logfile) {
- int rc1 = vfprintf(logfile, format, ap);
- int rc2 = fprintf(logfile, "\n");
- if (rc1 < 0 || rc2 < 0) {
- warn_log_fail();
- }
- }
+vlog(const char* format, va_list ap, bool log_updated_time)
+{
+ if (!init_log()) {
+ return;
+ }
+
+ va_list aq;
+ va_copy(aq, ap);
+ log_prefix(log_updated_time);
+ if (logfile) {
+ int rc1 = vfprintf(logfile, format, ap);
+ int rc2 = fprintf(logfile, "\n");
+ if (rc1 < 0 || rc2 < 0) {
+ warn_log_fail();
+ }
+ }
#ifdef HAVE_SYSLOG
- if (use_syslog) {
- vsyslog(LOG_DEBUG, format, ap);
- }
+ if (use_syslog) {
+ vsyslog(LOG_DEBUG, format, ap);
+ }
#endif
- if (debug_log_buffer) {
- char buf[8192];
- int len = vsnprintf(buf, sizeof(buf), format, aq);
- if (len >= 0) {
- append_to_debug_log(buf, MIN((size_t)len, sizeof(buf) - 1));
- append_to_debug_log("\n", 1);
- }
- }
- va_end(aq);
+ if (debug_log_buffer) {
+ char buf[8192];
+ int len = vsnprintf(buf, sizeof(buf), format, aq);
+ if (len >= 0) {
+ append_to_debug_log(buf, MIN((size_t)len, sizeof(buf) - 1));
+ append_to_debug_log("\n", 1);
+ }
+ }
+ va_end(aq);
}
// Write a message to the log file (adding a newline) and flush.
void
-cc_log(const char *format, ...)
+cc_log(const char* format, ...)
{
- va_list ap;
- va_start(ap, format);
- vlog(format, ap, true);
- va_end(ap);
- if (logfile) {
- fflush(logfile);
- }
+ va_list ap;
+ va_start(ap, format);
+ vlog(format, ap, true);
+ va_end(ap);
+ if (logfile) {
+ fflush(logfile);
+ }
}
// Write a message to the log file (adding a newline) without flushing and with
// a reused timestamp.
void
-cc_bulklog(const char *format, ...)
+cc_bulklog(const char* format, ...)
{
- va_list ap;
- va_start(ap, format);
- vlog(format, ap, false);
- va_end(ap);
+ va_list ap;
+ va_start(ap, format);
+ vlog(format, ap, false);
+ va_end(ap);
}
// Log an executed command to the CCACHE_LOGFILE location.
void
-cc_log_argv(const char *prefix, char **argv)
-{
- if (!init_log()) {
- return;
- }
-
- log_prefix(true);
- if (logfile) {
- fputs(prefix, logfile);
- print_command(logfile, argv);
- int rc = fflush(logfile);
- if (rc) {
- warn_log_fail();
- }
- }
+cc_log_argv(const char* prefix, char** argv)
+{
+ if (!init_log()) {
+ return;
+ }
+
+ log_prefix(true);
+ if (logfile) {
+ fputs(prefix, logfile);
+ print_command(logfile, argv);
+ int rc = fflush(logfile);
+ if (rc) {
+ warn_log_fail();
+ }
+ }
#ifdef HAVE_SYSLOG
- if (use_syslog) {
- char *s = format_command(argv);
- syslog(LOG_DEBUG, "%s", s);
- free(s);
- }
+ if (use_syslog) {
+ char* s = format_command(argv);
+ syslog(LOG_DEBUG, "%s", s);
+ free(s);
+ }
#endif
- if (debug_log_buffer) {
- append_to_debug_log(prefix, strlen(prefix));
- char *s = format_command(argv);
- append_to_debug_log(s, strlen(s));
- free(s);
- }
+ if (debug_log_buffer) {
+ append_to_debug_log(prefix, strlen(prefix));
+ char* s = format_command(argv);
+ append_to_debug_log(s, strlen(s));
+ free(s);
+ }
}
// Copy the current log memory buffer to an output file.
void
-cc_dump_debug_log_buffer(const char *path)
+cc_dump_debug_log_buffer(const char* path)
{
- FILE *file = fopen(path, "w");
- if (file) {
- (void) fwrite(debug_log_buffer, 1, debug_log_size, file);
- fclose(file);
- } else {
- cc_log("Failed to open %s: %s", path, strerror(errno));
- }
+ FILE* file = fopen(path, "w");
+ if (file) {
+ (void)fwrite(debug_log_buffer, 1, debug_log_size, file);
+ fclose(file);
+ } else {
+ cc_log("Failed to open %s: %s", path, strerror(errno));
+ }
}
// Something went badly wrong!
void
-fatal(const char *format, ...)
+fatal(const char* format, ...)
{
- va_list ap;
- va_start(ap, format);
- char msg[8192];
- vsnprintf(msg, sizeof(msg), format, ap);
- va_end(ap);
+ va_list ap;
+ va_start(ap, format);
+ char msg[8192];
+ vsnprintf(msg, sizeof(msg), format, ap);
+ va_end(ap);
- cc_log("FATAL: %s", msg);
- fprintf(stderr, "ccache: error: %s\n", msg);
+ cc_log("FATAL: %s", msg);
+ fprintf(stderr, "ccache: error: %s\n", msg);
- x_exit(1);
+ x_exit(1);
}
// Transform a name to a full path into the cache directory, creating needed
// sublevels if needed. Caller frees.
-char *
-get_path_in_cache(const char *name, const char *suffix)
+char*
+get_path_in_cache(const char* name, const char* suffix)
{
- char *path = x_strdup(conf->cache_dir);
- for (unsigned i = 0; i < conf->cache_dir_levels; ++i) {
- char *p = format("%s/%c", path, name[i]);
- free(path);
- path = p;
- }
+ char* path = x_strdup(conf->cache_dir);
+ for (unsigned i = 0; i < conf->cache_dir_levels; ++i) {
+ char* p = format("%s/%c", path, name[i]);
+ free(path);
+ path = p;
+ }
- char *result =
- format("%s/%s%s", path, name + conf->cache_dir_levels, suffix);
- free(path);
- return result;
+ char* result = format("%s/%s%s", path, name + conf->cache_dir_levels, suffix);
+ free(path);
+ return result;
}
// Copy all data from fd_in to fd_out.
bool
copy_fd(int fd_in, int fd_out)
{
- int n;
- char buf[READ_BUFFER_SIZE];
- while ((n = read(fd_in, buf, sizeof(buf))) > 0) {
- ssize_t written = 0;
- do {
- ssize_t count = write(fd_out, buf + written, n - written);
- if (count == -1) {
- if (errno != EAGAIN && errno != EINTR) {
- return false;
- }
- } else {
- written += count;
- }
- } while (written < n);
- }
-
- return true;
+ int n;
+ char buf[READ_BUFFER_SIZE];
+ while ((n = read(fd_in, buf, sizeof(buf))) > 0) {
+ ssize_t written = 0;
+ do {
+ ssize_t count = write(fd_out, buf + written, n - written);
+ if (count == -1) {
+ if (errno != EAGAIN && errno != EINTR) {
+ return false;
+ }
+ } else {
+ written += count;
+ }
+ } while (written < n);
+ }
+
+ return true;
}
#ifndef HAVE_MKSTEMP
// Cheap and nasty mkstemp replacement.
int
-mkstemp(char *name_template)
+mkstemp(char* name_template)
{
-#ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
- mktemp(name_template);
-#ifdef __GNUC__
- #pragma GCC diagnostic pop
-#endif
- return open(name_template, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
+# ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+# endif
+ mktemp(name_template);
+# ifdef __GNUC__
+# pragma GCC diagnostic pop
+# endif
+ return open(name_template, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
}
#endif
@@ -363,1121 +368,1127 @@ mkstemp(char *name_template)
static mode_t
get_umask(void)
{
- static bool mask_retrieved = false;
- static mode_t mask;
- if (!mask_retrieved) {
- mask = umask(0);
- umask(mask);
- mask_retrieved = true;
- }
- return mask;
+ static bool mask_retrieved = false;
+ static mode_t mask;
+ if (!mask_retrieved) {
+ mask = umask(0);
+ umask(mask);
+ mask_retrieved = true;
+ }
+ return mask;
}
#endif
// Clone a file from src to dest. If via_tmp_file is true, the file is cloned
// to a temporary file and then renamed to dest.
bool
-clone_file(const char *src, const char *dest, bool via_tmp_file)
+clone_file(const char* src, const char* dest, bool via_tmp_file)
{
- bool result;
+ bool result;
#ifdef FILE_CLONING_SUPPORTED
-#if defined(__linux__)
- int src_fd = open(src, O_RDONLY);
- if (src_fd == -1) {
- return false;
- }
-
- int dest_fd;
- char *tmp_file = NULL;
- if (via_tmp_file) {
- tmp_file = x_strdup(dest);
- dest_fd = create_tmp_fd(&tmp_file);
- } else {
- dest_fd = open(dest, O_WRONLY | O_CREAT | O_BINARY, 0666);
- if (dest_fd == -1) {
- close(dest_fd);
- close(src_fd);
- return false;
- }
- }
-
- int saved_errno = 0;
- if (ioctl(dest_fd, FICLONE, src_fd) == 0) {
- result = true;
- } else {
- result = false;
- saved_errno = errno;
- }
-
- close(dest_fd);
- close(src_fd);
-
- if (via_tmp_file) {
- x_try_unlink(dest);
- if (x_rename(tmp_file, dest) != 0) {
- result = false;
- }
- free(tmp_file);
- }
-
- errno = saved_errno;
-#elif defined(__APPLE__)
- (void)via_tmp_file;
- result = clonefile(src, dest, CLONE_NOOWNERCOPY) == 0;
-#endif
+# if defined(__linux__)
+ int src_fd = open(src, O_RDONLY);
+ if (src_fd == -1) {
+ return false;
+ }
+
+ int dest_fd;
+ char* tmp_file = NULL;
+ if (via_tmp_file) {
+ tmp_file = x_strdup(dest);
+ dest_fd = create_tmp_fd(&tmp_file);
+ } else {
+ dest_fd = open(dest, O_WRONLY | O_CREAT | O_BINARY, 0666);
+ if (dest_fd == -1) {
+ close(dest_fd);
+ close(src_fd);
+ return false;
+ }
+ }
+
+ int saved_errno = 0;
+ if (ioctl(dest_fd, FICLONE, src_fd) == 0) {
+ result = true;
+ } else {
+ result = false;
+ saved_errno = errno;
+ }
+
+ close(dest_fd);
+ close(src_fd);
+
+ if (via_tmp_file) {
+ x_try_unlink(dest);
+ if (x_rename(tmp_file, dest) != 0) {
+ result = false;
+ }
+ free(tmp_file);
+ }
+
+ errno = saved_errno;
+# elif defined(__APPLE__)
+ (void)via_tmp_file;
+ result = clonefile(src, dest, CLONE_NOOWNERCOPY) == 0;
+# endif
#else // FILE_CLONING_SUPPORTED
- (void)src;
- (void)dest;
- (void)via_tmp_file;
- errno = EOPNOTSUPP;
- result = false;
+ (void)src;
+ (void)dest;
+ (void)via_tmp_file;
+ errno = EOPNOTSUPP;
+ result = false;
#endif // FILE_CLONING_SUPPORTED
- return result;
+ return result;
}
// Copy a file from src to dest. If via_tmp_file is true, the file is copied to
// a temporary file and then renamed to dest.
bool
-copy_file(const char *src, const char *dest, bool via_tmp_file)
-{
- bool result = false;
-
- int src_fd = open(src, O_RDONLY);
- if (src_fd == -1) {
- return false;
- }
-
- int dest_fd;
- char *tmp_file = NULL;
- if (via_tmp_file) {
- tmp_file = x_strdup(dest);
- dest_fd = create_tmp_fd(&tmp_file);
- } else {
- dest_fd = open(dest, O_WRONLY | O_CREAT | O_BINARY, 0666);
- if (dest_fd == -1) {
- close(dest_fd);
- close(src_fd);
- return false;
- }
- }
-
- if (copy_fd(src_fd, dest_fd)) {
- result = true;
- }
-
- close(dest_fd);
- close(src_fd);
-
- if (via_tmp_file) {
- x_try_unlink(dest);
- if (x_rename(tmp_file, dest) != 0) {
- result = false;
- }
- free(tmp_file);
- }
-
- return result;
+copy_file(const char* src, const char* dest, bool via_tmp_file)
+{
+ bool result = false;
+
+ int src_fd = open(src, O_RDONLY);
+ if (src_fd == -1) {
+ return false;
+ }
+
+ int dest_fd;
+ char* tmp_file = NULL;
+ if (via_tmp_file) {
+ tmp_file = x_strdup(dest);
+ dest_fd = create_tmp_fd(&tmp_file);
+ } else {
+ dest_fd = open(dest, O_WRONLY | O_CREAT | O_BINARY, 0666);
+ if (dest_fd == -1) {
+ close(dest_fd);
+ close(src_fd);
+ return false;
+ }
+ }
+
+ if (copy_fd(src_fd, dest_fd)) {
+ result = true;
+ }
+
+ close(dest_fd);
+ close(src_fd);
+
+ if (via_tmp_file) {
+ x_try_unlink(dest);
+ if (x_rename(tmp_file, dest) != 0) {
+ result = false;
+ }
+ free(tmp_file);
+ }
+
+ return result;
}
// Run copy_file() and, if successful, delete the source file.
bool
-move_file(const char *src, const char *dest)
+move_file(const char* src, const char* dest)
{
- bool ok = copy_file(src, dest, false);
- if (ok) {
- x_unlink(src);
- }
- return ok;
+ bool ok = copy_file(src, dest, false);
+ if (ok) {
+ x_unlink(src);
+ }
+ return ok;
}
// Make sure a directory exists.
int
-create_dir(const char *dir)
-{
- struct stat st;
- if (stat(dir, &st) == 0) {
- if (S_ISDIR(st.st_mode)) {
- return 0;
- }
- errno = ENOTDIR;
- return 1;
- }
- if (mkdir(dir, 0777) != 0 && errno != EEXIST) {
- return 1;
- }
- return 0;
+create_dir(const char* dir)
+{
+ struct stat st;
+ if (stat(dir, &st) == 0) {
+ if (S_ISDIR(st.st_mode)) {
+ return 0;
+ }
+ errno = ENOTDIR;
+ return 1;
+ }
+ if (mkdir(dir, 0777) != 0 && errno != EEXIST) {
+ return 1;
+ }
+ return 0;
}
// Create directories leading to path. Returns 0 on success, otherwise -1.
int
-create_parent_dirs(const char *path)
-{
- int res;
- char *parent = x_dirname(path);
- struct stat st;
- if (stat(parent, &st) == 0) {
- if (S_ISDIR(st.st_mode)) {
- res = 0;
- } else {
- res = -1;
- errno = ENOTDIR;
- }
- } else {
- res = create_parent_dirs(parent);
- if (res == 0) {
- res = mkdir(parent, 0777);
- // Have to handle the condition of the directory already existing because
- // the file system could have changed in between calling stat and
- // actually creating the directory. This can happen when there are
- // multiple instances of ccache running and trying to create the same
- // directory chain, which usually is the case when the cache root does
- // not initially exist. As long as one of the processes creates the
- // directories then our condition is satisfied and we avoid a race
- // condition.
- if (res != 0 && errno == EEXIST) {
- res = 0;
- }
- } else {
- res = -1;
- }
- }
- free(parent);
- return res;
+create_parent_dirs(const char* path)
+{
+ int res;
+ char* parent = x_dirname(path);
+ struct stat st;
+ if (stat(parent, &st) == 0) {
+ if (S_ISDIR(st.st_mode)) {
+ res = 0;
+ } else {
+ res = -1;
+ errno = ENOTDIR;
+ }
+ } else {
+ res = create_parent_dirs(parent);
+ if (res == 0) {
+ res = mkdir(parent, 0777);
+ // Have to handle the condition of the directory already existing because
+ // the file system could have changed in between calling stat and
+ // actually creating the directory. This can happen when there are
+ // multiple instances of ccache running and trying to create the same
+ // directory chain, which usually is the case when the cache root does
+ // not initially exist. As long as one of the processes creates the
+ // directories then our condition is satisfied and we avoid a race
+ // condition.
+ if (res != 0 && errno == EEXIST) {
+ res = 0;
+ }
+ } else {
+ res = -1;
+ }
+ }
+ free(parent);
+ return res;
}
// Return a static string with the current hostname.
-const char *
+const char*
get_hostname(void)
{
- static char hostname[260] = "";
+ static char hostname[260] = "";
- if (hostname[0]) {
- return hostname;
- }
+ if (hostname[0]) {
+ return hostname;
+ }
- strcpy(hostname, "unknown");
+ strcpy(hostname, "unknown");
#if HAVE_GETHOSTNAME
- gethostname(hostname, sizeof(hostname) - 1);
+ gethostname(hostname, sizeof(hostname) - 1);
#elif defined(_WIN32)
- const char *computer_name = getenv("COMPUTERNAME");
- if (computer_name) {
- snprintf(hostname, sizeof(hostname), "%s", computer_name);
- return hostname;
- }
-
- WORD w_version_requested = MAKEWORD(2, 2);
- WSADATA wsa_data;
- int err = WSAStartup(w_version_requested, &wsa_data);
- if (err != 0) {
- // Tell the user that we could not find a usable Winsock DLL.
- cc_log("WSAStartup failed with error: %d", err);
- return hostname;
- }
-
- if (LOBYTE(wsa_data.wVersion) != 2 || HIBYTE(wsa_data.wVersion) != 2) {
- // Tell the user that we could not find a usable WinSock DLL.
- cc_log("Could not find a usable version of Winsock.dll");
- WSACleanup();
- return hostname;
- }
-
- int result = gethostname(hostname, sizeof(hostname) - 1);
- if (result != 0) {
- LPVOID lp_msg_buf;
- DWORD dw = WSAGetLastError();
-
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lp_msg_buf, 0, NULL);
-
- LPVOID lp_display_buf = (LPVOID) LocalAlloc(
- LMEM_ZEROINIT,
- (lstrlen((LPCTSTR) lp_msg_buf) + lstrlen((LPCTSTR) __FILE__) + 200)
- * sizeof(TCHAR));
- _snprintf((LPTSTR) lp_display_buf,
- LocalSize(lp_display_buf) / sizeof(TCHAR),
- TEXT("%s failed with error %lu: %s"), __FILE__, dw,
- (const char *)lp_msg_buf);
-
- cc_log("can't get hostname OS returned error: %s", (char *)lp_display_buf);
-
- LocalFree(lp_msg_buf);
- LocalFree(lp_display_buf);
- }
- WSACleanup();
+ const char* computer_name = getenv("COMPUTERNAME");
+ if (computer_name) {
+ snprintf(hostname, sizeof(hostname), "%s", computer_name);
+ return hostname;
+ }
+
+ WORD w_version_requested = MAKEWORD(2, 2);
+ WSADATA wsa_data;
+ int err = WSAStartup(w_version_requested, &wsa_data);
+ if (err != 0) {
+ // Tell the user that we could not find a usable Winsock DLL.
+ cc_log("WSAStartup failed with error: %d", err);
+ return hostname;
+ }
+
+ if (LOBYTE(wsa_data.wVersion) != 2 || HIBYTE(wsa_data.wVersion) != 2) {
+ // Tell the user that we could not find a usable WinSock DLL.
+ cc_log("Could not find a usable version of Winsock.dll");
+ WSACleanup();
+ return hostname;
+ }
+
+ int result = gethostname(hostname, sizeof(hostname) - 1);
+ if (result != 0) {
+ LPVOID lp_msg_buf;
+ DWORD dw = WSAGetLastError();
+
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ dw,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&lp_msg_buf,
+ 0,
+ NULL);
+
+ LPVOID lp_display_buf = (LPVOID)LocalAlloc(
+ LMEM_ZEROINIT,
+ (lstrlen((LPCTSTR)lp_msg_buf) + lstrlen((LPCTSTR)__FILE__) + 200)
+ * sizeof(TCHAR));
+ _snprintf((LPTSTR)lp_display_buf,
+ LocalSize(lp_display_buf) / sizeof(TCHAR),
+ TEXT("%s failed with error %lu: %s"),
+ __FILE__,
+ dw,
+ (const char*)lp_msg_buf);
+
+ cc_log("can't get hostname OS returned error: %s", (char*)lp_display_buf);
+
+ LocalFree(lp_msg_buf);
+ LocalFree(lp_display_buf);
+ }
+ WSACleanup();
#endif
- hostname[sizeof(hostname) - 1] = 0;
- return hostname;
+ hostname[sizeof(hostname) - 1] = 0;
+ return hostname;
}
// Return a string to be passed to mkstemp to create a temporary file. Also
// tries to cope with NFS by adding the local hostname.
-const char *
+const char*
tmp_string(void)
{
- static char *ret;
- if (!ret) {
- ret = format("%s.%u.XXXXXX", get_hostname(), (unsigned)getpid());
- }
- return ret;
+ static char* ret;
+ if (!ret) {
+ ret = format("%s.%u.XXXXXX", get_hostname(), (unsigned)getpid());
+ }
+ return ret;
}
static char const CACHEDIR_TAG[] =
- "Signature: 8a477f597d28d172789f06886806bc55\n"
- "# This file is a cache directory tag created by ccache.\n"
- "# For information about cache directory tags, see:\n"
- "#\thttp://www.brynosaurus.com/cachedir/\n";
+ "Signature: 8a477f597d28d172789f06886806bc55\n"
+ "# This file is a cache directory tag created by ccache.\n"
+ "# For information about cache directory tags, see:\n"
+ "#\thttp://www.brynosaurus.com/cachedir/\n";
int
-create_cachedirtag(const char *dir)
-{
- char *filename = format("%s/CACHEDIR.TAG", dir);
- FILE* f;
- struct stat st;
-
- if (stat(filename, &st) == 0) {
- if (S_ISREG(st.st_mode)) {
- goto success;
- }
- errno = EEXIST;
- goto error;
- }
-
- f = fopen(filename, "w");
- if (!f) {
- goto error;
- }
- if (fwrite(CACHEDIR_TAG, sizeof(CACHEDIR_TAG)-1, 1, f) != 1) {
- fclose(f);
- goto error;
- }
- if (fclose(f)) {
- goto error;
- }
+create_cachedirtag(const char* dir)
+{
+ char* filename = format("%s/CACHEDIR.TAG", dir);
+ FILE* f;
+ struct stat st;
+
+ if (stat(filename, &st) == 0) {
+ if (S_ISREG(st.st_mode)) {
+ goto success;
+ }
+ errno = EEXIST;
+ goto error;
+ }
+
+ f = fopen(filename, "w");
+ if (!f) {
+ goto error;
+ }
+ if (fwrite(CACHEDIR_TAG, sizeof(CACHEDIR_TAG) - 1, 1, f) != 1) {
+ fclose(f);
+ goto error;
+ }
+ if (fclose(f)) {
+ goto error;
+ }
success:
- free(filename);
- return 0;
+ free(filename);
+ return 0;
error:
- free(filename);
- return 1;
+ free(filename);
+ return 1;
}
// Construct a string according to a format. Caller frees.
-char *
-format(const char *format, ...)
+char*
+format(const char* format, ...)
{
- va_list ap;
- va_start(ap, format);
+ va_list ap;
+ va_start(ap, format);
- char *ptr = NULL;
- if (vasprintf(&ptr, format, ap) == -1) {
- fatal("Out of memory in format");
- }
- va_end(ap);
+ char* ptr = NULL;
+ if (vasprintf(&ptr, format, ap) == -1) {
+ fatal("Out of memory in format");
+ }
+ va_end(ap);
- if (!*ptr) {
- fatal("Internal error in format");
- }
- return ptr;
+ if (!*ptr) {
+ fatal("Internal error in format");
+ }
+ return ptr;
}
// Construct a hexadecimal string representing binary data. The buffer must
// hold at least 2 * size + 1 bytes.
void
-format_hex(const uint8_t *data, size_t size, char *buffer)
+format_hex(const uint8_t* data, size_t size, char* buffer)
{
- for (size_t i = 0; i < size; i++) {
- sprintf(&buffer[i*2], "%02x", (unsigned)data[i]);
- }
- buffer[2 * size] = '\0';
+ for (size_t i = 0; i < size; i++) {
+ sprintf(&buffer[i * 2], "%02x", (unsigned)data[i]);
+ }
+ buffer[2 * size] = '\0';
}
// This is like strdup() but dies if the malloc fails.
-char *
-x_strdup(const char *s)
+char*
+x_strdup(const char* s)
{
- char *ret = strdup(s);
- if (!ret) {
- fatal("Out of memory in x_strdup");
- }
- return ret;
+ char* ret = strdup(s);
+ if (!ret) {
+ fatal("Out of memory in x_strdup");
+ }
+ return ret;
}
// This is like strndup() but dies if the malloc fails.
-char *
-x_strndup(const char *s, size_t n)
+char*
+x_strndup(const char* s, size_t n)
{
#ifndef HAVE_STRNDUP
- if (!s) {
- return NULL;
- }
- size_t m = 0;
- while (m < n && s[m]) {
- m++;
- }
- char *ret = static_cast<char*>(malloc(m + 1));
- if (ret) {
- memcpy(ret, s, m);
- ret[m] = '\0';
- }
+ if (!s) {
+ return NULL;
+ }
+ size_t m = 0;
+ while (m < n && s[m]) {
+ m++;
+ }
+ char* ret = static_cast<char*>(malloc(m + 1));
+ if (ret) {
+ memcpy(ret, s, m);
+ ret[m] = '\0';
+ }
#else
- char *ret = strndup(s, n);
+ char* ret = strndup(s, n);
#endif
- if (!ret) {
- fatal("x_strndup: Could not allocate %lu bytes", (unsigned long)n);
- }
- return ret;
+ if (!ret) {
+ fatal("x_strndup: Could not allocate %lu bytes", (unsigned long)n);
+ }
+ return ret;
}
// This is like malloc() but dies if the malloc fails.
-void *
+void*
x_malloc(size_t size)
{
- if (size == 0) {
- // malloc() may return NULL if size is zero, so always do this to make sure
- // that the code handles it regardless of platform.
- return NULL;
- }
- void *ret = malloc(size);
- if (!ret) {
- fatal("x_malloc: Could not allocate %lu bytes", (unsigned long)size);
- }
- return ret;
+ if (size == 0) {
+ // malloc() may return NULL if size is zero, so always do this to make sure
+ // that the code handles it regardless of platform.
+ return NULL;
+ }
+ void* ret = malloc(size);
+ if (!ret) {
+ fatal("x_malloc: Could not allocate %lu bytes", (unsigned long)size);
+ }
+ return ret;
}
// This is like calloc() but dies if the allocation fails.
-void *
+void*
x_calloc(size_t nmemb, size_t size)
{
- if (nmemb * size == 0) {
- // calloc() may return NULL if nmemb or size is 0, so always do this to
- // make sure that the code handles it regardless of platform.
- return NULL;
- }
- void *ret = calloc(nmemb, size);
- if (!ret) {
- fatal("x_calloc: Could not allocate %lu bytes", (unsigned long)size);
- }
- return ret;
+ if (nmemb * size == 0) {
+ // calloc() may return NULL if nmemb or size is 0, so always do this to
+ // make sure that the code handles it regardless of platform.
+ return NULL;
+ }
+ void* ret = calloc(nmemb, size);
+ if (!ret) {
+ fatal("x_calloc: Could not allocate %lu bytes", (unsigned long)size);
+ }
+ return ret;
}
// This is like realloc() but dies if the malloc fails.
-void *
-x_realloc(void *ptr, size_t size)
+void*
+x_realloc(void* ptr, size_t size)
{
- if (!ptr) {
- return x_malloc(size);
- }
- void *p2 = realloc(ptr, size);
- if (!p2) {
- fatal("x_realloc: Could not allocate %lu bytes", (unsigned long)size);
- }
- return p2;
+ if (!ptr) {
+ return x_malloc(size);
+ }
+ void* p2 = realloc(ptr, size);
+ if (!p2) {
+ fatal("x_realloc: Could not allocate %lu bytes", (unsigned long)size);
+ }
+ return p2;
}
// This is like setenv.
-void x_setenv(const char *name, const char *value)
+void
+x_setenv(const char* name, const char* value)
{
#ifdef HAVE_SETENV
- setenv(name, value, true);
+ setenv(name, value, true);
#else
- putenv(format("%s=%s", name, value)); // Leak to environment.
+ putenv(format("%s=%s", name, value)); // Leak to environment.
#endif
}
// This is like unsetenv.
-void x_unsetenv(const char *name)
+void
+x_unsetenv(const char* name)
{
#ifdef HAVE_UNSETENV
- unsetenv(name);
+ unsetenv(name);
#else
- putenv(x_strdup(name)); // Leak to environment.
+ putenv(x_strdup(name)); // Leak to environment.
#endif
}
// Like fstat() but also call cc_log on failure.
int
-x_fstat(int fd, struct stat *buf)
+x_fstat(int fd, struct stat* buf)
{
- int result = fstat(fd, buf);
- if (result != 0) {
- cc_log("Failed to fstat fd %d: %s", fd, strerror(errno));
- }
- return result;
+ int result = fstat(fd, buf);
+ if (result != 0) {
+ cc_log("Failed to fstat fd %d: %s", fd, strerror(errno));
+ }
+ return result;
}
// Like lstat() but also call cc_log on failure.
int
-x_lstat(const char *pathname, struct stat *buf)
+x_lstat(const char* pathname, struct stat* buf)
{
- int result = lstat(pathname, buf);
- if (result != 0) {
- cc_log("Failed to lstat %s: %s", pathname, strerror(errno));
- }
- return result;
+ int result = lstat(pathname, buf);
+ if (result != 0) {
+ cc_log("Failed to lstat %s: %s", pathname, strerror(errno));
+ }
+ return result;
}
// Like stat() but also call cc_log on failure.
int
-x_stat(const char *pathname, struct stat *buf)
+x_stat(const char* pathname, struct stat* buf)
{
- int result = stat(pathname, buf);
- if (result != 0) {
- cc_log("Failed to stat %s: %s", pathname, strerror(errno));
- }
- return result;
+ int result = stat(pathname, buf);
+ if (result != 0) {
+ cc_log("Failed to stat %s: %s", pathname, strerror(errno));
+ }
+ return result;
}
// Construct a string according to the format and store it in *ptr. The
// original *ptr is then freed.
void
-reformat(char **ptr, const char *format, ...)
+reformat(char** ptr, const char* format, ...)
{
- char *saved = *ptr;
- *ptr = NULL;
+ char* saved = *ptr;
+ *ptr = NULL;
- va_list ap;
- va_start(ap, format);
- if (vasprintf(ptr, format, ap) == -1) {
- fatal("Out of memory in reformat");
- }
- va_end(ap);
+ va_list ap;
+ va_start(ap, format);
+ if (vasprintf(ptr, format, ap) == -1) {
+ fatal("Out of memory in reformat");
+ }
+ va_end(ap);
- if (saved) {
- free(saved);
- }
+ if (saved) {
+ free(saved);
+ }
}
// Recursive directory traversal. fn() is called on all entries in the tree.
void
-traverse(const char *dir, void (*fn)(const char *, struct stat *))
-{
- DIR *d = opendir(dir);
- if (!d) {
- return;
- }
-
- struct dirent *de;
- while ((de = readdir(d))) {
- if (str_eq(de->d_name, ".")) {
- continue;
- }
- if (str_eq(de->d_name, "..")) {
- continue;
- }
-
- if (strlen(de->d_name) == 0) {
- continue;
- }
-
- char *fname = format("%s/%s", dir, de->d_name);
- struct stat st;
- if (lstat(fname, &st)) {
- if (errno != ENOENT && errno != ESTALE) {
- fatal("lstat %s failed: %s", fname, strerror(errno));
- }
- free(fname);
- continue;
- }
-
- if (S_ISDIR(st.st_mode)) {
- traverse(fname, fn);
- }
-
- fn(fname, &st);
- free(fname);
- }
-
- closedir(d);
+traverse(const char* dir, void (*fn)(const char*, struct stat*))
+{
+ DIR* d = opendir(dir);
+ if (!d) {
+ return;
+ }
+
+ struct dirent* de;
+ while ((de = readdir(d))) {
+ if (str_eq(de->d_name, ".")) {
+ continue;
+ }
+ if (str_eq(de->d_name, "..")) {
+ continue;
+ }
+
+ if (strlen(de->d_name) == 0) {
+ continue;
+ }
+
+ char* fname = format("%s/%s", dir, de->d_name);
+ struct stat st;
+ if (lstat(fname, &st)) {
+ if (errno != ENOENT && errno != ESTALE) {
+ fatal("lstat %s failed: %s", fname, strerror(errno));
+ }
+ free(fname);
+ continue;
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ traverse(fname, fn);
+ }
+
+ fn(fname, &st);
+ free(fname);
+ }
+
+ closedir(d);
}
-
// Return the base name of a file - caller frees.
-char *
-x_basename(const char *path)
+char*
+x_basename(const char* path)
{
- const char *p = strrchr(path, '/');
- if (p) {
- path = p + 1;
- }
+ const char* p = strrchr(path, '/');
+ if (p) {
+ path = p + 1;
+ }
#ifdef _WIN32
- p = strrchr(path, '\\');
- if (p) {
- path = p + 1;
- }
+ p = strrchr(path, '\\');
+ if (p) {
+ path = p + 1;
+ }
#endif
- return x_strdup(path);
+ return x_strdup(path);
}
// Return the dir name of a file - caller frees.
-char *
-x_dirname(const char *path)
+char*
+x_dirname(const char* path)
{
- char *s = x_strdup(path);
- char *p = strrchr(s, '/');
+ char* s = x_strdup(path);
+ char* p = strrchr(s, '/');
#ifdef _WIN32
- char *p2 = strrchr(s, '\\');
- if (!p || (p2 && p < p2)) {
- p = p2;
- }
+ char* p2 = strrchr(s, '\\');
+ if (!p || (p2 && p < p2)) {
+ p = p2;
+ }
#endif
- if (!p) {
- free(s);
- s = x_strdup(".");
- } else if (p == s) {
- *(p + 1) = 0;
- } else {
- *p = 0;
- }
- return s;
+ if (!p) {
+ free(s);
+ s = x_strdup(".");
+ } else if (p == s) {
+ *(p + 1) = 0;
+ } else {
+ *p = 0;
+ }
+ return s;
}
// Return the file extension (including the dot) of a path as a pointer into
// path. If path has no file extension, the empty string and the end of path is
// returned.
-const char *
-get_extension(const char *path)
+const char*
+get_extension(const char* path)
{
- size_t len = strlen(path);
- for (const char *p = &path[len - 1]; p >= path; --p) {
- if (*p == '.') {
- return p;
- }
- if (*p == '/') {
- break;
- }
- }
- return &path[len];
+ size_t len = strlen(path);
+ for (const char* p = &path[len - 1]; p >= path; --p) {
+ if (*p == '.') {
+ return p;
+ }
+ if (*p == '/') {
+ break;
+ }
+ }
+ return &path[len];
}
// Return a string containing the given path without the filename extension.
// Caller frees.
-char *
-remove_extension(const char *path)
+char*
+remove_extension(const char* path)
{
- return x_strndup(path, strlen(path) - strlen(get_extension(path)));
+ return x_strndup(path, strlen(path) - strlen(get_extension(path)));
}
// Return size on disk of a file.
size_t
-file_size(struct stat *st)
+file_size(struct stat* st)
{
#ifdef _WIN32
- return (st->st_size + 1023) & ~1023;
+ return (st->st_size + 1023) & ~1023;
#else
- return st->st_blocks * 512;
+ return st->st_blocks * 512;
#endif
}
// Format a size as a human-readable string. Caller frees.
-char *
+char*
format_human_readable_size(uint64_t v)
{
- char *s;
- if (v >= 1000*1000*1000) {
- s = format("%.1f GB", v/((double)(1000*1000*1000)));
- } else {
- s = format("%.1f MB", v/((double)(1000*1000)));
- }
- return s;
+ char* s;
+ if (v >= 1000 * 1000 * 1000) {
+ s = format("%.1f GB", v / ((double)(1000 * 1000 * 1000)));
+ } else {
+ s = format("%.1f MB", v / ((double)(1000 * 1000)));
+ }
+ return s;
}
// Format a size as a parsable string. Caller frees.
-char *
+char*
format_parsable_size_with_suffix(uint64_t size)
{
- char *s;
- if (size >= 1000*1000*1000) {
- s = format("%.1fG", size / ((double)(1000*1000*1000)));
- } else if (size >= 1000*1000) {
- s = format("%.1fM", size / ((double)(1000*1000)));
- } else {
- s = format("%u", (unsigned)size);
- }
- return s;
+ char* s;
+ if (size >= 1000 * 1000 * 1000) {
+ s = format("%.1fG", size / ((double)(1000 * 1000 * 1000)));
+ } else if (size >= 1000 * 1000) {
+ s = format("%.1fM", size / ((double)(1000 * 1000)));
+ } else {
+ s = format("%u", (unsigned)size);
+ }
+ return s;
}
// Parse a "size value", i.e. a string that can end in k, M, G, T (10-based
// suffixes) or Ki, Mi, Gi, Ti (2-based suffixes). For backward compatibility,
// K is also recognized as a synonym of k.
bool
-parse_size_with_suffix(const char *str, uint64_t *size)
-{
- errno = 0;
-
- char *p;
- double x = strtod(str, &p);
- if (errno != 0 || x < 0 || p == str || *str == '\0') {
- return false;
- }
-
- while (isspace(*p)) {
- ++p;
- }
-
- if (*p != '\0') {
- unsigned multiplier = *(p+1) == 'i' ? 1024 : 1000;
- switch (*p) {
- case 'T':
- x *= multiplier;
- // Fallthrough.
- case 'G':
- x *= multiplier;
- // Fallthrough.
- case 'M':
- x *= multiplier;
- // Fallthrough.
- case 'K':
- case 'k':
- x *= multiplier;
- break;
- default:
- return false;
- }
- } else {
- // Default suffix: G.
- x *= 1000 * 1000 * 1000;
- }
- *size = (uint64_t)x;
- return true;
-}
-
-
-#if !defined(HAVE_REALPATH) && \
- defined(_WIN32) && \
- !defined(HAVE_GETFINALPATHNAMEBYHANDLEW)
-static BOOL GetFileNameFromHandle(HANDLE file_handle, TCHAR *filename,
- WORD cch_filename)
-{
- BOOL success = FALSE;
-
- // Get the file size.
- DWORD file_size_hi = 0;
- DWORD file_size_lo = GetFileSize(file_handle, &file_size_hi);
- if (file_size_lo == 0 && file_size_hi == 0) {
- // Cannot map a file with a length of zero.
- return FALSE;
- }
-
- // Create a file mapping object.
- HANDLE file_map =
- CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 1, NULL);
- if (!file_map) {
- return FALSE;
- }
-
- // Create a file mapping to get the file name.
- void *mem = MapViewOfFile(file_map, FILE_MAP_READ, 0, 0, 1);
- if (mem) {
- if (GetMappedFileName(GetCurrentProcess(),
- mem,
- filename,
- cch_filename)) {
- // Translate path with device name to drive letters.
- TCHAR temp[512];
- temp[0] = '\0';
-
- if (GetLogicalDriveStrings(512-1, temp)) {
- TCHAR name[MAX_PATH];
- TCHAR drive[3] = TEXT(" :");
- BOOL found = FALSE;
- TCHAR *p = temp;
-
- do {
- // Copy the drive letter to the template string.
- *drive = *p;
-
- // Look up each device name.
- if (QueryDosDevice(drive, name, MAX_PATH)) {
- size_t name_len = _tcslen(name);
- if (name_len < MAX_PATH) {
- found = _tcsnicmp(filename, name, name_len) == 0
- && *(filename + name_len) == _T('\\');
- if (found) {
- // Reconstruct filename using temp_file and replace device path
- // with DOS path.
- TCHAR temp_file[MAX_PATH];
- _sntprintf(temp_file,
- MAX_PATH - 1,
- TEXT("%s%s"),
- drive,
- filename+name_len);
- strcpy(filename, temp_file);
- }
- }
- }
-
- // Go to the next NULL character.
- while (*p++) {
- // Do nothing.
- }
- } while (!found && *p); // End of string.
- }
- }
- success = TRUE;
- UnmapViewOfFile(mem);
- }
-
- CloseHandle(file_map);
- return success;
+parse_size_with_suffix(const char* str, uint64_t* size)
+{
+ errno = 0;
+
+ char* p;
+ double x = strtod(str, &p);
+ if (errno != 0 || x < 0 || p == str || *str == '\0') {
+ return false;
+ }
+
+ while (isspace(*p)) {
+ ++p;
+ }
+
+ if (*p != '\0') {
+ unsigned multiplier = *(p + 1) == 'i' ? 1024 : 1000;
+ switch (*p) {
+ case 'T':
+ x *= multiplier;
+ // Fallthrough.
+ case 'G':
+ x *= multiplier;
+ // Fallthrough.
+ case 'M':
+ x *= multiplier;
+ // Fallthrough.
+ case 'K':
+ case 'k':
+ x *= multiplier;
+ break;
+ default:
+ return false;
+ }
+ } else {
+ // Default suffix: G.
+ x *= 1000 * 1000 * 1000;
+ }
+ *size = (uint64_t)x;
+ return true;
+}
+
+#if !defined(HAVE_REALPATH) && defined(_WIN32) \
+ && !defined(HAVE_GETFINALPATHNAMEBYHANDLEW)
+static BOOL
+GetFileNameFromHandle(HANDLE file_handle, TCHAR* filename, WORD cch_filename)
+{
+ BOOL success = FALSE;
+
+ // Get the file size.
+ DWORD file_size_hi = 0;
+ DWORD file_size_lo = GetFileSize(file_handle, &file_size_hi);
+ if (file_size_lo == 0 && file_size_hi == 0) {
+ // Cannot map a file with a length of zero.
+ return FALSE;
+ }
+
+ // Create a file mapping object.
+ HANDLE file_map =
+ CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 1, NULL);
+ if (!file_map) {
+ return FALSE;
+ }
+
+ // Create a file mapping to get the file name.
+ void* mem = MapViewOfFile(file_map, FILE_MAP_READ, 0, 0, 1);
+ if (mem) {
+ if (GetMappedFileName(GetCurrentProcess(), mem, filename, cch_filename)) {
+ // Translate path with device name to drive letters.
+ TCHAR temp[512];
+ temp[0] = '\0';
+
+ if (GetLogicalDriveStrings(512 - 1, temp)) {
+ TCHAR name[MAX_PATH];
+ TCHAR drive[3] = TEXT(" :");
+ BOOL found = FALSE;
+ TCHAR* p = temp;
+
+ do {
+ // Copy the drive letter to the template string.
+ *drive = *p;
+
+ // Look up each device name.
+ if (QueryDosDevice(drive, name, MAX_PATH)) {
+ size_t name_len = _tcslen(name);
+ if (name_len < MAX_PATH) {
+ found = _tcsnicmp(filename, name, name_len) == 0
+ && *(filename + name_len) == _T('\\');
+ if (found) {
+ // Reconstruct filename using temp_file and replace device path
+ // with DOS path.
+ TCHAR temp_file[MAX_PATH];
+ _sntprintf(temp_file,
+ MAX_PATH - 1,
+ TEXT("%s%s"),
+ drive,
+ filename + name_len);
+ strcpy(filename, temp_file);
+ }
+ }
+ }
+
+ // Go to the next NULL character.
+ while (*p++) {
+ // Do nothing.
+ }
+ } while (!found && *p); // End of string.
+ }
+ }
+ success = TRUE;
+ UnmapViewOfFile(mem);
+ }
+
+ CloseHandle(file_map);
+ return success;
}
#endif
// A sane realpath() function, trying to cope with stupid path limits and a
// broken API. Caller frees.
-char *
-x_realpath(const char *path)
+char*
+x_realpath(const char* path)
{
- long maxlen = path_max(path);
- char *ret = static_cast<char*>(x_malloc(maxlen));
- char *p;
+ long maxlen = path_max(path);
+ char* ret = static_cast<char*>(x_malloc(maxlen));
+ char* p;
#if HAVE_REALPATH
- p = realpath(path, ret);
+ p = realpath(path, ret);
#elif defined(_WIN32)
- if (path[0] == '/') {
- path++; // Skip leading slash.
- }
- HANDLE path_handle = CreateFile(
- path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, NULL);
- if (INVALID_HANDLE_VALUE != path_handle) {
-#ifdef HAVE_GETFINALPATHNAMEBYHANDLEW
- GetFinalPathNameByHandle(path_handle, ret, maxlen, FILE_NAME_NORMALIZED);
-#else
- GetFileNameFromHandle(path_handle, ret, maxlen);
-#endif
- CloseHandle(path_handle);
- p = ret + 4; // Strip \\?\ from the file name.
- } else {
- snprintf(ret, maxlen, "%s", path);
- p = ret;
- }
+ if (path[0] == '/') {
+ path++; // Skip leading slash.
+ }
+ HANDLE path_handle = CreateFile(path,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (INVALID_HANDLE_VALUE != path_handle) {
+# ifdef HAVE_GETFINALPATHNAMEBYHANDLEW
+ GetFinalPathNameByHandle(path_handle, ret, maxlen, FILE_NAME_NORMALIZED);
+# else
+ GetFileNameFromHandle(path_handle, ret, maxlen);
+# endif
+ CloseHandle(path_handle);
+ p = ret + 4; // Strip \\?\ from the file name.
+ } else {
+ snprintf(ret, maxlen, "%s", path);
+ p = ret;
+ }
#else
- // Yes, there are such systems. This replacement relies on the fact that when
- // we call x_realpath we only care about symlinks.
- {
- int len = readlink(path, ret, maxlen-1);
- if (len == -1) {
- free(ret);
- return NULL;
- }
- ret[len] = 0;
- p = ret;
- }
+ // Yes, there are such systems. This replacement relies on the fact that when
+ // we call x_realpath we only care about symlinks.
+ {
+ int len = readlink(path, ret, maxlen - 1);
+ if (len == -1) {
+ free(ret);
+ return NULL;
+ }
+ ret[len] = 0;
+ p = ret;
+ }
#endif
- if (p) {
- p = x_strdup(p);
- free(ret);
- return p;
- }
- free(ret);
- return NULL;
+ if (p) {
+ p = x_strdup(p);
+ free(ret);
+ return p;
+ }
+ free(ret);
+ return NULL;
}
// A getcwd that will returns an allocated buffer.
-char *
+char*
gnu_getcwd(void)
{
- unsigned size = 128;
+ unsigned size = 128;
- while (true) {
- char *buffer = (char *)x_malloc(size);
- if (getcwd(buffer, size) == buffer) {
- return buffer;
- }
- free(buffer);
- if (errno != ERANGE) {
- cc_log("getcwd error: %d (%s)", errno, strerror(errno));
- return NULL;
- }
- size *= 2;
- }
+ while (true) {
+ char* buffer = (char*)x_malloc(size);
+ if (getcwd(buffer, size) == buffer) {
+ return buffer;
+ }
+ free(buffer);
+ if (errno != ERANGE) {
+ cc_log("getcwd error: %d (%s)", errno, strerror(errno));
+ return NULL;
+ }
+ size *= 2;
+ }
}
#if !defined(_WIN32) && !defined(HAVE_LOCALTIME_R)
// localtime_r replacement. (Mingw-w64 has an inline localtime_r which is not
// detected by AC_CHECK_FUNCS.)
-struct tm *
-localtime_r(const time_t *timep, struct tm *result)
+struct tm*
+localtime_r(const time_t* timep, struct tm* result)
{
- struct tm *tm = localtime(timep);
- *result = *tm;
- return result;
+ struct tm* tm = localtime(timep);
+ *result = *tm;
+ return result;
}
#endif
#ifndef HAVE_STRTOK_R
// strtok_r replacement.
-char *
-strtok_r(char *str, const char *delim, char **saveptr)
-{
- if (!str) {
- str = *saveptr;
- }
- int len = strlen(str);
- char *ret = strtok(str, delim);
- if (ret) {
- char *save = ret;
- while (*save++) {
- // Do nothing.
- }
- if ((len + 1) == (intptr_t) (save - str)) {
- save--;
- }
- *saveptr = save;
- }
- return ret;
+char*
+strtok_r(char* str, const char* delim, char** saveptr)
+{
+ if (!str) {
+ str = *saveptr;
+ }
+ int len = strlen(str);
+ char* ret = strtok(str, delim);
+ if (ret) {
+ char* save = ret;
+ while (*save++) {
+ // Do nothing.
+ }
+ if ((len + 1) == (intptr_t)(save - str)) {
+ save--;
+ }
+ *saveptr = save;
+ }
+ return ret;
}
#endif
// Create an empty temporary file. *fname will be reallocated and set to the
// resulting filename. Returns an open file descriptor to the file.
int
-create_tmp_fd(char **fname)
-{
- char *tmpl = format("%s.%s", *fname, tmp_string());
- int fd = mkstemp(tmpl);
- if (fd == -1 && errno == ENOENT) {
- if (create_parent_dirs(*fname) != 0) {
- fatal("Failed to create directory %s: %s",
- x_dirname(*fname), strerror(errno));
- }
- reformat(&tmpl, "%s.%s", *fname, tmp_string());
- fd = mkstemp(tmpl);
- }
- if (fd == -1) {
- fatal("Failed to create temporary file for %s: %s",
- *fname, strerror(errno));
- }
- set_cloexec_flag(fd);
+create_tmp_fd(char** fname)
+{
+ char* tmpl = format("%s.%s", *fname, tmp_string());
+ int fd = mkstemp(tmpl);
+ if (fd == -1 && errno == ENOENT) {
+ if (create_parent_dirs(*fname) != 0) {
+ fatal("Failed to create directory %s: %s",
+ x_dirname(*fname),
+ strerror(errno));
+ }
+ reformat(&tmpl, "%s.%s", *fname, tmp_string());
+ fd = mkstemp(tmpl);
+ }
+ if (fd == -1) {
+ fatal(
+ "Failed to create temporary file for %s: %s", *fname, strerror(errno));
+ }
+ set_cloexec_flag(fd);
#ifndef _WIN32
- fchmod(fd, 0666 & ~get_umask());
+ fchmod(fd, 0666 & ~get_umask());
#endif
- free(*fname);
- *fname = tmpl;
- return fd;
+ free(*fname);
+ *fname = tmpl;
+ return fd;
}
// Create an empty temporary file. *fname will be reallocated and set to the
// resulting filename. Returns an open FILE*.
-FILE *
-create_tmp_file(char **fname, const char *mode)
+FILE*
+create_tmp_file(char** fname, const char* mode)
{
- FILE *file = fdopen(create_tmp_fd(fname), mode);
- if (!file) {
- fatal("Failed to create file %s: %s", *fname, strerror(errno));
- }
- return file;
+ FILE* file = fdopen(create_tmp_fd(fname), mode);
+ if (!file) {
+ fatal("Failed to create file %s: %s", *fname, strerror(errno));
+ }
+ return file;
}
// Return current user's home directory, or NULL if it can't be determined.
-const char *
+const char*
get_home_directory(void)
{
- const char *p = getenv("HOME");
- if (p) {
- return p;
- }
+ const char* p = getenv("HOME");
+ if (p) {
+ return p;
+ }
#ifdef _WIN32
- p = getenv("APPDATA");
- if (p) {
- return p;
- }
+ p = getenv("APPDATA");
+ if (p) {
+ return p;
+ }
#endif
#ifdef HAVE_GETPWUID
- {
- struct passwd *pwd = getpwuid(getuid());
- if (pwd) {
- return pwd->pw_dir;
- }
- }
+ {
+ struct passwd* pwd = getpwuid(getuid());
+ if (pwd) {
+ return pwd->pw_dir;
+ }
+ }
#endif
- return NULL;
+ return NULL;
}
// Get the current directory by reading $PWD. If $PWD isn't sane, gnu_getcwd()
// is used. Caller frees.
-char *
+char*
get_cwd(void)
{
- struct stat st_pwd;
- struct stat st_cwd;
-
- char *cwd = gnu_getcwd();
- if (!cwd) {
- return NULL;
- }
- char *pwd = getenv("PWD");
- if (!pwd) {
- return cwd;
- }
- if (stat(pwd, &st_pwd) != 0) {
- return cwd;
- }
- if (stat(cwd, &st_cwd) != 0) {
- return cwd;
- }
- if (st_pwd.st_dev == st_cwd.st_dev && st_pwd.st_ino == st_cwd.st_ino) {
- free(cwd);
- return x_strdup(pwd);
- } else {
- return cwd;
- }
+ struct stat st_pwd;
+ struct stat st_cwd;
+
+ char* cwd = gnu_getcwd();
+ if (!cwd) {
+ return NULL;
+ }
+ char* pwd = getenv("PWD");
+ if (!pwd) {
+ return cwd;
+ }
+ if (stat(pwd, &st_pwd) != 0) {
+ return cwd;
+ }
+ if (stat(cwd, &st_cwd) != 0) {
+ return cwd;
+ }
+ if (st_pwd.st_dev == st_cwd.st_dev && st_pwd.st_ino == st_cwd.st_ino) {
+ free(cwd);
+ return x_strdup(pwd);
+ } else {
+ return cwd;
+ }
}
// Check whether s1 and s2 have the same executable name.
bool
-same_executable_name(const char *s1, const char *s2)
+same_executable_name(const char* s1, const char* s2)
{
#ifdef _WIN32
- bool eq = strcasecmp(s1, s2) == 0;
- if (!eq) {
- char *tmp = format("%s.exe", s2);
- eq = strcasecmp(s1, tmp) == 0;
- free(tmp);
- }
- return eq;
+ bool eq = strcasecmp(s1, s2) == 0;
+ if (!eq) {
+ char* tmp = format("%s.exe", s2);
+ eq = strcasecmp(s1, tmp) == 0;
+ free(tmp);
+ }
+ return eq;
#else
- return str_eq(s1, s2);
+ return str_eq(s1, s2);
#endif
}
// Compute the length of the longest directory path that is common to two
// paths. s1 is assumed to be the path to a directory.
size_t
-common_dir_prefix_length(const char *s1, const char *s2)
-{
- const char *p1 = s1;
- const char *p2 = s2;
-
- while (*p1 && *p2 && *p1 == *p2) {
- ++p1;
- ++p2;
- }
- while ((*p1 && *p1 != '/') || (*p2 && *p2 != '/')) {
- p1--;
- p2--;
- }
- if (!*p1 && !*p2 && p2 == s2 + 1) {
- // Special case for s1 and s2 both being "/".
- return 0;
- }
- return p1 - s1;
+common_dir_prefix_length(const char* s1, const char* s2)
+{
+ const char* p1 = s1;
+ const char* p2 = s2;
+
+ while (*p1 && *p2 && *p1 == *p2) {
+ ++p1;
+ ++p2;
+ }
+ while ((*p1 && *p1 != '/') || (*p2 && *p2 != '/')) {
+ p1--;
+ p2--;
+ }
+ if (!*p1 && !*p2 && p2 == s2 + 1) {
+ // Special case for s1 and s2 both being "/".
+ return 0;
+ }
+ return p1 - s1;
}
// Compute a relative path from from (an absolute path to a directory) to to (a
// path). Assumes that both from and to are well-formed and canonical. Caller
// frees.
-char *
-get_relative_path(const char *from, const char *to)
+char*
+get_relative_path(const char* from, const char* to)
{
- size_t common_prefix_len;
- char *result;
+ size_t common_prefix_len;
+ char* result;
- assert(from && is_absolute_path(from));
- assert(to);
+ assert(from && is_absolute_path(from));
+ assert(to);
- if (!*to || !is_absolute_path(to)) {
- return x_strdup(to);
- }
+ if (!*to || !is_absolute_path(to)) {
+ return x_strdup(to);
+ }
#ifdef _WIN32
- // Paths can be escaped by a slash for use with -isystem.
- if (from[0] == '/') {
- from++;
- }
- if (to[0] == '/') {
- to++;
- }
- // Both paths are absolute, drop the drive letters.
- assert(from[0] == to[0]); // Assume the same drive letter.
- from += 2;
- to += 2;
+ // Paths can be escaped by a slash for use with -isystem.
+ if (from[0] == '/') {
+ from++;
+ }
+ if (to[0] == '/') {
+ to++;
+ }
+ // Both paths are absolute, drop the drive letters.
+ assert(from[0] == to[0]); // Assume the same drive letter.
+ from += 2;
+ to += 2;
#endif
- result = x_strdup("");
- common_prefix_len = common_dir_prefix_length(from, to);
- if (common_prefix_len > 0 || !str_eq(from, "/")) {
- const char *p;
- for (p = from + common_prefix_len; *p; p++) {
- if (*p == '/') {
- reformat(&result, "../%s", result);
- }
- }
- }
- if (strlen(to) > common_prefix_len) {
- reformat(&result, "%s%s", result, to + common_prefix_len + 1);
- }
- for (int i = strlen(result) - 1; i >= 0 && result[i] == '/'; i--) {
- result[i] = '\0';
- }
- if (str_eq(result, "")) {
- free(result);
- result = x_strdup(".");
- }
- return result;
+ result = x_strdup("");
+ common_prefix_len = common_dir_prefix_length(from, to);
+ if (common_prefix_len > 0 || !str_eq(from, "/")) {
+ const char* p;
+ for (p = from + common_prefix_len; *p; p++) {
+ if (*p == '/') {
+ reformat(&result, "../%s", result);
+ }
+ }
+ }
+ if (strlen(to) > common_prefix_len) {
+ reformat(&result, "%s%s", result, to + common_prefix_len + 1);
+ }
+ for (int i = strlen(result) - 1; i >= 0 && result[i] == '/'; i--) {
+ result[i] = '\0';
+ }
+ if (str_eq(result, "")) {
+ free(result);
+ result = x_strdup(".");
+ }
+ return result;
}
// Return whether path is absolute.
bool
-is_absolute_path(const char *path)
+is_absolute_path(const char* path)
{
#ifdef _WIN32
- return path[0] && path[1] == ':';
+ return path[0] && path[1] == ':';
#else
- return path[0] == '/';
+ return path[0] == '/';
#endif
}
// Return whether the argument is a full path.
bool
-is_full_path(const char *path)
+is_full_path(const char* path)
{
- if (strchr(path, '/')) {
- return true;
- }
+ if (strchr(path, '/')) {
+ return true;
+ }
#ifdef _WIN32
- if (strchr(path, '\\')) {
- return true;
- }
+ if (strchr(path, '\\')) {
+ return true;
+ }
#endif
- return false;
+ return false;
}
-bool is_symlink(const char *path)
+bool
+is_symlink(const char* path)
{
#ifdef _WIN32
- (void)path;
- return false;
+ (void)path;
+ return false;
#else
- struct stat st;
- return x_lstat(path, &st) == 0 && ((st.st_mode & S_IFMT) == S_IFLNK);
+ struct stat st;
+ return x_lstat(path, &st) == 0 && ((st.st_mode & S_IFMT) == S_IFLNK);
#endif
}
// Update the modification time of a file in the cache to save it from LRU
// cleanup.
void
-update_mtime(const char *path)
+update_mtime(const char* path)
{
#ifdef HAVE_UTIMES
- utimes(path, NULL);
+ utimes(path, NULL);
#else
- utime(path, NULL);
+ utime(path, NULL);
#endif
}
@@ -1486,294 +1497,299 @@ update_mtime(const char *path)
void
x_exit(int status)
{
- static bool first_time = true;
- if (first_time) {
- first_time = false;
- exit(status);
- } else {
- _exit(status);
- }
+ static bool first_time = true;
+ if (first_time) {
+ first_time = false;
+ exit(status);
+ } else {
+ _exit(status);
+ }
}
// Rename oldpath to newpath (deleting newpath).
int
-x_rename(const char *oldpath, const char *newpath)
+x_rename(const char* oldpath, const char* newpath)
{
#ifndef _WIN32
- return rename(oldpath, newpath);
+ return rename(oldpath, newpath);
#else
- // Windows' rename() refuses to overwrite an existing file.
- unlink(newpath); // Not x_unlink, as x_unlink calls x_rename.
- // If the function succeeds, the return value is nonzero.
- if (MoveFileA(oldpath, newpath) == 0) {
- LPVOID lp_msg_buf;
- DWORD dw = GetLastError();
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, dw,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lp_msg_buf,
- 0,
- NULL);
-
- LPVOID lp_display_buf = (LPVOID) LocalAlloc(
- LMEM_ZEROINIT,
- (lstrlen((LPCTSTR) lp_msg_buf) + lstrlen((LPCTSTR) __FILE__) + 40)
- * sizeof(TCHAR));
- _snprintf((LPTSTR) lp_display_buf,
- LocalSize(lp_display_buf) / sizeof(TCHAR),
- TEXT("%s failed with error %lu: %s"), __FILE__, dw,
- (const char *)lp_msg_buf);
-
- cc_log("can't rename file %s to %s OS returned error: %s",
- oldpath, newpath, (char *) lp_display_buf);
-
- LocalFree(lp_msg_buf);
- LocalFree(lp_display_buf);
- return -1;
- } else {
- return 0;
- }
+ // Windows' rename() refuses to overwrite an existing file.
+ unlink(newpath); // Not x_unlink, as x_unlink calls x_rename.
+ // If the function succeeds, the return value is nonzero.
+ if (MoveFileA(oldpath, newpath) == 0) {
+ LPVOID lp_msg_buf;
+ DWORD dw = GetLastError();
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ dw,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&lp_msg_buf,
+ 0,
+ NULL);
+
+ LPVOID lp_display_buf = (LPVOID)LocalAlloc(
+ LMEM_ZEROINIT,
+ (lstrlen((LPCTSTR)lp_msg_buf) + lstrlen((LPCTSTR)__FILE__) + 40)
+ * sizeof(TCHAR));
+ _snprintf((LPTSTR)lp_display_buf,
+ LocalSize(lp_display_buf) / sizeof(TCHAR),
+ TEXT("%s failed with error %lu: %s"),
+ __FILE__,
+ dw,
+ (const char*)lp_msg_buf);
+
+ cc_log("can't rename file %s to %s OS returned error: %s",
+ oldpath,
+ newpath,
+ (char*)lp_display_buf);
+
+ LocalFree(lp_msg_buf);
+ LocalFree(lp_display_buf);
+ return -1;
+ } else {
+ return 0;
+ }
#endif
}
// Remove path, NFS hazardous. Use only for temporary files that will not exist
// on other systems. That is, the path should include tmp_string().
int
-tmp_unlink(const char *path)
+tmp_unlink(const char* path)
{
- cc_log("Unlink %s", path);
- int rc = unlink(path);
- if (rc) {
- cc_log("Unlink failed: %s", strerror(errno));
- }
- return rc;
+ cc_log("Unlink %s", path);
+ int rc = unlink(path);
+ if (rc) {
+ cc_log("Unlink failed: %s", strerror(errno));
+ }
+ return rc;
}
static int
-do_x_unlink(const char *path, bool log_failure)
-{
- int saved_errno = 0;
-
- // If path is on an NFS share, unlink isn't atomic, so we rename to a temp
- // file. We don't care if the temp file is trashed, so it's always safe to
- // unlink it first.
- char *tmp_name = format("%s.rm.%s", path, tmp_string());
-
- int result = 0;
- if (x_rename(path, tmp_name) == -1) {
- result = -1;
- saved_errno = errno;
- goto out;
- }
- if (unlink(tmp_name) == -1) {
- // If it was released in a race, that's OK.
- if (errno != ENOENT && errno != ESTALE) {
- result = -1;
- saved_errno = errno;
- }
- }
+do_x_unlink(const char* path, bool log_failure)
+{
+ int saved_errno = 0;
+
+ // If path is on an NFS share, unlink isn't atomic, so we rename to a temp
+ // file. We don't care if the temp file is trashed, so it's always safe to
+ // unlink it first.
+ char* tmp_name = format("%s.rm.%s", path, tmp_string());
+
+ int result = 0;
+ if (x_rename(path, tmp_name) == -1) {
+ result = -1;
+ saved_errno = errno;
+ goto out;
+ }
+ if (unlink(tmp_name) == -1) {
+ // If it was released in a race, that's OK.
+ if (errno != ENOENT && errno != ESTALE) {
+ result = -1;
+ saved_errno = errno;
+ }
+ }
out:
- if (result == 0 || log_failure) {
- cc_log("Unlink %s via %s", path, tmp_name);
- if (result != 0 && log_failure) {
- cc_log("x_unlink failed: %s", strerror(saved_errno));
- }
- }
- free(tmp_name);
- errno = saved_errno;
- return result;
+ if (result == 0 || log_failure) {
+ cc_log("Unlink %s via %s", path, tmp_name);
+ if (result != 0 && log_failure) {
+ cc_log("x_unlink failed: %s", strerror(saved_errno));
+ }
+ }
+ free(tmp_name);
+ errno = saved_errno;
+ return result;
}
// Remove path, NFS safe, log both successes and failures.
int
-x_unlink(const char *path)
+x_unlink(const char* path)
{
- return do_x_unlink(path, true);
+ return do_x_unlink(path, true);
}
// Remove path, NFS safe, only log successes.
int
-x_try_unlink(const char *path)
+x_try_unlink(const char* path)
{
- return do_x_unlink(path, false);
+ return do_x_unlink(path, false);
}
#ifndef _WIN32
// Like readlink() but returns the string or NULL on failure. Caller frees.
-char *
-x_readlink(const char *path)
-{
- long maxlen = path_max(path);
- char *buf = static_cast<char*>(x_malloc(maxlen));
- ssize_t len = readlink(path, buf, maxlen-1);
- if (len == -1) {
- free(buf);
- return NULL;
- }
- buf[len] = 0;
- return buf;
+char*
+x_readlink(const char* path)
+{
+ long maxlen = path_max(path);
+ char* buf = static_cast<char*>(x_malloc(maxlen));
+ ssize_t len = readlink(path, buf, maxlen - 1);
+ if (len == -1) {
+ free(buf);
+ return NULL;
+ }
+ buf[len] = 0;
+ return buf;
}
#endif
// Reads the content of a file. Size hint 0 means no hint. Returns true on
// success, otherwise false.
bool
-read_file(const char *path, size_t size_hint, char **data, size_t *size)
-{
- if (size_hint == 0) {
- struct stat st;
- if (x_stat(path, &st) == 0) {
- size_hint = st.st_size;
- }
- }
- size_hint = (size_hint < 1024) ? 1024 : size_hint;
-
- int fd = open(path, O_RDONLY | O_BINARY);
- if (fd == -1) {
- return false;
- }
- size_t allocated = size_hint;
- *data = static_cast<char*>(x_malloc(allocated));
- int ret;
- size_t pos = 0;
- while (true) {
- if (pos > allocated / 2) {
- allocated *= 2;
- *data = static_cast<char*>(x_realloc(*data, allocated));
- }
- ret = read(fd, *data + pos, allocated - pos);
- if (ret == 0 || (ret == -1 && errno != EINTR)) {
- break;
- }
- if (ret > 0) {
- pos += ret;
- }
- }
- close(fd);
- if (ret == -1) {
- cc_log("Failed reading %s", path);
- free(*data);
- *data = NULL;
- return false;
- }
-
- *size = pos;
- return true;
+read_file(const char* path, size_t size_hint, char** data, size_t* size)
+{
+ if (size_hint == 0) {
+ struct stat st;
+ if (x_stat(path, &st) == 0) {
+ size_hint = st.st_size;
+ }
+ }
+ size_hint = (size_hint < 1024) ? 1024 : size_hint;
+
+ int fd = open(path, O_RDONLY | O_BINARY);
+ if (fd == -1) {
+ return false;
+ }
+ size_t allocated = size_hint;
+ *data = static_cast<char*>(x_malloc(allocated));
+ int ret;
+ size_t pos = 0;
+ while (true) {
+ if (pos > allocated / 2) {
+ allocated *= 2;
+ *data = static_cast<char*>(x_realloc(*data, allocated));
+ }
+ ret = read(fd, *data + pos, allocated - pos);
+ if (ret == 0 || (ret == -1 && errno != EINTR)) {
+ break;
+ }
+ if (ret > 0) {
+ pos += ret;
+ }
+ }
+ close(fd);
+ if (ret == -1) {
+ cc_log("Failed reading %s", path);
+ free(*data);
+ *data = NULL;
+ return false;
+ }
+
+ *size = pos;
+ return true;
}
// Return the content (with NUL termination) of a text file, or NULL on error.
// Caller frees. Size hint 0 means no hint.
-char *
-read_text_file(const char *path, size_t size_hint)
+char*
+read_text_file(const char* path, size_t size_hint)
{
- size_t size;
- char *data;
- if (read_file(path, size_hint, &data, &size)) {
- data = static_cast<char*>(x_realloc(data, size + 1));
- data[size] = '\0';
- return data;
- } else {
- return NULL;
- }
+ size_t size;
+ char* data;
+ if (read_file(path, size_hint, &data, &size)) {
+ data = static_cast<char*>(x_realloc(data, size + 1));
+ data[size] = '\0';
+ return data;
+ } else {
+ return NULL;
+ }
}
static bool
-expand_variable(const char **str, char **result, char **errmsg)
-{
- assert(**str == '$');
-
- bool curly;
- const char *p = *str + 1;
- if (*p == '{') {
- curly = true;
- ++p;
- } else {
- curly = false;
- }
-
- const char *q = p;
- while (isalnum(*q) || *q == '_') {
- ++q;
- }
- if (curly) {
- if (*q != '}') {
- *errmsg = format("syntax error: missing '}' after \"%s\"", p);
- return false;
- }
- }
-
- if (q == p) {
- // Special case: don't consider a single $ the start of a variable.
- reformat(result, "%s$", *result);
- return true;
- }
-
- char *name = x_strndup(p, q - p);
- const char *value = getenv(name);
- if (!value) {
- *errmsg = format("environment variable \"%s\" not set", name);
- free(name);
- return false;
- }
- reformat(result, "%s%s", *result, value);
- if (!curly) {
- --q;
- }
- *str = q;
- free(name);
- return true;
+expand_variable(const char** str, char** result, char** errmsg)
+{
+ assert(**str == '$');
+
+ bool curly;
+ const char* p = *str + 1;
+ if (*p == '{') {
+ curly = true;
+ ++p;
+ } else {
+ curly = false;
+ }
+
+ const char* q = p;
+ while (isalnum(*q) || *q == '_') {
+ ++q;
+ }
+ if (curly) {
+ if (*q != '}') {
+ *errmsg = format("syntax error: missing '}' after \"%s\"", p);
+ return false;
+ }
+ }
+
+ if (q == p) {
+ // Special case: don't consider a single $ the start of a variable.
+ reformat(result, "%s$", *result);
+ return true;
+ }
+
+ char* name = x_strndup(p, q - p);
+ const char* value = getenv(name);
+ if (!value) {
+ *errmsg = format("environment variable \"%s\" not set", name);
+ free(name);
+ return false;
+ }
+ reformat(result, "%s%s", *result, value);
+ if (!curly) {
+ --q;
+ }
+ *str = q;
+ free(name);
+ return true;
}
// Substitute all instances of $VAR or ${VAR}, where VAR is an environment
// variable, in a string. Caller frees. If one of the environment variables
// doesn't exist, NULL will be returned and *errmsg will be an appropriate
// error message (caller frees).
-char *
-subst_env_in_string(const char *str, char **errmsg)
-{
- assert(errmsg);
- *errmsg = NULL;
-
- char *result = x_strdup("");
- const char *p = str; // Interval start.
- const char *q = str; // Interval end.
- for (q = str; *q; ++q) {
- if (*q == '$') {
- reformat(&result, "%s%.*s", result, (int)(q - p), p);
- if (!expand_variable(&q, &result, errmsg)) {
- free(result);
- return NULL;
- }
- p = q + 1;
- }
- }
- reformat(&result, "%s%.*s", result, (int)(q - p), p);
- return result;
+char*
+subst_env_in_string(const char* str, char** errmsg)
+{
+ assert(errmsg);
+ *errmsg = NULL;
+
+ char* result = x_strdup("");
+ const char* p = str; // Interval start.
+ const char* q = str; // Interval end.
+ for (q = str; *q; ++q) {
+ if (*q == '$') {
+ reformat(&result, "%s%.*s", result, (int)(q - p), p);
+ if (!expand_variable(&q, &result, errmsg)) {
+ free(result);
+ return NULL;
+ }
+ p = q + 1;
+ }
+ }
+ reformat(&result, "%s%.*s", result, (int)(q - p), p);
+ return result;
}
void
set_cloexec_flag(int fd)
{
#ifndef _WIN32
- int flags = fcntl(fd, F_GETFD, 0);
- if (flags >= 0) {
- fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
- }
+ int flags = fcntl(fd, F_GETFD, 0);
+ if (flags >= 0) {
+ fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+ }
#else
- (void)fd;
+ (void)fd;
#endif
}
-double time_seconds(void)
+double
+time_seconds(void)
{
#ifdef HAVE_GETTIMEOFDAY
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
#else
- return (double)time(NULL);
+ return (double)time(NULL);
#endif
}
diff --git a/unittest/framework.cpp b/unittest/framework.cpp
index ca4bbbe3..4cab44be 100644
--- a/unittest/framework.cpp
+++ b/unittest/framework.cpp
@@ -17,23 +17,24 @@
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "framework.hpp"
+
#include "util.hpp"
#include <float.h>
#include <math.h>
#if defined(HAVE_TERMIOS_H)
-#define USE_COLOR
-#include <termios.h>
+# define USE_COLOR
+# include <termios.h>
#endif
static unsigned total_asserts;
static unsigned total_tests;
static unsigned total_suites;
static unsigned failed_tests;
-static const char *current_suite;
-static const char *current_test;
-static char *dir_before_suite;
-static char *dir_before_test;
+static const char* current_suite;
+static const char* current_test;
+static char* dir_before_suite;
+static char* dir_before_test;
static int verbose;
static const char COLOR_END[] = "\x1b[m";
@@ -41,282 +42,309 @@ static const char COLOR_GREEN[] = "\x1b[1;32m";
static const char COLOR_RED[] = "\x1b[1;31m";
static char CONFIG_PATH_ENV[] = "CCACHE_CONFIG_PATH=/dev/null";
-#define COLOR(tty, color) ((tty) ? COLOR_ ## color : "")
+#define COLOR(tty, color) ((tty) ? COLOR_##color : "")
static int
is_tty(int fd)
{
#ifdef USE_COLOR
- struct termios t;
- return tcgetattr(fd, &t) == 0;
+ struct termios t;
+ return tcgetattr(fd, &t) == 0;
#else
- (void)fd;
- return 0;
+ (void)fd;
+ return 0;
#endif
}
-static const char *
+static const char*
plural_s(unsigned n)
{
- return n == 1 ? "" : "s";
+ return n == 1 ? "" : "s";
}
int
-cct_run(suite_fn *suites, int verbose_output)
+cct_run(suite_fn* suites, int verbose_output)
{
- suite_fn *suite;
- int tty = is_tty(1);
+ suite_fn* suite;
+ int tty = is_tty(1);
- x_unsetenv("GCC_COLORS"); // Avoid confusing argument processing tests.
- verbose = verbose_output;
+ x_unsetenv("GCC_COLORS"); // Avoid confusing argument processing tests.
+ verbose = verbose_output;
- for (suite = suites; *suite; suite++) {
- unsigned test_index = 0;
- while (true) {
- test_index = (*suite)(test_index + 1);
- if (test_index == 0) {
- // We have reached the end of the suite.
- break;
- }
- }
- }
+ for (suite = suites; *suite; suite++) {
+ unsigned test_index = 0;
+ while (true) {
+ test_index = (*suite)(test_index + 1);
+ if (test_index == 0) {
+ // We have reached the end of the suite.
+ break;
+ }
+ }
+ }
- if (failed_tests == 0) {
- printf("%sPASSED%s: %u assertion%s, %u test%s, %u suite%s\n",
- COLOR(tty, GREEN), COLOR(tty, END),
- total_asserts, plural_s(total_asserts),
- total_tests, plural_s(total_tests),
- total_suites, plural_s(total_suites));
- } else {
- printf("%sFAILED%s: %u test%s\n",
- COLOR(tty, RED), COLOR(tty, END),
- failed_tests, plural_s(failed_tests));
- }
- return failed_tests > 0 ? 1 : 0;
+ if (failed_tests == 0) {
+ printf("%sPASSED%s: %u assertion%s, %u test%s, %u suite%s\n",
+ COLOR(tty, GREEN),
+ COLOR(tty, END),
+ total_asserts,
+ plural_s(total_asserts),
+ total_tests,
+ plural_s(total_tests),
+ total_suites,
+ plural_s(total_suites));
+ } else {
+ printf("%sFAILED%s: %u test%s\n",
+ COLOR(tty, RED),
+ COLOR(tty, END),
+ failed_tests,
+ plural_s(failed_tests));
+ }
+ return failed_tests > 0 ? 1 : 0;
}
void
-cct_suite_begin(const char *name)
+cct_suite_begin(const char* name)
{
- ++total_suites;
- if (verbose) {
- printf("=== SUITE: %s ===\n", name);
- }
- dir_before_suite = gnu_getcwd();
- create_dir(name);
- cct_chdir(name);
- current_suite = name;
+ ++total_suites;
+ if (verbose) {
+ printf("=== SUITE: %s ===\n", name);
+ }
+ dir_before_suite = gnu_getcwd();
+ create_dir(name);
+ cct_chdir(name);
+ current_suite = name;
}
void
cct_suite_end()
{
- cct_chdir(dir_before_suite);
- free(dir_before_suite);
- dir_before_suite = NULL;
+ cct_chdir(dir_before_suite);
+ free(dir_before_suite);
+ dir_before_suite = NULL;
}
void
-cct_test_begin(const char *name)
+cct_test_begin(const char* name)
{
- ++total_tests;
- if (verbose) {
- printf("--- TEST: %s ---\n", name);
- }
- dir_before_test = gnu_getcwd();
- create_dir(name);
- cct_chdir(name);
- current_test = name;
+ ++total_tests;
+ if (verbose) {
+ printf("--- TEST: %s ---\n", name);
+ }
+ dir_before_test = gnu_getcwd();
+ create_dir(name);
+ cct_chdir(name);
+ current_test = name;
- putenv(CONFIG_PATH_ENV);
- cc_reset();
+ putenv(CONFIG_PATH_ENV);
+ cc_reset();
}
void
cct_test_end()
{
- if (dir_before_test) {
- cct_chdir(dir_before_test);
- free(dir_before_test);
- dir_before_test = NULL;
- }
+ if (dir_before_test) {
+ cct_chdir(dir_before_test);
+ free(dir_before_test);
+ dir_before_test = NULL;
+ }
}
void
-cct_check_passed(const char *file, int line, const char *what)
+cct_check_passed(const char* file, int line, const char* what)
{
- ++total_asserts;
- if (verbose) {
- printf("%s:%d: Passed assertion: %s\n", file, line, what);
- }
+ ++total_asserts;
+ if (verbose) {
+ printf("%s:%d: Passed assertion: %s\n", file, line, what);
+ }
}
void
-cct_check_failed(const char *file, int line, const char *what,
- const char *expected, const char *actual)
+cct_check_failed(const char* file,
+ int line,
+ const char* what,
+ const char* expected,
+ const char* actual)
{
- ++total_asserts;
- ++failed_tests;
- fprintf(stderr, "%s:%d: Failed assertion:\n", file, line);
- fprintf(stderr, " Suite: %s\n", current_suite);
- fprintf(stderr, " Test: %s\n", current_test);
- if (expected) {
- fprintf(stderr, " Expression: %s\n", what);
- if (actual) {
- fprintf(stderr, " Expected: %s\n", expected);
- fprintf(stderr, " Actual: %s\n", actual);
- } else {
- fprintf(stderr, " Message: %s\n", expected);
- }
- } else {
- fprintf(stderr, " Assertion: %s\n", what);
- }
- fprintf(stderr, "\n");
+ ++total_asserts;
+ ++failed_tests;
+ fprintf(stderr, "%s:%d: Failed assertion:\n", file, line);
+ fprintf(stderr, " Suite: %s\n", current_suite);
+ fprintf(stderr, " Test: %s\n", current_test);
+ if (expected) {
+ fprintf(stderr, " Expression: %s\n", what);
+ if (actual) {
+ fprintf(stderr, " Expected: %s\n", expected);
+ fprintf(stderr, " Actual: %s\n", actual);
+ } else {
+ fprintf(stderr, " Message: %s\n", expected);
+ }
+ } else {
+ fprintf(stderr, " Assertion: %s\n", what);
+ }
+ fprintf(stderr, "\n");
}
bool
-cct_check_double_eq(const char *file, int line, const char *expression,
- double expected, double actual)
+cct_check_double_eq(const char* file,
+ int line,
+ const char* expression,
+ double expected,
+ double actual)
{
- if (fabs(expected - actual) < DBL_EPSILON) {
- cct_check_passed(file, line, expression);
- return true;
- } else {
- char *exp_str = format("%.1f", expected);
- char *act_str = format("%.1f", actual);
- cct_check_failed(file, line, expression, exp_str, act_str);
- free(exp_str);
- free(act_str);
- return false;
- }
+ if (fabs(expected - actual) < DBL_EPSILON) {
+ cct_check_passed(file, line, expression);
+ return true;
+ } else {
+ char* exp_str = format("%.1f", expected);
+ char* act_str = format("%.1f", actual);
+ cct_check_failed(file, line, expression, exp_str, act_str);
+ free(exp_str);
+ free(act_str);
+ return false;
+ }
}
bool
-cct_check_int_eq(const char *file, int line, const char *expression,
- int64_t expected, int64_t actual)
+cct_check_int_eq(const char* file,
+ int line,
+ const char* expression,
+ int64_t expected,
+ int64_t actual)
{
- if (expected == actual) {
- cct_check_passed(file, line, expression);
- return true;
- } else {
+ if (expected == actual) {
+ cct_check_passed(file, line, expression);
+ return true;
+ } else {
#if defined(HAVE_LONG_LONG) && !defined(__MINGW32__)
- char *exp_str = format("%lld", (long long)expected);
- char *act_str = format("%lld", (long long)actual);
+ char* exp_str = format("%lld", (long long)expected);
+ char* act_str = format("%lld", (long long)actual);
#else
- char *exp_str = format("%ld", (long)expected);
- char *act_str = format("%ld", (long)actual);
+ char* exp_str = format("%ld", (long)expected);
+ char* act_str = format("%ld", (long)actual);
#endif
- cct_check_failed(file, line, expression, exp_str, act_str);
- free(exp_str);
- free(act_str);
- return false;
- }
+ cct_check_failed(file, line, expression, exp_str, act_str);
+ free(exp_str);
+ free(act_str);
+ return false;
+ }
}
-bool cct_check_data_eq(const char *file, int line, const char *expression,
- const uint8_t *expected, const uint8_t *actual,
- size_t size)
+bool
+cct_check_data_eq(const char* file,
+ int line,
+ const char* expression,
+ const uint8_t* expected,
+ const uint8_t* actual,
+ size_t size)
{
- if (memcmp(actual, expected, size) == 0) {
- cct_check_passed(file, line, expression);
- return true;
- } else {
- char *exp_str = static_cast<char*>(x_malloc(2 * size + 1));
- char *act_str = static_cast<char*>(x_malloc(2 * size + 1));
- format_hex(expected, size, exp_str);
- format_hex(actual, size, act_str);
- cct_check_failed(file, line, expression, exp_str, act_str);
- free(exp_str);
- free(act_str);
- return false;
- }
+ if (memcmp(actual, expected, size) == 0) {
+ cct_check_passed(file, line, expression);
+ return true;
+ } else {
+ char* exp_str = static_cast<char*>(x_malloc(2 * size + 1));
+ char* act_str = static_cast<char*>(x_malloc(2 * size + 1));
+ format_hex(expected, size, exp_str);
+ format_hex(actual, size, act_str);
+ cct_check_failed(file, line, expression, exp_str, act_str);
+ free(exp_str);
+ free(act_str);
+ return false;
+ }
}
bool
-cct_check_str_eq(const char *file, int line, const char *expression,
- const char *expected, const char *actual,
- bool free1, bool free2)
+cct_check_str_eq(const char* file,
+ int line,
+ const char* expression,
+ const char* expected,
+ const char* actual,
+ bool free1,
+ bool free2)
{
- bool result;
+ bool result;
- if (expected && actual && str_eq(actual, expected)) {
- cct_check_passed(file, line, expression);
- result = true;
- } else {
- char *exp_str = expected ? format("\"%s\"", expected) : x_strdup("(null)");
- char *act_str = actual ? format("\"%s\"", actual) : x_strdup("(null)");
- cct_check_failed(file, line, expression, exp_str, act_str);
- free(exp_str);
- free(act_str);
- result = false;
- }
+ if (expected && actual && str_eq(actual, expected)) {
+ cct_check_passed(file, line, expression);
+ result = true;
+ } else {
+ char* exp_str = expected ? format("\"%s\"", expected) : x_strdup("(null)");
+ char* act_str = actual ? format("\"%s\"", actual) : x_strdup("(null)");
+ cct_check_failed(file, line, expression, exp_str, act_str);
+ free(exp_str);
+ free(act_str);
+ result = false;
+ }
- if (free1) {
- free(const_cast<char*>(expected));
- }
- if (free2) {
- free(const_cast<char*>(actual));
- }
- return result;
+ if (free1) {
+ free(const_cast<char*>(expected));
+ }
+ if (free2) {
+ free(const_cast<char*>(actual));
+ }
+ return result;
}
bool
-cct_check_args_eq(const char *file, int line, const char *expression,
- const struct args *expected, const struct args *actual,
- bool free1, bool free2)
+cct_check_args_eq(const char* file,
+ int line,
+ const char* expression,
+ const struct args* expected,
+ const struct args* actual,
+ bool free1,
+ bool free2)
{
- bool result;
+ bool result;
- if (expected && actual && args_equal(actual, expected)) {
- cct_check_passed(file, line, expression);
- result = true;
- } else {
- char *exp_str = expected ? args_to_string(expected) : x_strdup("(null)");
- char *act_str = actual ? args_to_string(actual) : x_strdup("(null)");
- cct_check_failed(file, line, expression, exp_str, act_str);
- free(exp_str);
- free(act_str);
- result = false;
- }
+ if (expected && actual && args_equal(actual, expected)) {
+ cct_check_passed(file, line, expression);
+ result = true;
+ } else {
+ char* exp_str = expected ? args_to_string(expected) : x_strdup("(null)");
+ char* act_str = actual ? args_to_string(actual) : x_strdup("(null)");
+ cct_check_failed(file, line, expression, exp_str, act_str);
+ free(exp_str);
+ free(act_str);
+ result = false;
+ }
- if (free1) {
- args_free(const_cast<struct args*>(expected));
- }
- if (free2) {
- args_free(const_cast<struct args*>(actual));
- }
- return result;
+ if (free1) {
+ args_free(const_cast<struct args*>(expected));
+ }
+ if (free2) {
+ args_free(const_cast<struct args*>(actual));
+ }
+ return result;
}
void
-cct_chdir(const char *path)
+cct_chdir(const char* path)
{
- if (chdir(path) != 0) {
- fprintf(stderr, "chdir: %s: %s", path, strerror(errno));
- abort();
- }
+ if (chdir(path) != 0) {
+ fprintf(stderr, "chdir: %s: %s", path, strerror(errno));
+ abort();
+ }
}
void
-cct_wipe(const char *path)
+cct_wipe(const char* path)
{
- // TODO: rewrite using traverse().
+ // TODO: rewrite using traverse().
#ifndef __MINGW32__
- char *command = format("rm -rf %s", path);
+ char* command = format("rm -rf %s", path);
#else
- char *command = format("rd /s /q %s", path);
+ char* command = format("rd /s /q %s", path);
#endif
- if (system(command) != 0) {
- perror(command);
- }
- free(command);
+ if (system(command) != 0) {
+ perror(command);
+ }
+ free(command);
}
void
-cct_create_fresh_dir(const char *path)
+cct_create_fresh_dir(const char* path)
{
- cct_wipe(path);
- if (mkdir(path, 0777) != 0) {
- fprintf(stderr, "mkdir: %s: %s", path, strerror(errno));
- abort();
- }
+ cct_wipe(path);
+ if (mkdir(path, 0777) != 0) {
+ fprintf(stderr, "mkdir: %s: %s", path, strerror(errno));
+ abort();
+ }
}
diff --git a/unittest/framework.hpp b/unittest/framework.hpp
index 77034410..f97a71d8 100644
--- a/unittest/framework.hpp
+++ b/unittest/framework.hpp
@@ -22,144 +22,167 @@
// ============================================================================
-#define TEST_SUITE(name) \
- unsigned suite_##name(unsigned _start_point); \
- unsigned suite_##name(unsigned _start_point) \
- { \
- unsigned _test_counter = 0; \
- cct_suite_begin(#name); \
- { \
- // Empty due to macro trickery.
-
-#define TEST(name) \
- cct_test_end(); \
- } \
- ++_test_counter; \
- { static int name = 0; (void)name; /* Verify test name. */ } \
- if (_test_counter >= _start_point) { \
- cct_test_begin(#name);
-
-#define TEST_SUITE_END \
- cct_test_end(); \
- } \
- cct_suite_end(); \
- return 0; /* We have reached the end. */ \
- }
+#define TEST_SUITE(name) \
+ unsigned suite_##name(unsigned _start_point); \
+ unsigned suite_##name(unsigned _start_point) \
+ { \
+ unsigned _test_counter = 0; \
+ cct_suite_begin(#name); \
+ { \
+ // Empty due to macro trickery.
+
+#define TEST(name) \
+ cct_test_end(); \
+ } \
+ ++_test_counter; \
+ { \
+ static int name = 0; \
+ (void)name; /* Verify test name. */ \
+ } \
+ if (_test_counter >= _start_point) { \
+ cct_test_begin(#name);
+
+#define TEST_SUITE_END \
+ cct_test_end(); \
+ } \
+ cct_suite_end(); \
+ return 0; /* We have reached the end. */ \
+ }
// ============================================================================
-#define CHECKM(assertion, message) \
- do { \
- if ((assertion)) { \
- cct_check_passed(__FILE__, __LINE__, #assertion); \
- } else { \
- cct_check_failed(__FILE__, __LINE__, #assertion, (message), NULL); \
- cct_test_end(); \
- cct_suite_end(); \
- return _test_counter; \
- } \
- } while (false)
-
-#define CHECK(assertion) \
- CHECKM(assertion, NULL)
-
-#define CHECK_POINTER_EQ_BASE(t, e, a, f1, f2) \
- do { \
- if (!cct_check_##t##_eq(__FILE__, __LINE__, #a, (e), (a), (f1), (f2))) { \
- cct_test_end(); \
- cct_suite_end(); \
- return _test_counter; \
- } \
- } while (false)
+#define CHECKM(assertion, message) \
+ do { \
+ if ((assertion)) { \
+ cct_check_passed(__FILE__, __LINE__, #assertion); \
+ } else { \
+ cct_check_failed(__FILE__, __LINE__, #assertion, (message), NULL); \
+ cct_test_end(); \
+ cct_suite_end(); \
+ return _test_counter; \
+ } \
+ } while (false)
+
+#define CHECK(assertion) CHECKM(assertion, NULL)
+
+#define CHECK_POINTER_EQ_BASE(t, e, a, f1, f2) \
+ do { \
+ if (!cct_check_##t##_eq(__FILE__, __LINE__, #a, (e), (a), (f1), (f2))) { \
+ cct_test_end(); \
+ cct_suite_end(); \
+ return _test_counter; \
+ } \
+ } while (false)
// ============================================================================
-#define CHECK_INT_EQ(expected, actual) \
- do { \
- if (!cct_check_int_eq(__FILE__, __LINE__, #actual, (expected), \
- (actual))) { \
- cct_test_end(); \
- cct_suite_end(); \
- return _test_counter; \
- } \
- } while (false)
+#define CHECK_INT_EQ(expected, actual) \
+ do { \
+ if (!cct_check_int_eq( \
+ __FILE__, __LINE__, #actual, (expected), (actual))) { \
+ cct_test_end(); \
+ cct_suite_end(); \
+ return _test_counter; \
+ } \
+ } while (false)
// ============================================================================
-#define CHECK_DOUBLE_EQ(expected, actual) \
- do { \
- if (!cct_check_double_eq(__FILE__, __LINE__, #actual, (expected), \
- (actual))) { \
- cct_test_end(); \
- cct_suite_end(); \
- return _test_counter; \
- } \
- } while (false)
+#define CHECK_DOUBLE_EQ(expected, actual) \
+ do { \
+ if (!cct_check_double_eq( \
+ __FILE__, __LINE__, #actual, (expected), (actual))) { \
+ cct_test_end(); \
+ cct_suite_end(); \
+ return _test_counter; \
+ } \
+ } while (false)
// ============================================================================
-#define CHECK_DATA_EQ(expected, actual, size) \
- do { \
- if (!cct_check_data_eq(__FILE__, __LINE__, #actual, (expected), \
- (actual), size)) { \
- cct_test_end(); \
- cct_suite_end(); \
- return _test_counter; \
- } \
- } while (false)
+#define CHECK_DATA_EQ(expected, actual, size) \
+ do { \
+ if (!cct_check_data_eq( \
+ __FILE__, __LINE__, #actual, (expected), (actual), size)) { \
+ cct_test_end(); \
+ cct_suite_end(); \
+ return _test_counter; \
+ } \
+ } while (false)
// ============================================================================
-#define CHECK_STR_EQ(expected, actual) \
- CHECK_POINTER_EQ_BASE(str, expected, actual, false, false)
+#define CHECK_STR_EQ(expected, actual) \
+ CHECK_POINTER_EQ_BASE(str, expected, actual, false, false)
-#define CHECK_STR_EQ_FREE1(expected, actual) \
- CHECK_POINTER_EQ_BASE(str, expected, actual, true, false)
+#define CHECK_STR_EQ_FREE1(expected, actual) \
+ CHECK_POINTER_EQ_BASE(str, expected, actual, true, false)
-#define CHECK_STR_EQ_FREE2(expected, actual) \
- CHECK_POINTER_EQ_BASE(str, expected, actual, false, true)
+#define CHECK_STR_EQ_FREE2(expected, actual) \
+ CHECK_POINTER_EQ_BASE(str, expected, actual, false, true)
-#define CHECK_STR_EQ_FREE12(expected, actual) \
- CHECK_POINTER_EQ_BASE(str, expected, actual, true, true)
+#define CHECK_STR_EQ_FREE12(expected, actual) \
+ CHECK_POINTER_EQ_BASE(str, expected, actual, true, true)
// ============================================================================
-#define CHECK_ARGS_EQ(expected, actual) \
- CHECK_POINTER_EQ_BASE(args, expected, actual, false, false)
+#define CHECK_ARGS_EQ(expected, actual) \
+ CHECK_POINTER_EQ_BASE(args, expected, actual, false, false)
-#define CHECK_ARGS_EQ_FREE1(expected, actual) \
- CHECK_POINTER_EQ_BASE(args, expected, actual, true, false)
+#define CHECK_ARGS_EQ_FREE1(expected, actual) \
+ CHECK_POINTER_EQ_BASE(args, expected, actual, true, false)
-#define CHECK_ARGS_EQ_FREE2(expected, actual) \
- CHECK_POINTER_EQ_BASE(args, expected, actual, false, true)
+#define CHECK_ARGS_EQ_FREE2(expected, actual) \
+ CHECK_POINTER_EQ_BASE(args, expected, actual, false, true)
-#define CHECK_ARGS_EQ_FREE12(expected, actual) \
- CHECK_POINTER_EQ_BASE(args, expected, actual, true, true)
+#define CHECK_ARGS_EQ_FREE12(expected, actual) \
+ CHECK_POINTER_EQ_BASE(args, expected, actual, true, true)
// ============================================================================
typedef unsigned (*suite_fn)(unsigned);
-int cct_run(suite_fn *suites, int verbose);
+int cct_run(suite_fn* suites, int verbose);
-void cct_suite_begin(const char *name);
+void cct_suite_begin(const char* name);
void cct_suite_end(void);
-void cct_test_begin(const char *name);
+void cct_test_begin(const char* name);
void cct_test_end(void);
-void cct_check_passed(const char *file, int line, const char *assertion);
-void cct_check_failed(const char *file, int line, const char *assertion,
- const char *expected, const char *actual);
-bool cct_check_double_eq(const char *file, int line, const char *expression,
- double expected, double actual);
-bool cct_check_int_eq(const char *file, int line, const char *expression,
- int64_t expected, int64_t actual);
-bool cct_check_data_eq(const char *file, int line, const char *expression,
- const uint8_t *expected, const uint8_t *actual, size_t size);
-bool cct_check_str_eq(const char *file, int line, const char *expression,
- const char *expected, const char *actual,
- bool free1, bool free2);
-bool cct_check_args_eq(const char *file, int line, const char *expression,
- const struct args *expected, const struct args *actual,
- bool free1, bool free2);
-void cct_chdir(const char *path);
-void cct_wipe(const char *path);
-void cct_create_fresh_dir(const char *path);
+void cct_check_passed(const char* file, int line, const char* assertion);
+void cct_check_failed(const char* file,
+ int line,
+ const char* assertion,
+ const char* expected,
+ const char* actual);
+bool cct_check_double_eq(const char* file,
+ int line,
+ const char* expression,
+ double expected,
+ double actual);
+bool cct_check_int_eq(const char* file,
+ int line,
+ const char* expression,
+ int64_t expected,
+ int64_t actual);
+bool cct_check_data_eq(const char* file,
+ int line,
+ const char* expression,
+ const uint8_t* expected,
+ const uint8_t* actual,
+ size_t size);
+bool cct_check_str_eq(const char* file,
+ int line,
+ const char* expression,
+ const char* expected,
+ const char* actual,
+ bool free1,
+ bool free2);
+bool cct_check_args_eq(const char* file,
+ int line,
+ const char* expression,
+ const struct args* expected,
+ const struct args* actual,
+ bool free1,
+ bool free2);
+void cct_chdir(const char* path);
+void cct_wipe(const char* path);
+void cct_create_fresh_dir(const char* path);
diff --git a/unittest/main.cpp b/unittest/main.cpp
index 9dbc6648..615044d9 100644
--- a/unittest/main.cpp
+++ b/unittest/main.cpp
@@ -18,72 +18,69 @@
#include "framework.hpp"
#ifdef HAVE_GETOPT_LONG
-#include <getopt.h>
+# include <getopt.h>
#else
-#include "../src/third_party/getopt_long.h"
+# include "../src/third_party/getopt_long.h"
#endif
-#define SUITE(name) unsigned suite_ ## name(unsigned);
+#define SUITE(name) unsigned suite_##name(unsigned);
#include "suites.hpp"
#undef SUITE
static const char USAGE_TEXT[] =
- "Usage:\n"
- " test [options]\n"
- "\n"
- "Options:\n"
- " -h, --help print this help text\n"
- " -v, --verbose enable verbose logging of tests\n";
+ "Usage:\n"
+ " test [options]\n"
+ "\n"
+ "Options:\n"
+ " -h, --help print this help text\n"
+ " -v, --verbose enable verbose logging of tests\n";
int
-main(int argc, char **argv)
+main(int argc, char** argv)
{
- suite_fn suites[] = {
-#define SUITE(name) &suite_ ## name,
+ suite_fn suites[] = {
+#define SUITE(name) &suite_##name,
#include "suites.hpp"
#undef SUITE
- NULL
- };
- static const struct option options[] = {
- {"help", no_argument, NULL, 'h'},
- {"verbose", no_argument, NULL, 'v'},
- {NULL, 0, NULL, 0}
- };
- int verbose = 0;
- int c;
- char *testdir, *dir_before;
- int result;
+ NULL};
+ static const struct option options[] = {{"help", no_argument, NULL, 'h'},
+ {"verbose", no_argument, NULL, 'v'},
+ {NULL, 0, NULL, 0}};
+ int verbose = 0;
+ int c;
+ char *testdir, *dir_before;
+ int result;
#ifdef _WIN32
- putenv("CCACHE_DETECT_SHEBANG=1");
+ putenv("CCACHE_DETECT_SHEBANG=1");
#endif
- while ((c = getopt_long(argc, argv, "hv", options, NULL)) != -1) {
- switch (c) {
- case 'h':
- fprintf(stdout, USAGE_TEXT);
- return 0;
+ while ((c = getopt_long(argc, argv, "hv", options, NULL)) != -1) {
+ switch (c) {
+ case 'h':
+ fprintf(stdout, USAGE_TEXT);
+ return 0;
- case 'v':
- verbose = 1;
- break;
+ case 'v':
+ verbose = 1;
+ break;
- default:
- fprintf(stderr, USAGE_TEXT);
- return 1;
- }
- }
+ default:
+ fprintf(stderr, USAGE_TEXT);
+ return 1;
+ }
+ }
- testdir = format("testdir.%d", (int)getpid());
- cct_create_fresh_dir(testdir);
- dir_before = gnu_getcwd();
- cct_chdir(testdir);
- result = cct_run(suites, verbose);
- if (result == 0) {
- cct_chdir(dir_before);
- cct_wipe(testdir);
- }
- free(testdir);
- free(dir_before);
- return result;
+ testdir = format("testdir.%d", (int)getpid());
+ cct_create_fresh_dir(testdir);
+ dir_before = gnu_getcwd();
+ cct_chdir(testdir);
+ result = cct_run(suites, verbose);
+ if (result == 0) {
+ cct_chdir(dir_before);
+ cct_wipe(testdir);
+ }
+ free(testdir);
+ free(dir_before);
+ return result;
}
diff --git a/unittest/test_args.cpp b/unittest/test_args.cpp
index 55129095..d46bfa66 100644
--- a/unittest/test_args.cpp
+++ b/unittest/test_args.cpp
@@ -26,190 +26,190 @@ TEST_SUITE(args)
TEST(args_init_empty)
{
- struct args *args = args_init(0, NULL);
- CHECK(args);
- CHECK_INT_EQ(0, args->argc);
- CHECK(!args->argv[0]);
- args_free(args);
+ struct args* args = args_init(0, NULL);
+ CHECK(args);
+ CHECK_INT_EQ(0, args->argc);
+ CHECK(!args->argv[0]);
+ args_free(args);
}
TEST(args_init_populated)
{
- const char *argv[] = {"first", "second"};
- struct args *args = args_init(2, argv);
- CHECK(args);
- CHECK_INT_EQ(2, args->argc);
- CHECK_STR_EQ("first", args->argv[0]);
- CHECK_STR_EQ("second", args->argv[1]);
- CHECK(!args->argv[2]);
- args_free(args);
+ const char* argv[] = {"first", "second"};
+ struct args* args = args_init(2, argv);
+ CHECK(args);
+ CHECK_INT_EQ(2, args->argc);
+ CHECK_STR_EQ("first", args->argv[0]);
+ CHECK_STR_EQ("second", args->argv[1]);
+ CHECK(!args->argv[2]);
+ args_free(args);
}
TEST(args_init_from_string)
{
- struct args *args = args_init_from_string("first second\tthird\nfourth");
- CHECK(args);
- CHECK_INT_EQ(4, args->argc);
- CHECK_STR_EQ("first", args->argv[0]);
- CHECK_STR_EQ("second", args->argv[1]);
- CHECK_STR_EQ("third", args->argv[2]);
- CHECK_STR_EQ("fourth", args->argv[3]);
- CHECK(!args->argv[4]);
- args_free(args);
+ struct args* args = args_init_from_string("first second\tthird\nfourth");
+ CHECK(args);
+ CHECK_INT_EQ(4, args->argc);
+ CHECK_STR_EQ("first", args->argv[0]);
+ CHECK_STR_EQ("second", args->argv[1]);
+ CHECK_STR_EQ("third", args->argv[2]);
+ CHECK_STR_EQ("fourth", args->argv[3]);
+ CHECK(!args->argv[4]);
+ args_free(args);
}
TEST(args_init_from_gcc_atfile)
{
- struct args *args;
- const char *argtext =
- "first\rsec\\\tond\tthi\\\\rd\nfourth \tfif\\ th \"si'x\\\" th\""
- " 'seve\nth'\\";
-
- create_file("gcc_atfile", argtext);
-
- args = args_init_from_gcc_atfile("gcc_atfile");
- CHECK(args);
- CHECK_INT_EQ(7, args->argc);
- CHECK_STR_EQ("first", args->argv[0]);
- CHECK_STR_EQ("sec\tond", args->argv[1]);
- CHECK_STR_EQ("thi\\rd", args->argv[2]);
- CHECK_STR_EQ("fourth", args->argv[3]);
- CHECK_STR_EQ("fif th", args->argv[4]);
- CHECK_STR_EQ("si'x\" th", args->argv[5]);
+ struct args* args;
+ const char* argtext =
+ "first\rsec\\\tond\tthi\\\\rd\nfourth \tfif\\ th \"si'x\\\" th\""
+ " 'seve\nth'\\";
+
+ create_file("gcc_atfile", argtext);
+
+ args = args_init_from_gcc_atfile("gcc_atfile");
+ CHECK(args);
+ CHECK_INT_EQ(7, args->argc);
+ CHECK_STR_EQ("first", args->argv[0]);
+ CHECK_STR_EQ("sec\tond", args->argv[1]);
+ CHECK_STR_EQ("thi\\rd", args->argv[2]);
+ CHECK_STR_EQ("fourth", args->argv[3]);
+ CHECK_STR_EQ("fif th", args->argv[4]);
+ CHECK_STR_EQ("si'x\" th", args->argv[5]);
#ifndef _WIN32
- CHECK_STR_EQ("seve\nth", args->argv[6]);
+ CHECK_STR_EQ("seve\nth", args->argv[6]);
#else
- CHECK_STR_EQ("seve\r\nth", args->argv[6]);
+ CHECK_STR_EQ("seve\r\nth", args->argv[6]);
#endif
- CHECK(!args->argv[7]);
- args_free(args);
+ CHECK(!args->argv[7]);
+ args_free(args);
}
TEST(args_copy)
{
- struct args *args1 = args_init_from_string("foo");
- struct args *args2 = args_copy(args1);
- CHECK_ARGS_EQ_FREE12(args1, args2);
+ struct args* args1 = args_init_from_string("foo");
+ struct args* args2 = args_copy(args1);
+ CHECK_ARGS_EQ_FREE12(args1, args2);
}
TEST(args_add)
{
- struct args *args = args_init_from_string("first");
- CHECK_INT_EQ(1, args->argc);
- args_add(args, "second");
- CHECK_INT_EQ(2, args->argc);
- CHECK_STR_EQ("second", args->argv[1]);
- CHECK(!args->argv[2]);
- args_free(args);
+ struct args* args = args_init_from_string("first");
+ CHECK_INT_EQ(1, args->argc);
+ args_add(args, "second");
+ CHECK_INT_EQ(2, args->argc);
+ CHECK_STR_EQ("second", args->argv[1]);
+ CHECK(!args->argv[2]);
+ args_free(args);
}
TEST(args_extend)
{
- struct args *args1 = args_init_from_string("first");
- struct args *args2 = args_init_from_string("second third");
- CHECK_INT_EQ(1, args1->argc);
- args_extend(args1, args2);
- CHECK_INT_EQ(3, args1->argc);
- CHECK_STR_EQ("second", args1->argv[1]);
- CHECK_STR_EQ("third", args1->argv[2]);
- CHECK(!args1->argv[3]);
- args_free(args1);
- args_free(args2);
+ struct args* args1 = args_init_from_string("first");
+ struct args* args2 = args_init_from_string("second third");
+ CHECK_INT_EQ(1, args1->argc);
+ args_extend(args1, args2);
+ CHECK_INT_EQ(3, args1->argc);
+ CHECK_STR_EQ("second", args1->argv[1]);
+ CHECK_STR_EQ("third", args1->argv[2]);
+ CHECK(!args1->argv[3]);
+ args_free(args1);
+ args_free(args2);
}
TEST(args_pop)
{
- struct args *args = args_init_from_string("first second third");
- args_pop(args, 2);
- CHECK_INT_EQ(1, args->argc);
- CHECK_STR_EQ("first", args->argv[0]);
- CHECK(!args->argv[1]);
- args_free(args);
+ struct args* args = args_init_from_string("first second third");
+ args_pop(args, 2);
+ CHECK_INT_EQ(1, args->argc);
+ CHECK_STR_EQ("first", args->argv[0]);
+ CHECK(!args->argv[1]);
+ args_free(args);
}
TEST(args_set)
{
- struct args *args = args_init_from_string("first second third");
- args_set(args, 1, "2nd");
- CHECK_INT_EQ(3, args->argc);
- CHECK_STR_EQ("first", args->argv[0]);
- CHECK_STR_EQ("2nd", args->argv[1]);
- CHECK_STR_EQ("third", args->argv[2]);
- CHECK(!args->argv[3]);
- args_free(args);
+ struct args* args = args_init_from_string("first second third");
+ args_set(args, 1, "2nd");
+ CHECK_INT_EQ(3, args->argc);
+ CHECK_STR_EQ("first", args->argv[0]);
+ CHECK_STR_EQ("2nd", args->argv[1]);
+ CHECK_STR_EQ("third", args->argv[2]);
+ CHECK(!args->argv[3]);
+ args_free(args);
}
TEST(args_remove_first)
{
- struct args *args1 = args_init_from_string("first second third");
- struct args *args2 = args_init_from_string("second third");
- args_remove_first(args1);
- CHECK_ARGS_EQ_FREE12(args1, args2);
+ struct args* args1 = args_init_from_string("first second third");
+ struct args* args2 = args_init_from_string("second third");
+ args_remove_first(args1);
+ CHECK_ARGS_EQ_FREE12(args1, args2);
}
TEST(args_add_prefix)
{
- struct args *args1 = args_init_from_string("second third");
- struct args *args2 = args_init_from_string("first second third");
- args_add_prefix(args1, "first");
- CHECK_ARGS_EQ_FREE12(args1, args2);
+ struct args* args1 = args_init_from_string("second third");
+ struct args* args2 = args_init_from_string("first second third");
+ args_add_prefix(args1, "first");
+ CHECK_ARGS_EQ_FREE12(args1, args2);
}
TEST(args_strip)
{
- struct args *args1 = args_init_from_string("first xsecond third xfourth");
- struct args *args2 = args_init_from_string("first third");
- args_strip(args1, "x");
- CHECK_ARGS_EQ_FREE12(args1, args2);
+ struct args* args1 = args_init_from_string("first xsecond third xfourth");
+ struct args* args2 = args_init_from_string("first third");
+ args_strip(args1, "x");
+ CHECK_ARGS_EQ_FREE12(args1, args2);
}
TEST(args_to_string)
{
- struct args *args = args_init_from_string("first second");
- CHECK_STR_EQ_FREE2("first second", args_to_string(args));
- args_free(args);
+ struct args* args = args_init_from_string("first second");
+ CHECK_STR_EQ_FREE2("first second", args_to_string(args));
+ args_free(args);
}
TEST(args_insert)
{
- struct args *args = args_init_from_string("first second third fourth fifth");
-
- struct args *src1 = args_init_from_string("alpha beta gamma");
- struct args *src2 = args_init_from_string("one");
- struct args *src3 = args_init_from_string("");
- struct args *src4 = args_init_from_string("alpha beta gamma");
- struct args *src5 = args_init_from_string("one");
- struct args *src6 = args_init_from_string("");
-
- args_insert(args, 2, src1, true);
- CHECK_STR_EQ_FREE2("first second alpha beta gamma fourth fifth",
- args_to_string(args));
- CHECK_INT_EQ(7, args->argc);
- args_insert(args, 2, src2, true);
- CHECK_STR_EQ_FREE2("first second one beta gamma fourth fifth",
- args_to_string(args));
- CHECK_INT_EQ(7, args->argc);
- args_insert(args, 2, src3, true);
- CHECK_STR_EQ_FREE2("first second beta gamma fourth fifth",
- args_to_string(args));
- CHECK_INT_EQ(6, args->argc);
-
- args_insert(args, 1, src4, false);
- CHECK_STR_EQ_FREE2("first alpha beta gamma second beta gamma fourth fifth",
- args_to_string(args));
- CHECK_INT_EQ(9, args->argc);
- args_insert(args, 1, src5, false);
- CHECK_STR_EQ_FREE2(
- "first one alpha beta gamma second beta gamma fourth fifth",
- args_to_string(args));
- CHECK_INT_EQ(10, args->argc);
- args_insert(args, 1, src6, false);
- CHECK_STR_EQ_FREE2(
- "first one alpha beta gamma second beta gamma fourth fifth",
- args_to_string(args));
- CHECK_INT_EQ(10, args->argc);
-
- args_free(args);
+ struct args* args = args_init_from_string("first second third fourth fifth");
+
+ struct args* src1 = args_init_from_string("alpha beta gamma");
+ struct args* src2 = args_init_from_string("one");
+ struct args* src3 = args_init_from_string("");
+ struct args* src4 = args_init_from_string("alpha beta gamma");
+ struct args* src5 = args_init_from_string("one");
+ struct args* src6 = args_init_from_string("");
+
+ args_insert(args, 2, src1, true);
+ CHECK_STR_EQ_FREE2("first second alpha beta gamma fourth fifth",
+ args_to_string(args));
+ CHECK_INT_EQ(7, args->argc);
+ args_insert(args, 2, src2, true);
+ CHECK_STR_EQ_FREE2("first second one beta gamma fourth fifth",
+ args_to_string(args));
+ CHECK_INT_EQ(7, args->argc);
+ args_insert(args, 2, src3, true);
+ CHECK_STR_EQ_FREE2("first second beta gamma fourth fifth",
+ args_to_string(args));
+ CHECK_INT_EQ(6, args->argc);
+
+ args_insert(args, 1, src4, false);
+ CHECK_STR_EQ_FREE2("first alpha beta gamma second beta gamma fourth fifth",
+ args_to_string(args));
+ CHECK_INT_EQ(9, args->argc);
+ args_insert(args, 1, src5, false);
+ CHECK_STR_EQ_FREE2(
+ "first one alpha beta gamma second beta gamma fourth fifth",
+ args_to_string(args));
+ CHECK_INT_EQ(10, args->argc);
+ args_insert(args, 1, src6, false);
+ CHECK_STR_EQ_FREE2(
+ "first one alpha beta gamma second beta gamma fourth fifth",
+ args_to_string(args));
+ CHECK_INT_EQ(10, args->argc);
+
+ args_free(args);
}
TEST_SUITE_END
diff --git a/unittest/test_argument_processing.cpp b/unittest/test_argument_processing.cpp
index c940ec61..6f46cc7c 100644
--- a/unittest/test_argument_processing.cpp
+++ b/unittest/test_argument_processing.cpp
@@ -23,42 +23,42 @@
#include "framework.hpp"
#include "util.hpp"
-extern struct conf *conf;
+extern struct conf* conf;
-static char *
+static char*
get_root(void)
{
#ifndef _WIN32
- return x_strdup("/");
+ return x_strdup("/");
#else
- char volume[4]; // "C:\"
- GetVolumePathName(get_cwd(), volume, sizeof(volume));
- return x_strdup(volume);
+ char volume[4]; // "C:\"
+ GetVolumePathName(get_cwd(), volume, sizeof(volume));
+ return x_strdup(volume);
#endif
}
-static char *
-get_posix_path(char *path)
+static char*
+get_posix_path(char* path)
{
#ifndef _WIN32
- return x_strdup(path);
+ return x_strdup(path);
#else
- char *posix;
- char *p;
-
- // /-escape volume.
- if (path[0] >= 'A' && path[0] <= 'Z' && path[1] == ':') {
- posix = format("/%s", path);
- } else {
- posix = x_strdup(path);
- }
- // Convert slashes.
- for (p = posix; *p; p++) {
- if (*p == '\\') {
- *p = '/';
- }
- }
- return posix;
+ char* posix;
+ char* p;
+
+ // /-escape volume.
+ if (path[0] >= 'A' && path[0] <= 'Z' && path[1] == ':') {
+ posix = format("/%s", path);
+ } else {
+ posix = x_strdup(path);
+ }
+ // Convert slashes.
+ for (p = posix; *p; p++) {
+ if (*p == '\\') {
+ *p = '/';
+ }
+ }
+ return posix;
#endif
}
@@ -66,452 +66,449 @@ TEST_SUITE(argument_processing)
TEST(dash_E_should_result_in_called_for_preprocessing)
{
- struct args *orig = args_init_from_string("cc -c foo.c -E");
- struct args *preprocessed, *compiler;
+ struct args* orig = args_init_from_string("cc -c foo.c -E");
+ struct args *preprocessed, *compiler;
- create_file("foo.c", "");
- CHECK(!cc_process_args(orig, &preprocessed, &compiler));
- CHECK_INT_EQ(1, stats_get_pending(STATS_PREPROCESSING));
+ create_file("foo.c", "");
+ CHECK(!cc_process_args(orig, &preprocessed, &compiler));
+ CHECK_INT_EQ(1, stats_get_pending(STATS_PREPROCESSING));
- args_free(orig);
+ args_free(orig);
}
TEST(dash_M_should_be_unsupported)
{
- struct args *orig = args_init_from_string("cc -c foo.c -M");
- struct args *preprocessed, *compiler;
+ struct args* orig = args_init_from_string("cc -c foo.c -M");
+ struct args *preprocessed, *compiler;
- create_file("foo.c", "");
- CHECK(!cc_process_args(orig, &preprocessed, &compiler));
- CHECK_INT_EQ(1, stats_get_pending(STATS_UNSUPPORTED_OPTION));
+ create_file("foo.c", "");
+ CHECK(!cc_process_args(orig, &preprocessed, &compiler));
+ CHECK_INT_EQ(1, stats_get_pending(STATS_UNSUPPORTED_OPTION));
- args_free(orig);
+ args_free(orig);
}
TEST(dependency_flags_should_only_be_sent_to_the_preprocessor)
{
-#define CMD \
- "cc -MD -MMD -MP -MF foo.d -MT mt1 -MT mt2 -MQ mq1 -MQ mq2" \
- " -Wp,-MD,wpmd -Wp,-MMD,wpmmd -Wp,-MP -Wp,-MT,wpmt -Wp,-MQ,wpmq -Wp,-MF,wpf"
- struct args *orig = args_init_from_string(CMD " -c foo.c -o foo.o");
- struct args *exp_cpp = args_init_from_string(CMD);
+#define CMD \
+ "cc -MD -MMD -MP -MF foo.d -MT mt1 -MT mt2 -MQ mq1 -MQ mq2" \
+ " -Wp,-MD,wpmd -Wp,-MMD,wpmmd -Wp,-MP -Wp,-MT,wpmt -Wp,-MQ,wpmq -Wp,-MF,wpf"
+ struct args* orig = args_init_from_string(CMD " -c foo.c -o foo.o");
+ struct args* exp_cpp = args_init_from_string(CMD);
#undef CMD
- struct args *exp_cc = args_init_from_string("cc -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
+ struct args* exp_cc = args_init_from_string("cc -c");
+ struct args *act_cpp = NULL, *act_cc = NULL;
+ create_file("foo.c", "");
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
- args_free(orig);
+ args_free(orig);
}
TEST(cpp_only_flags_to_preprocessor_if_run_second_cpp_is_false)
{
-#define CMD \
- "cc -I. -idirafter . -iframework. -imacros . -imultilib ." \
- " -include test.h -include-pch test.pch -iprefix . -iquote ." \
- " -isysroot . -isystem . -iwithprefix . -iwithprefixbefore ." \
- " -DTEST_MACRO -DTEST_MACRO2=1 -F. -trigraphs -fworking-directory" \
- " -fno-working-directory -MD -MMD -MP -MF foo.d -MT mt1 -MT mt2" \
- " -MQ mq1 -MQ mq2 -Wp,-MD,wpmd -Wp,-MMD,wpmmd -Wp,-MP -Wp,-MT,wpmt" \
- " -Wp,-MQ,wpmq -Wp,-MF,wpf"
- struct args *orig = args_init_from_string(CMD " -c foo.c -o foo.o");
- struct args *exp_cpp = args_init_from_string(CMD);
+#define CMD \
+ "cc -I. -idirafter . -iframework. -imacros . -imultilib ." \
+ " -include test.h -include-pch test.pch -iprefix . -iquote ." \
+ " -isysroot . -isystem . -iwithprefix . -iwithprefixbefore ." \
+ " -DTEST_MACRO -DTEST_MACRO2=1 -F. -trigraphs -fworking-directory" \
+ " -fno-working-directory -MD -MMD -MP -MF foo.d -MT mt1 -MT mt2" \
+ " -MQ mq1 -MQ mq2 -Wp,-MD,wpmd -Wp,-MMD,wpmmd -Wp,-MP -Wp,-MT,wpmt" \
+ " -Wp,-MQ,wpmq -Wp,-MF,wpf"
+ struct args* orig = args_init_from_string(CMD " -c foo.c -o foo.o");
+ struct args* exp_cpp = args_init_from_string(CMD);
#undef CMD
- struct args *exp_cc = args_init_from_string("cc -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
+ struct args* exp_cc = args_init_from_string("cc -c");
+ struct args *act_cpp = NULL, *act_cc = NULL;
+ create_file("foo.c", "");
- conf->run_second_cpp = false;
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+ conf->run_second_cpp = false;
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
- args_free(orig);
+ args_free(orig);
}
TEST(cpp_only_flags_to_preprocessor_and_compiler_if_run_second_cpp_is_true)
{
-#define CMD \
- "cc -I. -idirafter . -iframework. -imacros . -imultilib ." \
- " -include test.h -include-pch test.pch -iprefix . -iquote ." \
- " -isysroot . -isystem . -iwithprefix . -iwithprefixbefore ." \
- " -DTEST_MACRO -DTEST_MACRO2=1 -F. -trigraphs -fworking-directory" \
- " -fno-working-directory"
-#define DEP_OPTS \
- " -MD -MMD -MP -MF foo.d -MT mt1 -MT mt2 " \
- " -MQ mq1 -MQ mq2 -Wp,-MD,wpmd -Wp,-MMD,wpmmd"
- struct args *orig = args_init_from_string(CMD DEP_OPTS " -c foo.c -o foo.o");
- struct args *exp_cpp = args_init_from_string(CMD DEP_OPTS);
- struct args *exp_cc = args_init_from_string(CMD " -c");
+#define CMD \
+ "cc -I. -idirafter . -iframework. -imacros . -imultilib ." \
+ " -include test.h -include-pch test.pch -iprefix . -iquote ." \
+ " -isysroot . -isystem . -iwithprefix . -iwithprefixbefore ." \
+ " -DTEST_MACRO -DTEST_MACRO2=1 -F. -trigraphs -fworking-directory" \
+ " -fno-working-directory"
+#define DEP_OPTS \
+ " -MD -MMD -MP -MF foo.d -MT mt1 -MT mt2 " \
+ " -MQ mq1 -MQ mq2 -Wp,-MD,wpmd -Wp,-MMD,wpmmd"
+ struct args* orig = args_init_from_string(CMD DEP_OPTS " -c foo.c -o foo.o");
+ struct args* exp_cpp = args_init_from_string(CMD DEP_OPTS);
+ struct args* exp_cc = args_init_from_string(CMD " -c");
#undef CMD
- struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
+ struct args *act_cpp = NULL, *act_cc = NULL;
+ create_file("foo.c", "");
- conf->run_second_cpp = true;
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+ conf->run_second_cpp = true;
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
- args_free(orig);
+ args_free(orig);
}
TEST(dependency_flags_that_take_an_argument_should_not_require_space_delimiter)
{
- struct args *orig = args_init_from_string(
- "cc -c -MMD -MFfoo.d -MT mt -MTmt -MQmq foo.c -o foo.o");
- struct args *exp_cpp = args_init_from_string(
- "cc -MMD -MFfoo.d -MT mt -MTmt -MQmq");
- struct args *exp_cc = args_init_from_string("cc -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
+ struct args* orig = args_init_from_string(
+ "cc -c -MMD -MFfoo.d -MT mt -MTmt -MQmq foo.c -o foo.o");
+ struct args* exp_cpp =
+ args_init_from_string("cc -MMD -MFfoo.d -MT mt -MTmt -MQmq");
+ struct args* exp_cc = args_init_from_string("cc -c");
+ struct args *act_cpp = NULL, *act_cc = NULL;
+ create_file("foo.c", "");
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
}
TEST(sysroot_should_be_rewritten_if_basedir_is_used)
{
- extern char *current_working_dir;
- char *arg_string;
- struct args *orig;
- struct args *act_cpp = NULL, *act_cc = NULL;
-
- create_file("foo.c", "");
- free(conf->base_dir);
- conf->base_dir = get_root();
- current_working_dir = get_cwd();
- arg_string = format("cc --sysroot=%s/foo/bar -c foo.c", current_working_dir);
- orig = args_init_from_string(arg_string);
- free(arg_string);
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_STR_EQ(act_cpp->argv[1], "--sysroot=./foo/bar");
-
- args_free(orig);
- args_free(act_cpp);
- args_free(act_cc);
+ extern char* current_working_dir;
+ char* arg_string;
+ struct args* orig;
+ struct args *act_cpp = NULL, *act_cc = NULL;
+
+ create_file("foo.c", "");
+ free(conf->base_dir);
+ conf->base_dir = get_root();
+ current_working_dir = get_cwd();
+ arg_string = format("cc --sysroot=%s/foo/bar -c foo.c", current_working_dir);
+ orig = args_init_from_string(arg_string);
+ free(arg_string);
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_STR_EQ(act_cpp->argv[1], "--sysroot=./foo/bar");
+
+ args_free(orig);
+ args_free(act_cpp);
+ args_free(act_cc);
}
TEST(sysroot_with_separate_argument_should_be_rewritten_if_basedir_is_used)
{
- extern char *current_working_dir;
- char *arg_string;
- struct args *orig;
- struct args *act_cpp = NULL, *act_cc = NULL;
-
- create_file("foo.c", "");
- free(conf->base_dir);
- conf->base_dir = get_root();
- current_working_dir = get_cwd();
- arg_string = format("cc --sysroot %s/foo -c foo.c", current_working_dir);
- orig = args_init_from_string(arg_string);
- free(arg_string);
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_STR_EQ(act_cpp->argv[1], "--sysroot");
- CHECK_STR_EQ(act_cpp->argv[2], "./foo");
-
- args_free(orig);
- args_free(act_cpp);
- args_free(act_cc);
+ extern char* current_working_dir;
+ char* arg_string;
+ struct args* orig;
+ struct args *act_cpp = NULL, *act_cc = NULL;
+
+ create_file("foo.c", "");
+ free(conf->base_dir);
+ conf->base_dir = get_root();
+ current_working_dir = get_cwd();
+ arg_string = format("cc --sysroot %s/foo -c foo.c", current_working_dir);
+ orig = args_init_from_string(arg_string);
+ free(arg_string);
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_STR_EQ(act_cpp->argv[1], "--sysroot");
+ CHECK_STR_EQ(act_cpp->argv[2], "./foo");
+
+ args_free(orig);
+ args_free(act_cpp);
+ args_free(act_cc);
}
TEST(MF_flag_with_immediate_argument_should_work_as_last_argument)
{
- struct args *orig = args_init_from_string(
- "cc -c foo.c -o foo.o -MMD -MT bar -MFfoo.d");
- struct args *exp_cpp = args_init_from_string(
- "cc -MMD -MT bar -MFfoo.d");
- struct args *exp_cc = args_init_from_string("cc -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
+ struct args* orig =
+ args_init_from_string("cc -c foo.c -o foo.o -MMD -MT bar -MFfoo.d");
+ struct args* exp_cpp = args_init_from_string("cc -MMD -MT bar -MFfoo.d");
+ struct args* exp_cc = args_init_from_string("cc -c");
+ struct args *act_cpp = NULL, *act_cc = NULL;
+ create_file("foo.c", "");
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
}
TEST(MT_flag_with_immediate_argument_should_work_as_last_argument)
{
- struct args *orig = args_init_from_string(
- "cc -c foo.c -o foo.o -MMD -MFfoo.d -MT foo -MTbar");
- struct args *exp_cpp = args_init_from_string(
- "cc -MMD -MFfoo.d -MT foo -MTbar");
- struct args *exp_cc = args_init_from_string("cc -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
+ struct args* orig =
+ args_init_from_string("cc -c foo.c -o foo.o -MMD -MFfoo.d -MT foo -MTbar");
+ struct args* exp_cpp =
+ args_init_from_string("cc -MMD -MFfoo.d -MT foo -MTbar");
+ struct args* exp_cc = args_init_from_string("cc -c");
+ struct args *act_cpp = NULL, *act_cc = NULL;
+ create_file("foo.c", "");
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
}
TEST(MQ_flag_with_immediate_argument_should_work_as_last_argument)
{
- struct args *orig = args_init_from_string(
- "cc -c foo.c -o foo.o -MMD -MFfoo.d -MQ foo -MQbar");
- struct args *exp_cpp = args_init_from_string(
- "cc -MMD -MFfoo.d -MQ foo -MQbar");
- struct args *exp_cc = args_init_from_string("cc -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
+ struct args* orig =
+ args_init_from_string("cc -c foo.c -o foo.o -MMD -MFfoo.d -MQ foo -MQbar");
+ struct args* exp_cpp =
+ args_init_from_string("cc -MMD -MFfoo.d -MQ foo -MQbar");
+ struct args* exp_cc = args_init_from_string("cc -c");
+ struct args *act_cpp = NULL, *act_cc = NULL;
+ create_file("foo.c", "");
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
}
TEST(MQ_flag_without_immediate_argument_should_not_add_MQobj)
{
- struct args *orig = args_init_from_string(
- "gcc -c -MD -MP -MFfoo.d -MQ foo.d foo.c");
- struct args *exp_cpp = args_init_from_string(
- "gcc -MD -MP -MFfoo.d -MQ foo.d");
- struct args *exp_cc = args_init_from_string("gcc -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
+ struct args* orig =
+ args_init_from_string("gcc -c -MD -MP -MFfoo.d -MQ foo.d foo.c");
+ struct args* exp_cpp =
+ args_init_from_string("gcc -MD -MP -MFfoo.d -MQ foo.d");
+ struct args* exp_cc = args_init_from_string("gcc -c");
+ struct args *act_cpp = NULL, *act_cc = NULL;
+ create_file("foo.c", "");
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
}
TEST(MT_flag_without_immediate_argument_should_not_add_MTobj)
{
- struct args *orig = args_init_from_string(
- "gcc -c -MD -MP -MFfoo.d -MT foo.d foo.c");
- struct args *exp_cpp = args_init_from_string(
- "gcc -MD -MP -MFfoo.d -MT foo.d");
- struct args *exp_cc = args_init_from_string("gcc -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
+ struct args* orig =
+ args_init_from_string("gcc -c -MD -MP -MFfoo.d -MT foo.d foo.c");
+ struct args* exp_cpp =
+ args_init_from_string("gcc -MD -MP -MFfoo.d -MT foo.d");
+ struct args* exp_cc = args_init_from_string("gcc -c");
+ struct args *act_cpp = NULL, *act_cc = NULL;
+ create_file("foo.c", "");
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
}
TEST(MQ_flag_with_immediate_argument_should_not_add_MQobj)
{
- struct args *orig = args_init_from_string(
- "gcc -c -MD -MP -MFfoo.d -MQfoo.d foo.c");
- struct args *exp_cpp = args_init_from_string(
- "gcc -MD -MP -MFfoo.d -MQfoo.d");
- struct args *exp_cc = args_init_from_string("gcc -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
+ struct args* orig =
+ args_init_from_string("gcc -c -MD -MP -MFfoo.d -MQfoo.d foo.c");
+ struct args* exp_cpp = args_init_from_string("gcc -MD -MP -MFfoo.d -MQfoo.d");
+ struct args* exp_cc = args_init_from_string("gcc -c");
+ struct args *act_cpp = NULL, *act_cc = NULL;
+ create_file("foo.c", "");
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
}
TEST(MT_flag_with_immediate_argument_should_not_add_MQobj)
{
- struct args *orig = args_init_from_string(
- "gcc -c -MD -MP -MFfoo.d -MTfoo.d foo.c");
- struct args *exp_cpp = args_init_from_string(
- "gcc -MD -MP -MFfoo.d -MTfoo.d");
- struct args *exp_cc = args_init_from_string("gcc -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
+ struct args* orig =
+ args_init_from_string("gcc -c -MD -MP -MFfoo.d -MTfoo.d foo.c");
+ struct args* exp_cpp = args_init_from_string("gcc -MD -MP -MFfoo.d -MTfoo.d");
+ struct args* exp_cc = args_init_from_string("gcc -c");
+ struct args *act_cpp = NULL, *act_cc = NULL;
+ create_file("foo.c", "");
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
}
TEST(fprofile_flag_with_existing_dir_should_be_rewritten_to_real_path)
{
- struct args *orig = args_init_from_string(
- "gcc -c -fprofile-generate=some/dir foo.c");
- struct args *exp_cpp = args_init_from_string("gcc");
- struct args *exp_cc = args_init_from_string("gcc");
- struct args *act_cpp = NULL, *act_cc = NULL;
- char *s, *path;
-
- create_file("foo.c", "");
- mkdir("some", 0777);
- mkdir("some/dir", 0777);
- path = x_realpath("some/dir");
- s = format("-fprofile-generate=%s", path);
- free(path);
- args_add(exp_cpp, s);
- args_add(exp_cc, s);
- args_add(exp_cc, "-c");
- free(s);
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
+ struct args* orig =
+ args_init_from_string("gcc -c -fprofile-generate=some/dir foo.c");
+ struct args* exp_cpp = args_init_from_string("gcc");
+ struct args* exp_cc = args_init_from_string("gcc");
+ struct args *act_cpp = NULL, *act_cc = NULL;
+ char *s, *path;
+
+ create_file("foo.c", "");
+ mkdir("some", 0777);
+ mkdir("some/dir", 0777);
+ path = x_realpath("some/dir");
+ s = format("-fprofile-generate=%s", path);
+ free(path);
+ args_add(exp_cpp, s);
+ args_add(exp_cc, s);
+ args_add(exp_cc, "-c");
+ free(s);
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
}
TEST(fprofile_flag_with_nonexistent_dir_should_not_be_rewritten)
{
- struct args *orig = args_init_from_string(
- "gcc -c -fprofile-generate=some/dir foo.c");
- struct args *exp_cpp = args_init_from_string(
- "gcc -fprofile-generate=some/dir");
- struct args *exp_cc = args_init_from_string(
- "gcc -fprofile-generate=some/dir -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
+ struct args* orig =
+ args_init_from_string("gcc -c -fprofile-generate=some/dir foo.c");
+ struct args* exp_cpp =
+ args_init_from_string("gcc -fprofile-generate=some/dir");
+ struct args* exp_cc =
+ args_init_from_string("gcc -fprofile-generate=some/dir -c");
+ struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
+ create_file("foo.c", "");
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
- args_free(orig);
+ args_free(orig);
}
TEST(isystem_flag_with_separate_arg_should_be_rewritten_if_basedir_is_used)
{
- extern char *current_working_dir;
- char *arg_string;
- struct args *orig;
- struct args *act_cpp = NULL, *act_cc = NULL;
-
- create_file("foo.c", "");
- free(conf->base_dir);
- conf->base_dir = get_root();
- current_working_dir = get_cwd();
- arg_string = format("cc -isystem %s/foo -c foo.c", current_working_dir);
- orig = args_init_from_string(arg_string);
- free(arg_string);
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_STR_EQ("./foo", act_cpp->argv[2]);
-
- args_free(orig);
- args_free(act_cpp);
- args_free(act_cc);
+ extern char* current_working_dir;
+ char* arg_string;
+ struct args* orig;
+ struct args *act_cpp = NULL, *act_cc = NULL;
+
+ create_file("foo.c", "");
+ free(conf->base_dir);
+ conf->base_dir = get_root();
+ current_working_dir = get_cwd();
+ arg_string = format("cc -isystem %s/foo -c foo.c", current_working_dir);
+ orig = args_init_from_string(arg_string);
+ free(arg_string);
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_STR_EQ("./foo", act_cpp->argv[2]);
+
+ args_free(orig);
+ args_free(act_cpp);
+ args_free(act_cc);
}
TEST(isystem_flag_with_concat_arg_should_be_rewritten_if_basedir_is_used)
{
- extern char *current_working_dir;
- char *cwd;
- char *arg_string;
- struct args *orig;
- struct args *act_cpp = NULL, *act_cc = NULL;
-
- create_file("foo.c", "");
- free(conf->base_dir);
- conf->base_dir = x_strdup("/"); // posix
- current_working_dir = get_cwd();
- // Windows path doesn't work concatenated.
- cwd = get_posix_path(current_working_dir);
- arg_string = format("cc -isystem%s/foo -c foo.c", cwd);
- orig = args_init_from_string(arg_string);
- free(arg_string);
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_STR_EQ("-isystem./foo", act_cpp->argv[1]);
-
- free(cwd);
- args_free(orig);
- args_free(act_cpp);
- args_free(act_cc);
+ extern char* current_working_dir;
+ char* cwd;
+ char* arg_string;
+ struct args* orig;
+ struct args *act_cpp = NULL, *act_cc = NULL;
+
+ create_file("foo.c", "");
+ free(conf->base_dir);
+ conf->base_dir = x_strdup("/"); // posix
+ current_working_dir = get_cwd();
+ // Windows path doesn't work concatenated.
+ cwd = get_posix_path(current_working_dir);
+ arg_string = format("cc -isystem%s/foo -c foo.c", cwd);
+ orig = args_init_from_string(arg_string);
+ free(arg_string);
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_STR_EQ("-isystem./foo", act_cpp->argv[1]);
+
+ free(cwd);
+ args_free(orig);
+ args_free(act_cpp);
+ args_free(act_cc);
}
TEST(I_flag_with_concat_arg_should_be_rewritten_if_basedir_is_used)
{
- extern char *current_working_dir;
- char *cwd;
- char *arg_string;
- struct args *orig;
- struct args *act_cpp = NULL, *act_cc = NULL;
-
- create_file("foo.c", "");
- free(conf->base_dir);
- conf->base_dir = x_strdup("/"); // posix
- current_working_dir = get_cwd();
- // Windows path doesn't work concatenated.
- cwd = get_posix_path(current_working_dir);
- arg_string = format("cc -I%s/foo -c foo.c", cwd);
- orig = args_init_from_string(arg_string);
- free(arg_string);
-
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_STR_EQ("-I./foo", act_cpp->argv[1]);
-
- free(cwd);
- args_free(orig);
- args_free(act_cpp);
- args_free(act_cc);
+ extern char* current_working_dir;
+ char* cwd;
+ char* arg_string;
+ struct args* orig;
+ struct args *act_cpp = NULL, *act_cc = NULL;
+
+ create_file("foo.c", "");
+ free(conf->base_dir);
+ conf->base_dir = x_strdup("/"); // posix
+ current_working_dir = get_cwd();
+ // Windows path doesn't work concatenated.
+ cwd = get_posix_path(current_working_dir);
+ arg_string = format("cc -I%s/foo -c foo.c", cwd);
+ orig = args_init_from_string(arg_string);
+ free(arg_string);
+
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_STR_EQ("-I./foo", act_cpp->argv[1]);
+
+ free(cwd);
+ args_free(orig);
+ args_free(act_cpp);
+ args_free(act_cc);
}
TEST(debug_flag_order_with_known_option_first)
{
- struct args *orig = args_init_from_string("cc -g1 -gsplit-dwarf foo.c -c");
- struct args *exp_cpp = args_init_from_string("cc -g1 -gsplit-dwarf");
- struct args *exp_cc = args_init_from_string("cc -g1 -gsplit-dwarf -c");
- struct args *act_cpp = NULL;
- struct args *act_cc = NULL;
-
- create_file("foo.c", "");
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
+ struct args* orig = args_init_from_string("cc -g1 -gsplit-dwarf foo.c -c");
+ struct args* exp_cpp = args_init_from_string("cc -g1 -gsplit-dwarf");
+ struct args* exp_cc = args_init_from_string("cc -g1 -gsplit-dwarf -c");
+ struct args* act_cpp = NULL;
+ struct args* act_cc = NULL;
+
+ create_file("foo.c", "");
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
}
TEST(debug_flag_order_with_known_option_last)
{
- struct args *orig = args_init_from_string("cc -gsplit-dwarf -g1 foo.c -c");
- struct args *exp_cpp = args_init_from_string("cc -gsplit-dwarf -g1");
- struct args *exp_cc = args_init_from_string("cc -gsplit-dwarf -g1 -c");
- struct args *act_cpp = NULL;
- struct args *act_cc = NULL;
-
- create_file("foo.c", "");
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
+ struct args* orig = args_init_from_string("cc -gsplit-dwarf -g1 foo.c -c");
+ struct args* exp_cpp = args_init_from_string("cc -gsplit-dwarf -g1");
+ struct args* exp_cc = args_init_from_string("cc -gsplit-dwarf -g1 -c");
+ struct args* act_cpp = NULL;
+ struct args* act_cc = NULL;
+
+ create_file("foo.c", "");
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
}
TEST(options_not_to_be_passed_to_the_preprocesor)
{
- struct args *orig = args_init_from_string(
- "cc -Wa,foo foo.c -g -Xlinker fie -Xlinker,fum -c -Werror");
- struct args *exp_cpp = args_init_from_string("cc -g");
- struct args *exp_cc = args_init_from_string(
- "cc -g -Wa,foo -Xlinker fie -Xlinker,fum -Werror -c");
- struct args *act_cpp = NULL;
- struct args *act_cc = NULL;
-
- create_file("foo.c", "");
- CHECK(cc_process_args(orig, &act_cpp, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
+ struct args* orig = args_init_from_string(
+ "cc -Wa,foo foo.c -g -Xlinker fie -Xlinker,fum -c -Werror");
+ struct args* exp_cpp = args_init_from_string("cc -g");
+ struct args* exp_cc =
+ args_init_from_string("cc -g -Wa,foo -Xlinker fie -Xlinker,fum -Werror -c");
+ struct args* act_cpp = NULL;
+ struct args* act_cc = NULL;
+
+ create_file("foo.c", "");
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
}
TEST_SUITE_END
diff --git a/unittest/test_compopt.cpp b/unittest/test_compopt.cpp
index 1b0c5bf5..99c3b2bd 100644
--- a/unittest/test_compopt.cpp
+++ b/unittest/test_compopt.cpp
@@ -26,115 +26,115 @@ TEST_SUITE(compopt)
TEST(option_table_should_be_sorted)
{
- bool compopt_verify_sortedness(void);
- CHECK(compopt_verify_sortedness());
+ bool compopt_verify_sortedness(void);
+ CHECK(compopt_verify_sortedness());
}
TEST(dash_I_affects_cpp)
{
- CHECK(compopt_affects_cpp("-I"));
- CHECK(!compopt_affects_cpp("-Ifoo"));
+ CHECK(compopt_affects_cpp("-I"));
+ CHECK(!compopt_affects_cpp("-Ifoo"));
}
TEST(compopt_short)
{
- CHECK(compopt_short(compopt_affects_cpp, "-Ifoo"));
- CHECK(!compopt_short(compopt_affects_cpp, "-include"));
+ CHECK(compopt_short(compopt_affects_cpp, "-Ifoo"));
+ CHECK(!compopt_short(compopt_affects_cpp, "-include"));
}
TEST(dash_V_doesnt_affect_cpp)
{
- CHECK(!compopt_affects_cpp("-V"));
+ CHECK(!compopt_affects_cpp("-V"));
}
TEST(dash_doesntexist_doesnt_affect_cpp)
{
- CHECK(!compopt_affects_cpp("-doesntexist"));
+ CHECK(!compopt_affects_cpp("-doesntexist"));
}
TEST(dash_MM_too_hard)
{
- CHECK(compopt_too_hard("-MM"));
+ CHECK(compopt_too_hard("-MM"));
}
TEST(dash_save_temps_too_hard)
{
- CHECK(compopt_too_hard("-save-temps"));
+ CHECK(compopt_too_hard("-save-temps"));
}
TEST(dash_save_temps_cwd_too_hard)
{
- CHECK(compopt_too_hard("-save-temps=cwd"));
+ CHECK(compopt_too_hard("-save-temps=cwd"));
}
TEST(dash_save_temps_obj_too_hard)
{
- CHECK(compopt_too_hard("-save-temps=obj"));
+ CHECK(compopt_too_hard("-save-temps=obj"));
}
TEST(dash_MD_not_too_hard)
{
- CHECK(!compopt_too_hard("-MD"));
+ CHECK(!compopt_too_hard("-MD"));
}
TEST(dash_fprofile_arcs_not_too_hard)
{
- CHECK(!compopt_too_hard("-fprofile-arcs"));
+ CHECK(!compopt_too_hard("-fprofile-arcs"));
}
TEST(dash_ftest_coverage_not_too_hard)
{
- CHECK(!compopt_too_hard("-ftest-coverage"));
+ CHECK(!compopt_too_hard("-ftest-coverage"));
}
TEST(dash_fstack_usage_not_too_hard)
{
- CHECK(!compopt_too_hard("-fstack-usage"));
+ CHECK(!compopt_too_hard("-fstack-usage"));
}
TEST(dash_doesntexist_not_too_hard)
{
- CHECK(!compopt_too_hard("-doesntexist"));
+ CHECK(!compopt_too_hard("-doesntexist"));
}
TEST(dash_Xpreprocessor_too_hard_for_direct_mode)
{
- CHECK(compopt_too_hard_for_direct_mode("-Xpreprocessor"));
+ CHECK(compopt_too_hard_for_direct_mode("-Xpreprocessor"));
}
TEST(dash_nostdinc_not_too_hard_for_direct_mode)
{
- CHECK(!compopt_too_hard_for_direct_mode("-nostdinc"));
+ CHECK(!compopt_too_hard_for_direct_mode("-nostdinc"));
}
TEST(dash_I_takes_path)
{
- CHECK(compopt_takes_path("-I"));
+ CHECK(compopt_takes_path("-I"));
}
TEST(dash_Xlinker_takes_arg)
{
- CHECK(compopt_takes_arg("-Xlinker"));
+ CHECK(compopt_takes_arg("-Xlinker"));
}
TEST(dash_xxx_doesnt_take_arg)
{
- CHECK(!compopt_takes_arg("-xxx"));
+ CHECK(!compopt_takes_arg("-xxx"));
}
TEST(dash_iframework_prefix_affects_cpp)
{
- CHECK(compopt_prefix_affects_cpp("-iframework"));
+ CHECK(compopt_prefix_affects_cpp("-iframework"));
}
TEST(dash_analyze_too_hard)
{
- CHECK(compopt_too_hard("-analyze"));
+ CHECK(compopt_too_hard("-analyze"));
}
TEST(dash_dash_analyze_too_hard)
{
- CHECK(compopt_too_hard("--analyze"));
+ CHECK(compopt_too_hard("--analyze"));
}
TEST_SUITE_END
diff --git a/unittest/test_compr_none.cpp b/unittest/test_compr_none.cpp
index 76411e7b..f19704c0 100644
--- a/unittest/test_compr_none.cpp
+++ b/unittest/test_compr_none.cpp
@@ -24,45 +24,45 @@ TEST_SUITE(compr_type_none)
TEST(small_roundtrip)
{
- const uint64_t expected_foobar_checksum = 0xa2aa05ed9085aaf9ULL;
+ const uint64_t expected_foobar_checksum = 0xa2aa05ed9085aaf9ULL;
- XXH64_state_t *checksum = XXH64_createState();
- XXH64_reset(checksum, 0);
+ XXH64_state_t* checksum = XXH64_createState();
+ XXH64_reset(checksum, 0);
- FILE *f = fopen("data.uncompressed", "w");
- struct compressor *compr_none = compressor_from_type(COMPR_TYPE_NONE);
- struct compr_state *c_state = compr_none->init(f, -1, checksum);
- CHECK(c_state);
+ FILE* f = fopen("data.uncompressed", "w");
+ struct compressor* compr_none = compressor_from_type(COMPR_TYPE_NONE);
+ struct compr_state* c_state = compr_none->init(f, -1, checksum);
+ CHECK(c_state);
- CHECK(compr_none->write(c_state, "foobar", 6));
+ CHECK(compr_none->write(c_state, "foobar", 6));
- CHECK(compr_none->free(c_state));
- fclose(f);
+ CHECK(compr_none->free(c_state));
+ fclose(f);
- CHECK_INT_EQ(XXH64_digest(checksum), expected_foobar_checksum);
+ CHECK_INT_EQ(XXH64_digest(checksum), expected_foobar_checksum);
- XXH64_reset(checksum, 0);
- f = fopen("data.uncompressed", "r");
- struct decompressor *decompr_none = decompressor_from_type(COMPR_TYPE_NONE);
- struct decompr_state *d_state = decompr_none->init(f, checksum);
- CHECK(d_state);
+ XXH64_reset(checksum, 0);
+ f = fopen("data.uncompressed", "r");
+ struct decompressor* decompr_none = decompressor_from_type(COMPR_TYPE_NONE);
+ struct decompr_state* d_state = decompr_none->init(f, checksum);
+ CHECK(d_state);
- char buffer[4];
- CHECK(decompr_none->read(d_state, buffer, 4));
- CHECK(memcmp(buffer, "foob", 4) == 0);
- CHECK(decompr_none->read(d_state, buffer, 2));
- CHECK(memcmp(buffer, "ar", 2) == 0);
+ char buffer[4];
+ CHECK(decompr_none->read(d_state, buffer, 4));
+ CHECK(memcmp(buffer, "foob", 4) == 0);
+ CHECK(decompr_none->read(d_state, buffer, 2));
+ CHECK(memcmp(buffer, "ar", 2) == 0);
- // Nothing left to read.
- CHECK(!decompr_none->read(d_state, buffer, 1));
+ // Nothing left to read.
+ CHECK(!decompr_none->read(d_state, buffer, 1));
- // Error state is remembered.
- CHECK(!decompr_none->free(d_state));
- fclose(f);
+ // Error state is remembered.
+ CHECK(!decompr_none->free(d_state));
+ fclose(f);
- CHECK_INT_EQ(XXH64_digest(checksum), expected_foobar_checksum);
+ CHECK_INT_EQ(XXH64_digest(checksum), expected_foobar_checksum);
- XXH64_freeState(checksum);
+ XXH64_freeState(checksum);
}
TEST_SUITE_END
diff --git a/unittest/test_compr_zstd.cpp b/unittest/test_compr_zstd.cpp
index 89d75b7f..393bb876 100644
--- a/unittest/test_compr_zstd.cpp
+++ b/unittest/test_compr_zstd.cpp
@@ -24,110 +24,110 @@ TEST_SUITE(compr_type_zstd)
TEST(small_roundtrip)
{
- const uint64_t expected_foobar_checksum = 0xa2aa05ed9085aaf9ULL;
+ const uint64_t expected_foobar_checksum = 0xa2aa05ed9085aaf9ULL;
- XXH64_state_t *checksum = XXH64_createState();
- XXH64_reset(checksum, 0);
+ XXH64_state_t* checksum = XXH64_createState();
+ XXH64_reset(checksum, 0);
- FILE *f = fopen("data.zstd", "w");
- struct compressor *compr_zstd = compressor_from_type(COMPR_TYPE_ZSTD);
- struct compr_state *c_state = compr_zstd->init(f, -1, checksum);
- CHECK(c_state);
+ FILE* f = fopen("data.zstd", "w");
+ struct compressor* compr_zstd = compressor_from_type(COMPR_TYPE_ZSTD);
+ struct compr_state* c_state = compr_zstd->init(f, -1, checksum);
+ CHECK(c_state);
- CHECK(compr_zstd->write(c_state, "foobar", 6));
+ CHECK(compr_zstd->write(c_state, "foobar", 6));
- CHECK(compr_zstd->free(c_state));
- fclose(f);
+ CHECK(compr_zstd->free(c_state));
+ fclose(f);
- CHECK_INT_EQ(XXH64_digest(checksum), expected_foobar_checksum);
+ CHECK_INT_EQ(XXH64_digest(checksum), expected_foobar_checksum);
- XXH64_reset(checksum, 0);
- f = fopen("data.zstd", "r");
- struct decompressor *decompr_zstd = decompressor_from_type(COMPR_TYPE_ZSTD);
- struct decompr_state *d_state = decompr_zstd->init(f, checksum);
- CHECK(d_state);
+ XXH64_reset(checksum, 0);
+ f = fopen("data.zstd", "r");
+ struct decompressor* decompr_zstd = decompressor_from_type(COMPR_TYPE_ZSTD);
+ struct decompr_state* d_state = decompr_zstd->init(f, checksum);
+ CHECK(d_state);
- char buffer[4];
- CHECK(decompr_zstd->read(d_state, buffer, 4));
- CHECK(memcmp(buffer, "foob", 4) == 0);
- CHECK(decompr_zstd->read(d_state, buffer, 2));
- CHECK(memcmp(buffer, "ar", 2) == 0);
+ char buffer[4];
+ CHECK(decompr_zstd->read(d_state, buffer, 4));
+ CHECK(memcmp(buffer, "foob", 4) == 0);
+ CHECK(decompr_zstd->read(d_state, buffer, 2));
+ CHECK(memcmp(buffer, "ar", 2) == 0);
- // Nothing left to read.
- CHECK(!decompr_zstd->read(d_state, buffer, 1));
+ // Nothing left to read.
+ CHECK(!decompr_zstd->read(d_state, buffer, 1));
- // Error state is remembered.
- CHECK(!decompr_zstd->free(d_state));
- fclose(f);
+ // Error state is remembered.
+ CHECK(!decompr_zstd->free(d_state));
+ fclose(f);
- CHECK_INT_EQ(XXH64_digest(checksum), expected_foobar_checksum);
+ CHECK_INT_EQ(XXH64_digest(checksum), expected_foobar_checksum);
- XXH64_freeState(checksum);
+ XXH64_freeState(checksum);
}
TEST(large_compressible_roundtrip)
{
- char data[] = "The quick brown fox jumps over the lazy dog";
+ char data[] = "The quick brown fox jumps over the lazy dog";
- FILE *f = fopen("data.zstd", "w");
- struct compressor *compr_zstd = compressor_from_type(COMPR_TYPE_ZSTD);
- struct compr_state *c_state = compr_zstd->init(f, 1, NULL);
- CHECK(c_state);
+ FILE* f = fopen("data.zstd", "w");
+ struct compressor* compr_zstd = compressor_from_type(COMPR_TYPE_ZSTD);
+ struct compr_state* c_state = compr_zstd->init(f, 1, NULL);
+ CHECK(c_state);
- for (size_t i = 0; i < 1000; i++) {
- CHECK(compr_zstd->write(c_state, data, sizeof(data)));
- }
+ for (size_t i = 0; i < 1000; i++) {
+ CHECK(compr_zstd->write(c_state, data, sizeof(data)));
+ }
- CHECK(compr_zstd->free(c_state));
- fclose(f);
+ CHECK(compr_zstd->free(c_state));
+ fclose(f);
- f = fopen("data.zstd", "r");
- struct decompressor *decompr_zstd = decompressor_from_type(COMPR_TYPE_ZSTD);
- struct decompr_state *d_state = decompr_zstd->init(f, NULL);
- CHECK(d_state);
+ f = fopen("data.zstd", "r");
+ struct decompressor* decompr_zstd = decompressor_from_type(COMPR_TYPE_ZSTD);
+ struct decompr_state* d_state = decompr_zstd->init(f, NULL);
+ CHECK(d_state);
- char buffer[sizeof(data)];
- for (size_t i = 0; i < 1000; i++) {
- CHECK(decompr_zstd->read(d_state, buffer, sizeof(buffer)));
- CHECK(memcmp(buffer, data, sizeof(data)) == 0);
- }
+ char buffer[sizeof(data)];
+ for (size_t i = 0; i < 1000; i++) {
+ CHECK(decompr_zstd->read(d_state, buffer, sizeof(buffer)));
+ CHECK(memcmp(buffer, data, sizeof(data)) == 0);
+ }
- // Nothing left to read.
- CHECK(!decompr_zstd->read(d_state, buffer, 1));
+ // Nothing left to read.
+ CHECK(!decompr_zstd->read(d_state, buffer, 1));
- // Error state is remembered.
- CHECK(!decompr_zstd->free(d_state));
- fclose(f);
+ // Error state is remembered.
+ CHECK(!decompr_zstd->free(d_state));
+ fclose(f);
}
TEST(large_uncompressible_roundtrip)
{
- char data[100000];
- for (size_t i = 0; i < sizeof(data); i++) {
- data[i] = rand() % 256;
- }
+ char data[100000];
+ for (size_t i = 0; i < sizeof(data); i++) {
+ data[i] = rand() % 256;
+ }
- FILE *f = fopen("data.zstd", "w");
- struct compressor *compr_zstd = compressor_from_type(COMPR_TYPE_ZSTD);
- struct compr_state *c_state = compr_zstd->init(f, 1, NULL);
- CHECK(c_state);
+ FILE* f = fopen("data.zstd", "w");
+ struct compressor* compr_zstd = compressor_from_type(COMPR_TYPE_ZSTD);
+ struct compr_state* c_state = compr_zstd->init(f, 1, NULL);
+ CHECK(c_state);
- CHECK(compr_zstd->write(c_state, data, sizeof(data)));
+ CHECK(compr_zstd->write(c_state, data, sizeof(data)));
- CHECK(compr_zstd->free(c_state));
- fclose(f);
+ CHECK(compr_zstd->free(c_state));
+ fclose(f);
- f = fopen("data.zstd", "r");
- struct decompressor *decompr_zstd = decompressor_from_type(COMPR_TYPE_ZSTD);
- struct decompr_state *d_state = decompr_zstd->init(f, NULL);
- CHECK(d_state);
+ f = fopen("data.zstd", "r");
+ struct decompressor* decompr_zstd = decompressor_from_type(COMPR_TYPE_ZSTD);
+ struct decompr_state* d_state = decompr_zstd->init(f, NULL);
+ CHECK(d_state);
- char buffer[sizeof(data)];
- CHECK(decompr_zstd->read(d_state, buffer, sizeof(buffer)));
- CHECK(memcmp(buffer, data, sizeof(data)) == 0);
+ char buffer[sizeof(data)];
+ CHECK(decompr_zstd->read(d_state, buffer, sizeof(buffer)));
+ CHECK(memcmp(buffer, data, sizeof(data)) == 0);
- CHECK(decompr_zstd->free(d_state));
- fclose(f);
+ CHECK(decompr_zstd->free(d_state));
+ fclose(f);
}
TEST_SUITE_END
diff --git a/unittest/test_conf.cpp b/unittest/test_conf.cpp
index b2a765ae..d4c10bcf 100644
--- a/unittest/test_conf.cpp
+++ b/unittest/test_conf.cpp
@@ -21,9 +21,10 @@
#include "util.hpp"
#define N_CONFIG_ITEMS 35
-static struct {
- char *descr;
- char *origin;
+static struct
+{
+ char* descr;
+ char* origin;
} received_conf_items[N_CONFIG_ITEMS];
static size_t n_received_conf_items = 0;
@@ -32,541 +33,530 @@ static char COMPRESS_1_ENV[] = "CCACHE_COMPRESS=1";
static char NOCOMPRESS_1_ENV[] = "CCACHE_NOCOMPRESS=1";
static void
-conf_item_receiver(const char *descr, const char *origin, void *context)
+conf_item_receiver(const char* descr, const char* origin, void* context)
{
- (void)context;
- received_conf_items[n_received_conf_items].descr = x_strdup(descr);
- received_conf_items[n_received_conf_items].origin = x_strdup(origin);
- ++n_received_conf_items;
+ (void)context;
+ received_conf_items[n_received_conf_items].descr = x_strdup(descr);
+ received_conf_items[n_received_conf_items].origin = x_strdup(origin);
+ ++n_received_conf_items;
}
static void
free_received_conf_items(void)
{
- while (n_received_conf_items > 0) {
- --n_received_conf_items;
- free(received_conf_items[n_received_conf_items].descr);
- free(received_conf_items[n_received_conf_items].origin);
- }
+ while (n_received_conf_items > 0) {
+ --n_received_conf_items;
+ free(received_conf_items[n_received_conf_items].descr);
+ free(received_conf_items[n_received_conf_items].origin);
+ }
}
TEST_SUITE(conf)
TEST(conf_create)
{
- struct conf *conf = conf_create();
- CHECK_STR_EQ("", conf->base_dir);
- CHECK_STR_EQ_FREE1(format("%s/.ccache", get_home_directory()),
- conf->cache_dir);
- CHECK_INT_EQ(2, conf->cache_dir_levels);
- CHECK_STR_EQ("", conf->compiler);
- CHECK_STR_EQ("mtime", conf->compiler_check);
- CHECK(conf->compression);
- CHECK_INT_EQ(0, conf->compression_level);
- CHECK_STR_EQ("", conf->cpp_extension);
- CHECK(!conf->debug);
- CHECK(!conf->depend_mode);
- CHECK(conf->direct_mode);
- CHECK(!conf->disable);
- CHECK_STR_EQ("", conf->extra_files_to_hash);
- CHECK(!conf->file_clone);
- CHECK(!conf->hard_link);
- CHECK(conf->hash_dir);
- CHECK_STR_EQ("", conf->ignore_headers_in_manifest);
- CHECK(!conf->keep_comments_cpp);
- CHECK_DOUBLE_EQ(0.8, conf->limit_multiple);
- CHECK_STR_EQ("", conf->log_file);
- CHECK_INT_EQ(0, conf->max_files);
- CHECK_INT_EQ((uint64_t)5 * 1000 * 1000 * 1000, conf->max_size);
- CHECK_STR_EQ("", conf->path);
- CHECK(!conf->pch_external_checksum);
- CHECK_STR_EQ("", conf->prefix_command);
- CHECK_STR_EQ("", conf->prefix_command_cpp);
- CHECK(!conf->read_only);
- CHECK(!conf->read_only_direct);
- CHECK(!conf->recache);
- CHECK(conf->run_second_cpp);
- CHECK_INT_EQ(0, conf->sloppiness);
- CHECK(conf->stats);
- CHECK_STR_EQ("", conf->temporary_dir);
- CHECK_INT_EQ(UINT_MAX, conf->umask);
- CHECK(!conf->unify);
- conf_free(conf);
+ struct conf* conf = conf_create();
+ CHECK_STR_EQ("", conf->base_dir);
+ CHECK_STR_EQ_FREE1(format("%s/.ccache", get_home_directory()),
+ conf->cache_dir);
+ CHECK_INT_EQ(2, conf->cache_dir_levels);
+ CHECK_STR_EQ("", conf->compiler);
+ CHECK_STR_EQ("mtime", conf->compiler_check);
+ CHECK(conf->compression);
+ CHECK_INT_EQ(0, conf->compression_level);
+ CHECK_STR_EQ("", conf->cpp_extension);
+ CHECK(!conf->debug);
+ CHECK(!conf->depend_mode);
+ CHECK(conf->direct_mode);
+ CHECK(!conf->disable);
+ CHECK_STR_EQ("", conf->extra_files_to_hash);
+ CHECK(!conf->file_clone);
+ CHECK(!conf->hard_link);
+ CHECK(conf->hash_dir);
+ CHECK_STR_EQ("", conf->ignore_headers_in_manifest);
+ CHECK(!conf->keep_comments_cpp);
+ CHECK_DOUBLE_EQ(0.8, conf->limit_multiple);
+ CHECK_STR_EQ("", conf->log_file);
+ CHECK_INT_EQ(0, conf->max_files);
+ CHECK_INT_EQ((uint64_t)5 * 1000 * 1000 * 1000, conf->max_size);
+ CHECK_STR_EQ("", conf->path);
+ CHECK(!conf->pch_external_checksum);
+ CHECK_STR_EQ("", conf->prefix_command);
+ CHECK_STR_EQ("", conf->prefix_command_cpp);
+ CHECK(!conf->read_only);
+ CHECK(!conf->read_only_direct);
+ CHECK(!conf->recache);
+ CHECK(conf->run_second_cpp);
+ CHECK_INT_EQ(0, conf->sloppiness);
+ CHECK(conf->stats);
+ CHECK_STR_EQ("", conf->temporary_dir);
+ CHECK_INT_EQ(UINT_MAX, conf->umask);
+ CHECK(!conf->unify);
+ conf_free(conf);
}
TEST(conf_read_valid_config)
{
- struct conf *conf = conf_create();
- char *errmsg, *user;
- putenv(USER_ENV);
- user = getenv("USER");
- CHECK_STR_EQ("rabbit", user);
- create_file(
- "ccache.conf",
+ struct conf* conf = conf_create();
+ char *errmsg, *user;
+ putenv(USER_ENV);
+ user = getenv("USER");
+ CHECK_STR_EQ("rabbit", user);
+ create_file(
+ "ccache.conf",
#ifndef _WIN32
- "base_dir = /$USER/foo/${USER} \n"
+ "base_dir = /$USER/foo/${USER} \n"
#else
- "base_dir = C:/$USER/foo/${USER}\n"
+ "base_dir = C:/$USER/foo/${USER}\n"
#endif
- "cache_dir=\n"
- "cache_dir = $USER$/${USER}/.ccache\n"
- "\n"
- "\n"
- " #A comment\n"
- " cache_dir_levels = 4\n"
- "\t compiler = foo\n"
- "compiler_check = none\n"
- "compression=false\n"
- "compression_level= 2\n"
- "cpp_extension = .foo\n"
- "depend_mode = true\n"
- "direct_mode = false\n"
- "disable = true\n"
- "extra_files_to_hash = a:b c:$USER\n"
- "file_clone = true\n"
- "hard_link = true\n"
- "hash_dir = false\n"
- "ignore_headers_in_manifest = a:b/c\n"
- "keep_comments_cpp = true\n"
- "limit_multiple = 1.0\n"
- "log_file = $USER${USER} \n"
- "max_files = 17\n"
- "max_size = 123M\n"
- "path = $USER.x\n"
- "pch_external_checksum = true\n"
- "prefix_command = x$USER\n"
- "prefix_command_cpp = y\n"
- "read_only = true\n"
- "read_only_direct = true\n"
- "recache = true\n"
- "run_second_cpp = false\n"
- "sloppiness = file_macro ,time_macros, include_file_mtime,include_file_ctime,file_stat_matches,file_stat_matches_ctime,pch_defines , no_system_headers,system_headers,clang_index_store\n"
- "stats = false\n"
- "temporary_dir = ${USER}_foo\n"
- "umask = 777\n"
- "unify = true"); // Note: no newline.
- CHECK(conf_read(conf, "ccache.conf", &errmsg));
- CHECK(!errmsg);
+ "cache_dir=\n"
+ "cache_dir = $USER$/${USER}/.ccache\n"
+ "\n"
+ "\n"
+ " #A comment\n"
+ " cache_dir_levels = 4\n"
+ "\t compiler = foo\n"
+ "compiler_check = none\n"
+ "compression=false\n"
+ "compression_level= 2\n"
+ "cpp_extension = .foo\n"
+ "depend_mode = true\n"
+ "direct_mode = false\n"
+ "disable = true\n"
+ "extra_files_to_hash = a:b c:$USER\n"
+ "file_clone = true\n"
+ "hard_link = true\n"
+ "hash_dir = false\n"
+ "ignore_headers_in_manifest = a:b/c\n"
+ "keep_comments_cpp = true\n"
+ "limit_multiple = 1.0\n"
+ "log_file = $USER${USER} \n"
+ "max_files = 17\n"
+ "max_size = 123M\n"
+ "path = $USER.x\n"
+ "pch_external_checksum = true\n"
+ "prefix_command = x$USER\n"
+ "prefix_command_cpp = y\n"
+ "read_only = true\n"
+ "read_only_direct = true\n"
+ "recache = true\n"
+ "run_second_cpp = false\n"
+ "sloppiness = file_macro ,time_macros, "
+ "include_file_mtime,include_file_ctime,file_stat_matches,file_stat_"
+ "matches_ctime,pch_defines , "
+ "no_system_headers,system_headers,clang_index_store\n"
+ "stats = false\n"
+ "temporary_dir = ${USER}_foo\n"
+ "umask = 777\n"
+ "unify = true"); // Note: no newline.
+ CHECK(conf_read(conf, "ccache.conf", &errmsg));
+ CHECK(!errmsg);
#ifndef _WIN32
- CHECK_STR_EQ_FREE1(format("/%s/foo/%s", user, user), conf->base_dir);
+ CHECK_STR_EQ_FREE1(format("/%s/foo/%s", user, user), conf->base_dir);
#else
- CHECK_STR_EQ_FREE1(format("C:/%s/foo/%s", user, user), conf->base_dir);
+ CHECK_STR_EQ_FREE1(format("C:/%s/foo/%s", user, user), conf->base_dir);
#endif
- CHECK_STR_EQ_FREE1(format("%s$/%s/.ccache", user, user), conf->cache_dir);
- CHECK_INT_EQ(4, conf->cache_dir_levels);
- CHECK_STR_EQ("foo", conf->compiler);
- CHECK_STR_EQ("none", conf->compiler_check);
- CHECK(!conf->compression);
- CHECK_INT_EQ(2, conf->compression_level);
- CHECK_STR_EQ(".foo", conf->cpp_extension);
- CHECK(conf->depend_mode);
- CHECK(!conf->direct_mode);
- CHECK(conf->disable);
- CHECK_STR_EQ_FREE1(format("a:b c:%s", user), conf->extra_files_to_hash);
- CHECK(conf->file_clone);
- CHECK(conf->hard_link);
- CHECK(!conf->hash_dir);
- CHECK_STR_EQ("a:b/c", conf->ignore_headers_in_manifest);
- CHECK(conf->keep_comments_cpp);
- CHECK_DOUBLE_EQ(1.0, conf->limit_multiple);
- CHECK_STR_EQ_FREE1(format("%s%s", user, user), conf->log_file);
- CHECK_INT_EQ(17, conf->max_files);
- CHECK_INT_EQ(123 * 1000 * 1000, conf->max_size);
- CHECK_STR_EQ_FREE1(format("%s.x", user), conf->path);
- CHECK(conf->pch_external_checksum);
- CHECK_STR_EQ_FREE1(format("x%s", user), conf->prefix_command);
- CHECK_STR_EQ("y", conf->prefix_command_cpp);
- CHECK(conf->read_only);
- CHECK(conf->read_only_direct);
- CHECK(conf->recache);
- CHECK(!conf->run_second_cpp);
- CHECK_INT_EQ(
- SLOPPY_INCLUDE_FILE_MTIME
- |SLOPPY_INCLUDE_FILE_CTIME
- |SLOPPY_FILE_MACRO
- |SLOPPY_TIME_MACROS
- |SLOPPY_FILE_STAT_MATCHES
- |SLOPPY_FILE_STAT_MATCHES_CTIME
- |SLOPPY_SYSTEM_HEADERS
- |SLOPPY_PCH_DEFINES
- |SLOPPY_CLANG_INDEX_STORE,
- conf->sloppiness);
- CHECK(!conf->stats);
- CHECK_STR_EQ_FREE1(format("%s_foo", user), conf->temporary_dir);
- CHECK_INT_EQ(0777, conf->umask);
- CHECK(conf->unify);
-
- conf_free(conf);
+ CHECK_STR_EQ_FREE1(format("%s$/%s/.ccache", user, user), conf->cache_dir);
+ CHECK_INT_EQ(4, conf->cache_dir_levels);
+ CHECK_STR_EQ("foo", conf->compiler);
+ CHECK_STR_EQ("none", conf->compiler_check);
+ CHECK(!conf->compression);
+ CHECK_INT_EQ(2, conf->compression_level);
+ CHECK_STR_EQ(".foo", conf->cpp_extension);
+ CHECK(conf->depend_mode);
+ CHECK(!conf->direct_mode);
+ CHECK(conf->disable);
+ CHECK_STR_EQ_FREE1(format("a:b c:%s", user), conf->extra_files_to_hash);
+ CHECK(conf->file_clone);
+ CHECK(conf->hard_link);
+ CHECK(!conf->hash_dir);
+ CHECK_STR_EQ("a:b/c", conf->ignore_headers_in_manifest);
+ CHECK(conf->keep_comments_cpp);
+ CHECK_DOUBLE_EQ(1.0, conf->limit_multiple);
+ CHECK_STR_EQ_FREE1(format("%s%s", user, user), conf->log_file);
+ CHECK_INT_EQ(17, conf->max_files);
+ CHECK_INT_EQ(123 * 1000 * 1000, conf->max_size);
+ CHECK_STR_EQ_FREE1(format("%s.x", user), conf->path);
+ CHECK(conf->pch_external_checksum);
+ CHECK_STR_EQ_FREE1(format("x%s", user), conf->prefix_command);
+ CHECK_STR_EQ("y", conf->prefix_command_cpp);
+ CHECK(conf->read_only);
+ CHECK(conf->read_only_direct);
+ CHECK(conf->recache);
+ CHECK(!conf->run_second_cpp);
+ CHECK_INT_EQ(SLOPPY_INCLUDE_FILE_MTIME | SLOPPY_INCLUDE_FILE_CTIME
+ | SLOPPY_FILE_MACRO | SLOPPY_TIME_MACROS
+ | SLOPPY_FILE_STAT_MATCHES | SLOPPY_FILE_STAT_MATCHES_CTIME
+ | SLOPPY_SYSTEM_HEADERS | SLOPPY_PCH_DEFINES
+ | SLOPPY_CLANG_INDEX_STORE,
+ conf->sloppiness);
+ CHECK(!conf->stats);
+ CHECK_STR_EQ_FREE1(format("%s_foo", user), conf->temporary_dir);
+ CHECK_INT_EQ(0777, conf->umask);
+ CHECK(conf->unify);
+
+ conf_free(conf);
}
TEST(conf_read_with_missing_equal_sign)
{
- struct conf *conf = conf_create();
- char *errmsg;
- create_file("ccache.conf", "no equal sign");
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_INT_EQ(errno, 0);
- CHECK_STR_EQ_FREE2("ccache.conf:1: missing equal sign",
- errmsg);
- conf_free(conf);
+ struct conf* conf = conf_create();
+ char* errmsg;
+ create_file("ccache.conf", "no equal sign");
+ CHECK(!conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_INT_EQ(errno, 0);
+ CHECK_STR_EQ_FREE2("ccache.conf:1: missing equal sign", errmsg);
+ conf_free(conf);
}
TEST(conf_read_with_unknown_config_key)
{
- struct conf *conf = conf_create();
- char *errmsg;
- create_file("ccache.conf", "# Comment\nfoo = bar");
- CHECK(conf_read(conf, "ccache.conf", &errmsg));
- conf_free(conf);
+ struct conf* conf = conf_create();
+ char* errmsg;
+ create_file("ccache.conf", "# Comment\nfoo = bar");
+ CHECK(conf_read(conf, "ccache.conf", &errmsg));
+ conf_free(conf);
}
TEST(conf_read_invalid_bool)
{
- struct conf *conf = conf_create();
- char *errmsg;
-
- create_file("ccache.conf", "disable=");
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_INT_EQ(errno, 0);
- CHECK_STR_EQ_FREE2("ccache.conf:1: not a boolean value: \"\"",
- errmsg);
-
- create_file("ccache.conf", "disable=foo");
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_INT_EQ(errno, 0);
- CHECK_STR_EQ_FREE2("ccache.conf:1: not a boolean value: \"foo\"",
- errmsg);
- conf_free(conf);
+ struct conf* conf = conf_create();
+ char* errmsg;
+
+ create_file("ccache.conf", "disable=");
+ CHECK(!conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_INT_EQ(errno, 0);
+ CHECK_STR_EQ_FREE2("ccache.conf:1: not a boolean value: \"\"", errmsg);
+
+ create_file("ccache.conf", "disable=foo");
+ CHECK(!conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_INT_EQ(errno, 0);
+ CHECK_STR_EQ_FREE2("ccache.conf:1: not a boolean value: \"foo\"", errmsg);
+ conf_free(conf);
}
TEST(conf_read_invalid_env_string)
{
- struct conf *conf = conf_create();
- char *errmsg;
- create_file("ccache.conf", "base_dir = ${foo");
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_INT_EQ(errno, 0);
- CHECK_STR_EQ_FREE2("ccache.conf:1: syntax error: missing '}' after \"foo\"",
- errmsg);
- // Other cases tested in test_util.c.
- conf_free(conf);
+ struct conf* conf = conf_create();
+ char* errmsg;
+ create_file("ccache.conf", "base_dir = ${foo");
+ CHECK(!conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_INT_EQ(errno, 0);
+ CHECK_STR_EQ_FREE2("ccache.conf:1: syntax error: missing '}' after \"foo\"",
+ errmsg);
+ // Other cases tested in test_util.c.
+ conf_free(conf);
}
TEST(conf_read_empty_umask)
{
- struct conf *conf = conf_create();
- char *errmsg;
- create_file("ccache.conf", "umask = ");
- CHECK(conf_read(conf, "ccache.conf", &errmsg));
- CHECK_INT_EQ(conf->umask, UINT_MAX);
- conf_free(conf);
+ struct conf* conf = conf_create();
+ char* errmsg;
+ create_file("ccache.conf", "umask = ");
+ CHECK(conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_INT_EQ(conf->umask, UINT_MAX);
+ conf_free(conf);
}
TEST(conf_read_invalid_size)
{
- struct conf *conf = conf_create();
- char *errmsg;
- create_file("ccache.conf", "max_size = foo");
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_INT_EQ(errno, 0);
- CHECK_STR_EQ_FREE2("ccache.conf:1: invalid size: \"foo\"",
- errmsg);
- // Other cases tested in test_util.c.
- conf_free(conf);
+ struct conf* conf = conf_create();
+ char* errmsg;
+ create_file("ccache.conf", "max_size = foo");
+ CHECK(!conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_INT_EQ(errno, 0);
+ CHECK_STR_EQ_FREE2("ccache.conf:1: invalid size: \"foo\"", errmsg);
+ // Other cases tested in test_util.c.
+ conf_free(conf);
}
TEST(conf_read_invalid_sloppiness)
{
- struct conf *conf = conf_create();
- char *errmsg;
- create_file("ccache.conf", "sloppiness = file_macro, foo");
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_INT_EQ(errno, 0);
- CHECK_STR_EQ_FREE2("ccache.conf:1: unknown sloppiness: \"foo\"",
- errmsg);
- conf_free(conf);
+ struct conf* conf = conf_create();
+ char* errmsg;
+ create_file("ccache.conf", "sloppiness = file_macro, foo");
+ CHECK(!conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_INT_EQ(errno, 0);
+ CHECK_STR_EQ_FREE2("ccache.conf:1: unknown sloppiness: \"foo\"", errmsg);
+ conf_free(conf);
}
TEST(conf_read_invalid_unsigned)
{
- struct conf *conf = conf_create();
- char *errmsg;
-
- create_file("ccache.conf", "max_files =");
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_INT_EQ(errno, 0);
- CHECK_STR_EQ_FREE2("ccache.conf:1: invalid unsigned integer: \"\"",
- errmsg);
-
- create_file("ccache.conf", "max_files = -42");
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_STR_EQ_FREE2("ccache.conf:1: invalid unsigned integer: \"-42\"",
- errmsg);
-
- create_file("ccache.conf", "max_files = foo");
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_STR_EQ_FREE2("ccache.conf:1: invalid unsigned integer: \"foo\"",
- errmsg);
-
- conf_free(conf);
+ struct conf* conf = conf_create();
+ char* errmsg;
+
+ create_file("ccache.conf", "max_files =");
+ CHECK(!conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_INT_EQ(errno, 0);
+ CHECK_STR_EQ_FREE2("ccache.conf:1: invalid unsigned integer: \"\"", errmsg);
+
+ create_file("ccache.conf", "max_files = -42");
+ CHECK(!conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_STR_EQ_FREE2("ccache.conf:1: invalid unsigned integer: \"-42\"",
+ errmsg);
+
+ create_file("ccache.conf", "max_files = foo");
+ CHECK(!conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_STR_EQ_FREE2("ccache.conf:1: invalid unsigned integer: \"foo\"",
+ errmsg);
+
+ conf_free(conf);
}
TEST(conf_read_missing_config_file)
{
- struct conf *conf = conf_create();
- char *errmsg;
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_INT_EQ(errno, ENOENT);
- conf_free(conf);
+ struct conf* conf = conf_create();
+ char* errmsg;
+ CHECK(!conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_INT_EQ(errno, ENOENT);
+ conf_free(conf);
}
TEST(verify_absolute_base_dir)
{
- struct conf *conf = conf_create();
- char *errmsg;
+ struct conf* conf = conf_create();
+ char* errmsg;
- create_file("ccache.conf", "base_dir = relative/path");
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_STR_EQ_FREE2("ccache.conf:1: not an absolute path: \"relative/path\"",
- errmsg);
+ create_file("ccache.conf", "base_dir = relative/path");
+ CHECK(!conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_STR_EQ_FREE2("ccache.conf:1: not an absolute path: \"relative/path\"",
+ errmsg);
- create_file("ccache.conf", "base_dir =");
- CHECK(conf_read(conf, "ccache.conf", &errmsg));
+ create_file("ccache.conf", "base_dir =");
+ CHECK(conf_read(conf, "ccache.conf", &errmsg));
- conf_free(conf);
+ conf_free(conf);
}
TEST(verify_dir_levels)
{
- struct conf *conf = conf_create();
- char *errmsg;
-
- create_file("ccache.conf", "cache_dir_levels = 0");
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_STR_EQ_FREE2(
- "ccache.conf:1: cache directory levels must be between 1 and 8",
- errmsg);
- create_file("ccache.conf", "cache_dir_levels = 9");
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_STR_EQ_FREE2(
- "ccache.conf:1: cache directory levels must be between 1 and 8",
- errmsg);
-
- conf_free(conf);
+ struct conf* conf = conf_create();
+ char* errmsg;
+
+ create_file("ccache.conf", "cache_dir_levels = 0");
+ CHECK(!conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_STR_EQ_FREE2(
+ "ccache.conf:1: cache directory levels must be between 1 and 8", errmsg);
+ create_file("ccache.conf", "cache_dir_levels = 9");
+ CHECK(!conf_read(conf, "ccache.conf", &errmsg));
+ CHECK_STR_EQ_FREE2(
+ "ccache.conf:1: cache directory levels must be between 1 and 8", errmsg);
+
+ conf_free(conf);
}
TEST(conf_update_from_environment)
{
- struct conf *conf = conf_create();
- char *errmsg;
+ struct conf* conf = conf_create();
+ char* errmsg;
- putenv(COMPRESS_1_ENV);
- CHECK(conf_update_from_environment(conf, &errmsg));
- CHECK(conf->compression);
+ putenv(COMPRESS_1_ENV);
+ CHECK(conf_update_from_environment(conf, &errmsg));
+ CHECK(conf->compression);
- x_unsetenv("CCACHE_COMPRESS");
- putenv(NOCOMPRESS_1_ENV);
- CHECK(conf_update_from_environment(conf, &errmsg));
- CHECK(!conf->compression);
+ x_unsetenv("CCACHE_COMPRESS");
+ putenv(NOCOMPRESS_1_ENV);
+ CHECK(conf_update_from_environment(conf, &errmsg));
+ CHECK(!conf->compression);
- conf_free(conf);
+ conf_free(conf);
}
TEST(conf_set_new_value)
{
- char *errmsg;
- char *data;
-
- create_file("ccache.conf", "path = vanilla\n");
- CHECKM(conf_set_value_in_file("ccache.conf", "compiler", "chocolate",
- &errmsg),
- errmsg);
- data = read_text_file("ccache.conf", 0);
- CHECK(data);
- CHECK_STR_EQ_FREE2("path = vanilla\ncompiler = chocolate\n", data);
+ char* errmsg;
+ char* data;
+
+ create_file("ccache.conf", "path = vanilla\n");
+ CHECKM(
+ conf_set_value_in_file("ccache.conf", "compiler", "chocolate", &errmsg),
+ errmsg);
+ data = read_text_file("ccache.conf", 0);
+ CHECK(data);
+ CHECK_STR_EQ_FREE2("path = vanilla\ncompiler = chocolate\n", data);
}
TEST(conf_set_existing_value)
{
- char *errmsg;
- char *data;
-
- create_file("ccache.conf", "path = chocolate\nstats = chocolate\n");
- CHECKM(conf_set_value_in_file("ccache.conf", "path", "vanilla", &errmsg),
- errmsg);
- data = read_text_file("ccache.conf", 0);
- CHECK(data);
- CHECK_STR_EQ_FREE2("path = vanilla\nstats = chocolate\n", data);
+ char* errmsg;
+ char* data;
+
+ create_file("ccache.conf", "path = chocolate\nstats = chocolate\n");
+ CHECKM(conf_set_value_in_file("ccache.conf", "path", "vanilla", &errmsg),
+ errmsg);
+ data = read_text_file("ccache.conf", 0);
+ CHECK(data);
+ CHECK_STR_EQ_FREE2("path = vanilla\nstats = chocolate\n", data);
}
TEST(conf_set_unknown_option)
{
- char *errmsg;
- char *data;
+ char* errmsg;
+ char* data;
- create_file("ccache.conf", "path = chocolate\nstats = chocolate\n");
- CHECKM(!conf_set_value_in_file("ccache.conf", "foo", "bar", &errmsg),
- errmsg);
- CHECK_STR_EQ_FREE2("unknown configuration option \"foo\"", errmsg);
+ create_file("ccache.conf", "path = chocolate\nstats = chocolate\n");
+ CHECKM(!conf_set_value_in_file("ccache.conf", "foo", "bar", &errmsg), errmsg);
+ CHECK_STR_EQ_FREE2("unknown configuration option \"foo\"", errmsg);
- data = read_text_file("ccache.conf", 0);
- CHECK(data);
- CHECK_STR_EQ_FREE2("path = chocolate\nstats = chocolate\n", data);
+ data = read_text_file("ccache.conf", 0);
+ CHECK(data);
+ CHECK_STR_EQ_FREE2("path = chocolate\nstats = chocolate\n", data);
}
TEST(conf_print_existing_value)
{
- struct conf *conf = conf_create();
- conf->max_files = 42;
- char *errmsg;
- {
- FILE *log = fopen("log", "w");
- CHECK(log);
- CHECK(conf_print_value(conf, "max_files", log, &errmsg));
- fclose(log);
- }
- {
- FILE *log = fopen("log", "r");
- CHECK(log);
- char buf[100];
- CHECK(fgets(buf, sizeof(buf), log));
- CHECK_STR_EQ("42\n", buf);
- fclose(log);
- }
- conf_free(conf);
+ struct conf* conf = conf_create();
+ conf->max_files = 42;
+ char* errmsg;
+ {
+ FILE* log = fopen("log", "w");
+ CHECK(log);
+ CHECK(conf_print_value(conf, "max_files", log, &errmsg));
+ fclose(log);
+ }
+ {
+ FILE* log = fopen("log", "r");
+ CHECK(log);
+ char buf[100];
+ CHECK(fgets(buf, sizeof(buf), log));
+ CHECK_STR_EQ("42\n", buf);
+ fclose(log);
+ }
+ conf_free(conf);
}
TEST(conf_print_unknown_value)
{
- struct conf *conf = conf_create();
- char *errmsg;
- {
- FILE *log = fopen("log", "w");
- CHECK(log);
- CHECK(!conf_print_value(conf, "foo", log, &errmsg));
- CHECK_STR_EQ_FREE2("unknown configuration option \"foo\"",
- errmsg);
- fclose(log);
- }
- {
- FILE *log = fopen("log", "r");
- CHECK(log);
- char buf[100];
- CHECK(!fgets(buf, sizeof(buf), log));
- fclose(log);
- }
- conf_free(conf);
+ struct conf* conf = conf_create();
+ char* errmsg;
+ {
+ FILE* log = fopen("log", "w");
+ CHECK(log);
+ CHECK(!conf_print_value(conf, "foo", log, &errmsg));
+ CHECK_STR_EQ_FREE2("unknown configuration option \"foo\"", errmsg);
+ fclose(log);
+ }
+ {
+ FILE* log = fopen("log", "r");
+ CHECK(log);
+ char buf[100];
+ CHECK(!fgets(buf, sizeof(buf), log));
+ fclose(log);
+ }
+ conf_free(conf);
}
TEST(conf_print_items)
{
- struct conf* conf = conf_create();
- conf->base_dir = x_strdup("bd");
- conf->cache_dir = x_strdup("cd");
- conf->cache_dir_levels = 7;
- conf->compiler = x_strdup("c");
- conf->compiler_check = x_strdup("cc");
- conf->compression = true;
- conf->compression_level = 8;
- conf->cpp_extension = x_strdup("ce");
- conf->debug = false;
- conf->depend_mode = true;
- conf->direct_mode = false;
- conf->disable = true;
- conf->extra_files_to_hash = x_strdup("efth");
- conf->file_clone = true;
- conf->hard_link = true;
- conf->hash_dir = false;
- conf->ignore_headers_in_manifest = x_strdup("ihim");
- conf->keep_comments_cpp = true;
- conf->limit_multiple = 0.0;
- conf->log_file = x_strdup("lf");
- conf->max_files = 4711;
- conf->max_size = 98.7 * 1000 * 1000;
- conf->path = x_strdup("p");
- conf->pch_external_checksum = true;
- conf->prefix_command = x_strdup("pc");
- conf->prefix_command_cpp = x_strdup("pcc");
- conf->read_only = true;
- conf->read_only_direct = true;
- conf->recache = true;
- conf->run_second_cpp = false;
- conf->sloppiness =
- SLOPPY_FILE_MACRO | SLOPPY_INCLUDE_FILE_MTIME | SLOPPY_INCLUDE_FILE_CTIME
- | SLOPPY_TIME_MACROS | SLOPPY_FILE_STAT_MATCHES
- | SLOPPY_FILE_STAT_MATCHES_CTIME | SLOPPY_PCH_DEFINES
- | SLOPPY_SYSTEM_HEADERS | SLOPPY_CLANG_INDEX_STORE;
- conf->stats = false;
- conf->temporary_dir = x_strdup("td");
- conf->umask = 022;
- conf->unify = true;
-
- conf->item_origins =
- static_cast<const char**>(x_malloc(N_CONFIG_ITEMS * sizeof(char *)));
- for (size_t i = 0; i < N_CONFIG_ITEMS; ++i) {
+ struct conf* conf = conf_create();
+ conf->base_dir = x_strdup("bd");
+ conf->cache_dir = x_strdup("cd");
+ conf->cache_dir_levels = 7;
+ conf->compiler = x_strdup("c");
+ conf->compiler_check = x_strdup("cc");
+ conf->compression = true;
+ conf->compression_level = 8;
+ conf->cpp_extension = x_strdup("ce");
+ conf->debug = false;
+ conf->depend_mode = true;
+ conf->direct_mode = false;
+ conf->disable = true;
+ conf->extra_files_to_hash = x_strdup("efth");
+ conf->file_clone = true;
+ conf->hard_link = true;
+ conf->hash_dir = false;
+ conf->ignore_headers_in_manifest = x_strdup("ihim");
+ conf->keep_comments_cpp = true;
+ conf->limit_multiple = 0.0;
+ conf->log_file = x_strdup("lf");
+ conf->max_files = 4711;
+ conf->max_size = 98.7 * 1000 * 1000;
+ conf->path = x_strdup("p");
+ conf->pch_external_checksum = true;
+ conf->prefix_command = x_strdup("pc");
+ conf->prefix_command_cpp = x_strdup("pcc");
+ conf->read_only = true;
+ conf->read_only_direct = true;
+ conf->recache = true;
+ conf->run_second_cpp = false;
+ conf->sloppiness = SLOPPY_FILE_MACRO | SLOPPY_INCLUDE_FILE_MTIME
+ | SLOPPY_INCLUDE_FILE_CTIME | SLOPPY_TIME_MACROS
+ | SLOPPY_FILE_STAT_MATCHES | SLOPPY_FILE_STAT_MATCHES_CTIME
+ | SLOPPY_PCH_DEFINES | SLOPPY_SYSTEM_HEADERS
+ | SLOPPY_CLANG_INDEX_STORE;
+ conf->stats = false;
+ conf->temporary_dir = x_strdup("td");
+ conf->umask = 022;
+ conf->unify = true;
+
+ conf->item_origins =
+ static_cast<const char**>(x_malloc(N_CONFIG_ITEMS * sizeof(char*)));
+ for (size_t i = 0; i < N_CONFIG_ITEMS; ++i) {
#ifndef __MINGW32__
- conf->item_origins[i] = format("origin%zu", i);
+ conf->item_origins[i] = format("origin%zu", i);
#else
- conf->item_origins[i] = format("origin%u", (unsigned) i);
+ conf->item_origins[i] = format("origin%u", (unsigned)i);
#endif
- }
-
- size_t n = 0;
- conf_print_items(conf, conf_item_receiver, NULL);
- CHECK_INT_EQ(N_CONFIG_ITEMS, n_received_conf_items);
- CHECK_STR_EQ("base_dir = bd", received_conf_items[n++].descr);
- CHECK_STR_EQ("cache_dir = cd", received_conf_items[n++].descr);
- CHECK_STR_EQ("cache_dir_levels = 7", received_conf_items[n++].descr);
- CHECK_STR_EQ("compiler = c", received_conf_items[n++].descr);
- CHECK_STR_EQ("compiler_check = cc", received_conf_items[n++].descr);
- CHECK_STR_EQ("compression = true", received_conf_items[n++].descr);
- CHECK_STR_EQ("compression_level = 8", received_conf_items[n++].descr);
- CHECK_STR_EQ("cpp_extension = ce", received_conf_items[n++].descr);
- CHECK_STR_EQ("debug = false", received_conf_items[n++].descr);
- CHECK_STR_EQ("depend_mode = true", received_conf_items[n++].descr);
- CHECK_STR_EQ("direct_mode = false", received_conf_items[n++].descr);
- CHECK_STR_EQ("disable = true", received_conf_items[n++].descr);
- CHECK_STR_EQ("extra_files_to_hash = efth", received_conf_items[n++].descr);
- CHECK_STR_EQ("file_clone = true", received_conf_items[n++].descr);
- CHECK_STR_EQ("hard_link = true", received_conf_items[n++].descr);
- CHECK_STR_EQ("hash_dir = false", received_conf_items[n++].descr);
- CHECK_STR_EQ("ignore_headers_in_manifest = ihim",
- received_conf_items[n++].descr);
- CHECK_STR_EQ("keep_comments_cpp = true", received_conf_items[n++].descr);
- CHECK_STR_EQ("limit_multiple = 0.0", received_conf_items[n++].descr);
- CHECK_STR_EQ("log_file = lf", received_conf_items[n++].descr);
- CHECK_STR_EQ("max_files = 4711", received_conf_items[n++].descr);
- CHECK_STR_EQ("max_size = 98.7M", received_conf_items[n++].descr);
- CHECK_STR_EQ("path = p", received_conf_items[n++].descr);
- CHECK_STR_EQ("pch_external_checksum = true", received_conf_items[n++].descr);
- CHECK_STR_EQ("prefix_command = pc", received_conf_items[n++].descr);
- CHECK_STR_EQ("prefix_command_cpp = pcc", received_conf_items[n++].descr);
- CHECK_STR_EQ("read_only = true", received_conf_items[n++].descr);
- CHECK_STR_EQ("read_only_direct = true", received_conf_items[n++].descr);
- CHECK_STR_EQ("recache = true", received_conf_items[n++].descr);
- CHECK_STR_EQ("run_second_cpp = false", received_conf_items[n++].descr);
- CHECK_STR_EQ("sloppiness = file_macro, include_file_mtime,"
- " include_file_ctime, time_macros, pch_defines,"
- " file_stat_matches, file_stat_matches_ctime, system_headers,"
- " clang_index_store",
- received_conf_items[n++].descr);
- CHECK_STR_EQ("stats = false", received_conf_items[n++].descr);
- CHECK_STR_EQ("temporary_dir = td", received_conf_items[n++].descr);
- CHECK_STR_EQ("umask = 022", received_conf_items[n++].descr);
- CHECK_STR_EQ("unify = true", received_conf_items[n++].descr);
-
- for (size_t i = 0; i < N_CONFIG_ITEMS; ++i) {
+ }
+
+ size_t n = 0;
+ conf_print_items(conf, conf_item_receiver, NULL);
+ CHECK_INT_EQ(N_CONFIG_ITEMS, n_received_conf_items);
+ CHECK_STR_EQ("base_dir = bd", received_conf_items[n++].descr);
+ CHECK_STR_EQ("cache_dir = cd", received_conf_items[n++].descr);
+ CHECK_STR_EQ("cache_dir_levels = 7", received_conf_items[n++].descr);
+ CHECK_STR_EQ("compiler = c", received_conf_items[n++].descr);
+ CHECK_STR_EQ("compiler_check = cc", received_conf_items[n++].descr);
+ CHECK_STR_EQ("compression = true", received_conf_items[n++].descr);
+ CHECK_STR_EQ("compression_level = 8", received_conf_items[n++].descr);
+ CHECK_STR_EQ("cpp_extension = ce", received_conf_items[n++].descr);
+ CHECK_STR_EQ("debug = false", received_conf_items[n++].descr);
+ CHECK_STR_EQ("depend_mode = true", received_conf_items[n++].descr);
+ CHECK_STR_EQ("direct_mode = false", received_conf_items[n++].descr);
+ CHECK_STR_EQ("disable = true", received_conf_items[n++].descr);
+ CHECK_STR_EQ("extra_files_to_hash = efth", received_conf_items[n++].descr);
+ CHECK_STR_EQ("file_clone = true", received_conf_items[n++].descr);
+ CHECK_STR_EQ("hard_link = true", received_conf_items[n++].descr);
+ CHECK_STR_EQ("hash_dir = false", received_conf_items[n++].descr);
+ CHECK_STR_EQ("ignore_headers_in_manifest = ihim",
+ received_conf_items[n++].descr);
+ CHECK_STR_EQ("keep_comments_cpp = true", received_conf_items[n++].descr);
+ CHECK_STR_EQ("limit_multiple = 0.0", received_conf_items[n++].descr);
+ CHECK_STR_EQ("log_file = lf", received_conf_items[n++].descr);
+ CHECK_STR_EQ("max_files = 4711", received_conf_items[n++].descr);
+ CHECK_STR_EQ("max_size = 98.7M", received_conf_items[n++].descr);
+ CHECK_STR_EQ("path = p", received_conf_items[n++].descr);
+ CHECK_STR_EQ("pch_external_checksum = true", received_conf_items[n++].descr);
+ CHECK_STR_EQ("prefix_command = pc", received_conf_items[n++].descr);
+ CHECK_STR_EQ("prefix_command_cpp = pcc", received_conf_items[n++].descr);
+ CHECK_STR_EQ("read_only = true", received_conf_items[n++].descr);
+ CHECK_STR_EQ("read_only_direct = true", received_conf_items[n++].descr);
+ CHECK_STR_EQ("recache = true", received_conf_items[n++].descr);
+ CHECK_STR_EQ("run_second_cpp = false", received_conf_items[n++].descr);
+ CHECK_STR_EQ(
+ "sloppiness = file_macro, include_file_mtime,"
+ " include_file_ctime, time_macros, pch_defines,"
+ " file_stat_matches, file_stat_matches_ctime, system_headers,"
+ " clang_index_store",
+ received_conf_items[n++].descr);
+ CHECK_STR_EQ("stats = false", received_conf_items[n++].descr);
+ CHECK_STR_EQ("temporary_dir = td", received_conf_items[n++].descr);
+ CHECK_STR_EQ("umask = 022", received_conf_items[n++].descr);
+ CHECK_STR_EQ("unify = true", received_conf_items[n++].descr);
+
+ for (size_t i = 0; i < N_CONFIG_ITEMS; ++i) {
#ifndef __MINGW32__
- char *expected = format("origin%zu", i);
+ char* expected = format("origin%zu", i);
#else
- char *expected = format("origin%u", (unsigned) i);
+ char* expected = format("origin%u", (unsigned)i);
#endif
- CHECK_STR_EQ_FREE1(expected, received_conf_items[i].origin);
- }
+ CHECK_STR_EQ_FREE1(expected, received_conf_items[i].origin);
+ }
- free_received_conf_items();
- conf_free(conf);
+ free_received_conf_items();
+ conf_free(conf);
}
TEST_SUITE_END
diff --git a/unittest/test_counters.cpp b/unittest/test_counters.cpp
index 7f07006d..e8416890 100644
--- a/unittest/test_counters.cpp
+++ b/unittest/test_counters.cpp
@@ -25,38 +25,38 @@ TEST_SUITE(counters)
TEST(counters_init_0_should_allocate_0)
{
- struct counters *counters = counters_init(0);
+ struct counters* counters = counters_init(0);
- CHECK_INT_EQ(0, counters->allocated);
- CHECK_INT_EQ(0, counters->size);
+ CHECK_INT_EQ(0, counters->allocated);
+ CHECK_INT_EQ(0, counters->size);
- counters_free(counters);
+ counters_free(counters);
}
TEST(counters_init_7_should_allocate_32)
{
- int i;
- struct counters *counters = counters_init(7);
+ int i;
+ struct counters* counters = counters_init(7);
- CHECK_INT_EQ(32, counters->allocated);
- CHECK_INT_EQ(7, counters->size);
- for (i = 0; i < 7; i++) {
- CHECK_INT_EQ(0, counters->data[i]);
- }
+ CHECK_INT_EQ(32, counters->allocated);
+ CHECK_INT_EQ(7, counters->size);
+ for (i = 0; i < 7; i++) {
+ CHECK_INT_EQ(0, counters->data[i]);
+ }
- counters_free(counters);
+ counters_free(counters);
}
TEST(counters_resize_50_should_allocate_96)
{
- struct counters *counters = counters_init(0);
+ struct counters* counters = counters_init(0);
- CHECK_INT_EQ(0, counters->allocated);
- counters_resize(counters, 50);
- CHECK_INT_EQ(50, counters->size);
- CHECK_INT_EQ(96, counters->allocated);
+ CHECK_INT_EQ(0, counters->allocated);
+ counters_resize(counters, 50);
+ CHECK_INT_EQ(50, counters->size);
+ CHECK_INT_EQ(96, counters->allocated);
- counters_free(counters);
+ counters_free(counters);
}
TEST_SUITE_END
diff --git a/unittest/test_hash.cpp b/unittest/test_hash.cpp
index df3bc8b9..6d8795c4 100644
--- a/unittest/test_hash.cpp
+++ b/unittest/test_hash.cpp
@@ -26,81 +26,81 @@ TEST_SUITE(hash)
TEST(test_known_strings)
{
- char d[DIGEST_STRING_BUFFER_SIZE];
+ char d[DIGEST_STRING_BUFFER_SIZE];
- {
- struct hash *h = hash_init();
- hash_string(h, "");
- hash_result_as_string(h, d);
- CHECK_STR_EQ("3345524abf6bbe1809449224b5972c41790b6cf2", d);
- hash_free(h);
- }
+ {
+ struct hash* h = hash_init();
+ hash_string(h, "");
+ hash_result_as_string(h, d);
+ CHECK_STR_EQ("3345524abf6bbe1809449224b5972c41790b6cf2", d);
+ hash_free(h);
+ }
- {
- struct hash *h = hash_init();
- hash_string(h, "a");
- hash_result_as_string(h, d);
- CHECK_STR_EQ("948caa2db61bc4cdb4faf7740cd491f195043914", d);
- hash_free(h);
- }
+ {
+ struct hash* h = hash_init();
+ hash_string(h, "a");
+ hash_result_as_string(h, d);
+ CHECK_STR_EQ("948caa2db61bc4cdb4faf7740cd491f195043914", d);
+ hash_free(h);
+ }
- {
- struct hash *h = hash_init();
- hash_string(h, "message digest");
- hash_result_as_string(h, d);
- CHECK_STR_EQ("6bfec6f65e52962be863d6ea1005fc5e4cc8478c", d);
- hash_free(h);
- }
+ {
+ struct hash* h = hash_init();
+ hash_string(h, "message digest");
+ hash_result_as_string(h, d);
+ CHECK_STR_EQ("6bfec6f65e52962be863d6ea1005fc5e4cc8478c", d);
+ hash_free(h);
+ }
- {
- struct hash *h = hash_init();
- hash_string(
- h,
- "12345678901234567890123456789012345678901234567890123456789012345678901"
- "234567890");
- hash_result_as_string(h, d);
- CHECK_STR_EQ("c2be0e534a67d25947f0c7e78527b2f82abd260f", d);
- hash_free(h);
- }
+ {
+ struct hash* h = hash_init();
+ hash_string(
+ h,
+ "1234567890123456789012345678901234567890123456789012345678901234567890"
+ "1"
+ "234567890");
+ hash_result_as_string(h, d);
+ CHECK_STR_EQ("c2be0e534a67d25947f0c7e78527b2f82abd260f", d);
+ hash_free(h);
+ }
}
TEST(hash_result_should_not_alter_state)
{
- char d[DIGEST_STRING_BUFFER_SIZE];
- struct hash *h = hash_init();
- hash_string(h, "message");
- hash_result_as_string(h, d);
- hash_string(h, " digest");
- hash_result_as_string(h, d);
- CHECK_STR_EQ("6bfec6f65e52962be863d6ea1005fc5e4cc8478c", d);
- hash_free(h);
+ char d[DIGEST_STRING_BUFFER_SIZE];
+ struct hash* h = hash_init();
+ hash_string(h, "message");
+ hash_result_as_string(h, d);
+ hash_string(h, " digest");
+ hash_result_as_string(h, d);
+ CHECK_STR_EQ("6bfec6f65e52962be863d6ea1005fc5e4cc8478c", d);
+ hash_free(h);
}
TEST(hash_result_should_be_idempotent)
{
- char d[DIGEST_STRING_BUFFER_SIZE];
- struct hash *h = hash_init();
- hash_string(h, "");
- hash_result_as_string(h, d);
- CHECK_STR_EQ("3345524abf6bbe1809449224b5972c41790b6cf2", d);
- hash_result_as_string(h, d);
- CHECK_STR_EQ("3345524abf6bbe1809449224b5972c41790b6cf2", d);
+ char d[DIGEST_STRING_BUFFER_SIZE];
+ struct hash* h = hash_init();
+ hash_string(h, "");
+ hash_result_as_string(h, d);
+ CHECK_STR_EQ("3345524abf6bbe1809449224b5972c41790b6cf2", d);
+ hash_result_as_string(h, d);
+ CHECK_STR_EQ("3345524abf6bbe1809449224b5972c41790b6cf2", d);
- hash_free(h);
+ hash_free(h);
}
TEST(hash_result_as_bytes)
{
- struct hash *h = hash_init();
- hash_string(h, "message digest");
- struct digest d;
- hash_result_as_bytes(h, &d);
- uint8_t expected[sizeof(d.bytes)] = {
- 0x6b, 0xfe, 0xc6, 0xf6, 0x5e, 0x52, 0x96, 0x2b, 0xe8, 0x63, 0xd6, 0xea,
- 0x10, 0x05, 0xfc, 0x5e, 0x4c, 0xc8, 0x47, 0x8c
- };
- CHECK_DATA_EQ(d.bytes, expected, sizeof(d.bytes));
- hash_free(h);
+ struct hash* h = hash_init();
+ hash_string(h, "message digest");
+ struct digest d;
+ hash_result_as_bytes(h, &d);
+ uint8_t expected[sizeof(d.bytes)] = {0x6b, 0xfe, 0xc6, 0xf6, 0x5e, 0x52, 0x96,
+ 0x2b, 0xe8, 0x63, 0xd6, 0xea, 0x10, 0x05,
+ 0xfc, 0x5e, 0x4c, 0xc8, 0x47, 0x8c};
+ CHECK_DATA_EQ(d.bytes, expected, sizeof(d.bytes));
+ hash_free(h);
}
TEST_SUITE_END
diff --git a/unittest/test_hashutil.cpp b/unittest/test_hashutil.cpp
index a7432281..c42911b7 100644
--- a/unittest/test_hashutil.cpp
+++ b/unittest/test_hashutil.cpp
@@ -27,222 +27,220 @@ TEST_SUITE(hashutil)
TEST(hash_command_output_simple)
{
- char d1[DIGEST_STRING_BUFFER_SIZE];
- char d2[DIGEST_STRING_BUFFER_SIZE];
+ char d1[DIGEST_STRING_BUFFER_SIZE];
+ char d2[DIGEST_STRING_BUFFER_SIZE];
- struct hash *h1 = hash_init();
- struct hash *h2 = hash_init();
+ struct hash* h1 = hash_init();
+ struct hash* h2 = hash_init();
- CHECK(hash_command_output(h1, "echo", "not used"));
- CHECK(hash_command_output(h2, "echo", "not used"));
- hash_result_as_string(h1, d1);
- hash_result_as_string(h2, d2);
- CHECK_STR_EQ(d1, d2);
+ CHECK(hash_command_output(h1, "echo", "not used"));
+ CHECK(hash_command_output(h2, "echo", "not used"));
+ hash_result_as_string(h1, d1);
+ hash_result_as_string(h2, d2);
+ CHECK_STR_EQ(d1, d2);
- hash_free(h2);
- hash_free(h1);
+ hash_free(h2);
+ hash_free(h1);
}
TEST(hash_command_output_space_removal)
{
- char d1[DIGEST_STRING_BUFFER_SIZE];
- char d2[DIGEST_STRING_BUFFER_SIZE];
+ char d1[DIGEST_STRING_BUFFER_SIZE];
+ char d2[DIGEST_STRING_BUFFER_SIZE];
- struct hash *h1 = hash_init();
- struct hash *h2 = hash_init();
+ struct hash* h1 = hash_init();
+ struct hash* h2 = hash_init();
- CHECK(hash_command_output(h1, "echo", "not used"));
- CHECK(hash_command_output(h2, " echo ", "not used"));
- hash_result_as_string(h1, d1);
- hash_result_as_string(h2, d2);
- CHECK_STR_EQ(d1, d2);
+ CHECK(hash_command_output(h1, "echo", "not used"));
+ CHECK(hash_command_output(h2, " echo ", "not used"));
+ hash_result_as_string(h1, d1);
+ hash_result_as_string(h2, d2);
+ CHECK_STR_EQ(d1, d2);
- hash_free(h2);
- hash_free(h1);
+ hash_free(h2);
+ hash_free(h1);
}
TEST(hash_command_output_hash_inequality)
{
- char d1[DIGEST_STRING_BUFFER_SIZE];
- char d2[DIGEST_STRING_BUFFER_SIZE];
+ char d1[DIGEST_STRING_BUFFER_SIZE];
+ char d2[DIGEST_STRING_BUFFER_SIZE];
- struct hash *h1 = hash_init();
- struct hash *h2 = hash_init();
+ struct hash* h1 = hash_init();
+ struct hash* h2 = hash_init();
- CHECK(hash_command_output(h1, "echo foo", "not used"));
- CHECK(hash_command_output(h2, "echo bar", "not used"));
- hash_result_as_string(h1, d1);
- hash_result_as_string(h2, d2);
- CHECK(!str_eq(d1, d2));
+ CHECK(hash_command_output(h1, "echo foo", "not used"));
+ CHECK(hash_command_output(h2, "echo bar", "not used"));
+ hash_result_as_string(h1, d1);
+ hash_result_as_string(h2, d2);
+ CHECK(!str_eq(d1, d2));
- hash_free(h2);
- hash_free(h1);
+ hash_free(h2);
+ hash_free(h1);
}
TEST(hash_command_output_compiler_substitution)
{
- char d1[DIGEST_STRING_BUFFER_SIZE];
- char d2[DIGEST_STRING_BUFFER_SIZE];
+ char d1[DIGEST_STRING_BUFFER_SIZE];
+ char d2[DIGEST_STRING_BUFFER_SIZE];
- struct hash *h1 = hash_init();
- struct hash *h2 = hash_init();
+ struct hash* h1 = hash_init();
+ struct hash* h2 = hash_init();
- CHECK(hash_command_output(h1, "echo foo", "not used"));
- CHECK(hash_command_output(h2, "%compiler% foo", "echo"));
- hash_result_as_string(h1, d1);
- hash_result_as_string(h2, d2);
- CHECK_STR_EQ(d1, d2);
+ CHECK(hash_command_output(h1, "echo foo", "not used"));
+ CHECK(hash_command_output(h2, "%compiler% foo", "echo"));
+ hash_result_as_string(h1, d1);
+ hash_result_as_string(h2, d2);
+ CHECK_STR_EQ(d1, d2);
- hash_free(h2);
- hash_free(h1);
+ hash_free(h2);
+ hash_free(h1);
}
TEST(hash_command_output_stdout_versus_stderr)
{
- char d1[DIGEST_STRING_BUFFER_SIZE];
- char d2[DIGEST_STRING_BUFFER_SIZE];
+ char d1[DIGEST_STRING_BUFFER_SIZE];
+ char d2[DIGEST_STRING_BUFFER_SIZE];
- struct hash *h1 = hash_init();
- struct hash *h2 = hash_init();
+ struct hash* h1 = hash_init();
+ struct hash* h2 = hash_init();
#ifndef _WIN32
- create_file("stderr.sh", "#!/bin/sh\necho foo >&2\n");
- chmod("stderr.sh", 0555);
- CHECK(hash_command_output(h1, "echo foo", "not used"));
- CHECK(hash_command_output(h2, "./stderr.sh", "not used"));
+ create_file("stderr.sh", "#!/bin/sh\necho foo >&2\n");
+ chmod("stderr.sh", 0555);
+ CHECK(hash_command_output(h1, "echo foo", "not used"));
+ CHECK(hash_command_output(h2, "./stderr.sh", "not used"));
#else
- create_file("stderr.bat", "@echo off\r\necho foo>&2\r\n");
- CHECK(hash_command_output(h1, "echo foo", "not used"));
- CHECK(hash_command_output(h2, "stderr.bat", "not used"));
+ create_file("stderr.bat", "@echo off\r\necho foo>&2\r\n");
+ CHECK(hash_command_output(h1, "echo foo", "not used"));
+ CHECK(hash_command_output(h2, "stderr.bat", "not used"));
#endif
- hash_result_as_string(h1, d1);
- hash_result_as_string(h2, d2);
- CHECK_STR_EQ(d1, d2);
+ hash_result_as_string(h1, d1);
+ hash_result_as_string(h2, d2);
+ CHECK_STR_EQ(d1, d2);
- hash_free(h2);
- hash_free(h1);
+ hash_free(h2);
+ hash_free(h1);
}
TEST(hash_multicommand_output)
{
- char d1[DIGEST_STRING_BUFFER_SIZE];
- char d2[DIGEST_STRING_BUFFER_SIZE];
+ char d1[DIGEST_STRING_BUFFER_SIZE];
+ char d2[DIGEST_STRING_BUFFER_SIZE];
- struct hash *h1 = hash_init();
- struct hash *h2 = hash_init();
+ struct hash* h1 = hash_init();
+ struct hash* h2 = hash_init();
#ifndef _WIN32
- create_file("foo.sh", "#!/bin/sh\necho foo\necho bar\n");
- chmod("foo.sh", 0555);
- CHECK(hash_multicommand_output(h2, "echo foo; echo bar", "not used"));
- CHECK(hash_multicommand_output(h1, "./foo.sh", "not used"));
+ create_file("foo.sh", "#!/bin/sh\necho foo\necho bar\n");
+ chmod("foo.sh", 0555);
+ CHECK(hash_multicommand_output(h2, "echo foo; echo bar", "not used"));
+ CHECK(hash_multicommand_output(h1, "./foo.sh", "not used"));
#else
- create_file("foo.bat", "@echo off\r\necho foo\r\necho bar\r\n");
- CHECK(hash_multicommand_output(h2, "echo foo; echo bar", "not used"));
- CHECK(hash_multicommand_output(h1, "foo.bat", "not used"));
+ create_file("foo.bat", "@echo off\r\necho foo\r\necho bar\r\n");
+ CHECK(hash_multicommand_output(h2, "echo foo; echo bar", "not used"));
+ CHECK(hash_multicommand_output(h1, "foo.bat", "not used"));
#endif
- hash_result_as_string(h1, d1);
- hash_result_as_string(h2, d2);
- CHECK_STR_EQ(d1, d2);
+ hash_result_as_string(h1, d1);
+ hash_result_as_string(h2, d2);
+ CHECK_STR_EQ(d1, d2);
- hash_free(h2);
- hash_free(h1);
+ hash_free(h2);
+ hash_free(h1);
}
TEST(hash_multicommand_output_error_handling)
{
- struct hash *h1 = hash_init();
- struct hash *h2 = hash_init();
+ struct hash* h1 = hash_init();
+ struct hash* h2 = hash_init();
- CHECK(!hash_multicommand_output(h2, "false; true", "not used"));
+ CHECK(!hash_multicommand_output(h2, "false; true", "not used"));
- hash_free(h2);
- hash_free(h1);
+ hash_free(h2);
+ hash_free(h1);
}
TEST(check_for_temporal_macros)
{
- const char time_start[] =
- "__TIME__\n"
- "int a;\n";
- const char time_middle[] =
- "#define a __TIME__\n"
- "int a;\n";
- const char time_end[] =
- "#define a __TIME__";
-
- const char date_start[] =
- "__DATE__\n"
- "int ab;\n";
- const char date_middle[] =
- "#define ab __DATE__\n"
- "int ab;\n";
- const char date_end[] =
- "#define ab __DATE__";
-
- const char no_temporal[] =
- "#define ab a__DATE__\n"
- "#define ab __DATE__a\n"
- "#define ab A__DATE__\n"
- "#define ab __DATE__A\n"
- "#define ab 0__DATE__\n"
- "#define ab __DATE__0\n"
- "#define ab _ _DATE__\n"
- "#define ab _ _DATE__\n"
- "#define ab __ DATE__\n"
- "#define ab __D ATE__\n"
- "#define ab __DA TE__\n"
- "#define ab __DAT E__\n"
- "#define ab __DATE __\n"
- "#define ab __DATE_ _\n"
- "#define ab _ _TIME__\n"
- "#define ab __ TIME__\n"
- "#define ab __T IME__\n"
- "#define ab __TI ME__\n"
- "#define ab __TIM E__\n"
- "#define ab __TIME __\n"
- "#define ab __TIME_ _\n";
-
- CHECK(check_for_temporal_macros(time_start + 0, sizeof(time_start) - 0));
- CHECK(!check_for_temporal_macros(time_start + 1, sizeof(time_start) - 1));
-
- CHECK(check_for_temporal_macros(time_middle + 0, sizeof(time_middle) - 0));
- CHECK(check_for_temporal_macros(time_middle + 1, sizeof(time_middle) - 1));
- CHECK(check_for_temporal_macros(time_middle + 2, sizeof(time_middle) - 2));
- CHECK(check_for_temporal_macros(time_middle + 3, sizeof(time_middle) - 3));
- CHECK(check_for_temporal_macros(time_middle + 4, sizeof(time_middle) - 4));
- CHECK(check_for_temporal_macros(time_middle + 5, sizeof(time_middle) - 5));
- CHECK(check_for_temporal_macros(time_middle + 6, sizeof(time_middle) - 6));
- CHECK(check_for_temporal_macros(time_middle + 7, sizeof(time_middle) - 7));
-
- CHECK(check_for_temporal_macros(time_end + 0, sizeof(time_end) - 0));
- CHECK(check_for_temporal_macros(time_end + sizeof(time_end) - 9, 9));
- CHECK(!check_for_temporal_macros(time_end + sizeof(time_end) - 8, 8));
-
- CHECK(check_for_temporal_macros(date_start + 0, sizeof(date_start) - 0));
- CHECK(!check_for_temporal_macros(date_start + 1, sizeof(date_start) - 1));
-
- CHECK(check_for_temporal_macros(date_middle + 0, sizeof(date_middle) - 0));
- CHECK(check_for_temporal_macros(date_middle + 1, sizeof(date_middle) - 1));
- CHECK(check_for_temporal_macros(date_middle + 2, sizeof(date_middle) - 2));
- CHECK(check_for_temporal_macros(date_middle + 3, sizeof(date_middle) - 3));
- CHECK(check_for_temporal_macros(date_middle + 4, sizeof(date_middle) - 4));
- CHECK(check_for_temporal_macros(date_middle + 5, sizeof(date_middle) - 5));
- CHECK(check_for_temporal_macros(date_middle + 6, sizeof(date_middle) - 6));
- CHECK(check_for_temporal_macros(date_middle + 7, sizeof(date_middle) - 7));
-
- CHECK(check_for_temporal_macros(date_end + 0, sizeof(date_end) - 0));
- CHECK(check_for_temporal_macros(date_end + sizeof(date_end) - 9, 9));
- CHECK(!check_for_temporal_macros(date_end + sizeof(date_end) - 8, 8));
-
- CHECK(!check_for_temporal_macros(no_temporal + 0, sizeof(no_temporal) - 0));
- CHECK(!check_for_temporal_macros(no_temporal + 1, sizeof(no_temporal) - 1));
- CHECK(!check_for_temporal_macros(no_temporal + 2, sizeof(no_temporal) - 2));
- CHECK(!check_for_temporal_macros(no_temporal + 3, sizeof(no_temporal) - 3));
- CHECK(!check_for_temporal_macros(no_temporal + 4, sizeof(no_temporal) - 4));
- CHECK(!check_for_temporal_macros(no_temporal + 5, sizeof(no_temporal) - 5));
- CHECK(!check_for_temporal_macros(no_temporal + 6, sizeof(no_temporal) - 6));
- CHECK(!check_for_temporal_macros(no_temporal + 7, sizeof(no_temporal) - 7));
+ const char time_start[] =
+ "__TIME__\n"
+ "int a;\n";
+ const char time_middle[] =
+ "#define a __TIME__\n"
+ "int a;\n";
+ const char time_end[] = "#define a __TIME__";
+
+ const char date_start[] =
+ "__DATE__\n"
+ "int ab;\n";
+ const char date_middle[] =
+ "#define ab __DATE__\n"
+ "int ab;\n";
+ const char date_end[] = "#define ab __DATE__";
+
+ const char no_temporal[] =
+ "#define ab a__DATE__\n"
+ "#define ab __DATE__a\n"
+ "#define ab A__DATE__\n"
+ "#define ab __DATE__A\n"
+ "#define ab 0__DATE__\n"
+ "#define ab __DATE__0\n"
+ "#define ab _ _DATE__\n"
+ "#define ab _ _DATE__\n"
+ "#define ab __ DATE__\n"
+ "#define ab __D ATE__\n"
+ "#define ab __DA TE__\n"
+ "#define ab __DAT E__\n"
+ "#define ab __DATE __\n"
+ "#define ab __DATE_ _\n"
+ "#define ab _ _TIME__\n"
+ "#define ab __ TIME__\n"
+ "#define ab __T IME__\n"
+ "#define ab __TI ME__\n"
+ "#define ab __TIM E__\n"
+ "#define ab __TIME __\n"
+ "#define ab __TIME_ _\n";
+
+ CHECK(check_for_temporal_macros(time_start + 0, sizeof(time_start) - 0));
+ CHECK(!check_for_temporal_macros(time_start + 1, sizeof(time_start) - 1));
+
+ CHECK(check_for_temporal_macros(time_middle + 0, sizeof(time_middle) - 0));
+ CHECK(check_for_temporal_macros(time_middle + 1, sizeof(time_middle) - 1));
+ CHECK(check_for_temporal_macros(time_middle + 2, sizeof(time_middle) - 2));
+ CHECK(check_for_temporal_macros(time_middle + 3, sizeof(time_middle) - 3));
+ CHECK(check_for_temporal_macros(time_middle + 4, sizeof(time_middle) - 4));
+ CHECK(check_for_temporal_macros(time_middle + 5, sizeof(time_middle) - 5));
+ CHECK(check_for_temporal_macros(time_middle + 6, sizeof(time_middle) - 6));
+ CHECK(check_for_temporal_macros(time_middle + 7, sizeof(time_middle) - 7));
+
+ CHECK(check_for_temporal_macros(time_end + 0, sizeof(time_end) - 0));
+ CHECK(check_for_temporal_macros(time_end + sizeof(time_end) - 9, 9));
+ CHECK(!check_for_temporal_macros(time_end + sizeof(time_end) - 8, 8));
+
+ CHECK(check_for_temporal_macros(date_start + 0, sizeof(date_start) - 0));
+ CHECK(!check_for_temporal_macros(date_start + 1, sizeof(date_start) - 1));
+
+ CHECK(check_for_temporal_macros(date_middle + 0, sizeof(date_middle) - 0));
+ CHECK(check_for_temporal_macros(date_middle + 1, sizeof(date_middle) - 1));
+ CHECK(check_for_temporal_macros(date_middle + 2, sizeof(date_middle) - 2));
+ CHECK(check_for_temporal_macros(date_middle + 3, sizeof(date_middle) - 3));
+ CHECK(check_for_temporal_macros(date_middle + 4, sizeof(date_middle) - 4));
+ CHECK(check_for_temporal_macros(date_middle + 5, sizeof(date_middle) - 5));
+ CHECK(check_for_temporal_macros(date_middle + 6, sizeof(date_middle) - 6));
+ CHECK(check_for_temporal_macros(date_middle + 7, sizeof(date_middle) - 7));
+
+ CHECK(check_for_temporal_macros(date_end + 0, sizeof(date_end) - 0));
+ CHECK(check_for_temporal_macros(date_end + sizeof(date_end) - 9, 9));
+ CHECK(!check_for_temporal_macros(date_end + sizeof(date_end) - 8, 8));
+
+ CHECK(!check_for_temporal_macros(no_temporal + 0, sizeof(no_temporal) - 0));
+ CHECK(!check_for_temporal_macros(no_temporal + 1, sizeof(no_temporal) - 1));
+ CHECK(!check_for_temporal_macros(no_temporal + 2, sizeof(no_temporal) - 2));
+ CHECK(!check_for_temporal_macros(no_temporal + 3, sizeof(no_temporal) - 3));
+ CHECK(!check_for_temporal_macros(no_temporal + 4, sizeof(no_temporal) - 4));
+ CHECK(!check_for_temporal_macros(no_temporal + 5, sizeof(no_temporal) - 5));
+ CHECK(!check_for_temporal_macros(no_temporal + 6, sizeof(no_temporal) - 6));
+ CHECK(!check_for_temporal_macros(no_temporal + 7, sizeof(no_temporal) - 7));
}
TEST_SUITE_END
diff --git a/unittest/test_lockfile.cpp b/unittest/test_lockfile.cpp
index f75adf36..334b3388 100644
--- a/unittest/test_lockfile.cpp
+++ b/unittest/test_lockfile.cpp
@@ -26,53 +26,53 @@ TEST_SUITE(lockfile)
TEST(acquire_should_create_symlink)
{
- lockfile_acquire("test", 1000);
+ lockfile_acquire("test", 1000);
#if defined(_WIN32) || defined(__CYGWIN__)
- CHECK(path_exists("test.lock"));
+ CHECK(path_exists("test.lock"));
#else
- CHECK(is_symlink("test.lock"));
+ CHECK(is_symlink("test.lock"));
#endif
}
TEST(release_should_delete_file)
{
- create_file("test.lock", "");
- lockfile_release("test");
+ create_file("test.lock", "");
+ lockfile_release("test");
- CHECK(!path_exists("test.lock"));
+ CHECK(!path_exists("test.lock"));
}
TEST(lock_breaking)
{
- char *p;
+ char* p;
#if defined(_WIN32) || defined(__CYGWIN__)
- create_file("test.lock", "foo");
- create_file("test.lock.lock", "foo");
+ create_file("test.lock", "foo");
+ create_file("test.lock.lock", "foo");
#else
- CHECK_INT_EQ(0, symlink("foo", "test.lock"));
- CHECK_INT_EQ(0, symlink("foo", "test.lock.lock"));
+ CHECK_INT_EQ(0, symlink("foo", "test.lock"));
+ CHECK_INT_EQ(0, symlink("foo", "test.lock.lock"));
#endif
- CHECK(lockfile_acquire("test", 1000));
+ CHECK(lockfile_acquire("test", 1000));
#if defined(_WIN32) || defined(__CYGWIN__)
- p = read_text_file("test.lock", 0);
+ p = read_text_file("test.lock", 0);
#else
- p = x_readlink("test.lock");
+ p = x_readlink("test.lock");
#endif
- CHECK(p);
- CHECK(!str_eq(p, "foo"));
- CHECK(!path_exists("test.lock.lock"));
+ CHECK(p);
+ CHECK(!str_eq(p, "foo"));
+ CHECK(!path_exists("test.lock.lock"));
- free(p);
+ free(p);
}
#if !defined(_WIN32) && !defined(__CYGWIN__)
TEST(failed_lock_breaking)
{
- create_file("test.lock", "");
- CHECK(!lockfile_acquire("test", 1000));
+ create_file("test.lock", "");
+ CHECK(!lockfile_acquire("test", 1000));
}
#endif
diff --git a/unittest/test_stats.cpp b/unittest/test_stats.cpp
index 02a28414..aa3aaa26 100644
--- a/unittest/test_stats.cpp
+++ b/unittest/test_stats.cpp
@@ -27,25 +27,25 @@ TEST_SUITE(stats)
TEST(forward_compatibility)
{
- unsigned i;
- FILE *f;
- struct counters *counters = counters_init(0);
+ unsigned i;
+ FILE* f;
+ struct counters* counters = counters_init(0);
- f = fopen("stats", "w");
- for (i = 0; i < 100; i++) {
- fprintf(f, "%u\n", i);
- }
- fclose(f);
+ f = fopen("stats", "w");
+ for (i = 0; i < 100; i++) {
+ fprintf(f, "%u\n", i);
+ }
+ fclose(f);
- stats_read("stats", counters);
- CHECK_INT_EQ(100, counters->size);
- CHECK_INT_EQ(73, counters->data[73]);
+ stats_read("stats", counters);
+ CHECK_INT_EQ(100, counters->size);
+ CHECK_INT_EQ(73, counters->data[73]);
- stats_write("stats", counters);
- CHECK_INT_EQ(100, counters->size);
- CHECK_INT_EQ(99, counters->data[99]);
+ stats_write("stats", counters);
+ CHECK_INT_EQ(100, counters->size);
+ CHECK_INT_EQ(99, counters->data[99]);
- counters_free(counters);
+ counters_free(counters);
}
TEST_SUITE_END
diff --git a/unittest/test_util.cpp b/unittest/test_util.cpp
index c16c4663..88e6c8c6 100644
--- a/unittest/test_util.cpp
+++ b/unittest/test_util.cpp
@@ -27,182 +27,180 @@ TEST_SUITE(util)
TEST(x_basename)
{
- CHECK_STR_EQ_FREE2("foo.c", x_basename("foo.c"));
- CHECK_STR_EQ_FREE2("foo.c", x_basename("dir1/dir2/foo.c"));
- CHECK_STR_EQ_FREE2("foo.c", x_basename("/dir/foo.c"));
- CHECK_STR_EQ_FREE2("", x_basename("dir1/dir2/"));
+ CHECK_STR_EQ_FREE2("foo.c", x_basename("foo.c"));
+ CHECK_STR_EQ_FREE2("foo.c", x_basename("dir1/dir2/foo.c"));
+ CHECK_STR_EQ_FREE2("foo.c", x_basename("/dir/foo.c"));
+ CHECK_STR_EQ_FREE2("", x_basename("dir1/dir2/"));
}
TEST(x_dirname)
{
- CHECK_STR_EQ_FREE2(".", x_dirname("foo.c"));
- CHECK_STR_EQ_FREE2(".", x_dirname(""));
- CHECK_STR_EQ_FREE2("/", x_dirname("/"));
- CHECK_STR_EQ_FREE2("/", x_dirname("/foo.c"));
- CHECK_STR_EQ_FREE2("dir1/dir2", x_dirname("dir1/dir2/foo.c"));
- CHECK_STR_EQ_FREE2("/dir", x_dirname("/dir/foo.c"));
- CHECK_STR_EQ_FREE2("dir1/dir2", x_dirname("dir1/dir2/"));
+ CHECK_STR_EQ_FREE2(".", x_dirname("foo.c"));
+ CHECK_STR_EQ_FREE2(".", x_dirname(""));
+ CHECK_STR_EQ_FREE2("/", x_dirname("/"));
+ CHECK_STR_EQ_FREE2("/", x_dirname("/foo.c"));
+ CHECK_STR_EQ_FREE2("dir1/dir2", x_dirname("dir1/dir2/foo.c"));
+ CHECK_STR_EQ_FREE2("/dir", x_dirname("/dir/foo.c"));
+ CHECK_STR_EQ_FREE2("dir1/dir2", x_dirname("dir1/dir2/"));
}
TEST(common_dir_prefix_length)
{
- CHECK_INT_EQ(0, common_dir_prefix_length("", ""));
- CHECK_INT_EQ(0, common_dir_prefix_length("/", "/"));
- CHECK_INT_EQ(0, common_dir_prefix_length("/", "/b"));
- CHECK_INT_EQ(0, common_dir_prefix_length("/a", "/b"));
- CHECK_INT_EQ(2, common_dir_prefix_length("/a", "/a"));
- CHECK_INT_EQ(2, common_dir_prefix_length("/a", "/a/b"));
- CHECK_INT_EQ(2, common_dir_prefix_length("/a/b", "/a/c"));
- CHECK_INT_EQ(4, common_dir_prefix_length("/a/b", "/a/b"));
- CHECK_INT_EQ(2, common_dir_prefix_length("/a/bc", "/a/b"));
- CHECK_INT_EQ(2, common_dir_prefix_length("/a/b", "/a/bc"));
+ CHECK_INT_EQ(0, common_dir_prefix_length("", ""));
+ CHECK_INT_EQ(0, common_dir_prefix_length("/", "/"));
+ CHECK_INT_EQ(0, common_dir_prefix_length("/", "/b"));
+ CHECK_INT_EQ(0, common_dir_prefix_length("/a", "/b"));
+ CHECK_INT_EQ(2, common_dir_prefix_length("/a", "/a"));
+ CHECK_INT_EQ(2, common_dir_prefix_length("/a", "/a/b"));
+ CHECK_INT_EQ(2, common_dir_prefix_length("/a/b", "/a/c"));
+ CHECK_INT_EQ(4, common_dir_prefix_length("/a/b", "/a/b"));
+ CHECK_INT_EQ(2, common_dir_prefix_length("/a/bc", "/a/b"));
+ CHECK_INT_EQ(2, common_dir_prefix_length("/a/b", "/a/bc"));
}
TEST(get_relative_path)
{
#ifdef _WIN32
- CHECK_STR_EQ_FREE2("a", get_relative_path("C:/doesn't matter", "a"));
- CHECK_STR_EQ_FREE2("a/b", get_relative_path("C:/doesn't matter", "a/b"));
- CHECK_STR_EQ_FREE2(".", get_relative_path("C:/a", "C:/a"));
- CHECK_STR_EQ_FREE2("..", get_relative_path("C:/a/b", "C:/a"));
- CHECK_STR_EQ_FREE2("b", get_relative_path("C:/a", "C:/a/b"));
- CHECK_STR_EQ_FREE2("b/c", get_relative_path("C:/a", "C:/a/b/c"));
- CHECK_STR_EQ_FREE2("../c", get_relative_path("C:/a/b", "C:/a/c"));
- CHECK_STR_EQ_FREE2("../c/d", get_relative_path("C:/a/b", "C:/a/c/d"));
- CHECK_STR_EQ_FREE2("../../c/d", get_relative_path("C:/a/b/c", "C:/a/c/d"));
- CHECK_STR_EQ_FREE2("../..", get_relative_path("C:/a/b", "C:/"));
- CHECK_STR_EQ_FREE2("../../c", get_relative_path("C:/a/b", "C:/c"));
- CHECK_STR_EQ_FREE2("a/b", get_relative_path("C:/", "C:/a/b"));
+ CHECK_STR_EQ_FREE2("a", get_relative_path("C:/doesn't matter", "a"));
+ CHECK_STR_EQ_FREE2("a/b", get_relative_path("C:/doesn't matter", "a/b"));
+ CHECK_STR_EQ_FREE2(".", get_relative_path("C:/a", "C:/a"));
+ CHECK_STR_EQ_FREE2("..", get_relative_path("C:/a/b", "C:/a"));
+ CHECK_STR_EQ_FREE2("b", get_relative_path("C:/a", "C:/a/b"));
+ CHECK_STR_EQ_FREE2("b/c", get_relative_path("C:/a", "C:/a/b/c"));
+ CHECK_STR_EQ_FREE2("../c", get_relative_path("C:/a/b", "C:/a/c"));
+ CHECK_STR_EQ_FREE2("../c/d", get_relative_path("C:/a/b", "C:/a/c/d"));
+ CHECK_STR_EQ_FREE2("../../c/d", get_relative_path("C:/a/b/c", "C:/a/c/d"));
+ CHECK_STR_EQ_FREE2("../..", get_relative_path("C:/a/b", "C:/"));
+ CHECK_STR_EQ_FREE2("../../c", get_relative_path("C:/a/b", "C:/c"));
+ CHECK_STR_EQ_FREE2("a/b", get_relative_path("C:/", "C:/a/b"));
#else
- CHECK_STR_EQ_FREE2("a", get_relative_path("/doesn't matter", "a"));
- CHECK_STR_EQ_FREE2("a/b", get_relative_path("/doesn't matter", "a/b"));
- CHECK_STR_EQ_FREE2(".", get_relative_path("/a", "/a"));
- CHECK_STR_EQ_FREE2("..", get_relative_path("/a/b", "/a"));
- CHECK_STR_EQ_FREE2("b", get_relative_path("/a", "/a/b"));
- CHECK_STR_EQ_FREE2("b/c", get_relative_path("/a", "/a/b/c"));
- CHECK_STR_EQ_FREE2("../c", get_relative_path("/a/b", "/a/c"));
- CHECK_STR_EQ_FREE2("../c/d", get_relative_path("/a/b", "/a/c/d"));
- CHECK_STR_EQ_FREE2("../../c/d", get_relative_path("/a/b/c", "/a/c/d"));
- CHECK_STR_EQ_FREE2("../..", get_relative_path("/a/b", "/"));
- CHECK_STR_EQ_FREE2("../../c", get_relative_path("/a/b", "/c"));
- CHECK_STR_EQ_FREE2("a/b", get_relative_path("/", "/a/b"));
+ CHECK_STR_EQ_FREE2("a", get_relative_path("/doesn't matter", "a"));
+ CHECK_STR_EQ_FREE2("a/b", get_relative_path("/doesn't matter", "a/b"));
+ CHECK_STR_EQ_FREE2(".", get_relative_path("/a", "/a"));
+ CHECK_STR_EQ_FREE2("..", get_relative_path("/a/b", "/a"));
+ CHECK_STR_EQ_FREE2("b", get_relative_path("/a", "/a/b"));
+ CHECK_STR_EQ_FREE2("b/c", get_relative_path("/a", "/a/b/c"));
+ CHECK_STR_EQ_FREE2("../c", get_relative_path("/a/b", "/a/c"));
+ CHECK_STR_EQ_FREE2("../c/d", get_relative_path("/a/b", "/a/c/d"));
+ CHECK_STR_EQ_FREE2("../../c/d", get_relative_path("/a/b/c", "/a/c/d"));
+ CHECK_STR_EQ_FREE2("../..", get_relative_path("/a/b", "/"));
+ CHECK_STR_EQ_FREE2("../../c", get_relative_path("/a/b", "/c"));
+ CHECK_STR_EQ_FREE2("a/b", get_relative_path("/", "/a/b"));
#endif
}
TEST(subst_env_in_string)
{
- char *errmsg;
+ char* errmsg;
- putenv(FOO_ENV);
+ putenv(FOO_ENV);
- CHECK_STR_EQ_FREE2("bar",
- subst_env_in_string("$FOO", &errmsg));
- CHECK(!errmsg);
+ CHECK_STR_EQ_FREE2("bar", subst_env_in_string("$FOO", &errmsg));
+ CHECK(!errmsg);
- CHECK_STR_EQ_FREE2("$",
- subst_env_in_string("$", &errmsg));
- CHECK(!errmsg);
+ CHECK_STR_EQ_FREE2("$", subst_env_in_string("$", &errmsg));
+ CHECK(!errmsg);
- CHECK_STR_EQ_FREE2("bar bar:bar",
- subst_env_in_string("$FOO $FOO:$FOO", &errmsg));
- CHECK(!errmsg);
+ CHECK_STR_EQ_FREE2("bar bar:bar",
+ subst_env_in_string("$FOO $FOO:$FOO", &errmsg));
+ CHECK(!errmsg);
- CHECK_STR_EQ_FREE2("xbar",
- subst_env_in_string("x$FOO", &errmsg));
- CHECK(!errmsg);
+ CHECK_STR_EQ_FREE2("xbar", subst_env_in_string("x$FOO", &errmsg));
+ CHECK(!errmsg);
- CHECK_STR_EQ_FREE2("barx",
- subst_env_in_string("${FOO}x", &errmsg));
- CHECK(!errmsg);
+ CHECK_STR_EQ_FREE2("barx", subst_env_in_string("${FOO}x", &errmsg));
+ CHECK(!errmsg);
- CHECK(!subst_env_in_string("$surelydoesntexist", &errmsg));
- CHECK_STR_EQ_FREE2("environment variable \"surelydoesntexist\" not set",
- errmsg);
+ CHECK(!subst_env_in_string("$surelydoesntexist", &errmsg));
+ CHECK_STR_EQ_FREE2("environment variable \"surelydoesntexist\" not set",
+ errmsg);
- CHECK(!subst_env_in_string("${FOO", &errmsg));
- CHECK_STR_EQ_FREE2("syntax error: missing '}' after \"FOO\"", errmsg);
+ CHECK(!subst_env_in_string("${FOO", &errmsg));
+ CHECK_STR_EQ_FREE2("syntax error: missing '}' after \"FOO\"", errmsg);
}
TEST(format_human_readable_size)
{
- CHECK_STR_EQ_FREE2("0.0 MB", format_human_readable_size(0));
- CHECK_STR_EQ_FREE2("0.0 MB", format_human_readable_size(49));
- CHECK_STR_EQ_FREE2("0.4 MB", format_human_readable_size(420 * 1000));
- CHECK_STR_EQ_FREE2("1.0 MB", format_human_readable_size(1000 * 1000));
- CHECK_STR_EQ_FREE2("1.2 MB", format_human_readable_size(1234 * 1000));
- CHECK_STR_EQ_FREE2("438.5 MB",
- format_human_readable_size(438.5 * 1000 * 1000));
- CHECK_STR_EQ_FREE2("1.0 GB",
- format_human_readable_size(1000 * 1000 * 1000));
- CHECK_STR_EQ_FREE2("17.1 GB",
- format_human_readable_size(17.11 * 1000 * 1000 * 1000));
+ CHECK_STR_EQ_FREE2("0.0 MB", format_human_readable_size(0));
+ CHECK_STR_EQ_FREE2("0.0 MB", format_human_readable_size(49));
+ CHECK_STR_EQ_FREE2("0.4 MB", format_human_readable_size(420 * 1000));
+ CHECK_STR_EQ_FREE2("1.0 MB", format_human_readable_size(1000 * 1000));
+ CHECK_STR_EQ_FREE2("1.2 MB", format_human_readable_size(1234 * 1000));
+ CHECK_STR_EQ_FREE2("438.5 MB",
+ format_human_readable_size(438.5 * 1000 * 1000));
+ CHECK_STR_EQ_FREE2("1.0 GB", format_human_readable_size(1000 * 1000 * 1000));
+ CHECK_STR_EQ_FREE2("17.1 GB",
+ format_human_readable_size(17.11 * 1000 * 1000 * 1000));
}
TEST(format_parsable_size_with_suffix)
{
- CHECK_STR_EQ_FREE2("0", format_parsable_size_with_suffix(0));
- CHECK_STR_EQ_FREE2("42000", format_parsable_size_with_suffix(42 * 1000));
- CHECK_STR_EQ_FREE2("1.0M", format_parsable_size_with_suffix(1000 * 1000));
- CHECK_STR_EQ_FREE2("1.2M", format_parsable_size_with_suffix(1234 * 1000));
- CHECK_STR_EQ_FREE2("438.5M",
- format_parsable_size_with_suffix(438.5 * 1000 * 1000));
- CHECK_STR_EQ_FREE2("1.0G",
- format_parsable_size_with_suffix(1000 * 1000 * 1000));
- CHECK_STR_EQ_FREE2(
- "17.1G",
- format_parsable_size_with_suffix(17.11 * 1000 * 1000 * 1000));
+ CHECK_STR_EQ_FREE2("0", format_parsable_size_with_suffix(0));
+ CHECK_STR_EQ_FREE2("42000", format_parsable_size_with_suffix(42 * 1000));
+ CHECK_STR_EQ_FREE2("1.0M", format_parsable_size_with_suffix(1000 * 1000));
+ CHECK_STR_EQ_FREE2("1.2M", format_parsable_size_with_suffix(1234 * 1000));
+ CHECK_STR_EQ_FREE2("438.5M",
+ format_parsable_size_with_suffix(438.5 * 1000 * 1000));
+ CHECK_STR_EQ_FREE2("1.0G",
+ format_parsable_size_with_suffix(1000 * 1000 * 1000));
+ CHECK_STR_EQ_FREE2(
+ "17.1G", format_parsable_size_with_suffix(17.11 * 1000 * 1000 * 1000));
}
TEST(parse_size_with_suffix)
{
- uint64_t size;
- size_t i;
- struct { const char *size; int64_t expected; } sizes[] = {
- {"0", 0},
- {"42", (int64_t)42 * 1000 * 1000 * 1000}, // Default suffix: G
-
- {"78k", 78 * 1000},
- {"78K", 78 * 1000},
- {"1.1 M", (int64_t)(1.1 * 1000 * 1000)},
- {"438.55M", (int64_t)(438.55 * 1000 * 1000)},
- {"1 G", 1 * 1000 * 1000 * 1000},
- {"2T", (int64_t)2 * 1000 * 1000 * 1000 * 1000},
-
- {"78 Ki", 78 * 1024},
- {"1.1Mi", (int64_t)(1.1 * 1024 * 1024)},
- {"438.55 Mi", (int64_t)(438.55 * 1024 * 1024)},
- {"1Gi", 1 * 1024 * 1024 * 1024},
- {"2 Ti", (int64_t)2 * 1024 * 1024 * 1024 * 1024},
- };
-
- for (i = 0; i < ARRAY_SIZE(sizes); ++i) {
- CHECKM(parse_size_with_suffix(sizes[i].size, &size), sizes[i].size);
- CHECK_INT_EQ(sizes[i].expected, size);
- }
+ uint64_t size;
+ size_t i;
+ struct
+ {
+ const char* size;
+ int64_t expected;
+ } sizes[] = {
+ {"0", 0},
+ {"42", (int64_t)42 * 1000 * 1000 * 1000}, // Default suffix: G
+
+ {"78k", 78 * 1000},
+ {"78K", 78 * 1000},
+ {"1.1 M", (int64_t)(1.1 * 1000 * 1000)},
+ {"438.55M", (int64_t)(438.55 * 1000 * 1000)},
+ {"1 G", 1 * 1000 * 1000 * 1000},
+ {"2T", (int64_t)2 * 1000 * 1000 * 1000 * 1000},
+
+ {"78 Ki", 78 * 1024},
+ {"1.1Mi", (int64_t)(1.1 * 1024 * 1024)},
+ {"438.55 Mi", (int64_t)(438.55 * 1024 * 1024)},
+ {"1Gi", 1 * 1024 * 1024 * 1024},
+ {"2 Ti", (int64_t)2 * 1024 * 1024 * 1024 * 1024},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(sizes); ++i) {
+ CHECKM(parse_size_with_suffix(sizes[i].size, &size), sizes[i].size);
+ CHECK_INT_EQ(sizes[i].expected, size);
+ }
}
TEST(format_command)
{
- const char *argv[] = {"foo", "bar", NULL};
+ const char* argv[] = {"foo", "bar", NULL};
- CHECK_STR_EQ_FREE2("foo bar\n", format_command(argv));
+ CHECK_STR_EQ_FREE2("foo bar\n", format_command(argv));
}
TEST(format_hex)
{
- uint8_t none[] = "";
- uint8_t text[4] = "foo"; // incl. NUL
- uint8_t data[4] = {0, 1, 2, 3};
- char result[2 * sizeof(data) + 1] = ".";
+ uint8_t none[] = "";
+ uint8_t text[4] = "foo"; // incl. NUL
+ uint8_t data[4] = {0, 1, 2, 3};
+ char result[2 * sizeof(data) + 1] = ".";
- format_hex(none, 0, result);
- CHECK_STR_EQ("", result);
+ format_hex(none, 0, result);
+ CHECK_STR_EQ("", result);
- format_hex(text, sizeof(text), result);
- CHECK_STR_EQ("666f6f00", result);
+ format_hex(text, sizeof(text), result);
+ CHECK_STR_EQ("666f6f00", result);
- format_hex(data, sizeof(data), result);
- CHECK_STR_EQ("00010203", result);
+ format_hex(data, sizeof(data), result);
+ CHECK_STR_EQ("00010203", result);
}
TEST_SUITE_END
diff --git a/unittest/util.cpp b/unittest/util.cpp
index af451586..0a5009fd 100644
--- a/unittest/util.cpp
+++ b/unittest/util.cpp
@@ -16,28 +16,29 @@
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#include "../src/system.hpp"
#include "util.hpp"
+#include "../src/system.hpp"
+
#ifdef _WIN32
-# define lstat(a, b) stat(a, b)
+# define lstat(a, b) stat(a, b)
#endif
bool
-path_exists(const char *path)
+path_exists(const char* path)
{
- struct stat st;
- return lstat(path, &st) == 0;
+ struct stat st;
+ return lstat(path, &st) == 0;
}
void
-create_file(const char *path, const char *content)
+create_file(const char* path, const char* content)
{
- FILE *f = fopen(path, "w");
- if (!f || fputs(content, f) < 0) {
- fprintf(stderr, "create_file: %s: %s\n", path, strerror(errno));
- }
- if (f) {
- fclose(f);
- }
+ FILE* f = fopen(path, "w");
+ if (!f || fputs(content, f) < 0) {
+ fprintf(stderr, "create_file: %s: %s\n", path, strerror(errno));
+ }
+ if (f) {
+ fclose(f);
+ }
}
diff --git a/unittest/util.hpp b/unittest/util.hpp
index 275b7c42..294483e3 100644
--- a/unittest/util.hpp
+++ b/unittest/util.hpp
@@ -20,6 +20,6 @@
#include <stdbool.h>
-bool path_exists(const char *path);
-bool is_symlink(const char *path);
-void create_file(const char *path, const char *content);
+bool path_exists(const char* path);
+bool is_symlink(const char* path);
+void create_file(const char* path, const char* content);